@NotNull private GroovyResolveResult[] doPolyResolve(boolean incompleteCode, boolean genericsMatter) { String name = getReferenceName(); if (name == null) return GroovyResolveResult.EMPTY_ARRAY; if (incompleteCode) { ResolverProcessor processor = CompletionProcessor.createRefSameNameProcessor(this, name); new GrReferenceResolveRunner(this).resolveImpl(processor); GroovyResolveResult[] propertyCandidates = processor.getCandidates(); if (propertyCandidates.length > 0 && !PsiUtil.isSingleBindingVariant(propertyCandidates)) return propertyCandidates; } try { ResolveProfiler.start(); switch (getKind()) { case METHOD_OR_PROPERTY: return resolveMethodOrProperty(false, null, genericsMatter); case TYPE_OR_PROPERTY: return resolveTypeOrProperty(); case METHOD_OR_PROPERTY_OR_TYPE: GroovyResolveResult[] results = resolveMethodOrProperty(false, null, genericsMatter); if (results.length == 0) results = resolveTypeOrProperty(); return results; default: return GroovyResolveResult.EMPTY_ARRAY; } } finally { final long time = ResolveProfiler.finish(); ResolveProfiler.write("ref", this, time); } }
private static PsiType doFun(GrReferenceExpression refExpr) { if (ResolveUtil.isClassReference(refExpr)) { GrExpression qualifier = refExpr.getQualifier(); LOG.assertTrue(qualifier != null); return TypesUtil.createJavaLangClassType( qualifier.getType(), refExpr.getProject(), refExpr.getResolveScope()); } if (PsiUtil.isCompileStatic(refExpr)) { final GroovyResolveResult resolveResult = refExpr.advancedResolve(); final PsiElement resolvedF = resolveResult.getElement(); final PsiType type; if (resolvedF instanceof GrField) { type = ((GrField) resolvedF).getType(); } else if (resolvedF instanceof GrAccessorMethod) { type = ((GrAccessorMethod) resolvedF).getProperty().getType(); } else { type = null; } if (type != null) { return resolveResult.getSubstitutor().substitute(type); } } final PsiElement resolved = refExpr.resolve(); final PsiType nominal = refExpr.getNominalType(); Boolean reassigned = GrReassignedLocalVarsChecker.isReassignedVar(refExpr); if (reassigned != null && reassigned.booleanValue()) { return GrReassignedLocalVarsChecker.getReassignedVarType(refExpr, true); } final PsiType inferred = getInferredTypes(refExpr, resolved); if (inferred == null) { if (nominal == null) { // inside nested closure we could still try to infer from variable initializer. Not sound, // but makes sense if (resolved instanceof GrVariable) { LOG.assertTrue(resolved.isValid()); return ((GrVariable) resolved).getTypeGroovy(); } } return nominal; } if (nominal == null) return inferred; if (!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(nominal), inferred, false)) { if (resolved instanceof GrVariable && ((GrVariable) resolved).getTypeElementGroovy() != null) { return nominal; } } return inferred; }
@Override public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { final GroovyResolveResult result = advancedResolve(); if (result.isInvokedOnProperty()) { final String name = GroovyPropertyUtils.getPropertyNameByAccessorName(newElementName); if (name != null) { newElementName = name; } } if (PsiUtil.isThisOrSuperRef(this)) return this; return handleElementRenameSimple(newElementName); }
@Override public PsiElement handleElementRenameSimple(String newElementName) throws IncorrectOperationException { if (!PsiUtil.isValidReferenceName(newElementName)) { final PsiElement old = getReferenceNameElement(); if (old == null) throw new IncorrectOperationException("ref has no name element"); PsiElement element = GroovyPsiElementFactory.getInstance(getProject()) .createStringLiteralForReference(newElementName); old.replace(element); return this; } return super.handleElementRenameSimple(newElementName); }
@NotNull private MethodResolverProcessor createMethodProcessor( boolean allVariants, @Nullable 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]); } } PsiType qualifierType = PsiImplUtil.getQualifierType(this); return new MethodResolverProcessor( name, this, false, qualifierType, argTypes, getTypeArguments(), allVariants, byShape); }
@Nullable private PsiType getNominalTypeInner(@Nullable 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); } } else if (PsiUtil.isSuperReference(this)) { PsiClass contextClass = PsiUtil.getContextClass(this); if (GrTraitUtil.isTrait(contextClass)) { PsiClassType[] extendsTypes = contextClass.getExtendsListTypes(); PsiClassType[] implementsTypes = contextClass.getImplementsListTypes(); PsiClassType[] superTypes = ArrayUtil.mergeArrays(implementsTypes, extendsTypes, PsiClassType.ARRAY_FACTORY); return PsiIntersectionType.createIntersection(ArrayUtil.reverseArray(superTypes)); } return factory.createType((PsiClass) resolved); } if (getParent() instanceof GrReferenceExpression) { 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( PsiImplUtil.getQualifierType(this), getProject(), getResolveScope()); } return PsiUtil.getSmartReturnType(method); } 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; }
@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; }