diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java index 51b2856ba2e9..a9f42cc835ef 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java @@ -19,6 +19,7 @@ import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.util.ObjectUtils; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; @@ -67,13 +68,26 @@ public class StaticCallOnSubclassInspection extends BaseInspection implements Cl @Override public void doFix(Project project, ProblemDescriptor descriptor) { - final PsiIdentifier name = (PsiIdentifier)descriptor.getPsiElement(); - final PsiReferenceExpression expression = (PsiReferenceExpression)name.getParent(); + final PsiIdentifier name = ObjectUtils.tryCast(descriptor.getPsiElement(), PsiIdentifier.class); + if (name == null) return; + final PsiReferenceExpression expression = ObjectUtils.tryCast(name.getParent(), PsiReferenceExpression.class); if (expression == null) { return; } - final PsiMethodCallExpression call = (PsiMethodCallExpression)expression.getParent(); - final String methodName = expression.getReferenceName(); + if (expression instanceof PsiMethodReferenceExpression) { + PsiElement resolve = expression.resolve(); + if (resolve instanceof PsiMethod) { + PsiClass containingClass = ((PsiMethod)resolve).getContainingClass(); + if (containingClass != null) { + PsiExpression qualifierExpression = expression.getQualifierExpression(); + if (qualifierExpression instanceof PsiReferenceExpression) { + ((PsiReferenceExpression)qualifierExpression).bindToElement(containingClass); + } + } + } + return; + } + final PsiMethodCallExpression call = ObjectUtils.tryCast(expression.getParent(), PsiMethodCallExpression.class); if (call == null) { return; } @@ -90,6 +104,7 @@ public class StaticCallOnSubclassInspection extends BaseInspection implements Cl CommentTracker commentTracker = new CommentTracker(); final String argText = commentTracker.text(argumentList); final String typeArgText = commentTracker.text(call.getTypeArgumentList()); + final String methodName = expression.getReferenceName(); PsiReplacementUtil.replaceExpressionAndShorten(call, containingClassName + '.' + typeArgText + methodName + argText, commentTracker); } } @@ -99,26 +114,39 @@ public class StaticCallOnSubclassInspection extends BaseInspection implements Cl return new StaticCallOnSubclassVisitor(); } - private static class StaticCallOnSubclassVisitor - extends BaseInspectionVisitor { + private static class StaticCallOnSubclassVisitor extends BaseInspectionVisitor { @Override - public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression call) { + 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(); + final PsiReferenceExpression methodExpression = call.getMethodExpression(); + final PsiMethod method = call.resolveMethod(); if (method == null) { return; } + + checkCallOnSubclass(method, methodExpression); + } + + @Override + public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { + super.visitMethodReferenceExpression(expression); + if (PsiMethodReferenceUtil.isStaticallyReferenced(expression)) { + PsiElement resolve = expression.resolve(); + if (resolve instanceof PsiMethod) { + checkCallOnSubclass((PsiMethod)resolve, expression); + } + } + } + + private void checkCallOnSubclass(@NotNull PsiMethod method, PsiReferenceExpression methodExpression) { if (!method.hasModifierProperty(PsiModifier.STATIC)) { return; } + PsiExpression qualifier = methodExpression.getQualifierExpression(); + if (!(qualifier instanceof PsiReferenceExpression)) { + return; + } final PsiElement referent = ((PsiReference)qualifier).resolve(); if (!(referent instanceof PsiClass)) { return; @@ -131,11 +159,15 @@ public class StaticCallOnSubclassInspection extends BaseInspection implements Cl if (declaringClass.equals(referencedClass)) { return; } - final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(call.getProject()).getResolveHelper(); - if (!resolveHelper.isAccessible(declaringClass, call, null)) { + final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(methodExpression.getProject()).getResolveHelper(); + if (!resolveHelper.isAccessible(declaringClass, methodExpression, null)) { return; } - registerMethodCallError(call, declaringClass, referencedClass); + PsiElement referenceNameElement = methodExpression.getReferenceNameElement(); + if (referenceNameElement == null) { + return; + } + registerError(referenceNameElement, declaringClass, referencedClass); } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/bugs/staticCallOnSubclass/methodRef.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/bugs/staticCallOnSubclass/methodRef.after.java new file mode 100644 index 000000000000..64d09cef619d --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/bugs/staticCallOnSubclass/methodRef.after.java @@ -0,0 +1,13 @@ + +class I { + static void FOO() { + + } +} + +class A extends I { + { + Runnable r = I/*c2*/::FOO; + } +} + diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/bugs/staticCallOnSubclass/methodRef.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/bugs/staticCallOnSubclass/methodRef.java new file mode 100644 index 000000000000..508bc346c554 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/bugs/staticCallOnSubclass/methodRef.java @@ -0,0 +1,13 @@ + +class I { + static void FOO() { + + } +} + +class A extends I { + { + Runnable r = A/*c2*/::FOO; + } +} + diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/bugs/StaticCallOnSubclassTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/bugs/StaticCallOnSubclassTest.java index 4f20a75059e7..de0e71f994ee 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/bugs/StaticCallOnSubclassTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/bugs/StaticCallOnSubclassTest.java @@ -17,7 +17,6 @@ package com.siyeh.ig.fixes.bugs; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.IGQuickFixesTestCase; -import com.siyeh.ig.bugs.CastConflictsWithInstanceofInspection; import com.siyeh.ig.bugs.StaticCallOnSubclassInspection; public class StaticCallOnSubclassTest extends IGQuickFixesTestCase { @@ -31,6 +30,10 @@ public class StaticCallOnSubclassTest extends IGQuickFixesTestCase { doTest("preserveTypeArgs", InspectionGadgetsBundle.message("static.method.via.subclass.rationalize.quickfix")); } + public void testMethodReference() { + doTest("methodRef", InspectionGadgetsBundle.message("static.method.via.subclass.rationalize.quickfix")); + } + @Override protected String getRelativePath() { return "bugs/staticCallOnSubclass";