Files
openide/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingPatternsInSwitch/SwitchExhaustivenessIn21Java.java
Mikhail Pyltsin 717a44934b [java-highlighting] IDEA-354239 support exhaustiveness for record patterns with cross-section
GitOrigin-RevId: 3a5ce8c4aeb88270fc750f1b671d02e0e3a9b7a7
2024-05-30 11:57:36 +00:00

547 lines
16 KiB
Java

import java.util.Optional;
record PrimitiveAndSealed(int x, I y) {}
record NormalAndSealed(Integer x, I y) {}
sealed interface Super permits SuperChild, SuperRecord {}
final class SuperChild implements Super {}
record SuperRecord(I i) implements Super {}
record Generic<T>(T x) {}
class A {}
class B extends A {}
sealed interface I permits C, D {}
final class C implements I {}
final class D implements I {}
record Pair<T>(T x, T y) {}
record Top(Child c1, Child c2) {}
record Child(I x, I y){}
class Basic {
String o;
Super superInterface;
SuperRecord superRecord;
PrimitiveAndSealed primitiveAndSealed;
NormalAndSealed normalAndSealed;
Generic<I> genericInterface;
Generic<C> genericC;
<T extends Super> void testGenerics(T p, Pair<T> pair1, Pair<? extends Super> pair2) {
switch (p) {
case SuperChild superChild -> {}
case SuperRecord(C i) -> {}
case SuperRecord(D i) -> {}
}
switch(p) {
case SuperChild sc -> {}
case SuperRecord sr -> {}
}
switch (pair1.x()) {
case SuperChild sc -> {}
case SuperRecord sr -> {}
}
switch (pair2.x()) {
case SuperChild sc -> {}
case SuperRecord sr -> {}
}
}
void test(){
switch (superInterface) { //completed sealed with record
case SuperChild superChild -> {}
case SuperRecord(C i) -> {}
case SuperRecord(D i) -> {}
}
switch (superInterface) {
case SuperChild superChild -> {}
case SuperRecord(C i) -> {}
case SuperRecord(I i) -> {}
}
switch (<error descr="'switch' statement does not cover all possible input values">superInterface</error>) {
case SuperChild superChild -> {}
case SuperRecord(C i) -> {}
case SuperRecord(I i) when i.hashCode() > 0 -> {}
}
switch (o) { //non-record is completed
case String o -> {}
}
switch (<error descr="'switch' statement does not cover all possible input values">superRecord</error>) {
case SuperRecord(C i) -> {}
}
switch (superRecord) {
case SuperRecord(I i) -> {}
}
switch (<error descr="'switch' statement does not cover all possible input values">primitiveAndSealed</error>){ //error
case PrimitiveAndSealed(int x, C y) -> {}
}
switch (primitiveAndSealed){
case PrimitiveAndSealed(int x, I y) -> {}
}
switch (primitiveAndSealed){
case PrimitiveAndSealed(int x, C y) -> {}
case PrimitiveAndSealed(int x, D y) -> {}
}
switch (<error descr="'switch' statement does not cover all possible input values">normalAndSealed</error>){ //error
case NormalAndSealed(Integer x, C y) -> {}
}
switch (normalAndSealed){
case NormalAndSealed(Integer x, I y) -> {}
}
switch (normalAndSealed){
case NormalAndSealed(Integer x, C y) -> {}
case NormalAndSealed(Integer x, D y) -> {}
}
switch (genericInterface) {
case Generic<I>(I i) -> {}
}
switch (<error descr="'switch' statement does not cover all possible input values">genericInterface</error>) {
case Generic<I>(C i) -> {}
}
switch (genericInterface) {
case Generic<I>(C i) -> {}
case Generic<I>(D i) -> {}
}
switch (genericC) {
case Generic<C>(C i) -> {}
}
}
void testNested(Top t){
switch (<error descr="'switch' statement does not cover all possible input values">t</error>){
case Top(Child(I x1, C y1), Child(C x2, I y2)) -> {}
case Top(Child(I x1, D y1) , Child(I x2, C y2)) -> {}
}
switch (t){
case Top(Child(I x1, C y1) , Child c2) -> {}
case Top(Child(I x1, D y1) , Child c2) -> {}
}
switch (t){
case Top(Child(I x1, C y1) , Child(I x2, I y2) ) -> {}
case Top(Child(I x1, D y1) , Child(I x2, I y2) ) -> {}
}
switch (<error descr="'switch' statement does not cover all possible input values">t</error>){
case Top(Child c1, Child(C x2, I y2) ) -> {}
case Top(Child c1, Child(I x2, C y2) ) -> {}
}
switch (<error descr="'switch' statement does not cover all possible input values">t</error>){
case Top(Child(I x1, C y1) , Child(I x2, I y2) ) -> {}
case Top(Child(C x1, I y1) , Child(I x2, I y2) ) -> {}
}
switch (t){
case Top(Child(I x1, I y1) , Child(I x2, I y2) ) -> {}
}
}
void test(Pair<A> pairA, Pair<I> pairI) {
switch (<error descr="'switch' statement does not cover all possible input values">pairA</error>) { // Error!
case Pair<A>(A a,B b) -> { }
case Pair<A>(B b,A a) -> { }
}
switch (<error descr="'switch' statement does not cover all possible input values">pairI</error>) { // Error!
case Pair<I>(C fst, D snd) -> {}
case Pair<I>(D fst, C snd) -> {}
case Pair<I>(I fst, C snd) -> {}
}
switch (pairI) {
case Pair<I>(I i,C c) -> { }
case Pair<I>(I i,D d) -> { }
}
switch (pairI) {
case Pair<I>(C c,C i) -> { }
case Pair<I>(C c,D i) -> { }
case Pair<I>(D d,C c) -> { }
case Pair<I>(D d,D d2) -> { }
}
switch (pairI) {
case Pair<I>(C c,I i) -> { }
case Pair<I>(D d,C c) -> { }
case Pair<I>(D d,D d2) -> { }
}
switch(pairI.x()) {
case C c when true -> {}
case D d -> {}
}
}
record R(int x) {
}
void emptyRecord(R r) {
switch (<error descr="'switch' statement does not have any case clauses">r</error>) { //error
}
}
void emptyRecord2(R r) {
switch (<error descr="'switch' statement does not cover all possible input values">r</error>) { //error
case null -> System.out.println("1");
}
}
void emptyRecord3(R r) {
switch (<error descr="'switch' statement does not cover all possible input values">r</error>) { //error
case R r2 when r2.x() == 1 -> System.out.println("1");
}
}
void emptyInteger(int i) {
switch (i) {
}
}
void emptyObject0(Object o) {
switch (<error descr="'switch' statement does not have any case clauses">o</error>) { //error
}
}
void emptyObject(Object o) {
switch (<error descr="'switch' statement does not cover all possible input values">o</error>) { //error
case null -> System.out.println(1);
}
}
void emptyObject2(Object o) {
switch (<error descr="'switch' statement does not cover all possible input values">o</error>) {
case String s when s.length()==1 -> System.out.println(1);
}
}
void emptyRecord4(R r) {
switch (r) {
case R r2 when r2.x() == 1 -> System.out.println(1);
case R r2 -> System.out.println("1");
}
}
void emptyRecord5(R r) {
switch (<error descr="'switch' statement does not cover all possible input values">r</error>) { //error
case R r2 when r2.x() == 1 -> System.out.println(1);
}
}
void emptyRecord6(R r) {
switch (r) {
default -> System.out.println("1");
}
}
//see com.intellij.codeInsight.daemon.impl.analysis.PatternHighlightingModel.reduceRecordPatterns
void exhaustinvenessWithInterface(Pair<I> pairI) {
switch (pairI) {
case Pair<I>(C fst, D snd) -> {}
case Pair<I>(I fst, C snd) -> {}
case Pair<I>(D fst, I snd) -> {}
}
}
//see com.intellij.codeInsight.daemon.impl.analysis.PatternHighlightingModel.reduceRecordPatterns
void exhaustinvenessWithInterface2(Pair<? extends I> pairI) {
switch (pairI) {
case Pair<? extends I>(C fst, D snd) -> {}
case Pair<? extends I>(I fst, C snd) -> {}
case Pair<? extends I>(D fst, I snd) -> {}
}
}
sealed interface A1 permits A11, A12 {}
sealed interface A2 permits A21, A22 {}
record A11() implements A1 {}
record A12() implements A1 {}
record A21() implements A2 { }
record A22() implements A2 { }
record R1(A2 a2) { }
record R2(A1 a1, R1 r1) { }
record R12(A1 a1, A2 a2) { }
record R21(A2 a2, A1 a1) { }
void exhaustivenessWithCrossSectionNestedRecords(R2 r2) {
switch (r2) {
case R2(A11 b1, R1(A2 b2)) -> System.out.println("1");
case R2(A12 b1, R1(A22 b2)) -> System.out.println("2");
case R2(A1 b1, R1(A21 b2)) -> System.out.println("3");
}
}
void exhaustivenessWithCrossSection1(R12 r12) {
switch (r12) {
case R12(A11 b1, A2 b2) -> System.out.println("1");
case R12(A12 b1, A22 b2) -> System.out.println("2");
case R12(A1 b1, A21 b2) -> System.out.println("3");
}
}
void exhaustivenessWithCrossSection2(R21 r21) {
switch (r21) {
case R21(A2 b2, A11 b1) -> System.out.println("1");
case R21(A22 b2, A12 b1) -> System.out.println("2");
case R21(A21 b2, A1 b1) -> System.out.println("3");
}
}
sealed interface Parent {}
record AAA() implements Parent {}
record BBB() implements Parent {}
void test(Optional<? extends Parent> optional) {
switch (optional.get()) {
case AAA a -> {}
case BBB b -> {}
}
}
class CCCC{}
public <T extends CCCC & Comparable<T>> void test(T c) {
switch (c) {
case Comparable t -> System.out.println(13);
}
}
interface II1{}
sealed interface II2{}
non-sealed class Cl1 implements II2{}
public <T extends II1 & II2> void test(T c) {
switch (c) {
case Cl1 t:
System.out.println(21);
;
}
}
sealed interface J permits En, FC {
}
enum En implements J {A, B}
final class FC implements J {
}
static int testExhaustive2(J ji) {
return switch (ji) {
case FC c -> 42;
case En.A -> 0;
case En.B -> 0;
};
}
record PairT(T t1, T t2) {
}
sealed interface T {
}
sealed interface T1 extends T {
}
sealed interface T2 extends T {
}
record T11(T t1, T t2) implements T1 {
}
record T12(T t1, T t2) implements T1 {
}
record T21(T t1, T t2) implements T2 {
}
record T22(T t1, T t2) implements T2 {
}
public void test1(PairT pairT) {
switch (pairT) {
case PairT(T11 t1, T1 t2) -> System.out.println(1);
case PairT(T12 t1, T1 t2) -> System.out.println(1);
case PairT(T1 t1, T2 t2) -> System.out.println(1);
case PairT(T2 t1, T t2) -> System.out.println(1);
}
}
public void test2(PairT pairT) {
switch (<error descr="'switch' statement does not cover all possible input values">pairT</error>) { //error
case PairT(T11 t1, T1 t2) -> System.out.println(1);
case PairT(T12 t1, T1 t2) -> System.out.println(1);
case PairT(T2 t1, T t2) -> System.out.println(1);
}
}
public void test3(PairT pairT) {
switch (pairT) {
case PairT(T1 t1, T11 t2) -> System.out.println(1);
case PairT(T1 t1, T12 t2) -> System.out.println(1);
case PairT(T2 t1, T1 t2) -> System.out.println(1);
case PairT(T t1, T2 t2) -> System.out.println(1);
}
}
public void test4(PairT pairT) {
switch (pairT) {
case PairT(T1 t1, T11(T1 t12, T2 t22)) -> System.out.println(53714);
case PairT(T1 t1, T11(T2 t12, T2 t22)) -> System.out.println(1);
case PairT(T1 t1, T11(T t12, T1 t22)) -> System.out.println(1);
case PairT(T1 t1, T12 t2) -> System.out.println(1);
case PairT(T2 t1, T1 t2) -> System.out.println(1);
case PairT(T t1, T2 t2) -> System.out.println(1);
}
}
public void test5(PairT pairT) {
switch (<error descr="'switch' statement does not cover all possible input values">pairT</error>) {//error
case PairT(T1 t1, T11(T1 t12, T2 t22)) -> System.out.println(53714);
case PairT(T1 t1, T11(T t12, T1 t22)) -> System.out.println(1);
case PairT(T1 t1, T12 t2) -> System.out.println(1);
case PairT(T2 t1, T1 t2) -> System.out.println(1);
case PairT(T t1, T2 t2) -> System.out.println(1);
}
}
public void test6(PairT pairT) {
switch (pairT) {
case PairT(T1 t1, T11(T1 t12, T2 t22)) -> System.out.println(53714);
case PairT(T1 t1, T11(T2 t12, T2 t22)) -> System.out.println(1);
case PairT(T1 t1, T11(T t12, T1 t22)) -> System.out.println(1);
case PairT(T1 t1, T12(T1 t12, T t22)) -> System.out.println(1);
case PairT(T1 t1, T12(T2 t12, T t22)) -> System.out.println(1);
case PairT(T2 t1, T1 t2) -> System.out.println(1);
case PairT(T t1, T2 t2) -> System.out.println(1);
}
}
public void test7(PairT pairT) {
switch (pairT) {
case PairT(T11(T1 t12, T2 t22), T1 t1) -> System.out.println(53714);
case PairT(T11(T2 t12, T2 t22), T1 t1) -> System.out.println(1);
case PairT(T11(T t12, T1 t22), T1 t1) -> System.out.println(1);
case PairT(T12(T1 t12, T t22), T1 t1) -> System.out.println(1);
case PairT(T12(T2 t12, T t22), T1 t1) -> System.out.println(1);
case PairT( T1 t2, T2 t1) -> System.out.println(1);
case PairT( T2 t2, T t1) -> System.out.println(1);
}
}
public void test8(PairT pairT) {
switch (pairT) {
case PairT(T11(T1 t12, T2 t22), T1 t1) -> System.out.println(53714);
case PairT(T11(T2 t12, T2 t22), T1 t1) -> System.out.println(1);
case PairT(T11(T t12, T1 t22), T1 t1) -> System.out.println(1);
case PairT(T12(T1 t12, T t22), T1 t1) -> System.out.println(1);
case PairT(T12(T2 t12, T t22), T1 t1) -> System.out.println(1);
case PairT( T1 t2, T21 t1) -> System.out.println(1);
case PairT( T1 t2, T22(T t11, T1 t12)) -> System.out.println(1);
case PairT( T1 t2, T22(T t11, T2 t12)) -> System.out.println(1);
case PairT( T2 t2, T t1) -> System.out.println(1);
}
}
public void test9(PairT pairT) {
switch (<error descr="'switch' statement does not cover all possible input values">pairT</error>) {
case PairT(T11(T1 t12, T2 t22), T1 t1) when ((Object)pairT).hashCode()==1 -> System.out.println(53714);
case PairT(T11(T2 t12, T2 t22), T1 t1) -> System.out.println(1);
case PairT(T11(T t12, T1 t22), T1 t1) -> System.out.println(1);
case PairT(T12(T1 t12, T t22), T1 t1) -> System.out.println(1);
case PairT(T12(T2 t12, T t22), T1 t1) -> System.out.println(1);
case PairT( T1 t2, T21 t1) -> System.out.println(1);
case PairT( T1 t2, T22(T t11, T1 t12)) -> System.out.println(1);
case PairT( T1 t2, T22(T t11, T2 t12)) -> System.out.println(1);
case PairT( T2 t2, T t1) -> System.out.println(1);
}
}
sealed interface TInt {}
final class TI1 implements TInt {}
final class TI2 implements TInt {}
record RR(String s, TInt i) {}
void test(RR r) {
switch (r) {
case RR(CharSequence c1, TI1 c2) -> System.out.println("1");
case RR(Object c1, TI2 c2) -> System.out.println("2");
}
}
class OnlyDirectChildren{
sealed interface T permits T1, T2, T3 {}
sealed interface T1 extends T permits T12 {}
sealed class T2 implements T {}
sealed interface T3 extends T {}
final class T12 extends T2 implements T1 {}
final class T13 implements T3 {}
void test(T i) {
switch (<error descr="'switch' statement does not cover all possible input values">i</error>) {
case T2 i2 ->
System.out.println("2");
case T13 i3 ->
System.out.println("3");
}
}
void test2(T i) {
switch (i) {
case T2 i2 ->
System.out.println("2");
case T1 i1 ->
System.out.println("1");
case T13 i3 ->
System.out.println("3");
}
}
}
class Intersection{
sealed interface T1 {
}
sealed interface T2 {
}
final class T11 implements T1 {
}
final class T12 implements T2 {
}
final class T112 implements T1, T2 {
}
record Pair<L>(L a){}
<A extends T1 & T2> void test(A z) {
switch (z) {
case T112 c -> System.out.println("1");
}
}
<A extends T1 & T2> void test(Pair<A> z) {
switch (z) {
case Pair(T112 c) -> System.out.println("23875");
}
}
}
class EmptyStatement(){
sealed class A {}
final class AA extends A {}
sealed class AB extends A {}
non-sealed class AC extends A {}
final class ABA extends AB {}
non-sealed class ABC extends AB {}
void test(A a) {
switch (<error descr="'switch' statement does not have any case clauses">a</error>) {
}
}
}
}