diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnitCommonClassNames.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnitCommonClassNames.java index 9fd5d871168b..df73fecb6698 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnitCommonClassNames.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/JUnitCommonClassNames.java @@ -25,6 +25,7 @@ public final class JUnitCommonClassNames { public static final String ORG_JUNIT_JUPITER_CONDITION_PROVIDER_DISABLED_IF = "org.junit.jupiter.api.condition.DisabledIf"; public static final String ORG_JUNIT_JUPITER_PARAMS_VALUES_SOURCE = "org.junit.jupiter.params.provider.ValueSource"; public static final String ORG_JUNIT_JUPITER_PARAMS_ENUM_SOURCE = "org.junit.jupiter.params.provider.EnumSource"; + public static final String ORG_JUNIT_JUPITER_PARAMS_ENUM_SOURCE_SHORT = "EnumSource"; public static final String ORG_JUNIT_JUPITER_PARAMS_NULL_SOURCE = "org.junit.jupiter.params.provider.NullSource"; public static final String ORG_JUNIT_JUPITER_PARAMS_EMPTY_SOURCE = "org.junit.jupiter.params.provider.EmptySource"; public static final String ORG_JUNIT_JUPITER_PARAMS_NULL_AND_EMPTY_SOURCE = "org.junit.jupiter.params.provider.NullAndEmptySource"; 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 08efac2da26e..d006085161fd 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java +++ b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java @@ -1,4 +1,4 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.execution.junit2.inspection; import com.intellij.codeInsight.AnnotationUtil; @@ -9,14 +9,16 @@ import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.PsiSearchHelper; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiTreeUtil; +import com.siyeh.ig.junit.JUnitCommonClassNames; import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.List; -import static com.siyeh.ig.junit.JUnitCommonClassNames.ORG_JUNIT_JUPITER_PARAMS_ENUM_SOURCE; - public class JUnitImplicitUsageProvider implements ImplicitUsageProvider { private static final String MOCK = "org.mockito.Mock"; private static final List INJECTED_FIELD_ANNOTATIONS = Arrays.asList( @@ -34,30 +36,44 @@ public class JUnitImplicitUsageProvider implements ImplicitUsageProvider { private static boolean isReferencedInsideEnumSourceAnnotation(@NotNull PsiElement element) { if (element instanceof PsiEnumConstant) { PsiClass psiClass = ((PsiEnumConstant)element).getContainingClass(); - String className = psiClass != null ? psiClass.getName() : null; - if (className == null) return false; - SearchScope useScope = psiClass.getUseScope(); - - if (isExpensiveSearch(psiClass, className, useScope)) return false; - return ReferencesSearch.search(psiClass, useScope, false) - .anyMatch(reference -> { - PsiElement referenceElement = reference.getElement(); - PsiAnnotation annotation = PsiTreeUtil.getParentOfType(referenceElement, PsiAnnotation.class); - if (annotation != null) { - String annotationName = annotation.getQualifiedName(); - if (ORG_JUNIT_JUPITER_PARAMS_ENUM_SOURCE.equals(annotationName) && annotation.getAttributes().size() == 1) { - return true; - } - } - return false; - }); + return psiClass != null && + CachedValuesManager.getCachedValue(psiClass, + () -> CachedValueProvider.Result.create(areEnumConstantsReferenced(psiClass), + PsiModificationTracker.MODIFICATION_COUNT)); } return false; } + private static boolean areEnumConstantsReferenced(PsiClass psiClass) { + String className = psiClass.getName(); + if (className == null) { + return false; + } + SearchScope useScope = psiClass.getUseScope(); + if (isExpensiveSearch(psiClass, className, useScope)) { + return false; + } + return ReferencesSearch.search(psiClass, useScope, false) + .anyMatch(reference -> { + PsiElement referenceElement = reference.getElement(); + PsiAnnotation annotation = PsiTreeUtil.getParentOfType(referenceElement, PsiAnnotation.class, true, PsiStatement.class, PsiMember.class); + if (annotation != null) { + String annotationName = annotation.getQualifiedName(); + if (JUnitCommonClassNames.ORG_JUNIT_JUPITER_PARAMS_ENUM_SOURCE.equals(annotationName) && annotation.getAttributes().size() == 1) { + return true; + } + } + return false; + }); + } + private static boolean isExpensiveSearch(PsiClass psiClass, String name, SearchScope useScope) { if (!(useScope instanceof LocalSearchScope)) { PsiSearchHelper searchHelper = PsiSearchHelper.getInstance(psiClass.getProject()); + if (PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES == + searchHelper.isCheapEnoughToSearch(JUnitCommonClassNames.ORG_JUNIT_JUPITER_PARAMS_ENUM_SOURCE_SHORT, (GlobalSearchScope)useScope, null, null)) { + return true; + } PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, null, null); if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES || cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) { diff --git a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/LombokProcessorManager.java b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/LombokProcessorManager.java index 3cebab1eb572..82367f38ca66 100644 --- a/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/LombokProcessorManager.java +++ b/plugins/lombok/src/main/java/de/plushnikov/intellij/plugin/processor/LombokProcessorManager.java @@ -5,6 +5,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiJavaCodeReferenceElement; import com.intellij.util.containers.ContainerUtil; import de.plushnikov.intellij.plugin.processor.clazz.*; import de.plushnikov.intellij.plugin.processor.clazz.builder.*; @@ -22,12 +23,10 @@ import de.plushnikov.intellij.plugin.processor.method.DelegateMethodProcessor; import de.plushnikov.intellij.plugin.processor.modifier.*; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; +import java.util.stream.Collectors; public final class LombokProcessorManager { @@ -37,6 +36,11 @@ public final class LombokProcessorManager { return PROCESSOR_CACHE.computeIfAbsent(key, s -> function.get()); } + private static final Set ourSupportedShortNames = getAllProcessors() + .stream().flatMap(p -> Arrays.stream(p.getSupportedAnnotationClasses())) + .map(StringUtil::getShortName) + .collect(Collectors.toSet()); + @NotNull private static Collection getAllProcessors() { Application application = ApplicationManager.getApplication(); @@ -113,6 +117,14 @@ public final class LombokProcessorManager { @NotNull public static Collection getProcessors(@NotNull PsiAnnotation psiAnnotation) { + PsiJavaCodeReferenceElement nameReferenceElement = psiAnnotation.getNameReferenceElement(); + if (nameReferenceElement == null) { + return Collections.emptyList(); + } + String referenceName = nameReferenceElement.getReferenceName(); + if (referenceName == null || !ourSupportedShortNames.contains(referenceName)) { + return Collections.emptyList(); + } final String qualifiedName = psiAnnotation.getQualifiedName(); if (StringUtil.isEmpty(qualifiedName) || !qualifiedName.contains("lombok")) { return Collections.emptyList();