@Nullable private static PsiType guessElementTypeFromReference( MethodPatternMap methodPatternMap, PsiElement ref, TextRange rangeToIgnore) { PsiElement refParent = ref.getParent(); if (refParent instanceof PsiReferenceExpression) { PsiReferenceExpression parentExpr = (PsiReferenceExpression) refParent; if (ref.equals(parentExpr.getQualifierExpression()) && parentExpr.getParent() instanceof PsiMethodCallExpression) { String methodName = parentExpr.getReferenceName(); PsiMethodCallExpression methodCall = (PsiMethodCallExpression) parentExpr.getParent(); PsiExpression[] args = methodCall.getArgumentList().getExpressions(); MethodPattern pattern = methodPatternMap.findPattern(methodName, args.length); if (pattern != null) { if (pattern.parameterIndex < 0) { // return value if (methodCall.getParent() instanceof PsiTypeCastExpression && (rangeToIgnore == null || !rangeToIgnore.contains(methodCall.getTextRange()))) { return ((PsiTypeCastExpression) methodCall.getParent()).getType(); } } else { return args[pattern.parameterIndex].getType(); } } } } return null; }
@Override @Nullable public PsiType fun(final PsiMethodCallExpression call) { PsiReferenceExpression methodExpression = call.getMethodExpression(); PsiType theOnly = null; final JavaResolveResult[] results = methodExpression.multiResolve(false); LanguageLevel languageLevel = PsiUtil.getLanguageLevel(call); final PsiElement callParent = PsiUtil.skipParenthesizedExprUp(call.getParent()); final PsiExpressionList parentArgList; if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) { parentArgList = callParent instanceof PsiConditionalExpression && !PsiPolyExpressionUtil.isPolyExpression((PsiExpression) callParent) ? null : PsiTreeUtil.getParentOfType(call, PsiExpressionList.class); } else { parentArgList = null; } final MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(parentArgList); final boolean genericMethodCall = properties != null && properties.getInfo().isToInferApplicability(); for (int i = 0; i < results.length; i++) { final JavaResolveResult candidateInfo = results[i]; if (genericMethodCall && PsiPolyExpressionUtil.isMethodCallPolyExpression( call, (PsiMethod) candidateInfo.getElement())) { if (callParent instanceof PsiAssignmentExpression) { return null; } LOG.error("poly expression evaluation during overload resolution"); } final PsiType type = getResultType(call, methodExpression, candidateInfo, languageLevel); if (type == null) { return null; } if (i == 0) { theOnly = type; } else if (!theOnly.equals(type)) { return null; } } return PsiClassImplUtil.correctType(theOnly, call.getResolveScope()); }
private void updateRefMethod( PsiElement psiResolved, RefElement refResolved, PsiElement refExpression, final PsiElement psiFrom, final RefElement refFrom) { PsiMethod psiMethod = (PsiMethod) psiResolved; RefMethodImpl refMethod = (RefMethodImpl) refResolved; PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(refExpression, PsiMethodCallExpression.class); if (call != null) { PsiType returnType = psiMethod.getReturnType(); if (!psiMethod.isConstructor() && returnType != PsiType.VOID) { if (!(call.getParent() instanceof PsiExpressionStatement)) { refMethod.setReturnValueUsed(true); } addTypeReference(psiFrom, returnType, refFrom.getRefManager()); } PsiExpressionList argumentList = call.getArgumentList(); if (argumentList.getExpressions().length > 0) { refMethod.updateParameterValues(argumentList.getExpressions()); } final PsiExpression psiExpression = call.getMethodExpression().getQualifierExpression(); if (psiExpression != null) { final PsiType usedType = psiExpression.getType(); if (usedType != null) { final String fqName = psiMethod.getContainingClass().getQualifiedName(); if (fqName != null) { final PsiClassType methodOwnerType = JavaPsiFacade.getInstance(call.getProject()) .getElementFactory() .createTypeByFQClassName( fqName, GlobalSearchScope.allScope(psiMethod.getProject())); if (!usedType.equals(methodOwnerType)) { refMethod.setCalledOnSubClass(true); } } } } } }
@NotNull private List<PsiMethod> getMethodsToImport() { PsiShortNamesCache cache = PsiShortNamesCache.getInstance(myMethodCall.getProject()); PsiMethodCallExpression element = myMethodCall.getElement(); PsiReferenceExpression reference = element.getMethodExpression(); PsiExpressionList argumentList = element.getArgumentList(); String name = reference.getReferenceName(); List<PsiMethod> list = new ArrayList<PsiMethod>(); if (name == null) return list; GlobalSearchScope scope = element.getResolveScope(); PsiMethod[] methods = cache.getMethodsByNameIfNotMoreThan(name, scope, 20); List<PsiMethod> applicableList = new ArrayList<PsiMethod>(); final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(element.getProject()).getResolveHelper(); for (PsiMethod method : methods) { ProgressManager.checkCanceled(); if (JavaCompletionUtil.isInExcludedPackage(method)) continue; if (!method.hasModifierProperty(PsiModifier.STATIC)) continue; PsiFile file = method.getContainingFile(); if (file instanceof PsiJavaFile // do not show methods from default package && ((PsiJavaFile) file).getPackageName().length() != 0 && PsiUtil.isAccessible(method, element, method.getContainingClass())) { list.add(method); PsiSubstitutor substitutorForMethod = resolveHelper.inferTypeArguments( method.getTypeParameters(), method.getParameterList().getParameters(), argumentList.getExpressions(), PsiSubstitutor.EMPTY, element.getParent(), DefaultParameterTypeInferencePolicy.INSTANCE); if (PsiUtil.isApplicable(method, substitutorForMethod, argumentList)) { applicableList.add(method); } } } List<PsiMethod> result = applicableList.isEmpty() ? list : applicableList; for (int i = result.size() - 1; i >= 0; i--) { ProgressManager.checkCanceled(); PsiMethod method = result.get(i); PsiClass containingClass = method.getContainingClass(); for (int j = i + 1; j < result.size(); j++) { PsiMethod exMethod = result.get(j); if (!Comparing.strEqual(exMethod.getName(), method.getName())) continue; PsiClass exContainingClass = exMethod.getContainingClass(); if (containingClass != null && exContainingClass != null && !Comparing.equal( containingClass.getQualifiedName(), exContainingClass.getQualifiedName())) continue; // same named methods, drop one result.remove(i); break; } // check for manually excluded if (isExcluded(method)) { result.remove(i); } } Collections.sort(result, new PsiProximityComparator(argumentList)); return result; }
@Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) { super.visitClassObjectAccessExpression(expression); PsiElement parent = expression.getParent(); if (parent instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) parent; if (!expression.equals(referenceExpression.getQualifierExpression())) { return; } @NonNls final String name = referenceExpression.getReferenceName(); if (!"getName".equals(name)) { return; } final PsiElement grandParent = referenceExpression.getParent(); if (!(grandParent instanceof PsiMethodCallExpression)) { return; } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) grandParent; final PsiExpressionList list = methodCallExpression.getArgumentList(); if (list.getExpressions().length != 0) { return; } parent = methodCallExpression.getParent(); } if (!(parent instanceof PsiExpressionList)) { return; } final PsiElement grandParent = parent.getParent(); if (!(grandParent instanceof PsiMethodCallExpression)) { return; } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) grandParent; final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); final PsiExpression[] expressions = argumentList.getExpressions(); if (expressions.length != 1) { return; } final PsiClass containingClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class); if (containingClass == null) { return; } final String containingClassName = containingClass.getName(); if (containingClassName == null) { return; } final PsiMethod method = methodCallExpression.resolveMethod(); if (method == null) { return; } final PsiClass aClass = method.getContainingClass(); if (aClass == null) { return; } final String className = aClass.getQualifiedName(); final int index = loggerFactoryClassNames.indexOf(className); if (index < 0) { return; } final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final String referenceName = methodExpression.getReferenceName(); final String loggerFactoryMethodName = loggerFactoryMethodNames.get(index); if (!loggerFactoryMethodName.equals(referenceName)) { return; } final PsiTypeElement operand = expression.getOperand(); final PsiType type = operand.getType(); if (!(type instanceof PsiClassType)) { return; } final PsiClassType classType = (PsiClassType) type; final PsiClass initializerClass = classType.resolve(); if (initializerClass == null) { return; } if (containingClass.equals(initializerClass)) { return; } registerError(expression, containingClassName); }