@NotNull private Pair<Boolean, GroovyResolveResult[]> doResolveByShape( boolean allVariants, @Nullable GrExpression upToArgument) { final String name = getReferenceName(); LOG.assertTrue(name != null); final MethodResolverProcessor shapeProcessor = createMethodProcessor(allVariants, name, true, upToArgument); processMethods(shapeProcessor); GroovyResolveResult[] candidates = shapeProcessor.getCandidates(); assertAllAreValid(candidates); if (hasMemberPointer()) { candidates = collapseReflectedMethods(candidates); } return Pair.create(shapeProcessor.hasApplicableCandidates(), candidates); }
private void processMethods(@NotNull MethodResolverProcessor methodResolver) { new GrReferenceResolveRunner(this).resolveImpl(methodResolver); if (methodResolver.hasApplicableCandidates()) { return; } // Search in ClosureMissingMethodContributor if (!isQualified() && getContext() instanceof GrMethodCall) { ClosureMissingMethodContributor.processMethodsFromClosures(this, methodResolver); } }
/** * 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; }