@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); } } }
@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; }
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); } }