mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
call static on subclass: warn on method references (IDEA-187321)
This commit is contained in:
+50
-18
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
|
||||
class I {
|
||||
static <Z> void FOO() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class A extends I {
|
||||
{
|
||||
Runnable r = I/*c2*/::<String>FOO;
|
||||
}
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
|
||||
class I {
|
||||
static <Z> void FOO() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class A extends I {
|
||||
{
|
||||
Runnable r = A/*c2*/::<String>F<caret>OO;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user