From cbdf7bb2f99009bd04779899aa8a9cea9e2ca5ec Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 24 Mar 2021 15:21:33 +0700 Subject: [PATCH] [java-inspections] IDEA-264850 MagicConstant inspection does not work on varargs GitOrigin-RevId: 4ac1cdc65c10fc40dec8ba5a3add52d12897526a --- .../MagicCompletionContributor.java | 17 +++++-- .../MagicConstantInspection.java | 18 +++++-- .../inspection/magic/VarargMethodCall.java | 31 ++++++++++++ .../MagicConstantCompletionTest.groovy | 50 +++++++++++++++++++ .../MagicConstantInspectionTest.java | 1 + 5 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 java/java-tests/testData/inspection/magic/VarargMethodCall.java diff --git a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java index 3547a1d31d7b..87ffb8b6e3fc 100644 --- a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicCompletionContributor.java @@ -109,9 +109,20 @@ public final class MagicCompletionContributor extends CompletionContributor impl int i = ArrayUtil.indexOf(list.getExpressions(), argument); if (i == -1) continue; PsiParameter[] params = method.getParameterList().getParameters(); - if (i >= params.length) continue; - PsiParameter parameter = params[i]; - result.add(Pair.create(parameter, parameter.getType())); + PsiParameter parameter; + PsiType parameterType; + if (method.isVarArgs() && i >= params.length - 1) { + parameter = ArrayUtil.getLastElement(params); + parameterType = ((PsiEllipsisType)parameter.getType()).getComponentType(); + } + else if (i < params.length) { + parameter = params[i]; + parameterType = parameter.getType(); + } + else { + continue; + } + result.add(Pair.create(parameter, parameterType)); } } else if (IN_BINARY_COMPARISON.accepts(pos)) { diff --git a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java index 67a49b9abb57..e5a937883437 100644 --- a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java @@ -227,14 +227,22 @@ public final class MagicConstantInspection extends AbstractBaseJavaLocalInspecti PsiExpression[] arguments = argumentList.getExpressions(); for (int i = 0; i < parameters.length; i++) { PsiParameter parameter = parameters[i]; - AllowedValues values = MagicConstantUtils.getAllowedValues(parameter, parameter.getType()); + PsiType type = parameter.getType(); + int stopArg = i; + if (type instanceof PsiEllipsisType) { + type = ((PsiEllipsisType)type).getComponentType(); + stopArg = arguments.length - 1; + } + AllowedValues values = MagicConstantUtils.getAllowedValues(parameter, type); if (values == null) continue; if (i >= arguments.length) break; - PsiExpression argument = arguments[i]; - argument = PsiUtil.deparenthesizeExpression(argument); - if (argument == null) continue; + for (int j = i; j <= stopArg; j++) { + PsiExpression argument = arguments[j]; + argument = PsiUtil.deparenthesizeExpression(argument); + if (argument == null) continue; - checkMagicParameterArgument(parameter, argument, values, holder); + checkMagicParameterArgument(parameter, argument, values, holder); + } } } diff --git a/java/java-tests/testData/inspection/magic/VarargMethodCall.java b/java/java-tests/testData/inspection/magic/VarargMethodCall.java new file mode 100644 index 000000000000..b5d3f0d24485 --- /dev/null +++ b/java/java-tests/testData/inspection/magic/VarargMethodCall.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2011 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. + */ +import org.intellij.lang.annotations.MagicConstant; + +public class VarargMethodCall { + private static class Constants { + public static final int ONE = 1; + public static final int TWO = 2; + } + public static void testAnnotation1(@MagicConstant(valuesFromClass = Constants.class) int var0) { + } + public static void testAnnotation2(@MagicConstant(valuesFromClass = Constants.class) int... vars) { + } + public static void testMethod() { + testAnnotation1(1); + testAnnotation2(1, 2); + } +} diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/MagicConstantCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/MagicConstantCompletionTest.groovy index 9d47da9d0711..5053af3bd6dc 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/MagicConstantCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/MagicConstantCompletionTest.groovy @@ -157,4 +157,54 @@ interface Foo { myFixture.complete(CompletionType.SMART) myFixture.assertPreferredCompletionItems 0, 'BAR', 'FOO' } + + @NeedsIndex.ForStandardLibrary + void testVarargMethodCall() { + addMagicConstant() + + @Language("JAVA") + def s = """ +import org.intellij.lang.annotations.MagicConstant; + +public class VarargMethodCall { + private static class Constants { + public static final int ONE = 1; + public static final int TWO = 2; + } + public static void testAnnotation2(@MagicConstant(valuesFromClass = Constants.class) int... vars) { + } + public static void testMethod() { + testAnnotation2(); + } +} +""" + myFixture.configureByText "a.java", s + myFixture.complete(CompletionType.SMART) + myFixture.assertPreferredCompletionItems 0, 'ONE', 'TWO' + } + + @NeedsIndex.ForStandardLibrary + void testVarargMethodCall2() { + addMagicConstant() + + @Language("JAVA") + def s = """ +import org.intellij.lang.annotations.MagicConstant; + +public class VarargMethodCall { + private static class Constants { + public static final int ONE = 1; + public static final int TWO = 2; + } + public static void testAnnotation2(@MagicConstant(valuesFromClass = Constants.class) int... vars) { + } + public static void testMethod() { + testAnnotation2(Constants.ONE, ); + } +} +""" + myFixture.configureByText "a.java", s + myFixture.complete(CompletionType.SMART) + myFixture.assertPreferredCompletionItems 0, 'ONE', 'TWO' + } } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/MagicConstantInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/MagicConstantInspectionTest.java index 56041d0f7097..9d7453624fd4 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/MagicConstantInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/MagicConstantInspectionTest.java @@ -45,6 +45,7 @@ public class MagicConstantInspectionTest extends LightJavaCodeInsightFixtureTest // test that the optimisation for not loading AST works public void testWithLibrary() { doTest(); } public void testSpecialCases() { doTest(); } + public void testVarargMethodCall() { doTest(); } private void doTest() { myFixture.configureByFile(getTestName(false) + ".java");