diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java index 009e6663e..d677686a1 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java @@ -3,6 +3,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.exps.ExitExprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; +import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent; import org.jetbrains.java.decompiler.modules.decompiler.stats.*; import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement.EdgeDirection; @@ -470,7 +471,13 @@ public static boolean hideDefaultSwitchEdges(Statement stat) { if (last >= 0) { // empty switch possible Statement stlast = swst.getCaseStatements().get(last); - if (stlast.getExprents() != null && stlast.getExprents().isEmpty()) { + boolean needsExhaustive = swst.getCaseValues().stream() + .flatMap(List::stream) + .filter(exp -> exp instanceof FunctionExprent) + .map(exp -> (FunctionExprent) exp) + .filter(exp -> exp.getFuncType() == FunctionExprent.FunctionType.INSTANCEOF) + .findAny().isPresent(); + if (stlast.getExprents() != null && stlast.getExprents().isEmpty() && !needsExhaustive) { List edges = stlast.getAllSuccessorEdges(); // If we don't have an edge from this statement or if the edge that we have isn't explicit, delete the default edge if (edges.isEmpty() || !edges.get(0).explicit) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java index 0692ff61d..674fd3d09 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java @@ -317,14 +317,22 @@ private static boolean processStatement(SwitchStatement stat, Statement root) { // Check for non null if (basicHead != null && basicHead.size() >= 1 && realSelector instanceof VarExprent var && !nullCase) { Exprent last = basicHead.get(basicHead.size() - 1); - if (last instanceof InvocationExprent inv && inv.isStatic() && inv.getClassname().equals("java/util/Objects") && inv.getName().equals("requireNonNull") && inv.getStringDescriptor().equals("(Ljava/lang/Object;)Ljava/lang/Object;") && var.equals(inv.getLstParameters().get(0))) { - basicHead.remove(basicHead.size() - 1); - // Check for other assignment - if (basicHead.size() >= 1 && var.isStack() && !nullCase) { - last = basicHead.get(basicHead.size() - 1); - if (last instanceof AssignmentExprent assignment && assignment.getLeft() instanceof VarExprent assigned && var.equals(assigned)) { - if (!var.isVarReferenced(root, assigned)) { - realSelector = assignment.getRight(); + AssignmentExprent stackAssignment = null; + if (last instanceof InvocationExprent inv && inv.isStatic() && inv.getClassname().equals("java/util/Objects") && inv.getName().equals("requireNonNull") && inv.getStringDescriptor().equals("(Ljava/lang/Object;)Ljava/lang/Object;")) { + VarExprent requireNonNullStackVar = null; + if (inv.getLstParameters().get(0) instanceof VarExprent varExprent) { + requireNonNullStackVar = varExprent; + } + if (basicHead.size() >= 2 && var.isStack() && !nullCase && basicHead.get(basicHead.size() - 2) instanceof AssignmentExprent assignment && assignment.getLeft() instanceof VarExprent assigned && var.equals(assigned) && !var.isVarReferenced(root, assigned, requireNonNullStackVar)) { + stackAssignment = assignment; + } + if (var.equals(inv.getLstParameters().get(0)) || (inv.getLstParameters().get(0).getExprentUse() & Exprent.MULTIPLE_USES) != 0 && inv.getLstParameters().get(0).equals(stackAssignment.getRight())) { + basicHead.remove(basicHead.size() - 1); + // Check for other assignment + if (basicHead.size() >= 1 && var.isStack() && !nullCase) { + last = basicHead.get(basicHead.size() - 1); + if (stackAssignment != null) { + realSelector = stackAssignment.getRight(); basicHead.remove(basicHead.size() - 1); } } diff --git a/testData/results/pkg/TestSwitchPatternMatching15.dec b/testData/results/pkg/TestSwitchPatternMatching15.dec index 233d6e7c5..00cfa209a 100644 --- a/testData/results/pkg/TestSwitchPatternMatching15.dec +++ b/testData/results/pkg/TestSwitchPatternMatching15.dec @@ -18,6 +18,7 @@ public class TestSwitchPatternMatching15 { case Number nx:// 15 System.out.println("Number: " + nx);// 16 break;// 17 + default: } }// 21 } @@ -133,7 +134,7 @@ class 'pkg/TestSwitchPatternMatching15' { 95 18 96 18 97 19 - 9d 21 + 9d 22 } } @@ -151,6 +152,6 @@ Lines mapping: 15 <-> 18 16 <-> 19 17 <-> 20 -21 <-> 22 +21 <-> 23 Not mapped: 19 diff --git a/testData/results/pkg/TestSwitchPatternMatchingJ21.dec b/testData/results/pkg/TestSwitchPatternMatchingJ21.dec index b72e28ef3..e06678320 100644 --- a/testData/results/pkg/TestSwitchPatternMatchingJ21.dec +++ b/testData/results/pkg/TestSwitchPatternMatchingJ21.dec @@ -3,6 +3,8 @@ package pkg; import java.util.function.Supplier; public class TestSwitchPatternMatchingJ21 { + Object test4; + public void test1(Object o) { System.out.println(switch (o) {// 7 case Integer i -> Integer.toString(i);// 8 @@ -25,173 +27,313 @@ public class TestSwitchPatternMatchingJ21 { default -> "null";// 25 }; } + + public String test4() { + return switch (this.test4) {// 31 + case Integer i -> Integer.toString(i);// 32 + case String s -> s;// 33 + default -> null;// 34 + }; + } + + public void test4(Object o) { + switch (o) {// 39 + case Integer i:// 40 + System.out.println(Integer.toString(i));// 41 + break;// 42 + case String s:// 43 + System.out.println(s);// 44 + break;// 45 + default: + } + }// 48 } class 'pkg/TestSwitchPatternMatchingJ21' { method 'test1 (Ljava/lang/Object;)V' { - 0 6 - 1 6 - 2 6 - 3 6 - 7 6 - e 6 - f 6 - 10 6 - 11 6 - 12 6 - 13 6 - 14 6 - 15 6 - 16 6 - 17 6 - 18 6 - 19 6 - 1a 6 - 1b 6 - 1c 6 - 1d 6 - 1e 6 - 1f 6 - 20 6 - 21 6 - 22 6 - 23 6 - 24 6 - 25 6 - 26 6 - 27 6 - 2c 7 - 2d 7 - 2e 7 - 2f 7 - 30 7 - 31 7 - 32 7 - 33 7 - 34 7 - 35 7 - 39 8 - 3a 8 - 3b 6 - 3c 6 - 3d 6 - 3e 10 + 0 8 + 1 8 + 2 8 + 3 8 + 7 8 + e 8 + f 8 + 10 8 + 11 8 + 12 8 + 13 8 + 14 8 + 15 8 + 16 8 + 17 8 + 18 8 + 19 8 + 1a 8 + 1b 8 + 1c 8 + 1d 8 + 1e 8 + 1f 8 + 20 8 + 21 8 + 22 8 + 23 8 + 24 8 + 25 8 + 26 8 + 27 8 + 2c 9 + 2d 9 + 2e 9 + 2f 9 + 30 9 + 31 9 + 32 9 + 33 9 + 34 9 + 35 9 + 39 10 + 3a 10 + 3b 8 + 3c 8 + 3d 8 + 3e 12 } method 'test2 (Ljava/lang/Object;)Ljava/lang/String;' { - 0 13 - 9 13 - 10 13 - 11 13 - 12 13 - 13 13 - 14 13 - 15 13 - 16 13 - 17 13 - 18 13 - 19 13 - 1a 13 - 1b 13 - 1c 13 - 1d 13 - 1e 13 - 1f 13 - 20 13 - 21 13 - 22 13 - 23 13 - 24 13 - 25 13 - 26 13 - 27 13 - 28 13 - 29 13 - 2a 13 - 2b 13 - 30 14 - 31 14 - 32 14 - 33 14 - 34 14 - 35 14 - 36 14 - 37 14 - 38 14 - 39 14 - 41 15 - 42 15 - 43 15 - 44 15 - 48 16 - 49 16 - 4a 13 + 0 15 + 9 15 + 10 15 + 11 15 + 12 15 + 13 15 + 14 15 + 15 15 + 16 15 + 17 15 + 18 15 + 19 15 + 1a 15 + 1b 15 + 1c 15 + 1d 15 + 1e 15 + 1f 15 + 20 15 + 21 15 + 22 15 + 23 15 + 24 15 + 25 15 + 26 15 + 27 15 + 28 15 + 29 15 + 2a 15 + 2b 15 + 30 16 + 31 16 + 32 16 + 33 16 + 34 16 + 35 16 + 36 16 + 37 16 + 38 16 + 39 16 + 41 17 + 42 17 + 43 17 + 44 17 + 48 18 + 49 18 + 4a 15 } method 'test3 (Ljava/util/function/Supplier;)Ljava/lang/String;' { - 0 21 - 1 21 - 2 21 - 3 21 - 4 21 - 5 21 - 15 21 - 16 21 - 17 21 - 18 21 - 19 21 - 1a 21 - 1b 21 - 1c 21 - 1d 21 - 1e 21 - 1f 21 - 20 21 - 21 21 - 22 21 - 23 21 - 24 21 - 25 21 - 26 21 - 27 21 - 28 21 - 29 21 - 2a 21 - 2b 21 - 2c 21 - 2d 21 - 2e 21 - 2f 21 - 34 22 - 35 22 - 36 22 - 37 22 - 38 22 - 39 22 - 3a 22 - 3b 22 - 3c 22 - 3d 22 - 45 23 - 46 23 - 47 23 - 48 23 - 4c 24 - 4d 24 - 4e 21 + 0 23 + 1 23 + 2 23 + 3 23 + 4 23 + 5 23 + 15 23 + 16 23 + 17 23 + 18 23 + 19 23 + 1a 23 + 1b 23 + 1c 23 + 1d 23 + 1e 23 + 1f 23 + 20 23 + 21 23 + 22 23 + 23 23 + 24 23 + 25 23 + 26 23 + 27 23 + 28 23 + 29 23 + 2a 23 + 2b 23 + 2c 23 + 2d 23 + 2e 23 + 2f 23 + 34 24 + 35 24 + 36 24 + 37 24 + 38 24 + 39 24 + 3a 24 + 3b 24 + 3c 24 + 3d 24 + 45 25 + 46 25 + 47 25 + 48 25 + 4c 26 + 4d 26 + 4e 23 + } + + method 'test4 ()Ljava/lang/String;' { + 0 31 + 1 31 + 2 31 + 3 31 + 13 31 + 14 31 + 15 31 + 16 31 + 17 31 + 18 31 + 19 31 + 1a 31 + 1b 31 + 1c 31 + 1d 31 + 1e 31 + 1f 31 + 20 31 + 21 31 + 22 31 + 23 31 + 24 31 + 25 31 + 26 31 + 27 31 + 28 31 + 29 31 + 2a 31 + 2b 31 + 30 32 + 31 32 + 32 32 + 33 32 + 34 32 + 35 32 + 36 32 + 37 32 + 3f 33 + 40 33 + 41 33 + 42 33 + 46 34 + 47 31 + } + + method 'test4 (Ljava/lang/Object;)V' { + 0 39 + 9 39 + 10 39 + 11 39 + 12 39 + 13 39 + 14 39 + 15 39 + 16 39 + 17 39 + 18 39 + 19 39 + 1a 39 + 1b 39 + 1c 39 + 1d 39 + 1e 39 + 1f 39 + 20 39 + 21 39 + 22 39 + 23 39 + 24 39 + 25 39 + 26 39 + 27 39 + 28 39 + 29 39 + 2a 39 + 2b 39 + 30 40 + 31 40 + 32 41 + 33 41 + 34 41 + 35 41 + 36 41 + 37 41 + 38 41 + 39 41 + 3a 41 + 3b 41 + 3c 41 + 3d 41 + 3e 41 + 3f 41 + 40 42 + 47 43 + 48 43 + 49 44 + 4a 44 + 4b 44 + 4c 44 + 4d 44 + 4e 44 + 4f 44 + 50 44 + 51 45 + 54 48 } } Lines mapping: -7 <-> 7 -8 <-> 8 -9 <-> 9 -11 <-> 11 -14 <-> 14 -15 <-> 15 -16 <-> 16 -17 <-> 17 -22 <-> 22 -23 <-> 23 -24 <-> 24 -25 <-> 25 +7 <-> 9 +8 <-> 10 +9 <-> 11 +11 <-> 13 +14 <-> 16 +15 <-> 17 +16 <-> 18 +17 <-> 19 +22 <-> 24 +23 <-> 25 +24 <-> 26 +25 <-> 27 +31 <-> 32 +32 <-> 33 +33 <-> 34 +34 <-> 35 +39 <-> 40 +40 <-> 41 +41 <-> 42 +42 <-> 43 +43 <-> 44 +44 <-> 45 +45 <-> 46 +48 <-> 49 diff --git a/testData/src/java21/pkg/TestSwitchPatternMatchingJ21.java b/testData/src/java21/pkg/TestSwitchPatternMatchingJ21.java index 64e62ec2b..68713cb23 100644 --- a/testData/src/java21/pkg/TestSwitchPatternMatchingJ21.java +++ b/testData/src/java21/pkg/TestSwitchPatternMatchingJ21.java @@ -25,4 +25,25 @@ public String test3(Supplier o) { default -> "null"; }; } + + Object test4; + public String test4() { + return switch (this.test4) { + case Integer i -> Integer.toString(i); + case String s -> s; + default -> null; + }; + } + + public void test4(Object o) { + switch (o) { + case Integer i: + System.out.println(Integer.toString(i)); + break; + case String s: + System.out.println(s); + break; + default: + } + } }