@Override public Object[] getFileReferenceCompletionVariants(final FileReference reference) { final String s = reference.getText(); if (s != null && s.equals("/")) { return ArrayUtil.EMPTY_OBJECT_ARRAY; } final CommonProcessors.CollectUniquesProcessor<PsiFileSystemItem> collector = new CommonProcessors.CollectUniquesProcessor<PsiFileSystemItem>(); final PsiElementProcessor<PsiFileSystemItem> processor = new PsiElementProcessor<PsiFileSystemItem>() { @Override public boolean execute(@NotNull PsiFileSystemItem fileSystemItem) { return new FilteringProcessor<PsiFileSystemItem>( reference.getFileReferenceSet().getReferenceCompletionFilter(), collector) .process(FileReference.getOriginalFile(fileSystemItem)); } }; List<Object> additionalItems = ContainerUtil.newArrayList(); for (PsiFileSystemItem context : reference.getContexts()) { for (final PsiElement child : context.getChildren()) { if (child instanceof PsiFileSystemItem) { processor.execute((PsiFileSystemItem) child); } } if (context instanceof FileReferenceResolver) { additionalItems.addAll(((FileReferenceResolver) context).getVariants(reference)); } } final FileType[] types = reference.getFileReferenceSet().getSuitableFileTypes(); final THashSet<PsiElement> set = new THashSet<PsiElement>(collector.getResults(), VARIANTS_HASHING_STRATEGY); final PsiElement[] candidates = PsiUtilCore.toPsiElementArray(set); final Object[] variants = new Object[candidates.length + additionalItems.size()]; for (int i = 0; i < candidates.length; i++) { PsiElement candidate = candidates[i]; Object item = reference.createLookupItem(candidate); if (item == null) { item = FileInfoManager.getFileLookupItem(candidate); } if (candidate instanceof PsiFile && item instanceof LookupElement && types.length > 0 && ArrayUtil.contains(((PsiFile) candidate).getFileType(), types)) { item = PrioritizedLookupElement.withPriority((LookupElement) item, Double.MAX_VALUE); } variants[i] = item; } for (int i = 0; i < additionalItems.size(); i++) { variants[i + candidates.length] = additionalItems.get(i); } if (!reference.getFileReferenceSet().isUrlEncoded()) { return variants; } List<Object> encodedVariants = new ArrayList<Object>(variants.length + additionalItems.size()); for (int i = 0; i < candidates.length; i++) { final PsiElement element = candidates[i]; if (element instanceof PsiNamedElement) { final PsiNamedElement psiElement = (PsiNamedElement) element; String name = psiElement.getName(); final String encoded = reference.encode(name, psiElement); if (encoded == null) continue; if (!encoded.equals(name)) { final Icon icon = psiElement.getIcon(Iconable.ICON_FLAG_READ_STATUS | Iconable.ICON_FLAG_VISIBILITY); LookupElementBuilder item = FileInfoManager.getFileLookupItem(candidates[i], encoded, icon); encodedVariants.add(item.withTailText(" (" + name + ")")); } else { encodedVariants.add(variants[i]); } } } encodedVariants.addAll(additionalItems); return ArrayUtil.toObjectArray(encodedVariants); }
@NotNull public static LookupElement createLookupElement( @NotNull KotlinCodeAnalyzer analyzer, @NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) { if (declaration != null) { MutableLookupElement javaLookupElement = createJavaLookupElementIfPossible(declaration); if (javaLookupElement != null) { InsertHandler<LookupElement> customHandler = getInsertHandler(descriptor); if (customHandler != null) { return javaLookupElement.setInsertHandler(getInsertHandler(descriptor)); } else { return javaLookupElement; } } } LookupElementBuilder element = LookupElementBuilder.create( new JetLookupObject(descriptor, analyzer, declaration), descriptor.getName().getName()); String presentableText = descriptor.getName().getName(); String typeText = ""; String tailText = ""; boolean tailTextGrayed = true; if (descriptor instanceof FunctionDescriptor) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; JetType returnType = functionDescriptor.getReturnType(); typeText = DescriptorRenderer.TEXT.renderType(returnType); presentableText += DescriptorRenderer.TEXT.renderFunctionParameters(functionDescriptor); boolean extensionFunction = functionDescriptor.getReceiverParameter() != null; DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); if (containingDeclaration != null && extensionFunction) { tailText += " for " + DescriptorRenderer.TEXT.renderType( functionDescriptor.getReceiverParameter().getType()); tailText += " in " + DescriptorUtils.getFQName(containingDeclaration); } } else if (descriptor instanceof VariableDescriptor) { JetType outType = ((VariableDescriptor) descriptor).getType(); typeText = DescriptorRenderer.TEXT.renderType(outType); } else if (descriptor instanceof ClassDescriptor) { DeclarationDescriptor declaredIn = descriptor.getContainingDeclaration(); assert declaredIn != null; tailText = " (" + DescriptorUtils.getFQName(declaredIn) + ")"; tailTextGrayed = true; } else { typeText = DescriptorRenderer.TEXT.render(descriptor); } element = element.withInsertHandler(getInsertHandler(descriptor)); element = element .withTailText(tailText, tailTextGrayed) .withTypeText(typeText) .withPresentableText(presentableText); element = element.withIcon( JetDescriptorIconProvider.getIcon(descriptor, Iconable.ICON_FLAG_VISIBILITY)); element = element.withStrikeoutness(KotlinBuiltIns.getInstance().isDeprecated(descriptor)); return 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); } } }