From 5ba9f962bec8f98477727ec88b7c7bade3e14405 Mon Sep 17 00:00:00 2001 From: "Olga.Klisho" Date: Thu, 17 Feb 2022 19:41:28 +0300 Subject: [PATCH] [java] (IDEA-284762) cheap search for MethodSource reference default method implemented (Java and Kotlin) + test added GitOrigin-RevId: 05ef801405962a0960a4b818f0dce26213f97d0d --- .../deadCode/junitMethodSource/src/Main.java | 2 + .../{src => test_src}/Test.java | 0 .../UnusedDeclarationInspectionTest.java | 2 + .../JUnitImplicitUsageProvider.java | 44 ++++++++++++------- 4 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 java/java-tests/testData/inspection/deadCode/junitMethodSource/src/Main.java rename java/java-tests/testData/inspection/deadCode/junitMethodSource/{src => test_src}/Test.java (100%) diff --git a/java/java-tests/testData/inspection/deadCode/junitMethodSource/src/Main.java b/java/java-tests/testData/inspection/deadCode/junitMethodSource/src/Main.java new file mode 100644 index 000000000000..9b75b378afe7 --- /dev/null +++ b/java/java-tests/testData/inspection/deadCode/junitMethodSource/src/Main.java @@ -0,0 +1,2 @@ +@SuppressWarnings("ALL") +class Main {} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/deadCode/junitMethodSource/src/Test.java b/java/java-tests/testData/inspection/deadCode/junitMethodSource/test_src/Test.java similarity index 100% rename from java/java-tests/testData/inspection/deadCode/junitMethodSource/src/Test.java rename to java/java-tests/testData/inspection/deadCode/junitMethodSource/test_src/Test.java diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java index b94c0921b0c9..fb5d98a119e3 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/UnusedDeclarationInspectionTest.java @@ -259,6 +259,8 @@ public class UnusedDeclarationInspectionTest extends AbstractUnusedDeclarationTe doTest(); } + public void testJunitMethodSource() {doTest();} + private void doTest5() { IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_1_5, () -> doTest()); } diff --git a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java index 2058180415f2..36a4f5e00e0a 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java +++ b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java @@ -2,9 +2,8 @@ package com.intellij.execution.junit2.inspection; import com.intellij.codeInsight.AnnotationUtil; +import com.intellij.codeInsight.MetaAnnotationUtil; import com.intellij.codeInsight.daemon.ImplicitUsageProvider; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.psi.*; import com.intellij.psi.impl.JavaConstantExpressionEvaluator; import com.intellij.psi.search.GlobalSearchScope; @@ -18,17 +17,23 @@ import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.junit.JUnitCommonClassNames; +import com.siyeh.ig.psiutils.TestUtils; import org.jetbrains.annotations.NotNull; import java.util.Arrays; +import java.util.Collection; import java.util.List; -import static com.intellij.execution.util.JavaParametersUtil.isClassInProductionSources; import static com.siyeh.ig.junit.JUnitCommonClassNames.ORG_JUNIT_JUPITER_PARAMS_PARAMETERIZED_TEST; import static com.siyeh.ig.junit.JUnitCommonClassNames.ORG_JUNIT_JUPITER_PARAMS_PROVIDER_METHOD_SOURCE; public class JUnitImplicitUsageProvider implements ImplicitUsageProvider { private static final String MOCK = "org.mockito.Mock"; + private static final String KOTLIN_JVM_STATIC = "kotlin.jvm.JvmStatic"; + private static final String KOTLIN_COMPANION_OBJ_CLASS_NAME = "Companion"; + private static final Collection PARAMETERIZED_TEST_AND_METHOD_SOURCE = + ContainerUtil.immutableList(ORG_JUNIT_JUPITER_PARAMS_PROVIDER_METHOD_SOURCE, ORG_JUNIT_JUPITER_PARAMS_PARAMETERIZED_TEST); + private static final List INJECTED_FIELD_ANNOTATIONS = Arrays.asList( MOCK, "org.mockito.Spy", @@ -73,23 +78,30 @@ public class JUnitImplicitUsageProvider implements ImplicitUsageProvider { } private static boolean isReferencedInsideMethodSourceAnnotation(@NotNull PsiElement element) { - if (!(element instanceof PsiMethod)) return false; - PsiMethod method = (PsiMethod) element; - if (method.getAnnotation(ORG_JUNIT_JUPITER_PARAMS_PROVIDER_METHOD_SOURCE) != null) return false; - if (method.getParameterList().getParametersCount() != 0) return false; - PsiClass psiClass = method.getContainingClass(); - if (psiClass == null) return false; - String methodName = method.getName(); + if (element instanceof PsiMethod) { + PsiMethod psiMethod = (PsiMethod) element; + return CachedValuesManager.getCachedValue(psiMethod, + () -> CachedValueProvider.Result.create(isReferencedInsideMethodSourceAnnotation(psiMethod), + PsiModificationTracker.MODIFICATION_COUNT)); + } + return false; + } - Module classModule = psiClass.isValid() ? ModuleUtilCore.findModuleForPsiElement(psiClass) : null; - String className = psiClass.getQualifiedName(); - if (classModule != null && className != null) { - if (Boolean.TRUE.equals(isClassInProductionSources(className, classModule))) return false; + private static boolean isReferencedInsideMethodSourceAnnotation(@NotNull PsiMethod psiMethod) { + String methodName = psiMethod.getName(); + PsiClass psiClass = psiMethod.getContainingClass(); + if (psiMethod.getAnnotation(ORG_JUNIT_JUPITER_PARAMS_PROVIDER_METHOD_SOURCE) != null) return false; + if (psiMethod.getParameterList().getParametersCount() != 0) return false; + if (!TestUtils.isInTestSourceContent(psiClass)) return false; + + if (psiMethod.hasAnnotation(KOTLIN_JVM_STATIC) && KOTLIN_COMPANION_OBJ_CLASS_NAME.equals(psiClass.getName())) { + PsiElement parent = psiClass.getParent(); + if (parent != null) psiClass = (PsiClass)parent; } return ContainerUtil.exists(psiClass.findMethodsByName(methodName, false), - it -> it.getAnnotation(ORG_JUNIT_JUPITER_PARAMS_PARAMETERIZED_TEST) != null && - it.getAnnotation(ORG_JUNIT_JUPITER_PARAMS_PROVIDER_METHOD_SOURCE) != null); + it -> psiMethod != it && + MetaAnnotationUtil.isMetaAnnotated(it, PARAMETERIZED_TEST_AND_METHOD_SOURCE)); } private static boolean isEnumClassReferencedInEnumSourceAnnotation(PsiClass psiClass) {