@Nullable
  Map<LookupElement, PrefixMatcher> retainMatchingItems(
      final String newPrefix, final LookupImpl lookup) {
    synchronized (lock) {
      LinkedHashMap<LookupElement, PrefixMatcher> map =
          new LinkedHashMap<LookupElement, PrefixMatcher>();
      for (LookupElement item : myItems) {
        if (item.isValid()) {
          PrefixMatcher matcher = lookup.itemMatcher(item).cloneWithPrefix(newPrefix);
          if (matcher.prefixMatches(item)) {
            map.put(item, matcher);
          }
        }
      }

      if (map.size() != myItems.size()) {
        clearItems();
        for (LookupElement newItem : map.keySet()) {
          addItem(newItem);
        }
      }

      return map;
    }
  }
  static CharFilter.Result getLookupAction(final char charTyped, final LookupImpl lookup) {
    final CharFilter.Result filtersDecision = getFiltersDecision(charTyped, lookup);
    if (!Registry.is("ide.completion.allow.finishing.by.chars")
        && filtersDecision == CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP) {
      return CharFilter.Result.HIDE_LOOKUP;
    }

    final LookupElement currentItem = lookup.getCurrentItem();
    if (currentItem != null && charTyped != ' ') {
      String postfix = lookup.getAdditionalPrefix() + charTyped;
      final PrefixMatcher matcher = lookup.itemMatcher(currentItem);
      for (String lookupString : currentItem.getAllLookupStrings()) {
        if (lookupString.startsWith(matcher.getPrefix() + postfix)) {
          return CharFilter.Result.ADD_TO_PREFIX;
        }
      }
    }

    if (filtersDecision != null) {
      return filtersDecision;
    }
    throw new AssertionError(
        "Typed char not handler by char filter: c="
            + charTyped
            + "; prefix="
            + currentItem
            + "; filters="
            + Arrays.toString(getFilters()));
  }
  public boolean fillInCommonPrefix(boolean explicitlyInvoked) {
    if (explicitlyInvoked) {
      setFocusDegree(FocusDegree.FOCUSED);
    }

    if (explicitlyInvoked && myCalculating) return false;
    if (!explicitlyInvoked && mySelectionTouched) return false;

    ListModel listModel = getListModel();
    if (listModel.getSize() <= 1) return false;

    if (listModel.getSize() == 0) return false;

    final LookupElement firstItem = (LookupElement) listModel.getElementAt(0);
    if (listModel.getSize() == 1 && firstItem instanceof EmptyLookupItem) return false;

    final PrefixMatcher firstItemMatcher = itemMatcher(firstItem);
    final String oldPrefix = firstItemMatcher.getPrefix();
    final String presentPrefix = oldPrefix + getAdditionalPrefix();
    String commonPrefix = getCaseCorrectedLookupString(firstItem);

    for (int i = 1; i < listModel.getSize(); i++) {
      LookupElement item = (LookupElement) listModel.getElementAt(i);
      if (item instanceof EmptyLookupItem) return false;
      if (!oldPrefix.equals(itemMatcher(item).getPrefix())) return false;

      final String lookupString = getCaseCorrectedLookupString(item);
      final int length = Math.min(commonPrefix.length(), lookupString.length());
      if (length < commonPrefix.length()) {
        commonPrefix = commonPrefix.substring(0, length);
      }

      for (int j = 0; j < length; j++) {
        if (commonPrefix.charAt(j) != lookupString.charAt(j)) {
          commonPrefix = lookupString.substring(0, j);
          break;
        }
      }

      if (commonPrefix.length() == 0 || commonPrefix.length() < presentPrefix.length()) {
        return false;
      }
    }

    if (commonPrefix.equals(presentPrefix)) {
      return false;
    }

    for (int i = 0; i < listModel.getSize(); i++) {
      LookupElement item = (LookupElement) listModel.getElementAt(i);
      if (!itemMatcher(item).cloneWithPrefix(commonPrefix).prefixMatches(item)) {
        return false;
      }
    }

    myOffsets.setInitialPrefix(presentPrefix, explicitlyInvoked);

    replacePrefix(presentPrefix, commonPrefix);
    return true;
  }
  private void addPrimitives() {
    for (PsiType type : PRIMITIVE_TYPES) {
      if (type.getCanonicalText().startsWith(_prefixMatcher.getPrefix())) {
        addCompletion(new PrimitiveCompletionProposal(type), _javaCtx);
      }
    }

    if ("block".startsWith(_prefixMatcher.getPrefix())) {
      addCompletion(new RawCompletionProposal("block"));
    }
  }
  public static void addCompletions(
      @NotNull final JavaSmartCompletionParameters parameters,
      @NotNull Consumer<LookupElement> result,
      final PrefixMatcher matcher) {

    final Condition<String> shortNameCondition =
        new Condition<String>() {
          public boolean value(String s) {
            return matcher.prefixMatches(s);
          }
        };

    PsiType classParameter =
        PsiUtil.substituteTypeParameter(
            parameters.getExpectedType(), CommonClassNames.JAVA_LANG_CLASS, 0, false);

    boolean addInheritors = false;
    PsiElement position = parameters.getPosition();
    if (classParameter instanceof PsiWildcardType) {
      final PsiWildcardType wildcardType = (PsiWildcardType) classParameter;
      classParameter = wildcardType.getBound();
      addInheritors = wildcardType.isExtends() && classParameter instanceof PsiClassType;
    } else if (!matcher.getPrefix().isEmpty()) {
      addInheritors = true;
      classParameter = PsiType.getJavaLangObject(position.getManager(), position.getResolveScope());
    }
    if (classParameter != null) {
      PsiFile file = position.getContainingFile();
      addClassLiteralLookupElement(classParameter, result, file);
      if (addInheritors) {
        addInheritorClassLiterals(file, shortNameCondition, classParameter, result, matcher);
      }
    }
  }
  @NotNull
  private static Set<String> sortMatching(
      @NotNull PrefixMatcher matcher, @NotNull Collection<String> names, @NotNull GoFile file) {
    ProgressManager.checkCanceled();
    String prefix = matcher.getPrefix();
    if (prefix.isEmpty()) return ContainerUtil.newLinkedHashSet(names);

    Set<String> packagesWithAliases = ContainerUtil.newHashSet();
    for (Map.Entry<String, Collection<GoImportSpec>> entry : file.getImportMap().entrySet()) {
      for (GoImportSpec spec : entry.getValue()) {
        String alias = spec.getAlias();
        if (spec.isDot() || alias != null) {
          packagesWithAliases.add(entry.getKey());
          break;
        }
      }
    }

    List<String> sorted = ContainerUtil.newArrayList();
    for (String name : names) {
      if (matcher.prefixMatches(name) || packagesWithAliases.contains(substringBefore(name, '.'))) {
        sorted.add(name);
      }
    }

    ProgressManager.checkCanceled();
    Collections.sort(sorted, String.CASE_INSENSITIVE_ORDER);
    ProgressManager.checkCanceled();

    LinkedHashSet<String> result = new LinkedHashSet<String>();
    for (String name : sorted) {
      if (matcher.isStartMatch(name)) {
        result.add(name);
      }
    }

    ProgressManager.checkCanceled();

    result.addAll(sorted);
    return result;
  }
  private void addScratchpadInnerClasses(@Nullable PsiElement position) {
    if (position == null) {
      return;
    }

    PsiFile psiFile = position.getContainingFile();
    if (!(psiFile instanceof GosuScratchpadFileImpl)) {
      return;
    }

    GosuScratchpadFileImpl scratchpadFile = (GosuScratchpadFileImpl) psiFile;
    for (PsiClass cls : scratchpadFile.getPsiClass().getInnerClasses()) {
      if (cls.getName().startsWith(_prefixMatcher.getPrefix())) {
        addCompletion(new PsiClassCompletionProposal(cls, _weight), _javaCtx);
      }
    }
  }
示例#8
0
  @Nullable
  public static LookupElementBuilder createPropertyLookupElement(
      @NotNull PsiMethod accessor,
      @Nullable GroovyResolveResult resolveResult,
      @Nullable PrefixMatcher matcher) {
    String propName;
    PsiType propType;
    final boolean getter = GroovyPropertyUtils.isSimplePropertyGetter(accessor, null);
    if (getter) {
      propName = GroovyPropertyUtils.getPropertyNameByGetter(accessor);
    } else if (GroovyPropertyUtils.isSimplePropertySetter(accessor, null)) {
      propName = GroovyPropertyUtils.getPropertyNameBySetter(accessor);
    } else {
      return null;
    }
    assert propName != null;
    if (!PsiUtil.isValidReferenceName(propName)) {
      propName = "'" + propName + "'";
    }

    if (matcher != null && !matcher.prefixMatches(propName)) {
      return null;
    }

    if (getter) {
      propType = PsiUtil.getSmartReturnType(accessor);
    } else {
      propType = accessor.getParameterList().getParameters()[0].getType();
    }

    final PsiType substituted =
        resolveResult != null ? resolveResult.getSubstitutor().substitute(propType) : propType;

    LookupElementBuilder builder =
        LookupElementBuilder.create(
                generatePropertyResolveResult(propName, accessor, propType, resolveResult),
                propName)
            .withIcon(JetgroovyIcons.Groovy.Property);
    if (substituted != null) {
      builder = builder.withTypeText(substituted.getPresentableText());
    }
    return builder;
  }
  private void addTypeLoaderTypes() {
    Set<String> fqnSet = new HashSet<String>();
    for (ITypeLoader loader : TypeSystem.getAllTypeLoaders()) {
      if (!loader.showTypeNamesInIDE()) {
        continue;
      }
      for (CharSequence typeName : loader.getAllTypeNames()) {
        String fqn = typeName.toString();
        int iAngle = fqn.indexOf('<');
        if (iAngle >= 0) {
          fqn = fqn.substring(0, iAngle);
        }
        if (fqnSet.contains(fqn)) {
          continue;
        }
        int iDot = fqn.lastIndexOf('.');
        String relativeName = iDot >= 0 ? fqn.substring(iDot + 1) : fqn;
        if (_prefixMatcher.prefixMatches(relativeName)) {
          if (_filter == null || _filter.isAcceptable(fqn, _params.getPosition())) {
            IType type = TypeSystem.getByFullNameIfValid(fqn, loader.getModule());
            if (type == null) {
              continue;
            }

            // Note this second cache lookup exists because there is a many-to-one mapping
            // between type names and ITypes e.g., several type names may map to an entity type.
            fqn = type.getName();
            if (fqnSet.contains(fqn)) {
              continue;
            }
            fqnSet.add(fqn);

            addCompletion(
                new GosuTypeCompletionProposal(type, getContext().getPosition(), _weight),
                _javaCtx);
          }
        }
      }
    }
  }
  private static void addInheritorClassLiterals(
      final PsiFile context,
      Condition<String> shortNameCondition,
      final PsiType classParameter,
      final Consumer<LookupElement> result,
      PrefixMatcher matcher) {
    final String canonicalText = classParameter.getCanonicalText();
    if (CommonClassNames.JAVA_LANG_OBJECT.equals(canonicalText)
        && StringUtil.isEmpty(matcher.getPrefix())) {
      return;
    }

    CodeInsightUtil.processSubTypes(
        classParameter,
        context,
        true,
        shortNameCondition,
        new Consumer<PsiType>() {
          @Override
          public void consume(PsiType type) {
            addClassLiteralLookupElement(type, result, context);
          }
        });
  }
 private static boolean completeTillTypedCharOccurrence(
     char charTyped, LookupImpl lookup, LookupElement item) {
   PrefixMatcher matcher = lookup.itemMatcher(item);
   final String oldPrefix = matcher.getPrefix() + lookup.getAdditionalPrefix();
   PrefixMatcher expanded = matcher.cloneWithPrefix(oldPrefix + charTyped);
   if (expanded.prefixMatches(item)) {
     for (String s : item.getAllLookupStrings()) {
       if (matcher.prefixMatches(s)) {
         int i = -1;
         while (true) {
           i = s.indexOf(charTyped, i + 1);
           if (i < 0) break;
           final String newPrefix = s.substring(0, i + 1);
           if (expanded.prefixMatches(newPrefix)) {
             lookup.replacePrefix(oldPrefix, newPrefix);
             return true;
           }
         }
       }
     }
   }
   return false;
 }
示例#12
0
  public static void processSubTypes(
      PsiType psiType,
      final PsiElement context,
      boolean getRawSubtypes,
      @NotNull final PrefixMatcher matcher,
      Consumer<PsiType> consumer) {
    int arrayDim = psiType.getArrayDimensions();

    psiType = psiType.getDeepComponentType();
    if (!(psiType instanceof PsiClassType)) return;

    final Condition<String> shortNameCondition =
        new Condition<String>() {
          @Override
          public boolean value(String s) {
            return matcher.prefixMatches(s);
          }
        };

    final PsiClassType baseType = (PsiClassType) psiType;
    final PsiClassType.ClassResolveResult baseResult =
        ApplicationManager.getApplication()
            .runReadAction(
                new Computable<PsiClassType.ClassResolveResult>() {
                  @Override
                  public PsiClassType.ClassResolveResult compute() {
                    return JavaCompletionUtil.originalize(baseType).resolveGenerics();
                  }
                });
    final PsiClass baseClass = baseResult.getElement();
    final PsiSubstitutor baseSubstitutor = baseResult.getSubstitutor();
    if (baseClass == null) return;

    final GlobalSearchScope scope =
        ApplicationManager.getApplication()
            .runReadAction(
                new Computable<GlobalSearchScope>() {
                  @Override
                  public GlobalSearchScope compute() {
                    return context.getResolveScope();
                  }
                });

    final Processor<PsiClass> inheritorsProcessor =
        createInheritorsProcessor(
            context, baseType, arrayDim, getRawSubtypes, consumer, baseClass, baseSubstitutor);
    if (matcher.getPrefix().length() > 2) {
      AllClassesGetter.processJavaClasses(
          matcher,
          context.getProject(),
          scope,
          new Processor<PsiClass>() {
            @Override
            public boolean process(PsiClass psiClass) {
              if (psiClass.isInheritor(baseClass, true)) {
                return inheritorsProcessor.process(psiClass);
              }
              return true;
            }
          });
    } else {
      final Query<PsiClass> baseQuery =
          ClassInheritorsSearch.search(
              new ClassInheritorsSearch.SearchParameters(
                  baseClass, scope, true, false, false, shortNameCondition));
      final Query<PsiClass> query =
          new FilteredQuery<PsiClass>(
              baseQuery,
              new Condition<PsiClass>() {
                @Override
                public boolean value(final PsiClass psiClass) {
                  return !(psiClass instanceof PsiTypeParameter);
                }
              });
      query.forEach(inheritorsProcessor);
    }
  }