From 3f140ab0d7c64ff177f17f91c11df30ff47e8fe4 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 12 Dec 2024 14:34:05 +1100 Subject: [PATCH] Closes #73: Fix bug where we detect unreachable case pattern when using 'if' in pattern --- src/main/java/io/jactl/resolver/SwitchResolver.java | 12 +++++++----- src/test/java/io/jactl/SwitchTests.java | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/jactl/resolver/SwitchResolver.java b/src/main/java/io/jactl/resolver/SwitchResolver.java index 7838390..44b9e7d 100644 --- a/src/main/java/io/jactl/resolver/SwitchResolver.java +++ b/src/main/java/io/jactl/resolver/SwitchResolver.java @@ -47,12 +47,14 @@ public static JactlType visitSwitch(Resolver resolver, Expr.Switch expr) { // Check that if there is a pattern covering all cases that there are no subsequent patterns and no default Set coveredTypes = new HashSet<>(); - expr.cases.forEach(c -> c.patterns.stream().map(pair -> pair.first).forEach(p -> { - JactlType type = coveringType(p); - if (coveredTypes.stream().anyMatch(ct -> ct.is(ANY) || ct.is(subjectType) || ct.isAssignableFrom(p.type) || (type != null && ct.isAssignableFrom(type)))) { - resolver.error("Unreachable switch case (covered by a previous case)", p.location); + expr.cases.forEach(c -> c.patterns.stream().forEach(pair -> { + Expr pattern = pair.first; + Expr ifCond = pair.second; + JactlType type = coveringType(pattern); + if (coveredTypes.stream().anyMatch(ct -> ct.is(ANY) || ct.is(subjectType) || ct.isAssignableFrom(pattern.type) || (type != null && ct.isAssignableFrom(type)))) { + resolver.error("Unreachable switch case (covered by a previous case)", pattern.location); } - if (type != null) { + if (type != null && ifCond == null) { coveredTypes.add(type); } })); diff --git a/src/test/java/io/jactl/SwitchTests.java b/src/test/java/io/jactl/SwitchTests.java index 856052c..4c0c192 100644 --- a/src/test/java/io/jactl/SwitchTests.java +++ b/src/test/java/io/jactl/SwitchTests.java @@ -590,6 +590,9 @@ public class SwitchTests extends BaseTest { test("def x = [[[3,7]],[[4,9]]]; switch (x) { [[_],[[3,7]]] -> 3; [[[3,7]],_] -> 4; _ -> null }", 4); test("def x = [[[3,7]],[[4,9]]]; switch (x) { [[_],[[3,7]]] -> 3; [_,[a]] -> a; _ -> null } == [4,9]", true); test("def x = [[[3,7]],[[4,9]]]; switch (x) { [[_],[[3,7]]] -> 3; [_,[List a]] -> a; _ -> null } == [4,9]", true); + test("switch (3) {\n int if it == 3 -> '3'\n int -> 'something else'\n}", "3"); + test("def x = [1,2,3]; switch (x) { _ if it.size() == 2 -> 2; _ if it.size() == 3 -> 3 }", 3); + testError("def x = [1,2,3]; switch (x) { _ -> 2; _ if it.size() == 3 -> 3 }", "unreachable switch case"); } @Test public void switchArrays() {