@Override public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiIdentifier name = (PsiIdentifier) descriptor.getPsiElement(); final PsiReferenceExpression expression = (PsiReferenceExpression) name.getParent(); if (expression == null) { return; } final PsiMethodCallExpression call = (PsiMethodCallExpression) expression.getParent(); final String methodName = expression.getReferenceName(); if (call == null) { return; } final PsiMethod method = call.resolveMethod(); if (method == null) { return; } final PsiClass containingClass = method.getContainingClass(); final PsiExpressionList argumentList = call.getArgumentList(); if (containingClass == null) { return; } final String containingClassName = containingClass.getQualifiedName(); final String argText = argumentList.getText(); PsiReplacementUtil.replaceExpressionAndShorten( call, containingClassName + '.' + methodName + argText); }
@Override public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); @NonNls final String signal = "signal"; if (!signal.equals(methodName)) { return; } final PsiExpressionList argumentList = expression.getArgumentList(); if (argumentList.getExpressions().length != 0) { return; } final PsiMethod method = expression.resolveMethod(); if (method == null) { return; } final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) { return; } if (!ClassUtils.isSubclass(containingClass, "java.util.concurrent.locks.Condition")) { return; } registerMethodCallError(expression); }
@Override public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) { super.visitMethodCallExpression(call); final PsiReferenceExpression methodExpression = call.getMethodExpression(); final PsiElement qualifier = methodExpression.getQualifier(); if (!(qualifier instanceof PsiReferenceExpression)) { return; } final PsiMethod method = call.resolveMethod(); if (method == null) { return; } if (!method.hasModifierProperty(PsiModifier.STATIC)) { return; } final PsiElement referent = ((PsiReference) qualifier).resolve(); if (!(referent instanceof PsiClass)) { return; } final PsiClass referencedClass = (PsiClass) referent; final PsiClass declaringClass = method.getContainingClass(); if (declaringClass == null) { return; } if (declaringClass.equals(referencedClass)) { return; } final PsiClass containingClass = ClassUtils.getContainingClass(call); if (!ClassUtils.isClassVisibleFromClass(containingClass, declaringClass)) { return; } registerMethodCallError(call, declaringClass, referencedClass); }
static boolean isComplexArrayExpression(PsiExpression expression) { expression = ParenthesesUtils.stripParentheses(expression); if (expression == null) { return false; } if (expression instanceof PsiNewExpression) { final PsiNewExpression newExpression = (PsiNewExpression) expression; final PsiArrayInitializerExpression arrayInitializer = newExpression.getArrayInitializer(); return isComplexArrayExpression(arrayInitializer); } else if (expression instanceof PsiArrayInitializerExpression) { final PsiArrayInitializerExpression arrayInitializerExpression = (PsiArrayInitializerExpression) expression; for (PsiExpression initializer : arrayInitializerExpression.getInitializers()) { if (isComplexArrayExpression(initializer)) { return true; } } return false; } else if (expression instanceof PsiReferenceExpression) { return expression.getType() instanceof PsiArrayType; } else if (expression instanceof PsiArrayAccessExpression) { return true; } else if (expression instanceof PsiTypeCastExpression) { final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression) expression; return isComplexArrayExpression(typeCastExpression.getOperand()); } else if (expression instanceof PsiConditionalExpression) { final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression) expression; return isComplexArrayExpression(conditionalExpression.getThenExpression()) || isComplexArrayExpression(conditionalExpression.getElseExpression()); } else if (expression instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) expression; final PsiMethod method = methodCallExpression.resolveMethod(); if (method == null) { return true; } if (CloneUtils.isClone(method)) { return false; } @NonNls final String name = method.getName(); if ("copyOf".equals(name) || "copyOfRange".equals(name)) { final PsiClass aClass = method.getContainingClass(); if (aClass != null && CommonClassNames.JAVA_UTIL_ARRAYS.equals(aClass.getQualifiedName())) { return false; } } else if ("toArray".equals(name) && InheritanceUtil.isInheritor(method.getContainingClass(), "java.util.Collection")) { return false; } return true; } return true; }
@Override public void visitMethodCallExpression(final PsiMethodCallExpression expression) { if (myCollectExpressions) { final PsiMethod psiMethod = expression.resolveMethod(); if (psiMethod != null && !DebuggerUtils.hasSideEffectsOrReferencesMissingVars(expression, myVisibleLocals)) { myExpressions.add(new TextWithImportsImpl(expression)); } } super.visitMethodCallExpression(expression); }
private List<MethodContract> handleCallDelegation( PsiMethodCallExpression expression, final boolean negated) { final PsiMethod targetMethod = expression.resolveMethod(); if (targetMethod == null) return Collections.emptyList(); final PsiExpression[] arguments = expression.getArgumentList().getExpressions(); return RecursionManager.doPreventingRecursion( myMethod, true, new Computable<List<MethodContract>>() { @Override public List<MethodContract> compute() { List<MethodContract> delegateContracts = ControlFlowAnalyzer.getMethodContracts(targetMethod); return ContainerUtil.mapNotNull( delegateContracts, new NullableFunction<MethodContract, MethodContract>() { @Nullable @Override public MethodContract fun(MethodContract delegateContract) { ValueConstraint[] answer = MethodContract.createConstraintArray( myMethod.getParameterList().getParametersCount()); for (int i = 0; i < delegateContract.arguments.length; i++) { if (i >= arguments.length) return null; ValueConstraint argConstraint = delegateContract.arguments[i]; if (argConstraint != ANY_VALUE) { int paramIndex = resolveParameter(arguments[i]); if (paramIndex < 0) { if (argConstraint != getLiteralConstraint(arguments[i])) { return null; } } else { answer = withConstraint(answer, paramIndex, argConstraint); } } } return answer == null ? null : new MethodContract( answer, negated ? negateConstraint(delegateContract.returnValue) : delegateContract.returnValue); } }); } }); }
private static boolean isJavaUtilMethodCall(PsiMethodCallExpression expr) { PsiMethod method = expr.resolveMethod(); if (method == null) return false; return isJavaUtilMethod(method) || !MethodDeepestSuperSearcher.processDeepestSuperMethods( method, new Processor<PsiMethod>() { @Override public boolean process(PsiMethod method) { return !isJavaUtilMethod(method); } }); }
@Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); if (!"cast".equals(methodName)) { return; } final PsiMethod method = expression.resolveMethod(); if (method == null) { return; } final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) { return; } final String qualifiedName = containingClass.getQualifiedName(); if (!"java.lang.Class".equals(qualifiedName)) { return; } final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (!(qualifier instanceof PsiClassObjectAccessExpression)) { return; } final PsiClassObjectAccessExpression classObjectAccessExpression = (PsiClassObjectAccessExpression) qualifier; final PsiTypeElement operand = classObjectAccessExpression.getOperand(); final PsiType castType = operand.getType(); if (!(castType instanceof PsiClassType)) { return; } final PsiExpressionList argumentList = expression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); if (arguments.length != 1) { return; } final PsiExpression argument = arguments[0]; if (!(argument instanceof PsiReferenceExpression)) { return; } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) argument; final PsiInstanceOfExpression conflictingInstanceof = InstanceOfUtils.getConflictingInstanceof(castType, referenceExpression, expression); if (conflictingInstanceof == null) { return; } final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType(); registerError(expression, referenceExpression, operand, instanceofTypeElement); }
/** * Allows to check if static import may be performed for the given element. * * @param element element to check * @return target class that may be statically imported if any; <code>null</code> otherwise */ @Nullable public static PsiClass getClassToPerformStaticImport(@NotNull PsiElement element) { if (!PsiUtil.isLanguageLevel5OrHigher(element)) return null; if (!(element instanceof PsiIdentifier) || !(element.getParent() instanceof PsiJavaCodeReferenceElement)) { return null; } PsiJavaCodeReferenceElement refExpr = (PsiJavaCodeReferenceElement) element.getParent(); if (refExpr instanceof PsiMethodReferenceExpression) return null; final PsiElement gParent = refExpr.getParent(); if (gParent instanceof PsiMethodReferenceExpression) return null; if (!(gParent instanceof PsiJavaCodeReferenceElement) || isParameterizedReference((PsiJavaCodeReferenceElement) gParent)) return null; PsiElement resolved = refExpr.resolve(); if (!(resolved instanceof PsiClass)) { return null; } PsiClass psiClass = (PsiClass) resolved; if (PsiUtil.isFromDefaultPackage(psiClass) || psiClass.hasModifierProperty(PsiModifier.PRIVATE) || psiClass.getQualifiedName() == null) return null; final PsiElement ggParent = gParent.getParent(); if (ggParent instanceof PsiMethodCallExpression) { final PsiMethodCallExpression call = (PsiMethodCallExpression) ggParent.copy(); final PsiElement qualifier = call.getMethodExpression().getQualifier(); if (qualifier == null) return null; qualifier.delete(); final PsiMethod method = call.resolveMethod(); if (method != null && method.getContainingClass() != psiClass) return null; } else { final PsiJavaCodeReferenceElement copy = (PsiJavaCodeReferenceElement) gParent.copy(); final PsiElement qualifier = copy.getQualifier(); if (qualifier == null) return null; qualifier.delete(); final PsiElement target = copy.resolve(); if (target != null && PsiTreeUtil.getParentOfType(target, PsiClass.class) != psiClass) return null; } PsiFile file = refExpr.getContainingFile(); if (!(file instanceof PsiJavaFile)) return null; PsiImportList importList = ((PsiJavaFile) file).getImportList(); if (importList == null) return null; return psiClass; }
private static boolean expressionIsArrayToCollectionCopy( PsiExpression expression, PsiVariable variable, boolean shouldBeOffsetArrayAccess) { expression = ParenthesesUtils.stripParentheses(expression); if (expression == null) { return false; } if (!(expression instanceof PsiMethodCallExpression)) { return false; } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) expression; final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); if (arguments.length != 1) { return false; } final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (!(qualifier instanceof PsiReferenceExpression) && !(qualifier instanceof PsiThisExpression) && !(qualifier instanceof PsiSuperExpression)) { return false; } final PsiExpression argument = arguments[0]; final PsiType argumentType = argument.getType(); if (argumentType instanceof PsiPrimitiveType) { return false; } if (SideEffectChecker.mayHaveSideEffects(argument)) { return false; } if (shouldBeOffsetArrayAccess) { if (!ExpressionUtils.isOffsetArrayAccess(argument, variable)) { return false; } } else if (!VariableAccessUtils.evaluatesToVariable(argument, variable)) { return false; } final PsiMethod method = methodCallExpression.resolveMethod(); if (method == null) { return false; } @NonNls final String name = method.getName(); if (!name.equals("add")) { return false; } final PsiClass containingClass = method.getContainingClass(); return InheritanceUtil.isInheritor(containingClass, CommonClassNames.JAVA_UTIL_COLLECTION); }
private static boolean callTakesXPathExpression(PsiMethodCallExpression expression) { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String name = methodExpression.getReferenceName(); if (!xpathMethodNames.contains(name)) { return false; } final PsiMethod method = expression.resolveMethod(); if (method == null) { return false; } final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) { return false; } final String className = containingClass.getQualifiedName(); return "javax.xml.xpath.XPath".equals(className); }
@Override public void visitExpressionStatement(@NotNull PsiExpressionStatement statement) { super.visitExpressionStatement(statement); final PsiExpression expression = statement.getExpression(); if (!(expression instanceof PsiMethodCallExpression)) { return; } final PsiMethodCallExpression call = (PsiMethodCallExpression) expression; final PsiMethod method = call.resolveMethod(); if (method == null || method.isConstructor()) { return; } final PsiType returnType = method.getReturnType(); if (PsiType.VOID.equals(returnType)) { return; } final PsiClass aClass = method.getContainingClass(); if (aClass == null) { return; } if (PsiUtilCore.hasErrorElementChild(statement)) { return; } if (m_reportAllNonLibraryCalls && !LibraryUtil.classIsInLibrary(aClass)) { registerMethodCallError(call, aClass); return; } final PsiReferenceExpression methodExpression = call.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); if (methodName == null) { return; } for (int i = 0; i < methodNamePatterns.size(); i++) { final String methodNamePattern = methodNamePatterns.get(i); if (!methodNamesMatch(methodName, methodNamePattern)) { continue; } final String className = classNames.get(i); if (!InheritanceUtil.isInheritor(aClass, className)) { continue; } registerMethodCallError(call, aClass); return; } }
private static boolean canCallMethodsInConstructors(PsiClass aClass, boolean virtual) { for (PsiMethod constructor : aClass.getConstructors()) { if (!constructor.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return true; PsiCodeBlock body = constructor.getBody(); if (body == null) continue; for (PsiMethodCallExpression call : SyntaxTraverser.psiTraverser().withRoot(body).filter(PsiMethodCallExpression.class)) { PsiReferenceExpression methodExpression = call.getMethodExpression(); if (methodExpression instanceof PsiThisExpression || methodExpression instanceof PsiSuperExpression) continue; if (!virtual) return true; PsiMethod target = call.resolveMethod(); if (target != null && PsiUtil.canBeOverriden(target)) return true; } } return false; }
@Override public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { if (hasSuperCall) { return; } super.visitMethodCallExpression(expression); final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (qualifier == null) { return; } final String text = qualifier.getText(); if (!PsiKeyword.SUPER.equals(text)) { return; } final PsiMethod method = expression.resolveMethod(); if (method == null) { return; } if (method.equals(methodToSearchFor)) { hasSuperCall = true; } }
private static boolean isCallToRegexMethod(PsiMethodCallExpression expression) { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String name = methodExpression.getReferenceName(); if (!regexMethodNames.contains(name)) { return false; } final PsiExpressionList argumentList = expression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); for (PsiExpression argument : arguments) { if (!PsiUtil.isConstantExpression(argument)) { return false; } } final PsiMethod method = expression.resolveMethod(); if (method == null) { return false; } final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) { return false; } final String className = containingClass.getQualifiedName(); return "java.lang.String".equals(className); }
public static boolean callOnLibraryMethod(@NotNull PsiMethodCallExpression expression) { final PsiMethod method = expression.resolveMethod(); return method instanceof PsiCompiledElement; }
private static void findParameterUsages( final PsiParameter parameter, final List<UsageInfo> usages) { final PsiMethod method = (PsiMethod) parameter.getDeclarationScope(); final int parameterIndex = method.getParameterList().getParameterIndex(parameter); // search for refs to current method only, do not search for refs to overriding methods, they'll // be searched separately ReferencesSearch.search(method) .forEach( reference -> { PsiElement element = reference.getElement(); if (element != null) { final JavaSafeDeleteDelegate safeDeleteDelegate = JavaSafeDeleteDelegate.EP.forLanguage(element.getLanguage()); if (safeDeleteDelegate != null) { safeDeleteDelegate.createUsageInfoForParameter( reference, usages, parameter, method); } if (!parameter.isVarArgs() && !RefactoringChangeUtil.isSuperMethodCall(element.getParent())) { final PsiParameter paramInCaller = SafeDeleteJavaCallerChooser.isTheOnlyOneParameterUsage( element.getParent(), parameterIndex, method); if (paramInCaller != null) { final PsiMethod callerMethod = (PsiMethod) paramInCaller.getDeclarationScope(); if (ApplicationManager.getApplication().isUnitTestMode()) { usages.add( new SafeDeleteParameterCallHierarchyUsageInfo( callerMethod, paramInCaller, callerMethod)); } else { usages.add( new SafeDeleteParameterCallHierarchyUsageInfo( method, parameter, callerMethod)); } } } } return true; }); ReferencesSearch.search(parameter) .forEach( reference -> { PsiElement element = reference.getElement(); final PsiDocTag docTag = PsiTreeUtil.getParentOfType(element, PsiDocTag.class); if (docTag != null) { usages.add(new SafeDeleteReferenceJavaDeleteUsageInfo(docTag, parameter, true)); return true; } boolean isSafeDelete = false; if (element.getParent().getParent() instanceof PsiMethodCallExpression) { PsiMethodCallExpression call = (PsiMethodCallExpression) element.getParent().getParent(); PsiReferenceExpression methodExpression = call.getMethodExpression(); if (methodExpression.getText().equals(PsiKeyword.SUPER)) { isSafeDelete = true; } else if (methodExpression.getQualifierExpression() instanceof PsiSuperExpression) { final PsiMethod superMethod = call.resolveMethod(); if (superMethod != null && MethodSignatureUtil.isSuperMethod(superMethod, method)) { isSafeDelete = true; } } } usages.add( new SafeDeleteReferenceJavaDeleteUsageInfo(element, parameter, isSafeDelete)); return true; }); findFunctionalExpressions(usages, method); }
@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); }
@Override public void visitReferenceExpression(PsiReferenceExpression expression) { if (myWritten && myRead) { return; } super.visitReferenceExpression(expression); final PsiElement target = expression.resolve(); if (target != myVariable) { return; } if (PsiUtil.isAccessedForWriting(expression)) { final PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class); if (parent instanceof PsiAssignmentExpression) { final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) parent; final PsiExpression rhs = assignmentExpression.getRExpression(); if (isComplexArrayExpression(rhs)) { myWritten = true; myRead = true; } else if (!isSimpleArrayExpression(rhs)) { myWritten = true; } } return; } myIsReferenced = true; PsiElement parent = getParent(expression); if (parent instanceof PsiArrayAccessExpression) { PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression) parent; parent = getParent(parent); while (parent instanceof PsiArrayAccessExpression) { arrayAccessExpression = (PsiArrayAccessExpression) parent; parent = getParent(parent); } final PsiType type = arrayAccessExpression.getType(); if (type != null) { final int dimensions = type.getArrayDimensions(); if (dimensions > 0 && dimensions != myVariable.getType().getArrayDimensions()) { myWritten = true; } } if (PsiUtil.isAccessedForWriting(arrayAccessExpression)) { myWritten = true; } if (PsiUtil.isAccessedForReading(arrayAccessExpression)) { myRead = true; } } else if (parent instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) parent; final String name = referenceExpression.getReferenceName(); if ("length".equals(name) || ("clone".equals(name) && referenceExpression.getParent() instanceof PsiMethodCallExpression)) { myRead = true; } } else if (parent instanceof PsiForeachStatement) { final PsiForeachStatement foreachStatement = (PsiForeachStatement) parent; final PsiExpression iteratedValue = foreachStatement.getIteratedValue(); if (PsiTreeUtil.isAncestor(iteratedValue, expression, false)) { myRead = true; } } else if (parent instanceof PsiExpressionList) { final PsiExpressionList expressionList = (PsiExpressionList) parent; parent = parent.getParent(); if (parent instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) parent; final PsiMethod method = methodCallExpression.resolveMethod(); if (method != null) { final PsiClass aClass = method.getContainingClass(); if (aClass != null) { final String methodName = method.getName(); final String qualifiedName = aClass.getQualifiedName(); if ("java.lang.System".equals(qualifiedName)) { if ("arraycopy".equals(methodName)) { final PsiExpression[] expressions = expressionList.getExpressions(); if (expressions.length == 5) { if (PsiTreeUtil.isAncestor(expressions[0], expression, false)) { myRead = true; return; } else if (PsiTreeUtil.isAncestor(expressions[2], expression, false)) { myWritten = true; return; } } } } else if (CommonClassNames.JAVA_UTIL_ARRAYS.equals(qualifiedName)) { if ("fill".equals(methodName) || "parallelPrefix".equals(methodName) || "parallelSetAll".equals(methodName) || "parallelSort".equals(methodName) || "setAll".equals(methodName) || "sort".equals(methodName)) { myWritten = true; } else { myRead = true; } return; } } } } myRead = true; myWritten = true; } else { myWritten = true; myRead = true; } }