private static void addInheritors( CompletionParameters parameters, final CompletionResultSet resultSet, final PsiClass referencedClass, final int parameterIndex) { final List<PsiClassType> typeList = Collections.singletonList( (PsiClassType) TypeConversionUtil.typeParameterErasure( referencedClass.getTypeParameters()[parameterIndex])); JavaInheritorsGetter.processInheritors( parameters, typeList, resultSet.getPrefixMatcher(), new Consumer<PsiType>() { @Override public void consume(final PsiType type) { final PsiClass psiClass = PsiUtil.resolveClassInType(type); if (psiClass == null) return; resultSet.addElement( TailTypeDecorator.withTail( new JavaPsiClassReferenceElement(psiClass), getTail(parameterIndex == referencedClass.getTypeParameters().length - 1))); } }); }
public static void addAllClasses( CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritors) { if (!isClassNamePossible(parameters) || !mayStartClassName(result)) { return; } if (parameters.getInvocationCount() >= 2) { JavaClassNameCompletionContributor.addAllClasses( parameters, parameters.getInvocationCount() <= 2, result.getPrefixMatcher(), new Consumer<LookupElement>() { @Override public void consume(LookupElement element) { if (!inheritors.alreadyProcessed(element)) { result.addElement(element); } } }); } else { advertiseSecondCompletion(parameters.getPosition().getProject(), result); } }
private static void suggestChainedCalls( CompletionParameters parameters, CompletionResultSet result, PsiElement position) { PsiElement parent = position.getParent(); if (!(parent instanceof PsiJavaCodeReferenceElement)) { return; } PsiElement qualifier = ((PsiJavaCodeReferenceElement) parent).getQualifier(); if (!(qualifier instanceof PsiJavaCodeReferenceElement) || ((PsiJavaCodeReferenceElement) qualifier).isQualified() || ((PsiJavaCodeReferenceElement) qualifier).resolve() != null) { return; } String fullPrefix = position .getContainingFile() .getText() .substring(parent.getTextRange().getStartOffset(), parameters.getOffset()); CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix); ElementFilter filter = JavaCompletionContributor.getReferenceFilter(position); for (LookupElement base : suggestQualifierItems(parameters, (PsiJavaCodeReferenceElement) qualifier, filter)) { PsiType type = JavaCompletionUtil.getLookupElementType(base); if (type != null && !PsiType.VOID.equals(type)) { PsiReferenceExpression ref = ReferenceExpressionCompletionContributor.createMockReference(position, type, base); for (final LookupElement item : JavaSmartCompletionContributor.completeReference( position, ref, filter, true, true, parameters, result.getPrefixMatcher())) { qualifiedCollector.addElement(new JavaChainLookupElement(base, item)); } } } }
public static CompletionResultSet addJavaSorting( final CompletionParameters parameters, CompletionResultSet result) { final PsiElement position = parameters.getPosition(); final ExpectedTypeInfo[] expectedTypes = PsiJavaPatterns.psiElement() .beforeLeaf(PsiJavaPatterns.psiElement().withText(".")) .accepts(position) ? ExpectedTypeInfo.EMPTY_ARRAY : JavaSmartCompletionContributor.getExpectedTypes(parameters); final CompletionType type = parameters.getCompletionType(); final boolean smart = type == CompletionType.SMART; final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position); List<LookupElementWeigher> afterProximity = new ArrayList<LookupElementWeigher>(); afterProximity.add(new PreferContainingSameWords(expectedTypes)); if (smart) { afterProximity.add(new PreferFieldsAndGetters()); } afterProximity.add(new PreferShorter(expectedTypes)); CompletionSorter sorter = CompletionSorter.defaultSorter(parameters, result.getPrefixMatcher()); if (!smart && afterNew) { sorter = sorter.weighBefore("liftShorter", new PreferExpected(true, expectedTypes)); } else if (PsiTreeUtil.getParentOfType(position, PsiReferenceList.class) == null) { sorter = ((CompletionSorterImpl) sorter) .withClassifier("liftShorterClasses", true, new LiftShorterClasses(position)); } if (smart) { sorter = sorter.weighAfter("priority", new PreferDefaultTypeWeigher(expectedTypes, parameters)); } List<LookupElementWeigher> afterPrefix = ContainerUtil.newArrayList(); if (!smart) { ContainerUtil.addIfNotNull(afterPrefix, preferStatics(position, expectedTypes)); } ContainerUtil.addIfNotNull(afterPrefix, recursion(parameters, expectedTypes)); if (!smart && !afterNew) { afterPrefix.add(new PreferExpected(false, expectedTypes)); } Collections.addAll( afterPrefix, new PreferByKindWeigher(type, position), new PreferSimilarlyEnding(expectedTypes), new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple(), new PreferEnumConstants(parameters)); sorter = sorter.weighAfter( "prefix", afterPrefix.toArray(new LookupElementWeigher[afterPrefix.size()])); sorter = sorter.weighAfter( "proximity", afterProximity.toArray(new LookupElementWeigher[afterProximity.size()])); return result.withRelevanceSorter(sorter); }
private static void suggestCollectionUtilities( CompletionParameters parameters, final CompletionResultSet result, PsiElement position) { if (StringUtil.isNotEmpty(result.getPrefixMatcher().getPrefix())) { for (ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) { new CollectionsUtilityMethodsProvider( position, info.getType(), info.getDefaultType(), result) .addCompletions(true); } } }
private static void addKeywords(CompletionParameters parameters, CompletionResultSet result) { PsiElement position = parameters.getPosition(); final Set<LookupElement> lookupSet = new LinkedHashSet<LookupElement>(); final Set<CompletionVariant> keywordVariants = new HashSet<CompletionVariant>(); final JavaCompletionData completionData = getCompletionData(PsiUtil.getLanguageLevel(position)); completionData.addKeywordVariants(keywordVariants, position, parameters.getOriginalFile()); completionData.completeKeywordsBySet( lookupSet, keywordVariants, position, result.getPrefixMatcher(), parameters.getOriginalFile()); completionData.fillCompletions(parameters, result); for (final LookupElement item : lookupSet) { result.addElement(item); } }
@Override protected void addCompletions( @NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) { UnicodeCharacterNames.iterate( name -> { if (result.getPrefixMatcher().prefixMatches(name)) { final String type = new String(new int[] {UnicodeCharacterNames.getCodePoint(name)}, 0, 1); if (myEmbrace) { result.addElement(createLookupElement("{" + name + "}", type, emptyIcon)); } else { result.addElement( TailTypeDecorator.withTail( createLookupElement(name, type, emptyIcon), TailType.createSimpleTailType('}'))); } } ProgressManager.checkCanceled(); }); }
private static void suggestNonImportedClasses( CompletionParameters parameters, CompletionResultSet result, @Nullable JavaCompletionSession session) { JavaClassNameCompletionContributor.addAllClasses( parameters, true, result.getPrefixMatcher(), element -> { if (session != null && session.alreadyProcessed(element)) { return; } JavaPsiClassReferenceElement classElement = element.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); if (classElement != null) { classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); element = JavaClassNameCompletionContributor.highlightIfNeeded(classElement, parameters); } result.addElement(element); }); }
private static void completeAnnotationAttributeName( CompletionResultSet result, PsiElement insertedElement, CompletionParameters parameters) { PsiNameValuePair pair = PsiTreeUtil.getParentOfType(insertedElement, PsiNameValuePair.class); PsiAnnotationParameterList parameterList = (PsiAnnotationParameterList) pair.getParent(); PsiAnnotation anno = (PsiAnnotation) parameterList.getParent(); boolean showClasses = psiElement().afterLeaf("(").accepts(insertedElement); PsiClass annoClass = null; final PsiJavaCodeReferenceElement referenceElement = anno.getNameReferenceElement(); if (referenceElement != null) { final PsiElement element = referenceElement.resolve(); if (element instanceof PsiClass) { annoClass = (PsiClass) element; if (annoClass.findMethodsByName("value", false).length == 0) { showClasses = false; } } } if (showClasses && insertedElement.getParent() instanceof PsiReferenceExpression) { final Set<LookupElement> set = JavaCompletionUtil.processJavaReference( insertedElement, (PsiJavaReference) insertedElement.getParent(), new ElementExtractorFilter(createAnnotationFilter(insertedElement)), JavaCompletionProcessor.Options.DEFAULT_OPTIONS, result.getPrefixMatcher(), parameters); for (final LookupElement element : set) { result.addElement(element); } addAllClasses(parameters, result, new InheritorsHolder(insertedElement, result)); } if (annoClass != null) { final PsiNameValuePair[] existingPairs = parameterList.getAttributes(); methods: for (PsiMethod method : annoClass.getMethods()) { if (!(method instanceof PsiAnnotationMethod)) continue; final String attrName = method.getName(); for (PsiNameValuePair existingAttr : existingPairs) { if (PsiTreeUtil.isAncestor(existingAttr, insertedElement, false)) break; if (Comparing.equal(existingAttr.getName(), attrName) || PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(attrName) && existingAttr.getName() == null) continue methods; } LookupElementBuilder element = LookupElementBuilder.createWithIcon(method) .withInsertHandler( new InsertHandler<LookupElement>() { @Override public void handleInsert(InsertionContext context, LookupElement item) { final Editor editor = context.getEditor(); TailType.EQ.processTail(editor, editor.getCaretModel().getOffset()); context.setAddCompletionChar(false); context.commitDocument(); PsiAnnotationParameterList paramList = PsiTreeUtil.findElementOfClassAtOffset( context.getFile(), context.getStartOffset(), PsiAnnotationParameterList.class, false); if (paramList != null && paramList.getAttributes().length > 0 && paramList.getAttributes()[0].getName() == null) { int valueOffset = paramList.getAttributes()[0].getTextRange().getStartOffset(); context .getDocument() .insertString( valueOffset, PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME); TailType.EQ.processTail( editor, valueOffset + PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.length()); } } }); PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod) method).getDefaultValue(); if (defaultValue != null) { Object constant = JavaPsiFacade.getInstance(method.getProject()) .getConstantEvaluationHelper() .computeConstantExpression(defaultValue); if (constant != null) { element = element.withTailText( " default " + (constant instanceof String ? "\"" + constant + "\"" : constant), true); } } result.addElement(element); } } }
public static boolean mayStartClassName(CompletionResultSet result) { return StringUtil.isNotEmpty(result.getPrefixMatcher().getPrefix()); }
@Override public void fillCompletionVariants( final CompletionParameters parameters, final CompletionResultSet _result) { if (parameters.getCompletionType() != CompletionType.BASIC) { return; } final PsiElement position = parameters.getPosition(); if (!isInJavaContext(position)) { return; } if (AFTER_NUMBER_LITERAL.accepts(position) || UNEXPECTED_REFERENCE_AFTER_DOT.accepts(position)) { _result.stopHere(); return; } final CompletionResultSet result = JavaCompletionSorting.addJavaSorting(parameters, _result); if (ANNOTATION_ATTRIBUTE_NAME.accepts(position) && !JavaCompletionData.isAfterPrimitiveOrArrayType(position)) { JavaCompletionData.addExpectedTypeMembers(parameters, result); completeAnnotationAttributeName(result, position, parameters); result.stopHere(); return; } final InheritorsHolder inheritors = new InheritorsHolder(position, result); if (JavaSmartCompletionContributor.IN_TYPE_ARGS.accepts(position)) { new TypeArgumentCompletionProvider(false, inheritors) .addCompletions(parameters, new ProcessingContext(), result); } PrefixMatcher matcher = result.getPrefixMatcher(); if (JavaSmartCompletionContributor.AFTER_NEW.accepts(position)) { new JavaInheritorsGetter(ConstructorInsertHandler.BASIC_INSTANCE) .generateVariants(parameters, matcher, inheritors); } if (IMPORT_REFERENCE.accepts(position)) { result.addElement(LookupElementBuilder.create("*")); } addKeywords(parameters, result); Set<String> usedWords = addReferenceVariants(parameters, result, inheritors); if (psiElement().inside(PsiLiteralExpression.class).accepts(position)) { PsiReference reference = position.getContainingFile().findReferenceAt(parameters.getOffset()); if (reference == null || reference.isSoft()) { WordCompletionContributor.addWordCompletionVariants(result, parameters, usedWords); } } JavaGenerateMemberCompletionContributor.fillCompletionVariants(parameters, result); addAllClasses(parameters, result, inheritors); final PsiElement parent = position.getParent(); if (parent instanceof PsiReferenceExpression && !((PsiReferenceExpression) parent).isQualified() && parameters.isExtendedCompletion() && StringUtil.isNotEmpty(matcher.getPrefix())) { new JavaStaticMemberProcessor(parameters).processStaticMethodsGlobally(matcher, result); } result.stopHere(); }
public static CompletionResultSet addJavaSorting( final CompletionParameters parameters, CompletionResultSet result) { String prefix = result.getPrefixMatcher().getPrefix(); final PsiElement position = parameters.getPosition(); final ExpectedTypeInfo[] expectedTypes = PsiJavaPatterns.psiElement() .beforeLeaf(PsiJavaPatterns.psiElement().withText(".")) .accepts(position) ? ExpectedTypeInfo.EMPTY_ARRAY : JavaSmartCompletionContributor.getExpectedTypes(parameters); final CompletionType type = parameters.getCompletionType(); final boolean smart = type == CompletionType.SMART; final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position); List<LookupElementWeigher> afterNegativeStats = new ArrayList<LookupElementWeigher>(); if (!smart) { ContainerUtil.addIfNotNull(afterNegativeStats, preferStatics(position)); } afterNegativeStats.add(new PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(type, position)); ContainerUtil.addIfNotNull(afterNegativeStats, recursion(parameters, expectedTypes)); if (!smart && !afterNew) { afterNegativeStats.add(new PreferExpected(false, expectedTypes)); } afterNegativeStats.add(new PreferSimilarlyEnding(expectedTypes, prefix)); List<LookupElementWeigher> afterProximity = new ArrayList<LookupElementWeigher>(); afterProximity.add(new PreferContainingSameWords(expectedTypes)); if (smart) { afterProximity.add(new PreferFieldsAndGetters()); } afterProximity.add(new PreferShorter(expectedTypes, prefix)); CompletionSorter sorter = CompletionSorter.defaultSorter(parameters, result.getPrefixMatcher()); if (!smart && afterNew) { sorter = sorter.weighBefore("liftShorter", new PreferExpected(true, expectedTypes)); } else { final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(position.getProject()).getFileIndex(); sorter = ((CompletionSorterImpl) sorter) .withClassifier( "liftShorter", true, new ClassifierFactory<LookupElement>("liftShorterClasses") { @Override public Classifier<LookupElement> createClassifier( Classifier<LookupElement> next) { return new LiftShorterItemsClassifier( next, new LiftShorterItemsClassifier.LiftingCondition() { @Override public boolean shouldLift( LookupElement shorterElement, LookupElement longerElement, ProcessingContext context) { if (super.shouldLift(shorterElement, longerElement, context)) { return true; } Object object = shorterElement.getObject(); if (object instanceof PsiClass) { PsiFile file = ((PsiClass) object).getContainingFile(); if (file != null) { VirtualFile vFile = file.getOriginalFile().getVirtualFile(); if (vFile != null && fileIndex.isInSource(vFile)) { return true; } } } return false; } }); } }); } if (smart) { sorter = sorter.weighBefore( "negativeStats", new PreferDefaultTypeWeigher(expectedTypes, parameters)); } sorter = sorter.weighAfter( "negativeStats", afterNegativeStats.toArray(new LookupElementWeigher[afterNegativeStats.size()])); sorter = sorter.weighAfter( "prefix", new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple(), new PreferEnumConstants(parameters)); sorter = sorter.weighAfter( "proximity", afterProximity.toArray(new LookupElementWeigher[afterProximity.size()])); return result.withRelevanceSorter(sorter); }