From 8e3c26b879653ea1c13b06ea3341027f5ee80b02 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Fri, 17 Nov 2017 18:14:20 +0100 Subject: [PATCH] junit 5: check static attribute according to TestInstance configured --- .../java-analysis-impl/java-analysis-impl.iml | 1 + .../src/com/siyeh/ig/psiutils/TestUtils.java | 15 ++++++++++++- .../JUnit5MalformedParameterizedInspection.kt | 16 +++++++++----- .../JUnit5MalformedParameterizedTest.java | 6 +++++ .../MalformedSourcesTestInstancePerClass.java | 22 +++++++++++++++++++ 5 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 plugins/junit/testData/codeInsight/malformedParameterized/MalformedSourcesTestInstancePerClass.java diff --git a/java/java-analysis-impl/java-analysis-impl.iml b/java/java-analysis-impl/java-analysis-impl.iml index ebcda34a7da5..ac27777d1517 100644 --- a/java/java-analysis-impl/java-analysis-impl.iml +++ b/java/java-analysis-impl/java-analysis-impl.iml @@ -21,5 +21,6 @@ + \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java index ce9cf552c73a..fe0585333b9a 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java @@ -16,6 +16,7 @@ package com.siyeh.ig.psiutils; import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.codeInsight.MetaAnnotationUtil; import com.intellij.codeInsight.TestFrameworks; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.vfs.VirtualFile; @@ -25,12 +26,14 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.testIntegration.TestFramework; import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.hash.HashSet; import com.siyeh.ig.callMatcher.CallMatcher; import com.siyeh.ig.junit.JUnitCommonClassNames; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.Set; import static com.intellij.codeInsight.AnnotationUtil.CHECK_HIERARCHY; @@ -148,13 +151,23 @@ public class TestUtils { * @return true if class is annotated with {@code @TestInstance(TestInstance.Lifecycle.PER_CLASS)} */ public static boolean testInstancePerClass(@NotNull PsiClass containingClass) { - PsiAnnotation annotation = AnnotationUtil.findAnnotation(containingClass, JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_TEST_INSTANCE); + return testInstancePerClass(containingClass, new HashSet<>()); + } + + private static boolean testInstancePerClass(@NotNull PsiClass containingClass, HashSet classes) { + PsiAnnotation annotation = MetaAnnotationUtil.findMetaAnnotations(containingClass, Collections.singletonList(JUnitCommonClassNames.ORG_JUNIT_JUPITER_API_TEST_INSTANCE)) + .findFirst().orElse(null); if (annotation != null) { PsiAnnotationMemberValue value = annotation.findDeclaredAttributeValue(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME); if (value != null && value.getText().contains("PER_CLASS")) { return true; } } + else { + for (PsiClass superClass : containingClass.getSupers()) { + if (classes.add(superClass) && testInstancePerClass(superClass, classes)) return true; + } + } return false; } diff --git a/plugins/junit/src/com/intellij/execution/junit/codeInsight/JUnit5MalformedParameterizedInspection.kt b/plugins/junit/src/com/intellij/execution/junit/codeInsight/JUnit5MalformedParameterizedInspection.kt index 4115ccf8b0d5..dc0e105af152 100644 --- a/plugins/junit/src/com/intellij/execution/junit/codeInsight/JUnit5MalformedParameterizedInspection.kt +++ b/plugins/junit/src/com/intellij/execution/junit/codeInsight/JUnit5MalformedParameterizedInspection.kt @@ -28,6 +28,7 @@ import com.intellij.psi.util.TypeConversionUtil import com.intellij.util.containers.ContainerUtil import com.siyeh.InspectionGadgetsBundle import com.siyeh.ig.junit.JUnitCommonClassNames +import com.siyeh.ig.psiutils.TestUtils import org.jetbrains.annotations.Nls import java.util.* @@ -154,14 +155,16 @@ class JUnit5MalformedParameterizedInspection : AbstractBaseJavaLocalInspectionTo processArrayInAnnotationParameter(annotationMemberValue, { attributeValue -> for (reference in attributeValue.references) { if (reference is MethodSourceReference) { + val containingClass = method.containingClass val resolve = reference.resolve() if (resolve !is PsiMethod) { - val containingClass = method.containingClass var createFix : CreateMethodQuickFix? = null - if (containingClass != null && holder.isOnTheFly) + if (containingClass != null && holder.isOnTheFly) { + val staticModifier = if (!TestUtils.testInstancePerClass(containingClass)) " static" else ""; createFix = CreateMethodQuickFix.createFix(containingClass, - "static Object[][] " + reference.value + "()", + "private$staticModifier Object[][] " + reference.value + "()", "return new Object[][] {};") + } holder.registerProblem(attributeValue, "Cannot resolve target method source: \'" + reference.value + "\'", createFix) @@ -170,7 +173,8 @@ class JUnit5MalformedParameterizedInspection : AbstractBaseJavaLocalInspectionTo val sourceProvider : PsiMethod = resolve val providerName = sourceProvider.name - if (!sourceProvider.hasModifierProperty(PsiModifier.STATIC)) { + if (!sourceProvider.hasModifierProperty(PsiModifier.STATIC) && + containingClass != null && !TestUtils.testInstancePerClass(containingClass)) { holder.registerProblem(attributeValue, "Method source \'$providerName\' must be static", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, QuickFixFactory.getInstance().createModifierListFix(sourceProvider, PsiModifier.STATIC, true, false)) @@ -248,12 +252,12 @@ class JUnit5MalformedParameterizedInspection : AbstractBaseJavaLocalInspectionTo if (InheritanceUtil.isInheritor(returnType, CommonClassNames.JAVA_UTIL_STREAM_LONG_STREAM)) return PsiType.LONG if (InheritanceUtil.isInheritor(returnType, CommonClassNames.JAVA_UTIL_STREAM_DOUBLE_STREAM)) return PsiType.DOUBLE - val streamItemType = PsiUtil.substituteTypeParameter(returnType, CommonClassNames.JAVA_UTIL_STREAM_STREAM, 0, false) + val streamItemType = PsiUtil.substituteTypeParameter(returnType, CommonClassNames.JAVA_UTIL_STREAM_STREAM, 0, true) if (streamItemType != null) { return streamItemType } - return PsiUtil.substituteTypeParameter(returnType, CommonClassNames.JAVA_UTIL_ITERATOR, 0, false) + return PsiUtil.substituteTypeParameter(returnType, CommonClassNames.JAVA_UTIL_ITERATOR, 0, true) } } } diff --git a/plugins/junit/test/com/intellij/execution/junit/codeInsight/JUnit5MalformedParameterizedTest.java b/plugins/junit/test/com/intellij/execution/junit/codeInsight/JUnit5MalformedParameterizedTest.java index a7dfcebd3cf6..94c2677b68ad 100644 --- a/plugins/junit/test/com/intellij/execution/junit/codeInsight/JUnit5MalformedParameterizedTest.java +++ b/plugins/junit/test/com/intellij/execution/junit/codeInsight/JUnit5MalformedParameterizedTest.java @@ -66,12 +66,18 @@ public class JUnit5MalformedParameterizedTest extends LightInspectionTestCase { addEnvironmentClass("package org.junit.jupiter.params.provider;\n" + "public @interface ArgumentsSource {}"); + + addEnvironmentClass("package org.junit.jupiter.api;\n" + + "public @interface TestInstance {\n" + + "enum Lifecycle {PER_CLASS, PER_METHOD;}\n" + + "Lifecycle value();}"); } public void testMalformedSources() { doTest(); } public void testMethodSource() { doTest(); } public void testMalformedSourcesImplicitConversion() { doTest(); } public void testMalformedSourcesImplicitParameters() { doTest(); } + public void testMalformedSourcesTestInstancePerClass() { doTest(); } @Override protected String getBasePath() { diff --git a/plugins/junit/testData/codeInsight/malformedParameterized/MalformedSourcesTestInstancePerClass.java b/plugins/junit/testData/codeInsight/malformedParameterized/MalformedSourcesTestInstancePerClass.java new file mode 100644 index 000000000000..56c5d08b6465 --- /dev/null +++ b/plugins/junit/testData/codeInsight/malformedParameterized/MalformedSourcesTestInstancePerClass.java @@ -0,0 +1,22 @@ + +import java.util.Arrays; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.api.TestInstance; + +@TestInstance( TestInstance.Lifecycle.PER_CLASS ) +@interface Meta{} + +@Meta +abstract class AbstractTest {} +class TestWithMethodSource extends AbstractTest { + @ParameterizedTest + @MethodSource("getParameters") + public void shouldExecuteWithParameterizedMethodSource(String arguments) { } + + public Stream getParameters(){ //non static but that's expected due to PER_CLASS test instance + return Arrays.asList( "Another execution", "Last execution").stream(); + } +} \ No newline at end of file