IDEA-302550 [java highlighting] switch exhaustiveness: consider permitted classes inside pattern check

GitOrigin-RevId: 14c74921fb72a7915ad0c017cc1cafbab1ee5534
This commit is contained in:
Alexandr Suhinin
2022-10-28 13:33:18 +00:00
committed by intellij-monorepo-bot
parent c5a042c676
commit eb23765538
3 changed files with 41 additions and 0 deletions
@@ -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<PsiClass> consumer){
Set<PsiClass> visitedClasses = new HashSet<>();
Queue<PsiClass> 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<PsiClass> findMissedClasses(@NotNull PsiType selectorType, Map<PsiClass, PsiPattern> patternClasses) {
PsiClass selectorClass = PsiUtil.resolveClassInClassTypeOnly(selectorType);
if (selectorClass instanceof PsiTypeParameter) {
@@ -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 (<error descr="'switch' statement does not cover all possible input values">o</error>) {
case Second x -> System.out.println();
}
}
}
@@ -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);
}