public void registerReferenceProviders(PsiReferenceRegistrar registrar) { registrar.registerReferenceProvider( PsiJavaPatterns.literalExpression() .annotationParam("org.unitils.dbunit.annotation.DataSet", "value"), new URIReferenceProvider(), PsiReferenceRegistrar.HIGHER_PRIORITY); registrar.registerReferenceProvider( PsiJavaPatterns.literalExpression() .annotationParam("org.unitils.dbunit.annotation.ExpectedDataSet", "value"), new URIReferenceProvider(), PsiReferenceRegistrar.HIGHER_PRIORITY); registrar.registerReferenceProvider( PsiJavaPatterns.literalExpression() .insideAnnotationParam( PlatformPatterns.string() .with( new PatternCondition<String>("DataSet") { public boolean accepts( @NotNull final String annotationFQN, final ProcessingContext context) { return annotationFQN.equals("org.unitils.dbunit.annotation.DataSet"); } }), "value"), new URIReferenceProvider()); }
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); }
@Override @Nullable public ExpectedTypeInfo[] fun(final CompletionLocation location) { if (PsiJavaPatterns.psiElement() .beforeLeaf(PsiJavaPatterns.psiElement().withText(".")) .accepts(location.getCompletionParameters().getPosition())) { return ExpectedTypeInfo.EMPTY_ARRAY; } return JavaSmartCompletionContributor.getExpectedTypes( location.getCompletionParameters()); }
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); }
public class TypeCompletionHandler extends AbstractCompletionHandler { private static final List<PsiPrimitiveType> PRIMITIVE_TYPES = ImmutableList.of( PsiType.BYTE, PsiType.CHAR, PsiType.DOUBLE, PsiType.FLOAT, PsiType.INT, PsiType.LONG, PsiType.SHORT, PsiType.BOOLEAN, PsiType.VOID); public static final PsiJavaElementPattern.Capture<PsiElement> IN_TYPE_PARAMETER = PsiJavaPatterns.psiElement() .afterLeaf(PsiKeyword.EXTENDS, PsiKeyword.SUPER, "&") .withParent( PsiJavaPatterns.psiElement(PsiReferenceList.class) .withParent(PsiTypeParameter.class)); public static final PsiJavaElementPattern.Capture<PsiElement> INSIDE_METHOD_THROWS_CLAUSE = PsiJavaPatterns.psiElement() .afterLeaf(PsiKeyword.THROWS, ",") .inside(PsiMethod.class) .andNot(PsiJavaPatterns.psiElement().inside(PsiCodeBlock.class)) .andNot(PsiJavaPatterns.psiElement().inside(PsiParameterList.class)); public static final ElementPattern<PsiElement> AFTER_THROW_NEW = psiElement() .afterLeaf( psiElement() .withText(PsiKeyword.NEW) .afterLeaf(psiElement().withText(PsiKeyword.THROW))); private final ElementFilter _filter; private int _weight; @NotNull private final PrefixMatcher _prefixMatcher; private final boolean _javaCtx; public TypeCompletionHandler( @NotNull CompletionParameters parameters, @NotNull CompletionResultSet result, int weight) { super(parameters, result); _filter = getDefaultFilter(parameters.getPosition()); _weight = weight; _prefixMatcher = result.getPrefixMatcher(); _javaCtx = parameters.getPosition() instanceof PsiIdentifier; } public TypeCompletionHandler( @NotNull CompletionParameters parameters, @NotNull CompletionResultSet result, ElementFilter filter, int weight) { super(parameters, result); _filter = filter; _weight = weight; _prefixMatcher = result.getPrefixMatcher(); _javaCtx = parameters.getPosition() instanceof PsiIdentifier; } @NotNull private ElementFilter getDefaultFilter(PsiElement insertedElement) { return AFTER_THROW_NEW.accepts(insertedElement) ? new AssignableFromFilter("java.lang.Throwable") : IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) : INSIDE_METHOD_THROWS_CLAUSE.accepts(insertedElement) ? new AnyInnerFilter(new AssignableFromFilter("java.lang.Throwable")) : getLocalFilter(insertedElement); } @Override public void handleCompletePath() { final PsiElement position = getContext().getPosition(); if (position instanceof GosuIdentifierImpl) { if (position.getParent() instanceof GosuTypeLiteralImpl) { if (position.getParent().getParent() instanceof GosuUsesStatementImpl) { return; } } } // primitives are always available addPrimitives(); addScratchpadInnerClasses(position); // ## THIS IS DOGASS SLOW, the eventual call to CustomPsiClassCache.getByShortName() is f*****g // molasses, don't do this here. // AllClassesGetter.processJavaClasses( _params, _prefixMatcher, _params.getInvocationCount() // <= 1, new Consumer<PsiClass>() { // ... // } ); addTypeLoaderTypes(); if (getTotalCompletions() == 0 && _params.getInvocationCount() < 2) { stopFilterByInvocationCount(); addTypeLoaderTypes(); } } 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 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); } } } 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")); } } }
@Override public Result acceptChar(char c, final int prefixLength, final Lookup lookup) { if (!lookup.getPsiFile().getLanguage().isKindOf(JavaLanguage.INSTANCE)) { return null; } LookupElement item = lookup.getCurrentItem(); if (item == null) return null; final Object o = item.getObject(); if (c == '!') { if (o instanceof PsiVariable) { if (PsiType.BOOLEAN.isAssignableFrom(((PsiVariable) o).getType())) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } if (o instanceof PsiMethod) { final PsiType type = ((PsiMethod) o).getReturnType(); if (type != null && PsiType.BOOLEAN.isAssignableFrom(type)) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } if (o instanceof PsiKeyword && ((PsiKeyword) o).textMatches(PsiKeyword.INSTANCEOF)) { return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } return null; } if (c == '.' && isWithinLiteral(lookup)) return Result.ADD_TO_PREFIX; if (c == ':') { PsiFile file = lookup.getPsiFile(); PsiDocumentManager.getInstance(file.getProject()) .commitDocument(lookup.getEditor().getDocument()); PsiElement leaf = file.findElementAt(lookup.getEditor().getCaretModel().getOffset() - 1); if (PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_8)) { PsiStatement statement = PsiTreeUtil.getParentOfType(leaf, PsiStatement.class); if (statement == null || statement.getTextRange().getStartOffset() != leaf.getTextRange().getStartOffset()) { // not typing a statement label return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } } if (PsiTreeUtil.getParentOfType(leaf, PsiSwitchLabelStatement.class) != null || PsiTreeUtil.getParentOfType(leaf, PsiConditionalExpression.class) != null) { return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } return Result.HIDE_LOOKUP; } if (c == '[' || c == ']' || c == ')' || c == '>') return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP; if (c == '<' && o instanceof PsiClass) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; if (c == '(') { if (o instanceof PsiClass) { if (PsiJavaPatterns.psiElement() .afterLeaf(PsiKeyword.NEW) .accepts(lookup.getPsiElement())) { return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } return Result.HIDE_LOOKUP; } if (o instanceof PsiType) { return Result.HIDE_LOOKUP; } } if ((c == ',' || c == '=') && o instanceof PsiVariable) { int lookupStart = lookup.getLookupStart(); String name = ((PsiVariable) o).getName(); if (lookupStart >= 0 && name != null && name.equals(lookup.itemPattern(item))) { return Result.HIDE_LOOKUP; } } if (c == '#' && PsiTreeUtil.getParentOfType(lookup.getPsiElement(), PsiDocComment.class) != null) { if (o instanceof PsiClass) { return Result.SELECT_ITEM_AND_FINISH_LOOKUP; } } if (c == '(' && PsiKeyword.RETURN.equals(item.getLookupString())) { return Result.HIDE_LOOKUP; } return null; }
public void registerReferenceProviders(PsiReferenceRegistrar registrar) { // errors tag add Reference Provider for Setters Method on parameter field registerXmlAttributeReferenceProvider( registrar, new SetterMethodsReferenceProvider(FORM_TAG), FIELD_ATTR, ERRORS_TAG); // all stripes tags for input form add Reference Provider for Setters Method registerXmlAttributeReferenceProvider( registrar, new SetterMethodsReferenceProvider(FORM_TAG), NAME_ATTR, INPUT_TAGS); // param tag add Reference Provider for Setter Methods registerXmlAttributeReferenceProvider( registrar, new SetterMethodsReferenceProvider(LINK_TAG), NAME_ATTR, PARAM_TAG); registerXmlAttributeReferenceProvider( registrar, new SetterMethodsReferenceProvider(URL_TAG), NAME_ATTR, PARAM_TAG); registerXmlAttributeReferenceProvider( registrar, new PsiReferenceProvider() { @NotNull public PsiReference[] getReferencesByElement( @NotNull PsiElement element, @NotNull ProcessingContext context) { if (PsiTreeUtil.getChildOfType(element, ELExpressionHolder.class) != null) { return PsiReference.EMPTY_ARRAY; } final PsiClass actionBeanPsiClass = StripesReferenceUtil.getBeanClassFromParentTag( (XmlTag) element.getParent().getParent(), FORM_TAG); if (null != actionBeanPsiClass) { List<String> arr = StringUtil.split(ElementManipulators.getValueText(element), ","); List<PsiReference> retval = new LinkedList<PsiReference>(); int offset = 1; for (String anArr : arr) { Collections.addAll( retval, new SetterReferenceExSet(anArr, element, offset, '.', actionBeanPsiClass, false) .getPsiReferences()); offset += (anArr.length() + 1); } return retval.toArray(new PsiReference[retval.size()]); } return PsiReference.EMPTY_ARRAY; } }, FIELDS_ATTR, FIELD_METADATA_TAG); registrar.registerReferenceProvider( PsiJavaPatterns.literalExpression() .and( new FilterPattern( new AndFilter( new SuperParentFilter( new QualifiedNameElementFilter(VALIDATE_NESTED_PROPERTIES_ANNOTATION)), new AnnotationParameterFilter( PsiLiteralExpression.class, VALIDATE_ANNOTATION, FIELD_ATTR)))), new PsiReferenceProvider() { @NotNull public PsiReference[] getReferencesByElement( @NotNull PsiElement element, @NotNull ProcessingContext context) { PsiMember parent = PsiTreeUtil.getParentOfType(element, PsiMethod.class); if (parent == null) parent = PsiTreeUtil.getParentOfType(element, PsiField.class); PsiClass cls = StripesReferenceUtil.resolveClassInType( PropertyUtil.getPropertyType(parent), element.getProject()); return null == cls ? PsiReference.EMPTY_ARRAY : new SetterReferenceExSet(element, 1, '.', cls, false).getPsiReferences(); } }); registrar.registerReferenceProvider( PsiJavaPatterns.literalExpression() .and( new FilterPattern( new OrFilter( new StringArrayAnnotationParameterFilter( STRICT_BINDING_ANNOTATION, ALLOW_ATTR), new StringArrayAnnotationParameterFilter( STRICT_BINDING_ANNOTATION, DENY_ATTR)))), new PsiReferenceProvider() { @NotNull public PsiReference[] getReferencesByElement( @NotNull PsiElement element, @NotNull ProcessingContext context) { PsiClass cls = PsiTreeUtil.getParentOfType(element, PsiClass.class); return null == cls ? PsiReference.EMPTY_ARRAY : new SetterReferenceExSet(element, 1, '.', cls, false) { @NotNull @Override protected SetterReferenceEx<PsiElement> createReferenceWithBraces( TextRange range, int index, boolean hasBraces) { return new StrictBindingReference(range, this.isSupportBraces(), this, index); } }.getPsiReferences(); } }); registrar.registerReferenceProvider( PsiJavaPatterns.literalExpression() .and( new FilterPattern( new AnnotationParameterFilter( PsiLiteralExpression.class, URL_BINDING_ANNOTATION, VALUE_ATTR))), new PsiReferenceProvider() { @NotNull public PsiReference[] getReferencesByElement( @NotNull PsiElement element, @NotNull ProcessingContext context) { PsiClass actionBeanPsiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); String str = ElementManipulators.getValueText(element); if (null != actionBeanPsiClass && str.startsWith("/")) { final List<PsiReference> retval = new LinkedList<PsiReference>(); for (int i = 0, eqInd = -1, lBraceInd = -1, braceStack = 0; i < str.length(); i++) { if (str.charAt(i) == '{') { braceStack++; lBraceInd = i; eqInd = -1; } else if (str.charAt(i) == '}') { // we found closing brace and need to retrieve references if possible braceStack--; if (braceStack != 0) continue; // braces are unbalanced - we should not try to parse int endInd = eqInd != -1 ? eqInd // there's '=' sign within curly braces bounded part of string. // processign only part of text located within curl braces : i; // no '=' sign found. process whole text from curly braces; String txt = str.substring(1 + lBraceInd, endInd); if ($EVENT.equals(txt) && eqInd == -1) { retval.add( new UrlBindingReference( element, new TextRange(1 + lBraceInd + 1, 1 + endInd), actionBeanPsiClass)); } else { // final PsiReference[] psiReferences = new // SetterReferenceExSet(str, element, 1 + lBraceInd + 1, '.', // actionBeanPsiClass, true).getPsiReferences(); Collections.addAll( retval, new UrlSetterReferenceExSet( txt, element, 1 + lBraceInd + 1, '.', actionBeanPsiClass, true) .getPsiReferences() // new UrlSetterReferenceExSet(txt, // element, 1, '.', actionBeanPsiClass, true).getPsiReferences() ); } // retval.add(new UrlBindingReference(element, new TextRange(1 + lBraceInd + 1, 1 // + lBraceInd + 1), actionBeanPsiClass)); } else if (str.charAt(i) == '=') { eqInd = i; } } return retval.toArray(new PsiReference[retval.size()]); } return PsiReference.EMPTY_ARRAY; } }); registrar.registerReferenceProvider( PsiJavaPatterns.literalExpression() .methodCallParameter( 0, PsiJavaPatterns.psiMethod() .definedInClass(VALIDATION_ERRORS) .withName( StandardPatterns.string() .oneOf(ADD_METHOD, ADD_ALL_METHOD, PUT_METHOD, PUT_ALL_METHOD))), new PsiReferenceProvider() { @NotNull @Override public PsiReference[] getReferencesByElement( @NotNull PsiElement element, @NotNull ProcessingContext context) { PsiClass cls = PsiTreeUtil.getParentOfType(element, PsiClass.class); return null == cls ? PsiReference.EMPTY_ARRAY : new SetterReferenceExSet(element, 1, '.', cls, true).getPsiReferences(); } }); }