public void visitReferenceExpression(GrReferenceExpression refExpr) { super.visitReferenceExpression(refExpr); if (myPolicy.isReferenceAccepted(refExpr)) { String name = refExpr.getReferenceName(); if (name == null) return; if (ControlFlowUtils.isIncOrDecOperand(refExpr)) { final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, READ); addNodeAndCheckPending(i); addNode(new ReadWriteVariableInstruction(name, refExpr, WRITE)); } else { final int type = PsiUtil.isLValue(refExpr) ? WRITE : READ; addNodeAndCheckPending(new ReadWriteVariableInstruction(name, refExpr, type)); if (refExpr.getParent() instanceof GrArgumentList && refExpr.getParent().getParent() instanceof GrCall) { addNodeAndCheckPending(new ArgumentInstruction(refExpr)); } } } if (refExpr.isQualified() && !(refExpr.getParent() instanceof GrCall)) { visitCall(refExpr); } }
@Override public PsiType getNominalType() { if (getParent() instanceof GrThrowStatement) return super.getNominalType(); LOG.assertTrue( PsiUtil.isLValue(this), "it is assumed that nominal type is invoked only for assignment lhs"); GroovyResolveResult[] candidates = multiResolve(true); if (candidates.length == 1) { return extractLastParameterType(candidates[0]); } return null; }
private static boolean areGroovyObjectMethodsOverridden(GrReferenceExpression ref) { PsiType qualifierType = GrReferenceResolveUtil.getQualifierType(ref); if (!(qualifierType instanceof PsiClassType)) return false; PsiClass resolved = ((PsiClassType) qualifierType).resolve(); if (resolved == null) return false; PsiClass groovyObject = JavaPsiFacade.getInstance(ref.getProject()) .findClass(GroovyCommonClassNames.GROOVY_OBJECT, ref.getResolveScope()); if (groovyObject == null) return false; String methodName; if (ref.getParent() instanceof GrCall) { methodName = "invokeMethod"; } else if (PsiUtil.isLValue(ref)) { methodName = "setProperty"; } else { methodName = "getProperty"; } PsiMethod[] patternMethods = groovyObject.findMethodsByName(methodName, false); if (patternMethods.length != 1) return false; PsiMethod patternMethod = patternMethods[0]; PsiMethod found = resolved.findMethodBySignature(patternMethod, true); if (found == null) return false; PsiClass aClass = found.getContainingClass(); if (aClass == null) return false; String qname = aClass.getQualifiedName(); if (GroovyCommonClassNames.GROOVY_OBJECT.equals(qname)) return false; if (GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT.equals(qname)) return false; return true; }
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; }
@Override public PsiType fun(GrIndexPropertyImpl index) { GrExpression selected = index.getInvokedExpression(); PsiType thisType = selected.getType(); if (thisType == null) return null; GrArgumentList argList = index.getArgumentList(); PsiType[] argTypes = PsiUtil.getArgumentTypes(argList); if (argTypes == null) return null; final PsiManager manager = index.getManager(); final GlobalSearchScope resolveScope = index.getResolveScope(); if (argTypes.length == 0) { PsiType arrType = null; if (selected instanceof GrBuiltinTypeClassExpression) { arrType = ((GrBuiltinTypeClassExpression) selected).getPrimitiveType(); } if (selected instanceof GrReferenceExpression) { final PsiElement resolved = ((GrReferenceExpression) selected).resolve(); if (resolved instanceof PsiClass) { String qname = ((PsiClass) resolved).getQualifiedName(); if (qname != null) { arrType = TypesUtil.createTypeByFQClassName(qname, index); } } } if (arrType != null) { final PsiArrayType param = arrType.createArrayType(); return TypesUtil.createJavaLangClassType(param, index.getProject(), resolveScope); } } if (PsiImplUtil.isSimpleArrayAccess( thisType, argTypes, manager, resolveScope, PsiUtil.isLValue(index))) { return TypesUtil.boxPrimitiveType( ((PsiArrayType) thisType).getComponentType(), manager, resolveScope); } final GroovyResolveResult[] candidates = index.multiResolve(false); PsiType[] args = PsiUtil.getArgumentTypes( argList.getNamedArguments(), argList.getExpressionArguments(), GrClosableBlock.EMPTY_ARRAY, true, null, false); final GroovyResolveResult candidate = PsiImplUtil.extractUniqueResult(candidates); final PsiElement element = candidate.getElement(); if (element instanceof PsiNamedElement) { final String name = ((PsiNamedElement) element).getName(); if ("putAt".equals(name) && args != null) { args = ArrayUtil.append( args, TypeInferenceHelper.getInitializerFor(index), PsiType.class); } } PsiType overloadedOperatorType = ResolveUtil.extractReturnTypeFromCandidate(candidate, index, args); PsiType componentType = extractMapValueType(thisType, args, manager, resolveScope); if (overloadedOperatorType != null && (componentType == null || !TypesUtil.isAssignable( overloadedOperatorType, componentType, manager, resolveScope))) { return TypesUtil.boxPrimitiveType(overloadedOperatorType, manager, resolveScope); } return componentType; }
private GroovyResolveResult[] resolveImpl( boolean incompleteCode, @Nullable GrExpression upToArgument) { GrExpression invoked = getInvokedExpression(); PsiType thisType = invoked.getType(); if (thisType == null) return GroovyResolveResult.EMPTY_ARRAY; GrArgumentList argList = getArgumentList(); PsiType[] argTypes = PsiUtil.getArgumentTypes( argList.getNamedArguments(), argList.getExpressionArguments(), GrClosableBlock.EMPTY_ARRAY, true, upToArgument, false); if (argTypes == null) return GroovyResolveResult.EMPTY_ARRAY; final PsiManager manager = getManager(); final GlobalSearchScope resolveScope = getResolveScope(); if (argTypes.length == 0) { PsiType arrType = null; if (invoked instanceof GrBuiltinTypeClassExpression) { arrType = ((GrBuiltinTypeClassExpression) invoked).getPrimitiveType(); } if (invoked instanceof GrReferenceExpression) { final PsiElement resolved = ((GrReferenceExpression) invoked).resolve(); if (resolved instanceof PsiClass) { String qname = ((PsiClass) resolved).getQualifiedName(); if (qname != null) { arrType = TypesUtil.createTypeByFQClassName(qname, this); } } } if (arrType != null) { return GroovyResolveResult.EMPTY_ARRAY; } } GroovyResolveResult[] candidates; final String name; if (PsiUtil.isLValue(this)) { name = "putAt"; if (!incompleteCode) { argTypes = ArrayUtil.append(argTypes, TypeInferenceHelper.getInitializerFor(this), PsiType.class); } } else { name = "getAt"; } if (PsiImplUtil.isSimpleArrayAccess( thisType, argTypes, manager, resolveScope, PsiUtil.isLValue(this))) { return GroovyResolveResult.EMPTY_ARRAY; } candidates = ResolveUtil.getMethodCandidates( thisType, name, this, true, incompleteCode, false, argTypes); // hack for remove DefaultGroovyMethods.getAt(Object, ...) if (candidates.length == 2) { for (int i = 0; i < candidates.length; i++) { GroovyResolveResult candidate = candidates[i]; final PsiElement element = candidate.getElement(); if (element instanceof GrGdkMethod) { final PsiMethod staticMethod = ((GrGdkMethod) element).getStaticMethod(); final PsiParameter param = staticMethod.getParameterList().getParameters()[0]; if (param.getType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { return new GroovyResolveResult[] {candidates[1 - i]}; } } } } if (candidates.length != 1) { final GrTupleType tupleType = new GrTupleType(argTypes, JavaPsiFacade.getInstance(getProject()), resolveScope); candidates = ResolveUtil.getMethodCandidates(thisType, name, this, tupleType); } return candidates; }
@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; }