mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java: Implemented inspection "Reflective invocation arguments mismatch" (IDEA-167270)
This commit is contained in:
+228
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInspection.reflectiveAccess;
|
||||
|
||||
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.psiutils.MethodCallUtils;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_CLASS;
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_OBJECT;
|
||||
import static com.intellij.psi.impl.source.resolve.reference.impl.JavaReflectionReferenceUtil.*;
|
||||
|
||||
/**
|
||||
* @author Pavel.Dolgov
|
||||
*/
|
||||
public class JavaReflectionInvocationInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
|
||||
private static final String JAVA_LANG_REFLECT_METHOD = "java.lang.reflect.Method";
|
||||
private static final String JAVA_LANG_REFLECT_CONSTRUCTOR = "java.lang.reflect.Constructor";
|
||||
|
||||
private static final String INVOKE = "invoke";
|
||||
private static final String NEW_INSTANCE = "newInstance";
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
return new JavaElementVisitor() {
|
||||
@Override
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression methodCall) {
|
||||
super.visitMethodCallExpression(methodCall);
|
||||
|
||||
if (isCallToMethod(methodCall, JAVA_LANG_REFLECT_METHOD, INVOKE)) {
|
||||
checkReflectionCall(methodCall, 1, holder, JavaReflectionInvocationInspection::isReflectionMethod);
|
||||
}
|
||||
else if (isCallToMethod(methodCall, JAVA_LANG_REFLECT_CONSTRUCTOR, NEW_INSTANCE)) {
|
||||
checkReflectionCall(methodCall, 0, holder, JavaReflectionInvocationInspection::isReflectionConstructor);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isReflectionMethod(PsiMethodCallExpression callExpression) {
|
||||
return isCallToMethod(callExpression, JAVA_LANG_CLASS, GET_METHOD) ||
|
||||
isCallToMethod(callExpression, JAVA_LANG_CLASS, GET_DECLARED_METHOD);
|
||||
}
|
||||
|
||||
private static boolean isReflectionConstructor(PsiMethodCallExpression callExpression) {
|
||||
return isCallToMethod(callExpression, JAVA_LANG_CLASS, GET_CONSTRUCTOR) ||
|
||||
isCallToMethod(callExpression, JAVA_LANG_CLASS, GET_DECLARED_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
private static void checkReflectionCall(@NotNull PsiMethodCallExpression methodCall,
|
||||
int argumentOffset,
|
||||
@NotNull ProblemsHolder holder,
|
||||
@NotNull Predicate<PsiMethodCallExpression> methodPredicate) {
|
||||
final List<PsiExpression> requiredTypes =
|
||||
getRequiredMethodArguments(methodCall.getMethodExpression().getQualifierExpression(), argumentOffset, methodPredicate);
|
||||
if (requiredTypes != null) {
|
||||
final Arguments actualArguments = getActualMethodArguments(methodCall, argumentOffset);
|
||||
if (actualArguments != null) {
|
||||
|
||||
final PsiExpressionList argumentList = methodCall.getArgumentList();
|
||||
if (requiredTypes.size() != actualArguments.expressions.length) {
|
||||
if (actualArguments.varargAsArray) {
|
||||
final PsiExpression[] expressions = argumentList.getExpressions();
|
||||
final PsiElement element = expressions.length == argumentOffset + 1 ? expressions[argumentOffset] : argumentList;
|
||||
holder.registerProblem(element, InspectionsBundle.message(
|
||||
"inspection.reflection.invocation.item.count", requiredTypes.size()));
|
||||
}
|
||||
else {
|
||||
holder.registerProblem(argumentList, InspectionsBundle.message(
|
||||
"inspection.reflection.invocation.argument.count", requiredTypes.size() + argumentOffset));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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 PsiType actualType = argument.getType();
|
||||
if (actualType != null && !requiredType.isAssignableFrom(actualType)) {
|
||||
if (PsiTreeUtil.isAncestor(argumentList, argument, false)) {
|
||||
// either varargs or in-place arguments array
|
||||
holder.registerProblem(argument, InspectionsBundle.message(actualArguments.varargAsArray
|
||||
? "inspection.reflection.invocation.item.not.assignable"
|
||||
: "inspection.reflection.invocation.argument.not.assignable",
|
||||
requiredType.getQualifiedName()));
|
||||
}
|
||||
else {
|
||||
// arguments array in a variable
|
||||
final PsiExpression[] expressions = argumentList.getExpressions();
|
||||
final PsiElement element = expressions.length == argumentOffset + 1 ? expressions[argumentOffset] : argumentList;
|
||||
holder.registerProblem(element, InspectionsBundle.message(
|
||||
"inspection.reflection.invocation.item.number.not.assignable", i, requiredType.getQualifiedName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<PsiExpression> getRequiredMethodArguments(@Nullable PsiExpression qualifier,
|
||||
int argumentOffset,
|
||||
@NotNull Predicate<PsiMethodCallExpression> methodPredicate) {
|
||||
final PsiExpression definition = findDefinition(ParenthesesUtils.stripParentheses(qualifier));
|
||||
if (definition instanceof PsiMethodCallExpression) {
|
||||
final PsiMethodCallExpression definitionCall = (PsiMethodCallExpression)definition;
|
||||
if (methodPredicate.test(definitionCall)) {
|
||||
final PsiExpression[] arguments = definitionCall.getArgumentList().getExpressions();
|
||||
|
||||
if (arguments.length == argumentOffset + 1) {
|
||||
final PsiExpression[] arrayElements = getVarargAsArray(arguments[argumentOffset]);
|
||||
if (arrayElements != null) {
|
||||
return Arrays.asList(arrayElements);
|
||||
}
|
||||
}
|
||||
if (arguments.length >= argumentOffset) {
|
||||
return Arrays.asList(arguments).subList(argumentOffset, arguments.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Arguments getActualMethodArguments(PsiMethodCallExpression methodCall, int argumentOffset) {
|
||||
final PsiExpression[] arguments = methodCall.getArgumentList().getExpressions();
|
||||
if (arguments.length == argumentOffset + 1) {
|
||||
final PsiExpression[] expressions = getVarargAsArray(arguments[argumentOffset]);
|
||||
if (expressions != null) {
|
||||
return new Arguments(expressions, true);
|
||||
}
|
||||
}
|
||||
if (arguments.length >= argumentOffset) {
|
||||
final PsiExpression[] expressions = argumentOffset != 0 ? Arrays.copyOfRange(arguments, argumentOffset, arguments.length) : arguments;
|
||||
for (int i = 0; i < expressions.length; i++) {
|
||||
final PsiExpression castOperand = unwrapDisambiguatingCastToObject(expressions[i]);
|
||||
if (castOperand != null) {
|
||||
expressions[i] = castOperand;
|
||||
}
|
||||
}
|
||||
return new Arguments(expressions, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiExpression[] getVarargAsArray(@Nullable PsiExpression maybeArray) {
|
||||
if (maybeArray != null) {
|
||||
final PsiType type = maybeArray.getType();
|
||||
if (type instanceof PsiArrayType &&
|
||||
type.getArrayDimensions() == 1 &&
|
||||
type.getDeepComponentType() instanceof PsiClassType) {
|
||||
|
||||
final PsiExpression argumentsDefinition = findDefinition(maybeArray);
|
||||
if (argumentsDefinition instanceof PsiArrayInitializerExpression) {
|
||||
return ((PsiArrayInitializerExpression)argumentsDefinition).getInitializers();
|
||||
}
|
||||
if (argumentsDefinition instanceof PsiNewExpression) {
|
||||
final PsiArrayInitializerExpression arrayInitializer = ((PsiNewExpression)argumentsDefinition).getArrayInitializer();
|
||||
if (arrayInitializer != null) {
|
||||
return arrayInitializer.getInitializers();
|
||||
}
|
||||
final PsiExpression[] dimensions = ((PsiNewExpression)argumentsDefinition).getArrayDimensions();
|
||||
if (dimensions.length == 1) { // special case: new Object[0]
|
||||
final Integer itemCount = computeConstantExpression(findDefinition(dimensions[0]), Integer.class);
|
||||
if (itemCount != null && itemCount == 0) {
|
||||
return PsiExpression.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiExpression unwrapDisambiguatingCastToObject(@Nullable PsiExpression expression) {
|
||||
if (expression instanceof PsiTypeCastExpression) {
|
||||
final PsiTypeCastExpression typeCast = (PsiTypeCastExpression)expression;
|
||||
final PsiTypeElement castElement = typeCast.getCastType();
|
||||
if (castElement != null && castElement.getType().equalsToText(JAVA_LANG_OBJECT)) {
|
||||
return typeCast.getOperand();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isCallToMethod(PsiMethodCallExpression methodCall, String className, String methodName) {
|
||||
return MethodCallUtils.isCallToMethod(methodCall, className, null, methodName, (PsiType[])null);
|
||||
}
|
||||
|
||||
private static class Arguments {
|
||||
final PsiExpression[] expressions;
|
||||
final boolean varargAsArray;
|
||||
|
||||
public Arguments(PsiExpression[] expressions, boolean varargAsArray) {
|
||||
this.expressions = expressions;
|
||||
this.varargAsArray = varargAsArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
-6
@@ -27,10 +27,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
@@ -80,6 +77,8 @@ public class JavaReflectionReferenceUtil {
|
||||
public static final String GET_DECLARED_FIELD = "getDeclaredField";
|
||||
public static final String GET_METHOD = "getMethod";
|
||||
public static final String GET_DECLARED_METHOD = "getDeclaredMethod";
|
||||
public static final String GET_CONSTRUCTOR = "getConstructor";
|
||||
public static final String GET_DECLARED_CONSTRUCTOR = "getDeclaredConstructor";
|
||||
|
||||
public static final String JAVA_LANG_CLASS_LOADER = "java.lang.ClassLoader";
|
||||
public static final String FOR_NAME = "forName";
|
||||
@@ -176,8 +175,10 @@ public class JavaReflectionReferenceUtil {
|
||||
|
||||
@Nullable
|
||||
public static PsiExpression findDefinition(@Nullable PsiExpression expression) {
|
||||
if (expression instanceof PsiReferenceExpression) {
|
||||
return findVariableDefinition((PsiReferenceExpression)expression);
|
||||
int preventEndlessLoop = 5;
|
||||
while (expression instanceof PsiReferenceExpression) {
|
||||
if (--preventEndlessLoop == 0) return null;
|
||||
expression = findVariableDefinition((PsiReferenceExpression)expression);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
@@ -369,6 +370,21 @@ public class JavaReflectionReferenceUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAssignableFrom(@NotNull PsiType type) {
|
||||
if (type.equals(PsiType.NULL)) {
|
||||
return myPsiClass != null || myArrayDimensions != 0;
|
||||
}
|
||||
if (type.getArrayDimensions() != myArrayDimensions) {
|
||||
return false;
|
||||
}
|
||||
final PsiType otherType = type.getDeepComponentType();
|
||||
if (myPrimitiveType != null) {
|
||||
return myPrimitiveType.isAssignableFrom(otherType) || otherType.equalsToText(myPrimitiveType.getBoxedTypeName());
|
||||
}
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(myPsiClass.getProject()).getElementFactory();
|
||||
return factory.createType(myPsiClass).isAssignableFrom(otherType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ReflectiveType create(@Nullable PsiType originalType, @NotNull PsiElement context) {
|
||||
if (originalType == null) {
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
class ConstructorParamCount {
|
||||
void varargSignature() throws Exception {
|
||||
Class<?> cls = Test.class;
|
||||
|
||||
Constructor c1 = cls.getConstructor(int.class);
|
||||
Constructor c2 = cls.getConstructor(int.class, String.class);
|
||||
Constructor c3 = cls.getConstructor(int.class, String.class, String.class);
|
||||
|
||||
c1.newInstance<warning descr="One argument is expected">(42, "abc")</warning>;
|
||||
c2.newInstance(42, "abc");
|
||||
c3.newInstance<warning descr="3 arguments are expected">(42, "abc")</warning>;
|
||||
|
||||
c1.newInstance(<warning descr="Single-item array is expected">new Object[]{42, "abc"}</warning>);
|
||||
c2.newInstance(new Object[]{42, "abc"});
|
||||
c3.newInstance(<warning descr="3 array items are expected">new Object[]{42, "abc"}</warning>);
|
||||
|
||||
c1.newInstance<warning descr="One argument is expected">()</warning>;
|
||||
c2.newInstance<warning descr="2 arguments are expected">()</warning>;
|
||||
c3.newInstance<warning descr="3 arguments are expected">()</warning>;
|
||||
|
||||
cls.getConstructor(String.class).newInstance(new String[] {"abc"});
|
||||
}
|
||||
|
||||
void arraySignatutre() throws Exception {
|
||||
Class<?> cls = Test.class;
|
||||
|
||||
Constructor c1 = cls.getConstructor(new Class[]{int.class});
|
||||
Constructor c2 = cls.getConstructor(new Class[]{int.class, String.class});
|
||||
Constructor c3 = cls.getConstructor(new Class[]{int.class, String.class, String.class});
|
||||
|
||||
c1.newInstance<warning descr="One argument is expected">(42, "abc")</warning>;
|
||||
c2.newInstance(42, "abc");
|
||||
c3.newInstance<warning descr="3 arguments are expected">(42, "abc")</warning>;
|
||||
|
||||
c1.newInstance(<warning descr="Single-item array is expected">new Object[]{42, "abc"}</warning>);
|
||||
c2.newInstance(new Object[]{42, "abc"});
|
||||
c3.newInstance(<warning descr="3 array items are expected">new Object[]{42, "abc"}</warning>);
|
||||
|
||||
c1.newInstance<warning descr="One argument is expected">()</warning>;
|
||||
c2.newInstance<warning descr="2 arguments are expected">()</warning>;
|
||||
c3.newInstance<warning descr="3 arguments are expected">()</warning>;
|
||||
|
||||
cls.getConstructor(new Class[]{String.class}).newInstance(new String[] {"abc"});
|
||||
}
|
||||
|
||||
void manyArguments() throws Exception {
|
||||
Class<?> cls = M.class;
|
||||
|
||||
Constructor m0 = cls.getConstructor();
|
||||
Constructor m1 = cls.getConstructor(int.class);
|
||||
Constructor m2 = cls.getConstructor(int.class, short.class);
|
||||
Constructor m3 = cls.getConstructor(int.class, short.class, long.class);
|
||||
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<warning descr="No arguments are expected">(0, 0)</warning>;
|
||||
m1.newInstance(<warning descr="Argument is not assignable to 'int'">"abc"</warning>);
|
||||
m2.newInstance(0, <warning descr="Argument is not assignable to 'short'">"abc"</warning>);
|
||||
m3.newInstance(0, <warning descr="Argument is not assignable to 'short'">0</warning>, <warning descr="Argument is not assignable to 'long'">"abc"</warning>);
|
||||
m4.newInstance(0, <warning descr="Argument is not assignable to 'short'">0</warning>, 0, <warning descr="Argument is not assignable to 'float'">"abc"</warning>);
|
||||
m5.newInstance(0, <warning descr="Argument is not assignable to 'short'">0</warning>, 0, 0, <warning descr="Argument is not assignable to 'double'">"abc"</warning>);
|
||||
|
||||
Constructor m = cls.getConstructor(new Class[0]);
|
||||
m.newInstance(new Object[0]);
|
||||
m.newInstance(<warning descr="Empty array is expected">new Object[] {"abc"}</warning>);
|
||||
}
|
||||
|
||||
class Test {
|
||||
public Test(int n) {}
|
||||
public Test(int n, String s) {}
|
||||
public Test(int n, String s, String t) {}
|
||||
|
||||
public Test(String s) {}
|
||||
}
|
||||
|
||||
class M{
|
||||
public M() {}
|
||||
public M(int a1) {}
|
||||
public M(int a1, short a2) {}
|
||||
public M(int a1, short a2, long a3) {}
|
||||
public M(int a1, short a2, long a3, float a4) {}
|
||||
public M(int a1, short a2, long a3, float a4, double a5) {}
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.*;
|
||||
|
||||
class ConstructorParamTypes {
|
||||
void varargSignature() throws Exception {
|
||||
Class<?> cls = Test.class;
|
||||
|
||||
Constructor c1 = cls.getConstructor(int.class, String.class);
|
||||
Constructor c2 = cls.getConstructor(String.class, Integer.class);
|
||||
Constructor c3 = cls.getConstructor(int[].class, List.class);
|
||||
|
||||
c1.newInstance(42, "abc");
|
||||
c2.newInstance("abc", 42);
|
||||
c3.newInstance(new int[]{42, 23}, Arrays.asList("x", "y"));
|
||||
|
||||
c1.newInstance(<warning descr="Argument is not assignable to 'int'">"42"</warning>, "abc");
|
||||
c1.newInstance(<warning descr="Argument is not assignable to 'int'">42.5</warning>, "abc");
|
||||
c2.newInstance(<warning descr="Argument is not assignable to 'java.lang.String'">42</warning>, 23);
|
||||
c2.newInstance("abc", <warning descr="Argument is not assignable to 'java.lang.Integer'">"def"</warning>);
|
||||
c3.newInstance(<warning descr="Argument is not assignable to 'int[]'">Arrays.asList("x", "y")</warning>, <warning descr="Argument is not assignable to 'java.util.List'">new int[]{42, 23}</warning>);
|
||||
c3.newInstance(<warning descr="Argument is not assignable to 'int[]'">42</warning>, <warning descr="Argument is not assignable to 'java.util.List'">"def"</warning>);
|
||||
|
||||
|
||||
final Object[] a1 = {new Integer(42), "abc"};
|
||||
final Object[] a2 = {"abc", Integer.valueOf(42)};
|
||||
final Object[] a3 = {new int[]{42, 23}, Arrays.asList("x", "y")};
|
||||
c1.newInstance(a1);
|
||||
c2.newInstance(a2);
|
||||
c3.newInstance(a3);
|
||||
|
||||
c1.newInstance(new Object[] {new Integer(42), "abc"});
|
||||
c2.newInstance(new Object[] {"abc", Integer.valueOf(42)});
|
||||
c3.newInstance(new Object[] {new int[]{42, 23}, Arrays.asList("x", "y")});
|
||||
|
||||
c1.newInstance(<warning descr="Array item 0 is not assignable to 'int'"><warning descr="Array item 1 is not assignable to 'java.lang.String'">a2</warning></warning>);
|
||||
c2.newInstance(<warning descr="Array item 0 is not assignable to 'java.lang.String'"><warning descr="Array item 1 is not assignable to 'java.lang.Integer'">a3</warning></warning>);
|
||||
c3.newInstance(<warning descr="Array item 0 is not assignable to 'int[]'"><warning descr="Array item 1 is not assignable to 'java.util.List'">a1</warning></warning>);
|
||||
|
||||
c1.newInstance(new Object[]{<warning descr="Array item is not assignable to 'int'">"42"</warning>, "abc"});
|
||||
c2.newInstance(new Object[]{<warning descr="Array item is not assignable to 'java.lang.String'">42</warning>, 23});
|
||||
c3.newInstance(new Object[]{<warning descr="Array item is not assignable to 'int[]'">"x"</warning>, <warning descr="Array item is not assignable to 'java.util.List'">"y"</warning>});
|
||||
|
||||
c1.newInstance(<warning descr="Argument is not assignable to 'int'">null</warning>, null);
|
||||
c2.newInstance(null, null);
|
||||
c3.newInstance(null, null);
|
||||
|
||||
cls.getConstructor(String[].class).newInstance((Object)new String[] {"abc"});
|
||||
cls.getConstructor(String[].class).newInstance(new String[] {<warning descr="Array item is not assignable to 'java.lang.String[]'">"abc"</warning>});
|
||||
}
|
||||
|
||||
void arraySignatutre() throws Exception {
|
||||
Class<?> cls = Test.class;
|
||||
|
||||
Constructor c1 = cls.getConstructor(new Class[]{int.class, String.class});
|
||||
Constructor c2 = cls.getConstructor(new Class[]{String.class, Integer.class});
|
||||
Constructor c3 = cls.getConstructor(new Class[]{int[].class, List.class});
|
||||
|
||||
c1.newInstance(<warning descr="Argument is not assignable to 'int'">"42"</warning>, "abc");
|
||||
c1.newInstance(<warning descr="Argument is not assignable to 'int'">42.5</warning>, "abc");
|
||||
c2.newInstance(<warning descr="Argument is not assignable to 'java.lang.String'">42</warning>, 23);
|
||||
c2.newInstance("abc", <warning descr="Argument is not assignable to 'java.lang.Integer'">"def"</warning>);
|
||||
c3.newInstance(<warning descr="Argument is not assignable to 'int[]'">Arrays.asList("x", "y")</warning>, <warning descr="Argument is not assignable to 'java.util.List'">new int[]{42, 23}</warning>);
|
||||
c3.newInstance(<warning descr="Argument is not assignable to 'int[]'">42</warning>, <warning descr="Argument is not assignable to 'java.util.List'">"def"</warning>);
|
||||
|
||||
final Object[] a1 = {new Integer(42), "abc"};
|
||||
final Object[] a2 = {"abc", Integer.valueOf(42)};
|
||||
final Object[] a3 = {new int[]{42, 23}, Arrays.asList("x", "y")};
|
||||
c1.newInstance(a1);
|
||||
c2.newInstance(a2);
|
||||
c3.newInstance(a3);
|
||||
|
||||
c1.newInstance(new Object[] {new Integer(42), "abc"});
|
||||
c2.newInstance(new Object[] {"abc", Integer.valueOf(42)});
|
||||
c3.newInstance(new Object[] {new int[]{42, 23}, Arrays.asList("x", "y")});
|
||||
|
||||
c1.newInstance(<warning descr="Array item 0 is not assignable to 'int'"><warning descr="Array item 1 is not assignable to 'java.lang.String'">a2</warning></warning>);
|
||||
c2.newInstance(<warning descr="Array item 0 is not assignable to 'java.lang.String'"><warning descr="Array item 1 is not assignable to 'java.lang.Integer'">a3</warning></warning>);
|
||||
c3.newInstance(<warning descr="Array item 0 is not assignable to 'int[]'"><warning descr="Array item 1 is not assignable to 'java.util.List'">a1</warning></warning>);
|
||||
|
||||
c1.newInstance(new Object[]{<warning descr="Array item is not assignable to 'int'">"42"</warning>, "abc"});
|
||||
c2.newInstance(new Object[]{<warning descr="Array item is not assignable to 'java.lang.String'">42</warning>, 23});
|
||||
c3.newInstance(new Object[]{<warning descr="Array item is not assignable to 'int[]'">"x"</warning>, <warning descr="Array item is not assignable to 'java.util.List'">"y"</warning>});
|
||||
|
||||
c1.newInstance(<warning descr="Argument is not assignable to 'int'">null</warning>, null);
|
||||
c2.newInstance(null, null);
|
||||
c3.newInstance(null, null);
|
||||
|
||||
cls.getConstructor(new Class[]{String[].class}).newInstance((Object)new String[] {"abc"});
|
||||
cls.getConstructor(new Class[]{String[].class}).newInstance(new String[] {<warning descr="Array item is not assignable to 'java.lang.String[]'">"abc"</warning>});
|
||||
}
|
||||
|
||||
void manyArguments() throws Exception {
|
||||
Class<?> cls = M.class;
|
||||
|
||||
Constructor m0 = cls.getConstructor();
|
||||
Constructor m1 = cls.getConstructor(int.class);
|
||||
Constructor m2 = cls.getConstructor(int.class, short.class);
|
||||
Constructor m3 = cls.getConstructor(int.class, short.class, long.class);
|
||||
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);
|
||||
|
||||
Object[] a0 = {};
|
||||
Object[] a1 = {"abc"};
|
||||
Object[] a2 = {0, "abc"};
|
||||
Object[] a3 = {0, (short)0, "abc"};
|
||||
Object[] a4 = {0, (short)0, 0, "abc"};
|
||||
Object[] a5 = {0, (short)0, 0, 0.0f, "abc"};
|
||||
|
||||
m0.newInstance(a0);
|
||||
m1.newInstance(<warning descr="Array item 0 is not assignable to 'int'">a1</warning>);
|
||||
m2.newInstance(<warning descr="Array item 1 is not assignable to 'short'">a2</warning>);
|
||||
m3.newInstance(<warning descr="Array item 2 is not assignable to 'long'">a3</warning>);
|
||||
m4.newInstance(<warning descr="Array item 3 is not assignable to 'float'">a4</warning>);
|
||||
m5.newInstance(<warning descr="Array item 4 is not assignable to 'double'">a5</warning>);
|
||||
}
|
||||
|
||||
class Test {
|
||||
public Test(int n, String s) {}
|
||||
public Test(String s, Integer n) {}
|
||||
public Test(int[] n, List<String> s) {}
|
||||
public Test(String[] s) {}
|
||||
}
|
||||
|
||||
class M {
|
||||
public String m1(int a1) {return "";}
|
||||
public String m2(int a1, short a2) {return "";}
|
||||
public String m3(int a1, short a2, long a3) {return "";}
|
||||
public String m4(int a1, short a2, long a3, float a4) {return "";}
|
||||
public String m5(int a1, short a2, long a3, float a4, double a5) {return "";}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
class MethodParamCount {
|
||||
void varargSignature() throws Exception {
|
||||
Class<?> cls = Test.class;
|
||||
Object obj = new Test();
|
||||
|
||||
Method m1 = cls.getMethod("bar", int.class);
|
||||
Method m2 = cls.getMethod("bar", int.class, String.class);
|
||||
Method m3 = cls.getMethod("bar", int.class, String.class, String.class);
|
||||
|
||||
m1.invoke<warning descr="2 arguments are expected">(obj, 42, "abc")</warning>;
|
||||
m2.invoke(obj, 42, "abc");
|
||||
m3.invoke<warning descr="4 arguments are expected">(obj, 42, "abc")</warning>;
|
||||
|
||||
m1.invoke(obj, <warning descr="Single-item array is expected">new Object[]{42, "abc"}</warning>);
|
||||
m2.invoke(obj, new Object[]{42, "abc"});
|
||||
m3.invoke(obj, <warning descr="3 array items are expected">new Object[]{42, "abc"}</warning>);
|
||||
|
||||
m1.invoke<warning descr="2 arguments are expected">(obj)</warning>;
|
||||
m2.invoke<warning descr="3 arguments are expected">(obj)</warning>;
|
||||
m3.invoke<warning descr="4 arguments are expected">(obj)</warning>;
|
||||
|
||||
cls.getMethod("str", String.class).invoke(null, new String[] {"abc"});
|
||||
}
|
||||
|
||||
void arraySignatutre() throws Exception {
|
||||
Class<?> cls = Test.class;
|
||||
Object obj = new Test();
|
||||
|
||||
Method m1 = cls.getMethod("bar", new Class[]{int.class});
|
||||
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<warning descr="2 arguments are expected">(obj, 42, "abc")</warning>;
|
||||
m2.invoke(obj, 42, "abc");
|
||||
m3.invoke<warning descr="4 arguments are expected">(obj, 42, "abc")</warning>;
|
||||
|
||||
m1.invoke(obj, <warning descr="Single-item array is expected">new Object[]{42, "abc"}</warning>);
|
||||
m2.invoke(obj, new Object[]{42, "abc"});
|
||||
m3.invoke(obj, <warning descr="3 array items are expected">new Object[]{42, "abc"}</warning>);
|
||||
|
||||
m1.invoke<warning descr="2 arguments are expected">(obj)</warning>;
|
||||
m2.invoke<warning descr="3 arguments are expected">(obj)</warning>;
|
||||
m3.invoke<warning descr="4 arguments are expected">(obj)</warning>;
|
||||
|
||||
cls.getMethod("str", new Class[]{String.class}).invoke(null, new String[] {"abc"});
|
||||
}
|
||||
|
||||
void manyArguments() throws Exception {
|
||||
Class<?> cls = M.class;
|
||||
Object obj = new M();
|
||||
|
||||
Method m0 = cls.getMethod("m0");
|
||||
Method m1 = cls.getMethod("m1", int.class);
|
||||
Method m2 = cls.getMethod("m2", int.class, short.class);
|
||||
Method m3 = cls.getMethod("m3", int.class, short.class, long.class);
|
||||
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<warning descr="One argument is expected">(0, 0)</warning>;
|
||||
m1.invoke<warning descr="2 arguments are expected">("abc")</warning>;
|
||||
m2.invoke<warning descr="3 arguments are expected">(0, "abc")</warning>;
|
||||
m3.invoke<warning descr="4 arguments are expected">(0, 0, "abc")</warning>;
|
||||
m4.invoke<warning descr="5 arguments are expected">(0, 0, 0, "abc")</warning>;
|
||||
m5.invoke<warning descr="6 arguments are expected">(0, 0, 0, 0, "abc")</warning>;
|
||||
|
||||
Method m = cls.getMethod("m0", new Class[0]);
|
||||
m.invoke(obj, new Object[0]);
|
||||
m.invoke(obj, <warning descr="Empty array is expected">new Object[] {"abc"}</warning>);
|
||||
}
|
||||
|
||||
static class Test {
|
||||
public void bar(int n) {}
|
||||
public void bar(int n, String s) {}
|
||||
public void bar(int n, String s, String t) {}
|
||||
|
||||
public static void str(String s) {}
|
||||
}
|
||||
|
||||
class M {
|
||||
public String m0() {return "";}
|
||||
public String m1(int a1) {return "";}
|
||||
public String m2(int a1, short a2) {return "";}
|
||||
public String m3(int a1, short a2, long a3) {return "";}
|
||||
public String m4(int a1, short a2, long a3, float a4) {return "";}
|
||||
public String m5(int a1, short a2, long a3, float a4, double a5) {return "";}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
class MethodParamTypes {
|
||||
void varargSignature() throws Exception {
|
||||
Class<?> cls = Test.class;
|
||||
Object obj = new Test();
|
||||
|
||||
Method m1 = cls.getMethod("bar", int.class, String.class);
|
||||
Method m2 = cls.getMethod("bar", String.class, Integer.class);
|
||||
Method m3 = cls.getMethod("bar", int[].class, List.class);
|
||||
|
||||
m1.invoke(obj, 42, "abc");
|
||||
m2.invoke(obj, "abc", 42);
|
||||
m3.invoke(obj, new int[]{42, 23}, Arrays.asList("x", "y"));
|
||||
|
||||
m1.invoke(obj, <warning descr="Argument is not assignable to 'int'">"42"</warning>, "abc");
|
||||
m1.invoke(obj, <warning descr="Argument is not assignable to 'int'">42.5</warning>, "abc");
|
||||
m2.invoke(obj, <warning descr="Argument is not assignable to 'java.lang.String'">42</warning>, 23);
|
||||
m2.invoke(obj, "abc", <warning descr="Argument is not assignable to 'java.lang.Integer'">"def"</warning>);
|
||||
m3.invoke(obj, <warning descr="Argument is not assignable to 'int[]'">Arrays.asList("x", "y")</warning>, <warning descr="Argument is not assignable to 'java.util.List'">new int[]{42, 23}</warning>);
|
||||
m3.invoke(obj, <warning descr="Argument is not assignable to 'int[]'">42</warning>, <warning descr="Argument is not assignable to 'java.util.List'">"def"</warning>);
|
||||
|
||||
|
||||
final Object[] a1 = {new Integer(42), "abc"};
|
||||
final Object[] a2 = {"abc", Integer.valueOf(42)};
|
||||
final Object[] a3 = {new int[]{42, 23}, Arrays.asList("x", "y")};
|
||||
m1.invoke(obj, a1);
|
||||
m2.invoke(obj, a2);
|
||||
m3.invoke(obj, a3);
|
||||
|
||||
m1.invoke(obj, new Object[] {new Integer(42), "abc"});
|
||||
m2.invoke(obj, new Object[] {"abc", Integer.valueOf(42)});
|
||||
m3.invoke(obj, new Object[] {new int[]{42, 23}, Arrays.asList("x", "y")});
|
||||
|
||||
m1.invoke(obj, <warning descr="Array item 0 is not assignable to 'int'"><warning descr="Array item 1 is not assignable to 'java.lang.String'">a2</warning></warning>);
|
||||
m2.invoke(obj, <warning descr="Array item 0 is not assignable to 'java.lang.String'"><warning descr="Array item 1 is not assignable to 'java.lang.Integer'">a3</warning></warning>);
|
||||
m3.invoke(obj, <warning descr="Array item 0 is not assignable to 'int[]'"><warning descr="Array item 1 is not assignable to 'java.util.List'">a1</warning></warning>);
|
||||
|
||||
m1.invoke(obj, new Object[]{<warning descr="Array item is not assignable to 'int'">"42"</warning>, "abc"});
|
||||
m2.invoke(obj, new Object[]{<warning descr="Array item is not assignable to 'java.lang.String'">42</warning>, 23});
|
||||
m3.invoke(obj, new Object[]{<warning descr="Array item is not assignable to 'int[]'">"x"</warning>, <warning descr="Array item is not assignable to 'java.util.List'">"y"</warning>});
|
||||
|
||||
m1.invoke(obj, <warning descr="Argument is not assignable to 'int'">null</warning>, null);
|
||||
m2.invoke(obj, null, null);
|
||||
m3.invoke(obj, null, null);
|
||||
|
||||
cls.getMethod("str", String[].class).invoke(null, (Object)new String[] {"abc"});
|
||||
cls.getMethod("str", String[].class).invoke(null, new String[] {<warning descr="Array item is not assignable to 'java.lang.String[]'">"abc"</warning>});
|
||||
}
|
||||
|
||||
void arraySignatutre() throws Exception {
|
||||
Class<?> cls = Test.class;
|
||||
Object obj = new Test();
|
||||
|
||||
Method m1 = cls.getMethod("bar", new Class[]{int.class, String.class});
|
||||
Method m2 = cls.getMethod("bar", new Class[]{String.class, Integer.class});
|
||||
Method m3 = cls.getMethod("bar", new Class[]{int[].class, List.class});
|
||||
|
||||
m1.invoke(obj, <warning descr="Argument is not assignable to 'int'">"42"</warning>, "abc");
|
||||
m1.invoke(obj, <warning descr="Argument is not assignable to 'int'">42.5</warning>, "abc");
|
||||
m2.invoke(obj, <warning descr="Argument is not assignable to 'java.lang.String'">42</warning>, 23);
|
||||
m2.invoke(obj, "abc", <warning descr="Argument is not assignable to 'java.lang.Integer'">"def"</warning>);
|
||||
m3.invoke(obj, <warning descr="Argument is not assignable to 'int[]'">Arrays.asList("x", "y")</warning>, <warning descr="Argument is not assignable to 'java.util.List'">new int[]{42, 23}</warning>);
|
||||
m3.invoke(obj, <warning descr="Argument is not assignable to 'int[]'">42</warning>, <warning descr="Argument is not assignable to 'java.util.List'">"def"</warning>);
|
||||
|
||||
final Object[] a1 = {new Integer(42), "abc"};
|
||||
final Object[] a2 = {"abc", Integer.valueOf(42)};
|
||||
final Object[] a3 = {new int[]{42, 23}, Arrays.asList("x", "y")};
|
||||
m1.invoke(obj, a1);
|
||||
m2.invoke(obj, a2);
|
||||
m3.invoke(obj, a3);
|
||||
|
||||
m1.invoke(obj, new Object[] {new Integer(42), "abc"});
|
||||
m2.invoke(obj, new Object[] {"abc", Integer.valueOf(42)});
|
||||
m3.invoke(obj, new Object[] {new int[]{42, 23}, Arrays.asList("x", "y")});
|
||||
|
||||
m1.invoke(obj, <warning descr="Array item 0 is not assignable to 'int'"><warning descr="Array item 1 is not assignable to 'java.lang.String'">a2</warning></warning>);
|
||||
m2.invoke(obj, <warning descr="Array item 0 is not assignable to 'java.lang.String'"><warning descr="Array item 1 is not assignable to 'java.lang.Integer'">a3</warning></warning>);
|
||||
m3.invoke(obj, <warning descr="Array item 0 is not assignable to 'int[]'"><warning descr="Array item 1 is not assignable to 'java.util.List'">a1</warning></warning>);
|
||||
|
||||
m1.invoke(obj, new Object[]{<warning descr="Array item is not assignable to 'int'">"42"</warning>, "abc"});
|
||||
m2.invoke(obj, new Object[]{<warning descr="Array item is not assignable to 'java.lang.String'">42</warning>, 23});
|
||||
m3.invoke(obj, new Object[]{<warning descr="Array item is not assignable to 'int[]'">"x"</warning>, <warning descr="Array item is not assignable to 'java.util.List'">"y"</warning>});
|
||||
|
||||
m1.invoke(obj, <warning descr="Argument is not assignable to 'int'">null</warning>, null);
|
||||
m2.invoke(obj, null, null);
|
||||
m3.invoke(obj, null, null);
|
||||
|
||||
cls.getMethod("str", new Class[]{String[].class}).invoke(null, (Object)new String[] {"abc"});
|
||||
cls.getMethod("str", new Class[]{String[].class}).invoke(null, new String[] {<warning descr="Array item is not assignable to 'java.lang.String[]'">"abc"</warning>});
|
||||
}
|
||||
|
||||
void manyArguments() throws Exception {
|
||||
Class<?> cls = M.class;
|
||||
Object obj = new M();
|
||||
|
||||
Method m0 = cls.getMethod("m0");
|
||||
Method m1 = cls.getMethod("m1", int.class);
|
||||
Method m2 = cls.getMethod("m2", int.class, short.class);
|
||||
Method m3 = cls.getMethod("m3", int.class, short.class, long.class);
|
||||
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);
|
||||
|
||||
Object[] a0 = {};
|
||||
Object[] a1 = {"abc"};
|
||||
Object[] a2 = {0, "abc"};
|
||||
Object[] a3 = {0, (short)0, "abc"};
|
||||
Object[] a4 = {0, (short)0, 0, "abc"};
|
||||
Object[] a5 = {0, (short)0, 0, 0.0f, "abc"};
|
||||
|
||||
m0.invoke(obj, a0);
|
||||
m1.invoke(obj, <warning descr="Array item 0 is not assignable to 'int'">a1</warning>);
|
||||
m2.invoke(obj, <warning descr="Array item 1 is not assignable to 'short'">a2</warning>);
|
||||
m3.invoke(obj, <warning descr="Array item 2 is not assignable to 'long'">a3</warning>);
|
||||
m4.invoke(obj, <warning descr="Array item 3 is not assignable to 'float'">a4</warning>);
|
||||
m5.invoke(obj, <warning descr="Array item 4 is not assignable to 'double'">a5</warning>);
|
||||
}
|
||||
|
||||
static class Test {
|
||||
public void bar(int n, String s) {}
|
||||
public void bar(String s, Integer n) {}
|
||||
public void bar(int[] n, List<String> s) {}
|
||||
|
||||
public static void str(String[] s) {}
|
||||
}
|
||||
|
||||
class M {
|
||||
public String m1(int a1) {return "";}
|
||||
public String m2(int a1, short a2) {return "";}
|
||||
public String m3(int a1, short a2, long a3) {return "";}
|
||||
public String m4(int a1, short a2, long a3, float a4) {return "";}
|
||||
public String m5(int a1, short a2, long a3, float a4, double a5) {return "";}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInspection
|
||||
|
||||
import com.intellij.JavaTestUtil
|
||||
import com.intellij.codeInspection.reflectiveAccess.JavaReflectionInvocationInspection
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
|
||||
/**
|
||||
* @author Pavel.Dolgov
|
||||
*/
|
||||
class JavaReflectionInvocationTest : LightCodeInsightFixtureTestCase() {
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
LanguageLevelProjectExtension.getInstance(project).languageLevel = LanguageLevel.JDK_1_5
|
||||
myFixture.enableInspections(JavaReflectionInvocationInspection())
|
||||
}
|
||||
|
||||
override fun getProjectDescriptor(): LightProjectDescriptor = LightCodeInsightFixtureTestCase.JAVA_8
|
||||
|
||||
override fun getBasePath() = JavaTestUtil.getRelativeJavaTestDataPath() + "/inspection/javaReflectionInvocation"
|
||||
|
||||
fun testMethodParamCount() = doTest()
|
||||
fun testMethodParamTypes() = doTest()
|
||||
|
||||
fun testConstructorParamCount() = doTest()
|
||||
fun testConstructorParamTypes() = doTest()
|
||||
|
||||
private fun doTest() {
|
||||
myFixture.testHighlighting("${getTestName(false)}.java")
|
||||
}
|
||||
}
|
||||
@@ -812,4 +812,11 @@ inspection.handle.signature.replace.with.fix.name=Replace with ''{0}''
|
||||
inspection.handle.signature.use.method.fix.family.name=Use one of method overloads
|
||||
inspection.handle.signature.use.method.fix.name=Use method ''{0}''
|
||||
inspection.handle.signature.use.constructor.fix.family.name=Use one of constructor overloads
|
||||
inspection.handle.signature.use.constructor.fix.name=Use constructor ''{0}''
|
||||
inspection.handle.signature.use.constructor.fix.name=Use constructor ''{0}''
|
||||
|
||||
inspection.reflection.invocation.name=Reflective invocation arguments mismatch
|
||||
inspection.reflection.invocation.argument.count={0,choice,0#No arguments are|1#One argument is|1<{0} arguments are} expected
|
||||
inspection.reflection.invocation.item.count={0,choice,0#Empty array is|1#Single-item array is|1<{0} array items are} expected
|
||||
inspection.reflection.invocation.argument.not.assignable=Argument is not assignable to ''{0}''
|
||||
inspection.reflection.invocation.item.not.assignable=Array item is not assignable to ''{0}''
|
||||
inspection.reflection.invocation.item.number.not.assignable=Array item {0} is not assignable to ''{1}''
|
||||
@@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<body>
|
||||
The inspection checks that the arguments provided to Method.invoke() and Constructor.newInstance()
|
||||
match the signature specified in Class.getMethod() and Class.getConstructor()
|
||||
<!-- tooltip end -->
|
||||
<p>Example:</p>
|
||||
<pre><code>
|
||||
Method m = myObj.getClass().getMethod("myMethod", <b>int</b>.class);
|
||||
<i>// the argument should be an <b>int</b> value</i>
|
||||
m.invoke(myObj, "<b>abc</b>");
|
||||
</code></pre>
|
||||
|
||||
<p><small>New in 2017.2</small></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -922,6 +922,10 @@
|
||||
groupPath="Java" groupBundle="messages.InspectionsBundle" groupKey="group.names.reflective.access.issues"
|
||||
bundle="messages.InspectionsBundle" key="inspection.handle.signature.name"
|
||||
implementationClass="com.intellij.codeInspection.reflectiveAccess.JavaLangInvokeHandleSignatureInspection"/>
|
||||
<localInspection language="JAVA" shortName="JavaReflectionInvocation" enabledByDefault="true" level="WARNING"
|
||||
groupPath="Java" groupBundle="messages.InspectionsBundle" groupKey="group.names.reflective.access.issues"
|
||||
bundle="messages.InspectionsBundle" key="inspection.reflection.invocation.name"
|
||||
implementationClass="com.intellij.codeInspection.reflectiveAccess.JavaReflectionInvocationInspection"/>
|
||||
<localInspection language="JAVA" shortName="MoveFieldAssignmentToInitializer" enabledByDefault="true" level="INFORMATION"
|
||||
groupPath="Java" groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues"
|
||||
displayName="Move field assignment to initializer"
|
||||
|
||||
Reference in New Issue
Block a user