@Nullable private static PsiType getTypeFromClassRef(@NotNull GrReferenceExpressionImpl ref) { if ("class".equals(ref.getReferenceName())) { return TypesUtil.createJavaLangClassType( GrReferenceResolveUtil.getQualifierType(ref), ref.getProject(), ref.getResolveScope()); } return null; }
private MethodResolverProcessor createMethodProcessor( boolean allVariants, String name, final boolean byShape, @Nullable GrExpression upToArgument) { final PsiType[] argTypes = PsiUtil.getArgumentTypes(this, false, upToArgument, byShape); if (byShape && argTypes != null) { for (int i = 0; i < argTypes.length; i++) { argTypes[i] = TypeConversionUtil.erasure(argTypes[i]); } } return new MethodResolverProcessor( name, this, false, GrReferenceResolveUtil.getQualifierType(this), argTypes, getTypeArguments(), allVariants, byShape); }
@Nullable private PsiType getNominalTypeInner(PsiElement resolved) { if (resolved == null && !"class".equals(getReferenceName())) { resolved = resolve(); } if (resolved instanceof PsiClass) { final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); if (PsiUtil.isInstanceThisRef(this)) { final PsiClassType categoryType = GdkMethodUtil.getCategoryType((PsiClass) resolved); if (categoryType != null) { return categoryType; } else { return factory.createType((PsiClass) resolved); } } if (getParent() instanceof GrReferenceExpression || PsiUtil.isSuperReference(this)) { return factory.createType((PsiClass) resolved); } else { return TypesUtil.createJavaLangClassType( factory.createType((PsiClass) resolved), getProject(), getResolveScope()); } } if (resolved instanceof GrVariable) { return ((GrVariable) resolved).getDeclaredType(); } if (resolved instanceof PsiVariable) { return ((PsiVariable) resolved).getType(); } if (resolved instanceof PsiMethod) { PsiMethod method = (PsiMethod) resolved; if (PropertyUtil.isSimplePropertySetter(method) && !method.getName().equals(getReferenceName())) { return method.getParameterList().getParameters()[0].getType(); } // 'class' property with explicit generic PsiClass containingClass = method.getContainingClass(); if (containingClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName()) && "getClass".equals(method.getName())) { return TypesUtil.createJavaLangClassType( GrReferenceResolveUtil.getQualifierType(this), getProject(), getResolveScope()); } return PsiUtil.getSmartReturnType(method); } if (resolved instanceof GrReferenceExpression) { PsiElement parent = resolved.getParent(); if (parent instanceof GrAssignmentExpression) { GrAssignmentExpression assignment = (GrAssignmentExpression) parent; if (resolved.equals(assignment.getLValue())) { GrExpression rValue = assignment.getRValue(); if (rValue != null) { PsiType rType = rValue.getType(); if (rType != null) { return rType; } } } } } if (resolved == null) { final PsiType fromClassRef = getTypeFromClassRef(this); if (fromClassRef != null) { return fromClassRef; } final PsiType fromMapAccess = getTypeFromMapAccess(this); if (fromMapAccess != null) { return fromMapAccess; } final PsiType fromSpreadOperator = getTypeFromSpreadOperator(this); if (fromSpreadOperator != null) { return fromSpreadOperator; } } return null; }
/** * 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; PropertyResolverProcessor propertyResolver = new PropertyResolverProcessor(name, this); GrReferenceResolveUtil.resolveImpl(propertyResolver, this); final GroovyResolveResult[] propertyCandidates = propertyResolver.getCandidates(); if (!allVariants) { // search for local variables for (GroovyResolveResult candidate : propertyCandidates) { if (candidate.getElement() instanceof GrVariable && !(candidate.getElement() instanceof GrField)) { return propertyResolver.getCandidates(); } } } 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(ResolverProcessor.RESOLVE_CONTEXT, result.getCurrentFileResolveContext()) .put(SpreadState.SPREAD_STATE, result.getSpreadState()); methodResolver.execute(result.getElement(), 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); // search for getters for (String getterName : GroovyPropertyUtils.suggestGettersName(name)) { AccessorResolverProcessor getterResolver = new AccessorResolverProcessor( getterName, name, this, true, genericsMatter, GrReferenceResolveUtil.getQualifierType(this), getTypeArguments()); GrReferenceResolveUtil.resolveImpl(getterResolver, this); final GroovyResolveResult[] candidates = getterResolver.getCandidates(); // can be only one candidate if (!allVariants && candidates.length == 1) { return candidates; } ContainerUtil.addAll(allCandidates, candidates); } if (allCandidates.size() > 0) { return allCandidates.toArray(new GroovyResolveResult[allCandidates.size()]); } return GroovyResolveResult.EMPTY_ARRAY; }
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) { ArrayList<GroovyResolveResult> results = new ArrayList<GroovyResolveResult>(); if (GrReferenceResolveUtil.resolveThisExpression(this, results)) { return results.toArray(new GroovyResolveResult[results.size()]); } } else if (nameType == GroovyTokenTypes.kSUPER) { ArrayList<GroovyResolveResult> results = new ArrayList<GroovyResolveResult>(); if (GrReferenceResolveUtil.resolveSuperExpression(this, results)) { return results.toArray(new GroovyResolveResult[results.size()]); } } EnumSet<ClassHint.ResolveKind> kinds = getParent() instanceof GrReferenceExpression ? ResolverProcessor.RESOLVE_KINDS_CLASS_PACKAGE : ResolverProcessor.RESOLVE_KINDS_CLASS; GroovyResolveResult[] classCandidates = null; ResolverProcessor processor = new PropertyResolverProcessor(name, this); GrReferenceResolveUtil.resolveImpl(processor, this); final GroovyResolveResult[] fieldCandidates = processor.getCandidates(); if (hasAt()) { return fieldCandidates; } boolean canBeClassOrPackage = ResolveUtil.canBeClassOrPackage(this); if (canBeClassOrPackage && findClassOrPackageAtFirst()) { boolean preferVar = containsLocalVar(fieldCandidates); if (!preferVar) { ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds); GrReferenceResolveUtil.resolveImpl(classProcessor, this); classCandidates = classProcessor.getCandidates(); if (classCandidates.length > 0) 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 && PsiTreeUtil.isContextAncestor(containingClass, this, true)) return fieldCandidates; } else { return fieldCandidates; } } 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, GrReferenceResolveUtil.getQualifierType(this), getTypeArguments()); GrReferenceResolveUtil.resolveImpl(accessorResolver, this); 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); } } if (fieldCandidates.length > 0) return fieldCandidates; if (classCandidates == null && canBeClassOrPackage) { ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds); GrReferenceResolveUtil.resolveImpl(classProcessor, this); classCandidates = classProcessor.getCandidates(); } if (classCandidates != null && classCandidates.length > 0) return classCandidates; if (accessorResults.size() > 0) return new GroovyResolveResult[] {accessorResults.get(0)}; return GroovyResolveResult.EMPTY_ARRAY; }