From eb237655386cbcfe65f3c0cff73cb2e6e8c582ca Mon Sep 17 00:00:00 2001 From: Alexandr Suhinin Date: Fri, 28 Oct 2022 14:13:16 +0300 Subject: [PATCH] IDEA-302550 [java highlighting] switch exhaustiveness: consider permitted classes inside pattern check GitOrigin-RevId: 14c74921fb72a7915ad0c017cc1cafbab1ee5534 --- .../SwitchBlockHighlightingModel.java | 17 ++++++++++++++++ ...hExhaustivenessWithSealedIntersection.java | 20 +++++++++++++++++++ ...ightPatternsForSwitchHighlightingTest.java | 4 ++++ 3 files changed, 41 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingPatternsInSwitch/SwitchExhaustivenessWithSealedIntersection.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java index e9e4e18a4aa7..5142010f45eb 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java @@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -391,11 +392,27 @@ public class SwitchBlockHighlightingModel { PsiClass patternClass = PsiUtil.resolveClassInClassTypeOnly(JavaPsiPatternUtil.getPatternType(element)); if (patternClass != null) { patternClasses.put(patternClass, patternLabelElement); + visitAllPermittedClasses(patternClass, permittedClass -> patternClasses.put(permittedClass, patternLabelElement)); } } return patternClasses; } + private static void visitAllPermittedClasses(@NotNull PsiClass psiClass, Consumer consumer){ + Set visitedClasses = new HashSet<>(); + Queue notVisitedClasses = new LinkedList<>(); + notVisitedClasses.add(psiClass); + while (!notVisitedClasses.isEmpty()) { + PsiClass notVisitedClass = notVisitedClasses.poll(); + if (!notVisitedClass.hasModifierProperty(SEALED) || visitedClasses.contains(notVisitedClass)) continue; + visitedClasses.add(notVisitedClass); + for (PsiClass permittedClass : PatternsInSwitchBlockHighlightingModel.getPermittedClasses(psiClass)) { + consumer.accept(permittedClass); + notVisitedClasses.add(permittedClass); + } + } + } + private static @NotNull Set findMissedClasses(@NotNull PsiType selectorType, Map patternClasses) { PsiClass selectorClass = PsiUtil.resolveClassInClassTypeOnly(selectorType); if (selectorClass instanceof PsiTypeParameter) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingPatternsInSwitch/SwitchExhaustivenessWithSealedIntersection.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingPatternsInSwitch/SwitchExhaustivenessWithSealedIntersection.java new file mode 100644 index 000000000000..efca50168612 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingPatternsInSwitch/SwitchExhaustivenessWithSealedIntersection.java @@ -0,0 +1,20 @@ +sealed interface First {} +sealed interface Second {} +sealed interface Third extends First {} + +final class F1 implements First {} +final class F2 implements First, Second {} +final class F3 implements Second {} +final class F4 implements Third, Second {} //implicit First + +class Test { + void test(First o) { + switch (o) { + case F1 x -> System.out.println(); + case Second x -> System.out.println(); + } + switch (o) { + case Second x -> System.out.println(); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightPatternsForSwitchHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightPatternsForSwitchHighlightingTest.java index c97d0d5eb51b..591344c2bf6c 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightPatternsForSwitchHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightPatternsForSwitchHighlightingTest.java @@ -53,6 +53,10 @@ public class LightPatternsForSwitchHighlightingTest extends LightJavaCodeInsight IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_19_PREVIEW, this::doTest); } + public void testSwitchExhaustivenessWithSealedIntersection(){ + IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_19_PREVIEW, this::doTest); + } + public void testSwitchExhaustivenessWithGenericsIn19Java() { IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_19_PREVIEW, this::doTest); }