diff --git a/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaLangReflectHandleInvocationChecker.java b/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaLangReflectHandleInvocationChecker.java
index 260b90c5e911..45e69f9a5797 100644
--- a/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaLangReflectHandleInvocationChecker.java
+++ b/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaLangReflectHandleInvocationChecker.java
@@ -176,12 +176,22 @@ final class JavaLangReflectHandleInvocationChecker {
if (actualArguments == null) return true;
final int requiredArgumentCount = lazyMethodSignature.size() - 1; // -1 excludes the return type
- if (!checkArgumentCount(actualArguments.expressions, requiredArgumentCount, argumentOffset, argumentList, holder)) return false;
+ final boolean maybeVararg;
+ if (!isExact && requiredArgumentCount > 0) {
+ ReflectiveType type = lazyMethodSignature.get(requiredArgumentCount).get();
+ maybeVararg = type.getType() instanceof PsiArrayType;
+ } else {
+ maybeVararg = false;
+ }
+ PsiExpression[] expressions = actualArguments.expressions;
+ if (!maybeVararg || expressions.length < requiredArgumentCount - 1) {
+ if (!checkArgumentCount(expressions, requiredArgumentCount, argumentOffset, argumentList, holder)) return false;
+ }
- LOG.assertTrue(actualArguments.expressions.length == requiredArgumentCount);
- for (int i = 0; i < requiredArgumentCount; i++) {
- final ReflectiveType requiredType = lazyMethodSignature.get(i + 1).get();
- checkArgumentType(actualArguments.expressions[i], requiredType, argumentList, isExact, holder);
+ for (int i = 0; i < expressions.length; i++) {
+ int parameterIndex = maybeVararg && i >= requiredArgumentCount - 1 ? requiredArgumentCount : i + 1;
+ final ReflectiveType requiredType = lazyMethodSignature.get(parameterIndex).get();
+ checkArgumentType(expressions[i], requiredType, argumentList, isExact, maybeVararg && i >= requiredArgumentCount - 1, holder);
}
return true;
}
@@ -191,28 +201,34 @@ final class JavaLangReflectHandleInvocationChecker {
@Nullable ReflectiveType requiredType,
@NotNull PsiExpressionList argumentList,
boolean isExact,
+ boolean maybeVararg,
@NotNull ProblemsHolder holder) {
- if (requiredType != null) {
- final PsiType actualType = argument.getType();
- if (actualType != null) {
- if (!isCompatible(requiredType, actualType, isExact)) {
- if (PsiTreeUtil.isAncestor(argumentList, argument, false)) {
- holder.registerProblem(argument,
- JavaBundle.message(isExact
- ? "inspection.reflect.handle.invocation.argument.not.exact"
- : "inspection.reflection.invocation.argument.not.assignable",
- requiredType.getQualifiedName()));
- }
+ if (requiredType == null) return;
+ final PsiType actualType = argument.getType();
+ if (actualType == null) return;
+ if (!isCompatible(requiredType, actualType, isExact)) {
+ if (maybeVararg) {
+ ReflectiveType componentType = requiredType.getArrayComponentType();
+ if (componentType != null) {
+ requiredType = componentType;
+ if (isCompatible(requiredType, actualType, isExact)) return;
}
- else if (requiredType.isPrimitive()) {
- final PsiExpression definition = findDefinition(argument);
- if (definition != null && PsiType.NULL.equals(definition.getType())) {
- if (PsiTreeUtil.isAncestor(argumentList, argument, false)) {
- holder.registerProblem(argument,
- JavaBundle.message("inspection.reflect.handle.invocation.primitive.argument.null",
- requiredType.getQualifiedName()));
- }
- }
+ }
+ if (PsiTreeUtil.isAncestor(argumentList, argument, false)) {
+ holder.registerProblem(argument,
+ JavaBundle.message(isExact
+ ? "inspection.reflect.handle.invocation.argument.not.exact"
+ : "inspection.reflection.invocation.argument.not.assignable",
+ requiredType.getQualifiedName()));
+ }
+ }
+ else if (requiredType.isPrimitive()) {
+ final PsiExpression definition = findDefinition(argument);
+ if (definition != null && PsiType.NULL.equals(definition.getType())) {
+ if (PsiTreeUtil.isAncestor(argumentList, argument, false)) {
+ holder.registerProblem(argument,
+ JavaBundle.message("inspection.reflect.handle.invocation.primitive.argument.null",
+ requiredType.getQualifiedName()));
}
}
}
@@ -373,7 +389,7 @@ final class JavaLangReflectHandleInvocationChecker {
LOG.assertTrue(arguments.length == argumentOffset + 1);
final ReflectiveType requiredType = getReflectiveType(typeExpression);
- checkArgumentType(arguments[argumentOffset], requiredType, argumentList, isExact, holder);
+ checkArgumentType(arguments[argumentOffset], requiredType, argumentList, isExact, false, holder);
final PsiElement invokeParent = invokeCall.getParent();
if (!(invokeParent instanceof PsiStatement)) {
diff --git a/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaLangReflectVarHandleInvocationChecker.java b/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaLangReflectVarHandleInvocationChecker.java
index 5c6cd09d2e7e..69866cc262ed 100644
--- a/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaLangReflectVarHandleInvocationChecker.java
+++ b/java/java-impl-inspections/src/com/intellij/codeInspection/reflectiveAccess/JavaLangReflectVarHandleInvocationChecker.java
@@ -155,7 +155,7 @@ final class JavaLangReflectVarHandleInvocationChecker {
LOG.assertTrue(accessArguments.length == requiredArgumentCount);
for (int i = coordinateArguments; i < requiredArgumentCount; i++) {
- checkArgumentType(accessArguments[i], valueType, accessArgumentList, false, holder);
+ checkArgumentType(accessArguments[i], valueType, accessArgumentList, false, false, holder);
}
}
diff --git a/java/java-tests/testData/inspection/invokeHandleSignature/VarArgMethodHandle.java b/java/java-tests/testData/inspection/invokeHandleSignature/VarArgMethodHandle.java
new file mode 100644
index 000000000000..49a5e958753b
--- /dev/null
+++ b/java/java-tests/testData/inspection/invokeHandleSignature/VarArgMethodHandle.java
@@ -0,0 +1,27 @@
+import java.lang.invoke.MethodHandle;
+import java.util.Arrays;
+import java.util.List;
+
+import static java.lang.invoke.MethodHandles.publicLookup;
+import static java.lang.invoke.MethodType.methodType;
+
+public class VarArgMethodHandle {
+ public static void main(String... args) throws Throwable {
+ MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
+ "asList", methodType(List.class, Object[].class));
+ System.out.println(MH_asList.invoke("one", "two").toString());
+ System.out.println(MH_asList.invokeExact("one", "two").toString());
+ System.out.println(MH_asList.invokeExact(new Object[] {"one", "two"}).toString());
+ System.out.println(MH_asList.invoke(new Object[] {"one", "two"}).toString());
+ MethodHandle MH_main = publicLookup().findStatic(VarArgMethodHandle.class,
+ "main", methodType(void.class, String[].class));
+ System.out.println(MH_main.invoke("one", "two").toString());
+ System.out.println(MH_main.invoke(new String[] {"one", "two"}).toString());
+ System.out.println(MH_main.invoke(new Object[] {"one", "two"}).toString());
+ System.out.println(MH_main.invoke(1, 2).toString());
+ System.out.println(MH_main.invokeExact("one", "two").toString());
+ System.out.println(MH_main.invokeExact(1, 2).toString());
+ System.out.println(MH_main.invokeExact(new String[] {"one", "two"}).toString());
+ System.out.println(MH_main.invokeExact(new Object[] {"one", "two"}).toString());
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/JavaLangInvokeHandleSignatureTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInspection/JavaLangInvokeHandleSignatureTest.kt
index e0d1b8fd9e72..3d28061c5619 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInspection/JavaLangInvokeHandleSignatureTest.kt
+++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/JavaLangInvokeHandleSignatureTest.kt
@@ -52,6 +52,8 @@ class JavaLangInvokeHandleSignatureTest : LightJavaCodeInsightFixtureTestCase()
fun testSpecial() = doTest()
+ fun testVarArgMethodHandle() = doTest()
+
private fun doTest() {
myFixture.testHighlighting("${getTestName(false)}.java")
}