From 9bcd5c38eac8751a6e5a98ab39d37a92db24a9eb Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 17 Oct 2024 13:25:14 +0200 Subject: [PATCH] [java-inspections] JavaReflectionInvocationInspection: better message and range when number of arguments differs Fixes IDEA-171801 Make "Reflective invocation arguments mismatch" more verbose GitOrigin-RevId: 586b21e543959f53a082d6b0a1fdcb28c0f30039 --- .../JavaReflectionInvocationInspection.java | 21 ++++++++---- .../ConstructorParamCount.java | 22 ++++++------- .../MethodParamCount.java | 32 +++++++++---------- .../resources/messages/JavaBundle.properties | 1 + 4 files changed, 43 insertions(+), 33 deletions(-) diff --git a/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaReflectionInvocationInspection.java b/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaReflectionInvocationInspection.java index f98d99c37a04..cc2aea244ea8 100644 --- a/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaReflectionInvocationInspection.java +++ b/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaReflectionInvocationInspection.java @@ -4,6 +4,7 @@ package com.intellij.codeInspection.reflectiveAccess; import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.java.JavaBundle; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil; import com.intellij.psi.impl.source.resolve.reference.impl.JavaLangClassMemberReference; @@ -65,10 +66,11 @@ public final class JavaReflectionInvocationInspection extends AbstractBaseJavaLo getRequiredMethodArguments(methodCall.getMethodExpression().getQualifierExpression(), argumentOffset, methodPredicate); if (requiredTypes != null) { final PsiExpressionList argumentList = methodCall.getArgumentList(); - final Arguments actualArguments = getActualMethodArguments(argumentList.getExpressions(), argumentOffset, + final Arguments actualArguments = getActualMethodArguments(argumentList.getExpressions(), argumentOffset, MethodCallUtils.isVarArgCall(methodCall)); if (actualArguments != null) { - if (requiredTypes.size() != actualArguments.expressions.length) { + PsiExpression[] actualExpressions = actualArguments.expressions; + if (requiredTypes.size() != actualExpressions.length) { if (actualArguments.varargAsArray) { final PsiExpression[] expressions = argumentList.getExpressions(); final PsiElement element = expressions.length == argumentOffset + 1 ? expressions[argumentOffset] : argumentList; @@ -76,8 +78,15 @@ public final class JavaReflectionInvocationInspection extends AbstractBaseJavaLo "inspection.reflection.invocation.item.count", requiredTypes.size())); } else { - holder.registerProblem(argumentList, JavaBundle.message( - "inspection.reflection.invocation.argument.count", requiredTypes.size() + argumentOffset)); + if (actualExpressions.length > 0) { + TextRange range = + actualExpressions[0].getTextRangeInParent().union(actualExpressions[actualExpressions.length - 1].getTextRangeInParent()); + holder.registerProblem(argumentList, range, JavaBundle.message( + "inspection.reflection.invocation.reflective.argument.count", requiredTypes.size())); + } else { + holder.registerProblem(argumentList, JavaBundle.message( + "inspection.reflection.invocation.reflective.argument.count", requiredTypes.size())); + } } return; } @@ -85,7 +94,7 @@ public final class JavaReflectionInvocationInspection extends AbstractBaseJavaLo for (int i = 0; i < requiredTypes.size(); i++) { final ReflectiveType requiredType = getReflectiveType(requiredTypes.get(i)); if (requiredType != null) { - final PsiExpression argument = actualArguments.expressions[i]; + final PsiExpression argument = actualExpressions[i]; if (argument != null) { PsiType actualType = argument.getType(); if (TypeUtils.isJavaLangObject(actualType) && !requiredType.isAssignableFrom(actualType) && @@ -107,7 +116,7 @@ public final class JavaReflectionInvocationInspection extends AbstractBaseJavaLo final PsiExpression[] expressions = argumentList.getExpressions(); final PsiElement element = expressions.length == argumentOffset + 1 ? expressions[argumentOffset] : argumentList; holder.registerProblem(element, JavaBundle.message( - "inspection.reflection.invocation.array.not.assignable", actualArguments.expressions.length)); + "inspection.reflection.invocation.array.not.assignable", actualExpressions.length)); break; } } diff --git a/java/java-tests/testData/inspection/javaReflectionInvocation/ConstructorParamCount.java b/java/java-tests/testData/inspection/javaReflectionInvocation/ConstructorParamCount.java index e387d1eb237a..14d3b63fe3e5 100644 --- a/java/java-tests/testData/inspection/javaReflectionInvocation/ConstructorParamCount.java +++ b/java/java-tests/testData/inspection/javaReflectionInvocation/ConstructorParamCount.java @@ -10,17 +10,17 @@ class ConstructorParamCount { Constructor c2 = cls.getConstructor(int.class, String.class); Constructor c3 = cls.getConstructor(int.class, String.class, String.class); - c1.newInstance(42, "abc"); + c1.newInstance(42, "abc"); c2.newInstance(42, "abc"); - c3.newInstance(42, "abc"); + c3.newInstance(42, "abc"); c1.newInstance(new Object[]{42, "abc"}); c2.newInstance(new Object[]{42, "abc"}); c3.newInstance(new Object[]{42, "abc"}); - c1.newInstance(); - c2.newInstance(); - c3.newInstance(); + c1.newInstance(); + c2.newInstance(); + c3.newInstance(); cls.getConstructor(String.class).newInstance(new String[] {"abc"}); } @@ -32,17 +32,17 @@ class ConstructorParamCount { Constructor c2 = cls.getConstructor(new Class[]{int.class, String.class}); Constructor c3 = cls.getConstructor(new Class[]{int.class, String.class, String.class}); - c1.newInstance(42, "abc"); + c1.newInstance(42, "abc"); c2.newInstance(42, "abc"); - c3.newInstance(42, "abc"); + c3.newInstance(42, "abc"); c1.newInstance(new Object[]{42, "abc"}); c2.newInstance(new Object[]{42, "abc"}); c3.newInstance(new Object[]{42, "abc"}); - c1.newInstance(); - c2.newInstance(); - c3.newInstance(); + c1.newInstance(); + c2.newInstance(); + c3.newInstance(); cls.getConstructor(new Class[]{String.class}).newInstance(new String[] {"abc"}); } @@ -57,7 +57,7 @@ class ConstructorParamCount { Constructor m4 = cls.getConstructor(int.class, short.class, long.class, float.class); Constructor m5 = cls.getConstructor(int.class, short.class, long.class, float.class, double.class); - m0.newInstance(0, 0); + m0.newInstance(0, 0); m1.newInstance("abc"); m2.newInstance(0, "abc"); m3.newInstance(0, 0, "abc"); diff --git a/java/java-tests/testData/inspection/javaReflectionInvocation/MethodParamCount.java b/java/java-tests/testData/inspection/javaReflectionInvocation/MethodParamCount.java index 5ce1b6a8dc2f..2cb17ec08b3d 100644 --- a/java/java-tests/testData/inspection/javaReflectionInvocation/MethodParamCount.java +++ b/java/java-tests/testData/inspection/javaReflectionInvocation/MethodParamCount.java @@ -9,17 +9,17 @@ class MethodParamCount { Method m2 = cls.getMethod("bar", int.class, String.class); Method m3 = cls.getMethod("bar", int.class, String.class, String.class); - m1.invoke(obj, 42, "abc"); + m1.invoke(obj, 42, "abc"); m2.invoke(obj, 42, "abc"); - m3.invoke(obj, 42, "abc"); + m3.invoke(obj, 42, "abc"); m1.invoke(obj, new Object[]{42, "abc"}); m2.invoke(obj, new Object[]{42, "abc"}); m3.invoke(obj, new Object[]{42, "abc"}); - m1.invoke(obj); - m2.invoke(obj); - m3.invoke(obj); + m1.invoke(obj); + m2.invoke(obj); + m3.invoke(obj); cls.getMethod("str", String.class).invoke(null, new String[] {"abc"}); } @@ -32,17 +32,17 @@ class MethodParamCount { Method m2 = cls.getMethod("bar", new Class[]{int.class, String.class}); Method m3 = cls.getMethod("bar", new Class[]{int.class, String.class, String.class}); - m1.invoke(obj, 42, "abc"); + m1.invoke(obj, 42, "abc"); m2.invoke(obj, 42, "abc"); - m3.invoke(obj, 42, "abc"); + m3.invoke(obj, 42, "abc"); m1.invoke(obj, new Object[]{42, "abc"}); m2.invoke(obj, new Object[]{42, "abc"}); m3.invoke(obj, new Object[]{42, "abc"}); - m1.invoke(obj); - m2.invoke(obj); - m3.invoke(obj); + m1.invoke(obj); + m2.invoke(obj); + m3.invoke(obj); cls.getMethod("str", new Class[]{String.class}).invoke(null, new String[] {"abc"}); } @@ -58,12 +58,12 @@ class MethodParamCount { Method m4 = cls.getMethod("m4", int.class, short.class, long.class, float.class); Method m5 = cls.getMethod("m5", int.class, short.class, long.class, float.class, double.class); - m0.invoke(0, 0); - m1.invoke("abc"); - m2.invoke(0, "abc"); - m3.invoke(0, 0, "abc"); - m4.invoke(0, 0, 0, "abc"); - m5.invoke(0, 0, 0, 0, "abc"); + m0.invoke(0, 0); + m1.invoke("abc"); + m2.invoke(0, "abc"); + m3.invoke(0, 0, "abc"); + m4.invoke(0, 0, 0, "abc"); + m5.invoke(0, 0, 0, 0, "abc"); Method m = cls.getMethod("m0", new Class[0]); m.invoke(obj, new Object[0]); diff --git a/java/openapi/resources/messages/JavaBundle.properties b/java/openapi/resources/messages/JavaBundle.properties index d7e76f0b0b33..6ace2f17ad56 100644 --- a/java/openapi/resources/messages/JavaBundle.properties +++ b/java/openapi/resources/messages/JavaBundle.properties @@ -660,6 +660,7 @@ inspection.reflect.handle.invocation.result.not.exact=Should be cast to ''{0}'' inspection.reflect.handle.invocation.result.null=Returned value is always 'null' inspection.reflect.handle.invocation.result.void=Return type is 'void' inspection.reflection.invocation.argument.count={0,choice,0#No arguments are|1#One argument is|1<{0} arguments are} expected +inspection.reflection.invocation.reflective.argument.count=Reflectively called method requires {0,choice,0#no arguments|1#one argument|1<{0} arguments} inspection.reflection.invocation.argument.not.assignable=Argument is not assignable to ''{0}'' inspection.reflection.invocation.array.not.assignable=Array {0,choice,1#item has|1