@Nullable public static String getSuspiciousMethodCallMessage( @NotNull PsiMethodCallExpression methodCall, PsiType argType, boolean reportConvertibleMethodCalls, @NotNull List<PsiMethod> patternMethods, @NotNull IntArrayList indices) { final PsiReferenceExpression methodExpression = methodCall.getMethodExpression(); final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (qualifier == null || qualifier instanceof PsiThisExpression || qualifier instanceof PsiSuperExpression) return null; if (argType instanceof PsiPrimitiveType) { argType = ((PsiPrimitiveType) argType).getBoxedType(methodCall); } if (!(argType instanceof PsiClassType)) return null; final JavaResolveResult resolveResult = methodExpression.advancedResolve(false); PsiMethod calleeMethod = (PsiMethod) resolveResult.getElement(); if (calleeMethod == null) return null; PsiMethod contextMethod = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class); //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (patternMethods) { if (patternMethods.isEmpty()) { setupPatternMethods( methodCall.getManager(), methodCall.getResolveScope(), patternMethods, indices); } } for (int i = 0; i < patternMethods.size(); i++) { PsiMethod patternMethod = patternMethods.get(i); if (!patternMethod.getName().equals(methodExpression.getReferenceName())) continue; int index = indices.get(i); // we are in collections method implementation if (contextMethod != null && isInheritorOrSelf(contextMethod, patternMethod)) return null; final PsiClass calleeClass = calleeMethod.getContainingClass(); PsiSubstitutor substitutor = resolveResult.getSubstitutor(); final PsiClass patternClass = patternMethod.getContainingClass(); assert patternClass != null; assert calleeClass != null; substitutor = TypeConversionUtil.getClassSubstitutor(patternClass, calleeClass, substitutor); if (substitutor == null) continue; if (!patternMethod .getSignature(substitutor) .equals(calleeMethod.getSignature(PsiSubstitutor.EMPTY))) continue; PsiTypeParameter[] typeParameters = patternClass.getTypeParameters(); if (typeParameters.length <= index) return null; final PsiTypeParameter typeParameter = typeParameters[index]; PsiType typeParamMapping = substitutor.substitute(typeParameter); if (typeParamMapping == null) return null; PsiParameter[] parameters = patternMethod.getParameterList().getParameters(); if (parameters.length == 1 && "removeAll".equals(patternMethod.getName())) { PsiType paramType = parameters[0].getType(); if (InheritanceUtil.isInheritor(paramType, CommonClassNames.JAVA_UTIL_COLLECTION)) { PsiType qualifierType = qualifier.getType(); if (qualifierType != null) { final PsiType itemType = JavaGenericsUtil.getCollectionItemType(argType, calleeMethod.getResolveScope()); final PsiType qualifierItemType = JavaGenericsUtil.getCollectionItemType( qualifierType, calleeMethod.getResolveScope()); if (qualifierItemType != null && itemType != null && !qualifierItemType.isAssignableFrom(itemType)) { return InspectionsBundle.message( "inspection.suspicious.collections.method.calls.problem.descriptor", PsiFormatUtil.formatType(qualifierType, 0, PsiSubstitutor.EMPTY), PsiFormatUtil.formatType(itemType, 0, PsiSubstitutor.EMPTY)); } } return null; } } String message = null; if (typeParamMapping instanceof PsiCapturedWildcardType) { typeParamMapping = ((PsiCapturedWildcardType) typeParamMapping).getWildcard(); } if (!typeParamMapping.isAssignableFrom(argType)) { if (typeParamMapping.isConvertibleFrom(argType)) { if (reportConvertibleMethodCalls) { message = InspectionsBundle.message( "inspection.suspicious.collections.method.calls.problem.descriptor1", PsiFormatUtil.formatMethod( calleeMethod, substitutor, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_CONTAINING_CLASS, PsiFormatUtilBase.SHOW_TYPE)); } } else { PsiType qualifierType = qualifier.getType(); if (qualifierType != null) { message = InspectionsBundle.message( "inspection.suspicious.collections.method.calls.problem.descriptor", PsiFormatUtil.formatType(qualifierType, 0, PsiSubstitutor.EMPTY), PsiFormatUtil.formatType(argType, 0, PsiSubstitutor.EMPTY)); } } } return message; } return null; }
@Override protected PsiElement getElement() { if (!myMethodCall.isValid() || !myMethodCall.getManager().isInProject(myMethodCall)) return null; return myMethodCall; }