IDEA-187209 JavaReflectionMemberAccess: false-positive when array is initialized after creation

GitOrigin-RevId: c58c4d78086cc56f80112d1a2f5d6823ac62538c
This commit is contained in:
Tagir Valeev
2019-05-23 08:08:04 +03:00
committed by intellij-monorepo-bot
parent c97c3387d7
commit df27149ec6
5 changed files with 31 additions and 13 deletions
@@ -126,9 +126,9 @@ public class JavaReflectionInvocationInspection extends AbstractBaseJavaLocalIns
@Nullable
static Arguments getActualMethodArguments(PsiExpression[] arguments, int argumentOffset, boolean allowVarargAsArray) {
if (allowVarargAsArray && arguments.length == argumentOffset + 1) {
final PsiExpression[] expressions = getVarargAsArray(arguments[argumentOffset]);
final List<PsiExpression> expressions = getVarargs(arguments[argumentOffset]);
if (expressions != null) {
return new Arguments(expressions, true);
return new Arguments(expressions.toArray(PsiExpression.EMPTY_ARRAY), true);
}
}
if (arguments.length >= argumentOffset) {
@@ -229,9 +229,9 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
final PsiExpression[] arguments = definitionCall.getArgumentList().getExpressions();
if (arguments.length == argumentOffset + 1) {
final PsiExpression[] arrayElements = getVarargAsArray(arguments[argumentOffset]);
final List<PsiExpression> arrayElements = getVarargs(arguments[argumentOffset]);
if (arrayElements != null) {
return Arrays.asList(arrayElements);
return arrayElements;
}
}
if (arguments.length >= argumentOffset) {
@@ -468,26 +468,32 @@ public class JavaReflectionReferenceUtil {
return MethodCallUtils.isCallToMethod(methodCall, className, null, methodName, (PsiType[])null);
}
/**
* Tries to unwrap array and find its components
* @param maybeArray an array to unwrap
* @return list of unwrapped array components, some or all of them could be null if unknown (but the length is known);
* returns null if nothing is known.
*/
@Nullable
public static PsiExpression[] getVarargAsArray(@Nullable PsiExpression maybeArray) {
public static List<PsiExpression> getVarargs(@Nullable PsiExpression maybeArray) {
if (ExpressionUtils.isNullLiteral(maybeArray)) {
return PsiExpression.EMPTY_ARRAY;
return Collections.emptyList();
}
if (isVarargAsArray(maybeArray)) {
final PsiExpression argumentsDefinition = findDefinition(maybeArray);
if (argumentsDefinition instanceof PsiArrayInitializerExpression) {
return ((PsiArrayInitializerExpression)argumentsDefinition).getInitializers();
return Arrays.asList(((PsiArrayInitializerExpression)argumentsDefinition).getInitializers());
}
if (argumentsDefinition instanceof PsiNewExpression) {
final PsiArrayInitializerExpression arrayInitializer = ((PsiNewExpression)argumentsDefinition).getArrayInitializer();
if (arrayInitializer != null) {
return arrayInitializer.getInitializers();
return Arrays.asList(arrayInitializer.getInitializers());
}
final PsiExpression[] dimensions = ((PsiNewExpression)argumentsDefinition).getArrayDimensions();
if (dimensions.length == 1) { // special case: new Object[0]
if (dimensions.length == 1) { // new Object[length] or new Class<?>[length]
final Integer itemCount = computeConstantExpression(findDefinition(dimensions[0]), Integer.class);
if (itemCount != null && itemCount == 0) {
return PsiExpression.EMPTY_ARRAY;
if (itemCount != null && itemCount >= 0 && itemCount < 256) {
return Collections.nCopies(itemCount, null);
}
}
}
@@ -0,0 +1,12 @@
class X {
void test() throws NoSuchMethodException {
Class<?>[] params = new Class<?>[3];
params[0] = byte[].class;
params[1] = int.class;
params[2] = int.class;
String.class.getDeclaredMethod("checkBounds", params);
Class[] params2 = {byte[].class, int.class, int.class};
String.class.getDeclaredMethod("checkBounds", params2);
String.class.getDeclaredMethod("checkBounds", byte[].class, int.class, int.class);
}
}
@@ -32,8 +32,7 @@ class JavaReflectionMemberAccessTest : LightCodeInsightFixtureTestCase() {
myFixture.enableInspections(inspection)
}
override fun getProjectDescriptor(): LightProjectDescriptor =
LightCodeInsightFixtureTestCase.JAVA_8 // older mock JREs are missing some bits
override fun getProjectDescriptor(): LightProjectDescriptor = JAVA_8 // older mock JREs are missing some bits
override fun getBasePath() = JavaTestUtil.getRelativeJavaTestDataPath() + "/inspection/javaReflectionMemberAccess"
@@ -47,6 +46,7 @@ class JavaReflectionMemberAccessTest : LightCodeInsightFixtureTestCase() {
fun testNewInstance() = doTest(true)
fun testBugs() = doTest(true)
fun testClassArray() = doTest(true)
private fun doTest(checkExists: Boolean = false) {