@NotNull private GroovyResolveResult[] resolveTypeOrProperty() { if (isDefinitelyKeyOfMap()) return GroovyResolveResult.EMPTY_ARRAY; final GroovyResolveResult[] results = resolveTypeOrPropertyInner(); if (results.length == 0) return GroovyResolveResult.EMPTY_ARRAY; if (!ResolveUtil.mayBeKeyOfMap(this)) return results; // filter out all members from super classes. We should return only accessible members from map // classes List<GroovyResolveResult> filtered = new ArrayList<GroovyResolveResult>(); for (GroovyResolveResult result : results) { final PsiElement element = result.getElement(); if (element instanceof PsiMember) { if (((PsiMember) element).hasModifierProperty(PsiModifier.PRIVATE)) continue; final PsiClass containingClass = ((PsiMember) element).getContainingClass(); if (containingClass != null) { if (!InheritanceUtil.isInheritor(containingClass, CommonClassNames.JAVA_UTIL_MAP)) continue; final String name = containingClass.getQualifiedName(); if (name != null && name.startsWith("java.")) continue; if (containingClass.getLanguage() != GroovyLanguage.INSTANCE && !InheritanceUtil.isInheritor( containingClass, GroovyCommonClassNames.DEFAULT_BASE_CLASS_NAME)) { continue; } } } filtered.add(result); } return ContainerUtil.toArray(filtered, new GroovyResolveResult[filtered.size()]); }
@NotNull private static GroovyResolveResult[] collapseReflectedMethods(GroovyResolveResult[] candidates) { Set<GrMethod> visited = ContainerUtil.newHashSet(); List<GroovyResolveResult> collapsed = ContainerUtil.newArrayList(); for (GroovyResolveResult result : candidates) { PsiElement element = result.getElement(); if (element instanceof GrReflectedMethod) { GrMethod baseMethod = ((GrReflectedMethod) element).getBaseMethod(); if (visited.add(baseMethod)) { collapsed.add( PsiImplUtil.reflectedToBase(result, baseMethod, (GrReflectedMethod) element)); } } else { collapsed.add(result); } } return collapsed.toArray(new GroovyResolveResult[collapsed.size()]); }
private static void filterOutBindings(@NotNull List<GroovyResolveResult> candidates) { boolean hasNonBinding = false; for (GroovyResolveResult candidate : candidates) { if (!(candidate.getElement() instanceof GrBindingVariable)) { hasNonBinding = true; } } if (hasNonBinding) { for (Iterator<GroovyResolveResult> iterator = candidates.iterator(); iterator.hasNext(); ) { GroovyResolveResult candidate = iterator.next(); if (candidate.getElement() instanceof GrBindingVariable) { iterator.remove(); } } } }
/** * priority: inside class C: local variable, c.method, c.property, c.getter in other places: local * variable, c.method, c.getter, c.property */ @NotNull private GroovyResolveResult[] resolveMethodOrProperty( boolean allVariants, @Nullable GrExpression upToArgument, boolean genericsMatter) { final String name = getReferenceName(); if (name == null) return GroovyResolveResult.EMPTY_ARRAY; GrReferenceResolveRunner resolveRunner = new GrReferenceResolveRunner(this); PropertyResolverProcessor propertyResolver = new PropertyResolverProcessor(name, this); resolveRunner.resolveImpl(propertyResolver); final GroovyResolveResult[] propertyCandidates = propertyResolver.getCandidates(); if (!allVariants) { // search for local variables for (GroovyResolveResult candidate : propertyCandidates) { final PsiElement element = candidate.getElement(); if (element instanceof GrVariable && !(element instanceof GrField || element instanceof GrBindingVariable)) { return propertyCandidates; } } } final Pair<Boolean, GroovyResolveResult[]> shapeResults = resolveByShape(allVariants, upToArgument); if (!genericsMatter && !allVariants && shapeResults.first) { assertAllAreValid(shapeResults.second); return shapeResults.second; } MethodResolverProcessor methodResolver = null; if (genericsMatter) { methodResolver = createMethodProcessor(allVariants, name, false, upToArgument); for (GroovyResolveResult result : shapeResults.second) { final ResolveState state = ResolveState.initial() .put(PsiSubstitutor.KEY, result.getSubstitutor()) .put(ClassHint.RESOLVE_CONTEXT, result.getCurrentFileResolveContext()) .put(SpreadState.SPREAD_STATE, result.getSpreadState()); PsiElement element = result.getElement(); assert element != null; methodResolver.execute(element, state); } if (!allVariants && methodResolver.hasApplicableCandidates()) { return methodResolver.getCandidates(); } } // search for fields inside its class if (!allVariants) { for (GroovyResolveResult candidate : propertyCandidates) { final PsiElement element = candidate.getElement(); if (element instanceof GrField) { final PsiClass containingClass = ((PsiField) element).getContainingClass(); if (containingClass != null && PsiTreeUtil.isContextAncestor(containingClass, this, true)) return propertyCandidates; } } } List<GroovyResolveResult> allCandidates = new ArrayList<GroovyResolveResult>(); ContainerUtil.addAll(allCandidates, propertyCandidates); ContainerUtil.addAll( allCandidates, genericsMatter ? methodResolver.getCandidates() : shapeResults.second); filterOutBindings(allCandidates); // search for getters for (String getterName : GroovyPropertyUtils.suggestGettersName(name)) { AccessorResolverProcessor getterResolver = new AccessorResolverProcessor( getterName, name, this, true, genericsMatter, PsiImplUtil.getQualifierType(this), getTypeArguments()); resolveRunner.resolveImpl(getterResolver); final GroovyResolveResult[] candidates = getterResolver.getCandidates(); // can be only one candidate if (!allVariants && candidates.length == 1) { return candidates; } ContainerUtil.addAll(allCandidates, candidates); } if (!allCandidates.isEmpty()) { return allCandidates.toArray(new GroovyResolveResult[allCandidates.size()]); } return GroovyResolveResult.EMPTY_ARRAY; }
@NotNull private GroovyResolveResult[] resolveTypeOrPropertyInner() { PsiElement nameElement = getReferenceNameElement(); String name = getReferenceName(); if (name == null || nameElement == null) return GroovyResolveResult.EMPTY_ARRAY; IElementType nameType = nameElement.getNode().getElementType(); if (nameType == GroovyTokenTypes.kTHIS) { GroovyResolveResult[] results = GrThisReferenceResolver.resolveThisExpression(this); if (results != null) { return results; } } else if (nameType == GroovyTokenTypes.kSUPER) { GroovyResolveResult[] results = GrSuperReferenceResolver.resolveSuperExpression(this); if (results != null) { return results; } } EnumSet<ClassHint.ResolveKind> kinds = getParent() instanceof GrReferenceExpression ? ClassHint.RESOLVE_KINDS_CLASS_PACKAGE : ClassHint.RESOLVE_KINDS_CLASS; GroovyResolveResult[] classCandidates = null; GrReferenceResolveRunner resolveRunner = new GrReferenceResolveRunner(this); ResolverProcessor processor = new PropertyResolverProcessor(name, this); resolveRunner.resolveImpl(processor); final GroovyResolveResult[] fieldCandidates = processor.getCandidates(); if (hasAt()) { return fieldCandidates; } boolean canBeClassOrPackage = ResolveUtil.canBeClassOrPackage(this); if (canBeClassOrPackage && findClassOrPackageAtFirst()) { ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds); resolveRunner.resolveImpl(classProcessor); classCandidates = classProcessor.getCandidates(); if (classCandidates.length > 0 && containsPackage(classCandidates)) { final PsiElement firstNonReferenceExprParent = PsiTreeUtil.skipParentsOfType(this, GrReferenceExpressionImpl.class); final GrReferenceExpressionImpl topRef = (GrReferenceExpressionImpl) PsiTreeUtil.findFirstParent( this, new Condition<PsiElement>() { @Override public boolean value(PsiElement parent) { return parent.getParent() == firstNonReferenceExprParent && parent instanceof GrReferenceExpressionImpl; } }); if (topRef != null) { final String fqn = topRef.getTextSkipWhiteSpaceAndComments(); if (JavaPsiFacade.getInstance(getProject()).findClass(fqn, getResolveScope()) != null) { return classCandidates; } } } } // if reference expression is in class we need to return field instead of accessor method for (GroovyResolveResult candidate : fieldCandidates) { final PsiElement element = candidate.getElement(); if (element instanceof PsiField) { final PsiClass containingClass = ((PsiField) element).getContainingClass(); if (containingClass != null && PsiUtil.getContextClass(this) == containingClass) return fieldCandidates; } else if (!(element instanceof GrBindingVariable)) { return fieldCandidates; } } if (classCandidates != null && classCandidates.length > 0) return classCandidates; final boolean isLValue = PsiUtil.isLValue(this); String[] accessorNames = isLValue ? GroovyPropertyUtils.suggestSettersName(name) : GroovyPropertyUtils.suggestGettersName(name); List<GroovyResolveResult> accessorResults = new ArrayList<GroovyResolveResult>(); for (String accessorName : accessorNames) { AccessorResolverProcessor accessorResolver = new AccessorResolverProcessor( accessorName, name, this, !isLValue, false, PsiImplUtil.getQualifierType(this), getTypeArguments()); resolveRunner.resolveImpl(accessorResolver); final GroovyResolveResult[] candidates = accessorResolver.getCandidates(); // can be only one correct candidate or some incorrect if (candidates.length == 1 && candidates[0].isStaticsOK() && candidates[0].isAccessible()) { return candidates; } else { ContainerUtil.addAll(accessorResults, candidates); } } final ArrayList<GroovyResolveResult> fieldList = ContainerUtil.newArrayList(fieldCandidates); filterOutBindings(fieldList); if (!fieldList.isEmpty()) { return fieldList.toArray(new GroovyResolveResult[fieldList.size()]); } if (classCandidates == null && canBeClassOrPackage) { ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds); resolveRunner.resolveImpl(classProcessor); classCandidates = classProcessor.getCandidates(); } if (classCandidates != null && classCandidates.length > 0) return classCandidates; if (!accessorResults.isEmpty()) return new GroovyResolveResult[] {accessorResults.get(0)}; return GroovyResolveResult.EMPTY_ARRAY; }