From 9c0f911e6bccdfa2402643bcdc7c44d2573493d4 Mon Sep 17 00:00:00 2001 From: coehlrich Date: Mon, 20 May 2024 14:41:33 +1200 Subject: [PATCH 1/3] Fix variable used in switch head not being inlined --- .../SwitchPatternMatchProcessor.java | 39 +++++++++++++++++++ .../pkg/TestSwitchPatternMatchingJ21.java | 18 +++++++++ 2 files changed, 57 insertions(+) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java index daa4a5320..d97295de9 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java @@ -5,6 +5,7 @@ import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.modules.decompiler.exps.*; +import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent.FunctionType; import org.jetbrains.java.decompiler.modules.decompiler.stats.*; import org.jetbrains.java.decompiler.struct.consts.PooledConstant; import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant; @@ -15,6 +16,7 @@ import org.jetbrains.java.decompiler.util.Pair; import java.util.*; +import java.util.stream.Stream; public final class SwitchPatternMatchProcessor { public static boolean processPatternMatching(Statement root) { @@ -66,6 +68,7 @@ private static boolean processStatement(SwitchStatement stat, Statement root) { Exprent realSelector = origParams.get(0); boolean guarded = true; boolean isEnumSwitch = value.getName().equals("enumSwitch"); + boolean nullCase = false; List> references = new ArrayList<>(); if (origParams.get(1) instanceof VarExprent) { VarExprent var = (VarExprent) origParams.get(1); @@ -134,6 +137,7 @@ private static boolean processStatement(SwitchStatement stat, Statement root) { // -1 always means null if (caseValue == -1) { + nullCase = true; allCases.remove(caseExpr); ConstExprent nullConst = new ConstExprent(VarType.VARTYPE_NULL, null, null); // null can be shared with a pattern or default; put it at the end, but before default, to make sure it doesn't get @@ -262,6 +266,41 @@ private static boolean processStatement(SwitchStatement stat, Statement root) { } } + Exprent oldSelector = realSelector; + // inline head + List basicHead = stat.getBasichead().getExprents(); + if (realSelector instanceof VarExprent var && basicHead != null && basicHead.size() >= 1) { + if (basicHead.get(basicHead.size() - 1) instanceof AssignmentExprent assignment && assignment.getLeft() instanceof VarExprent assigned) { + if (var.equals(assigned) && !var.isVarReferenced(root, Stream.concat(Stream.of(assigned), stat.getCaseValues().stream().flatMap(List::stream).filter(exp -> exp instanceof FunctionExprent func && func.getFuncType() == FunctionType.INSTANCEOF && func.getLstOperands().get(0) instanceof VarExprent checked && checked.equals(var)).map(exp -> (VarExprent) ((FunctionExprent) exp).getLstOperands().get(0))).toArray(VarExprent[]::new))) { + realSelector = assignment.getRight(); + basicHead.remove(basicHead.size() - 1); + } + } + } + + // 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(); + basicHead.remove(basicHead.size() - 1); + } + } + } + } + } + + if (oldSelector != realSelector) { + Exprent finalSelector = realSelector; + stat.getCaseValues().stream().flatMap(List::stream).filter(Objects::nonNull).filter(exp -> exp instanceof FunctionExprent func && func.getFuncType() == FunctionType.INSTANCEOF && func.getLstOperands().get(0).equals(oldSelector)).forEach(exp -> ((FunctionExprent) exp).getLstOperands().set(0, finalSelector)); + } + head.setValue(realSelector); // SwitchBootstraps.typeSwitch(o, var1) -> o if (guarded && stat.getParent() instanceof DoStatement) { diff --git a/testData/src/java21/pkg/TestSwitchPatternMatchingJ21.java b/testData/src/java21/pkg/TestSwitchPatternMatchingJ21.java index db6546abc..64e62ec2b 100644 --- a/testData/src/java21/pkg/TestSwitchPatternMatchingJ21.java +++ b/testData/src/java21/pkg/TestSwitchPatternMatchingJ21.java @@ -1,5 +1,7 @@ package pkg; +import java.util.function.Supplier; + public class TestSwitchPatternMatchingJ21 { public void test1(Object o) { System.out.println(switch (o) { @@ -7,4 +9,20 @@ public void test1(Object o) { case null, default -> "null"; }); } + + public String test2(Object o) { + return switch (o) { + case Integer i -> Integer.toString(i); + case String s -> s; + default -> "null"; + }; + } + + public String test3(Supplier o) { + return switch (o.get()) { + case Integer i -> Integer.toString(i); + case String s -> s; + default -> "null"; + }; + } } From c6214eb45c98b53fd3b15d2ddddf660c115f2048 Mon Sep 17 00:00:00 2001 From: coehlrich Date: Mon, 20 May 2024 15:09:38 +1200 Subject: [PATCH 2/3] Update dec files --- .../pkg/TestSwitchPatternMatching1.dec | 140 ++--- .../pkg/TestSwitchPatternMatching22.dec | 572 +++++++++--------- .../pkg/TestSwitchPatternMatching4.dec | 60 +- .../TestSwitchPatternMatchingConstructor2.dec | 134 ++-- .../pkg/TestSwitchPatternMatchingJ21.dec | 235 +++++-- .../pkg/TestSwitchPatternMatchingLoop.dec | 136 ++--- .../pkg/TestSwitchPatternMatchingReturn1.dec | 107 ++-- testData/results/pkg/TestUnknownCastJ17.dec | 243 ++++---- 8 files changed, 839 insertions(+), 788 deletions(-) diff --git a/testData/results/pkg/TestSwitchPatternMatching1.dec b/testData/results/pkg/TestSwitchPatternMatching1.dec index 0694c6e77..418cdc1c4 100644 --- a/testData/results/pkg/TestSwitchPatternMatching1.dec +++ b/testData/results/pkg/TestSwitchPatternMatching1.dec @@ -1,11 +1,8 @@ package pkg; -import java.util.Objects; - public class TestSwitchPatternMatching1 { public void test(Object o) { - Objects.requireNonNull(o);// 5 - switch (o) { + switch (o) {// 5 case Integer i:// 6 System.out.println(i); break; @@ -20,76 +17,73 @@ public class TestSwitchPatternMatching1 { class 'pkg/TestSwitchPatternMatching1' { method 'test (Ljava/lang/Object;)V' { - 0 6 - 2 6 - 3 6 - 4 6 - 9 7 - 10 7 - 11 7 - 12 7 - 13 7 - 14 7 - 15 7 - 16 7 - 17 7 - 18 7 - 19 7 - 1a 7 - 1b 7 - 1c 7 - 1d 7 - 1e 7 - 1f 7 - 20 7 - 21 7 - 22 7 - 23 7 - 24 7 - 25 7 - 26 7 - 27 7 - 28 7 - 29 7 - 2a 7 - 2b 7 - 30 8 - 31 8 - 32 9 - 33 9 - 34 9 - 35 9 - 36 9 - 37 9 - 38 9 - 39 9 - 3a 10 - 41 11 - 42 11 - 43 12 - 44 12 - 45 12 - 46 12 - 47 12 - 48 12 - 49 12 - 4a 12 - 4b 13 - 4e 15 - 4f 15 - 50 15 - 51 15 - 52 15 - 53 15 - 54 15 - 55 15 - 56 17 + 0 4 + 9 4 + 10 4 + 11 4 + 12 4 + 13 4 + 14 4 + 15 4 + 16 4 + 17 4 + 18 4 + 19 4 + 1a 4 + 1b 4 + 1c 4 + 1d 4 + 1e 4 + 1f 4 + 20 4 + 21 4 + 22 4 + 23 4 + 24 4 + 25 4 + 26 4 + 27 4 + 28 4 + 29 4 + 2a 4 + 2b 4 + 30 5 + 31 5 + 32 6 + 33 6 + 34 6 + 35 6 + 36 6 + 37 6 + 38 6 + 39 6 + 3a 7 + 41 8 + 42 8 + 43 9 + 44 9 + 45 9 + 46 9 + 47 9 + 48 9 + 49 9 + 4a 9 + 4b 10 + 4e 12 + 4f 12 + 50 12 + 51 12 + 52 12 + 53 12 + 54 12 + 55 12 + 56 14 } } Lines mapping: -5 <-> 7 -6 <-> 9 -7 <-> 12 -8 <-> 16 -10 <-> 18 +5 <-> 5 +6 <-> 6 +7 <-> 9 +8 <-> 13 +10 <-> 15 diff --git a/testData/results/pkg/TestSwitchPatternMatching22.dec b/testData/results/pkg/TestSwitchPatternMatching22.dec index 3f3d20557..53a786e66 100644 --- a/testData/results/pkg/TestSwitchPatternMatching22.dec +++ b/testData/results/pkg/TestSwitchPatternMatching22.dec @@ -1,16 +1,11 @@ package pkg; -import java.util.Objects; - public class TestSwitchPatternMatching22 { public void test1() { try { System.out.println("hello");// 13 } catch (Exception var8) {// 14 - Object var10000 = new Object(); - Objects.requireNonNull(var10000);// 15 - Object var2 = var10000; - switch (var2) { + switch (new Object()) {// 15 case Short var4:// 19 break; default: @@ -26,10 +21,7 @@ public class TestSwitchPatternMatching22 { try { System.out.println("hello");// 28 } catch (Exception var8) {// 29 - Object var10000 = new Object(); - Objects.requireNonNull(var10000);// 30 - Object var2 = var10000; - switch (var2) { + switch (new Object()) {// 30 case Short var4:// 34 default: System.out.println("Not a short");// 32 @@ -44,8 +36,7 @@ public class TestSwitchPatternMatching22 { try { System.out.println("hello");// 43 } catch (Exception var8) {// 44 - Object var2 = new Object();// 45 - switch (var2) { + switch (new Object()) {// 45 case Short var4:// 50 case null: break; @@ -62,8 +53,7 @@ public class TestSwitchPatternMatching22 { try { System.out.println("hello");// 59 } catch (Exception var8) {// 60 - Object var2 = new Object();// 61 - switch (var2) { + switch (new Object()) {// 61 case Short var4:// 66 case null: default: @@ -94,306 +84,292 @@ public class TestSwitchPatternMatching22 { class 'pkg/TestSwitchPatternMatching22' { method 'test1 ()V' { - 0 7 - 1 7 - 2 7 - 3 7 - 4 7 - 5 7 - 6 7 - 7 7 - 13 8 - 1c 10 - 1d 10 - 1e 10 - 20 11 - 23 12 - 2a 12 - 2b 12 - 2c 12 - 2d 12 - 2e 12 - 2f 12 - 30 12 - 31 12 - 32 12 - 33 12 - 34 12 - 35 12 - 36 12 - 37 12 - 38 12 - 39 12 - 3a 12 - 3b 12 - 3c 16 - 3d 16 - 3e 16 - 3f 16 - 40 16 - 41 16 - 42 16 - 43 16 - 4b 17 - 50 13 - 51 13 - 5f 20 - 60 20 - 61 20 - 62 20 - 63 20 - 64 20 - 65 20 - 66 20 - 6a 22 + 0 5 + 1 5 + 2 5 + 3 5 + 4 5 + 5 5 + 6 5 + 7 5 + 13 6 + 2a 7 + 2b 7 + 2c 7 + 2d 7 + 2e 7 + 2f 7 + 30 7 + 31 7 + 32 7 + 33 7 + 34 7 + 35 7 + 36 7 + 37 7 + 38 7 + 39 7 + 3a 7 + 3b 7 + 3c 11 + 3d 11 + 3e 11 + 3f 11 + 40 11 + 41 11 + 42 11 + 43 11 + 4b 12 + 50 8 + 51 8 + 5f 15 + 60 15 + 61 15 + 62 15 + 63 15 + 64 15 + 65 15 + 66 15 + 6a 17 } method 'test2 ()V' { - 0 26 - 1 26 - 2 26 - 3 26 - 4 26 - 5 26 - 6 26 - 7 26 - 10 27 - 19 29 - 1a 29 - 1b 29 - 1d 30 - 20 31 - 27 31 - 28 31 - 29 31 - 2a 31 - 2b 31 - 2c 31 - 2d 31 - 2e 31 - 2f 31 - 30 31 - 31 31 - 32 31 - 33 31 - 34 31 - 35 31 - 36 31 - 37 31 - 38 34 - 39 34 - 3a 34 - 3b 34 - 3c 34 - 3d 34 - 3e 34 - 3f 34 - 47 35 - 4c 32 - 4d 32 - 5f 38 + 0 21 + 1 21 + 2 21 + 3 21 + 4 21 + 5 21 + 6 21 + 7 21 + 10 22 + 27 23 + 28 23 + 29 23 + 2a 23 + 2b 23 + 2c 23 + 2d 23 + 2e 23 + 2f 23 + 30 23 + 31 23 + 32 23 + 33 23 + 34 23 + 35 23 + 36 23 + 37 23 + 38 26 + 39 26 + 3a 26 + 3b 26 + 3c 26 + 3d 26 + 3e 26 + 3f 26 + 47 27 + 4c 24 + 4d 24 + 5f 30 } method 'test1Null ()V' { - 0 44 - 1 44 - 2 44 - 3 44 - 4 44 - 5 44 - 6 44 - 7 44 - 13 45 - 1b 46 - 1e 47 - 25 47 - 26 47 - 27 47 - 28 47 - 29 47 - 2a 47 - 2b 47 - 2c 47 - 2d 47 - 2e 47 - 2f 47 - 30 47 - 31 47 - 32 47 - 33 47 - 34 47 - 35 47 - 36 47 - 37 47 - 38 47 - 39 47 - 3a 47 - 3b 47 - 3c 47 - 3d 47 - 3e 47 - 3f 47 - 40 52 - 41 52 - 42 52 - 43 52 - 44 52 - 45 52 - 46 52 - 47 52 - 4f 53 - 54 48 - 55 48 - 63 56 - 64 56 - 65 56 - 66 56 - 67 56 - 68 56 - 69 56 - 6a 56 - 6e 58 + 0 36 + 1 36 + 2 36 + 3 36 + 4 36 + 5 36 + 6 36 + 7 36 + 13 37 + 25 38 + 26 38 + 27 38 + 28 38 + 29 38 + 2a 38 + 2b 38 + 2c 38 + 2d 38 + 2e 38 + 2f 38 + 30 38 + 31 38 + 32 38 + 33 38 + 34 38 + 35 38 + 36 38 + 37 38 + 38 38 + 39 38 + 3a 38 + 3b 38 + 3c 38 + 3d 38 + 3e 38 + 3f 38 + 40 43 + 41 43 + 42 43 + 43 43 + 44 43 + 45 43 + 46 43 + 47 43 + 4f 44 + 54 39 + 55 39 + 63 47 + 64 47 + 65 47 + 66 47 + 67 47 + 68 47 + 69 47 + 6a 47 + 6e 49 } method 'test2Null ()V' { - 0 62 - 1 62 - 2 62 - 3 62 - 4 62 - 5 62 - 6 62 - 7 62 - 10 63 - 18 64 - 1b 65 - 22 65 - 23 65 - 24 65 - 25 65 - 26 65 - 27 65 - 28 65 - 29 65 - 2a 65 - 2b 65 - 2c 65 - 2d 65 - 2e 65 - 2f 65 - 30 65 - 31 65 - 32 65 - 33 65 - 34 65 - 35 65 - 36 65 - 37 65 - 38 65 - 39 65 - 3a 65 - 3b 65 - 3c 69 - 3d 69 - 3e 69 - 3f 69 - 40 69 - 41 69 - 42 69 - 43 69 - 4b 70 - 50 66 - 51 66 - 63 73 + 0 53 + 1 53 + 2 53 + 3 53 + 4 53 + 5 53 + 6 53 + 7 53 + 10 54 + 22 55 + 23 55 + 24 55 + 25 55 + 26 55 + 27 55 + 28 55 + 29 55 + 2a 55 + 2b 55 + 2c 55 + 2d 55 + 2e 55 + 2f 55 + 30 55 + 31 55 + 32 55 + 33 55 + 34 55 + 35 55 + 36 55 + 37 55 + 38 55 + 39 55 + 3a 55 + 3b 55 + 3c 59 + 3d 59 + 3e 59 + 3f 59 + 40 59 + 41 59 + 42 59 + 43 59 + 4b 60 + 50 56 + 51 56 + 63 63 } method 'testNonPattern ()V' { - 0 79 - 1 79 - 2 79 - 3 79 - 4 79 - 5 79 - 6 79 - 7 79 - 10 80 - 11 81 - 12 81 - 13 81 - 14 81 - 15 81 - 16 81 - 17 81 - 18 81 - 19 81 - 1a 81 - 1b 81 - 1c 81 - 1d 81 - 1e 81 - 1f 81 - 20 81 - 21 81 - 22 81 - 23 81 - 24 81 - 25 81 - 26 81 - 27 81 - 28 81 - 29 81 - 2a 81 - 2b 81 - 2c 85 - 2d 85 - 2e 85 - 2f 85 - 30 85 - 31 85 - 32 85 - 33 85 - 3b 86 - 4c 89 + 0 69 + 1 69 + 2 69 + 3 69 + 4 69 + 5 69 + 6 69 + 7 69 + 10 70 + 11 71 + 12 71 + 13 71 + 14 71 + 15 71 + 16 71 + 17 71 + 18 71 + 19 71 + 1a 71 + 1b 71 + 1c 71 + 1d 71 + 1e 71 + 1f 71 + 20 71 + 21 71 + 22 71 + 23 71 + 24 71 + 25 71 + 26 71 + 27 71 + 28 71 + 29 71 + 2a 71 + 2b 71 + 2c 75 + 2d 75 + 2e 75 + 2f 75 + 30 75 + 31 75 + 32 75 + 33 75 + 3b 76 + 4c 79 } } Lines mapping: -13 <-> 8 -14 <-> 9 -15 <-> 11 -17 <-> 17 -18 <-> 18 -19 <-> 14 -22 <-> 21 -24 <-> 23 -28 <-> 27 -29 <-> 28 -30 <-> 30 -32 <-> 35 -33 <-> 36 -34 <-> 33 -37 <-> 39 -43 <-> 45 -44 <-> 46 -45 <-> 47 -47 <-> 53 -48 <-> 54 -50 <-> 49 -53 <-> 57 -55 <-> 59 -59 <-> 63 -60 <-> 64 -61 <-> 65 -63 <-> 70 -64 <-> 71 -66 <-> 67 -69 <-> 74 -75 <-> 80 -76 <-> 81 -77 <-> 82 -79 <-> 86 -80 <-> 87 -85 <-> 90 +13 <-> 6 +14 <-> 7 +15 <-> 8 +17 <-> 12 +18 <-> 13 +19 <-> 9 +22 <-> 16 +24 <-> 18 +28 <-> 22 +29 <-> 23 +30 <-> 24 +32 <-> 27 +33 <-> 28 +34 <-> 25 +37 <-> 31 +43 <-> 37 +44 <-> 38 +45 <-> 39 +47 <-> 44 +48 <-> 45 +50 <-> 40 +53 <-> 48 +55 <-> 50 +59 <-> 54 +60 <-> 55 +61 <-> 56 +63 <-> 60 +64 <-> 61 +66 <-> 57 +69 <-> 64 +75 <-> 70 +76 <-> 71 +77 <-> 72 +79 <-> 76 +80 <-> 77 +85 <-> 80 Not mapped: 23 54 diff --git a/testData/results/pkg/TestSwitchPatternMatching4.dec b/testData/results/pkg/TestSwitchPatternMatching4.dec index a987afc09..7b82360cf 100644 --- a/testData/results/pkg/TestSwitchPatternMatching4.dec +++ b/testData/results/pkg/TestSwitchPatternMatching4.dec @@ -1,11 +1,8 @@ package pkg; -import java.util.Objects; - public class TestSwitchPatternMatching4 { static void test(Object s) { - Objects.requireNonNull(s);// 5 - switch (s) { + switch (s) {// 5 default: System.out.println("default");// 7 } @@ -14,36 +11,33 @@ public class TestSwitchPatternMatching4 { class 'pkg/TestSwitchPatternMatching4' { method 'test (Ljava/lang/Object;)V' { - 0 6 - 2 6 - 3 6 - 4 6 - 9 7 - 10 7 - 11 7 - 12 7 - 13 7 - 14 7 - 15 7 - 16 7 - 17 7 - 18 7 - 19 7 - 1a 7 - 1b 7 - 1c 9 - 1d 9 - 1e 9 - 1f 9 - 20 9 - 21 9 - 22 9 - 23 9 - 24 11 + 0 4 + 9 4 + 10 4 + 11 4 + 12 4 + 13 4 + 14 4 + 15 4 + 16 4 + 17 4 + 18 4 + 19 4 + 1a 4 + 1b 4 + 1c 6 + 1d 6 + 1e 6 + 1f 6 + 20 6 + 21 6 + 22 6 + 23 6 + 24 8 } } Lines mapping: -5 <-> 7 -7 <-> 10 -9 <-> 12 +5 <-> 5 +7 <-> 7 +9 <-> 9 diff --git a/testData/results/pkg/TestSwitchPatternMatchingConstructor2.dec b/testData/results/pkg/TestSwitchPatternMatchingConstructor2.dec index c45b4f91b..a5721628e 100644 --- a/testData/results/pkg/TestSwitchPatternMatchingConstructor2.dec +++ b/testData/results/pkg/TestSwitchPatternMatchingConstructor2.dec @@ -1,7 +1,5 @@ package pkg; -import java.util.Objects; - public class TestSwitchPatternMatchingConstructor2 { private TestSwitchPatternMatchingConstructor2(String s) { System.out.println(s);// 5 @@ -15,7 +13,6 @@ public class TestSwitchPatternMatchingConstructor2 { }// 13 private TestSwitchPatternMatchingConstructor2(Object s, boolean unused) { - Objects.requireNonNull(s); switch (s) { default: this("Non-triangle");// 16 17 @@ -25,82 +22,79 @@ public class TestSwitchPatternMatchingConstructor2 { class 'pkg/TestSwitchPatternMatchingConstructor2' { method ' (Ljava/lang/String;)V' { - 4 6 - 5 6 - 6 6 - 7 6 - 8 6 - 9 6 - a 6 - b 7 + 4 4 + 5 4 + 6 4 + 7 4 + 8 4 + 9 4 + a 4 + b 5 } method ' (Ljava/lang/Object;)V' { - 1 10 - 5 10 - c 10 - d 10 - e 10 - f 10 - 10 10 - 11 10 - 12 10 - 13 10 - 14 10 - 15 10 - 16 10 - 17 10 - 18 10 - 19 10 - 1a 10 - 1b 10 - 1c 10 - 1d 10 - 1e 10 - 1f 10 - 20 11 - 21 11 - 25 12 - 26 12 - 27 10 - 28 10 - 29 10 - 2a 14 + 1 8 + 5 8 + c 8 + d 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 9 + 21 9 + 25 10 + 26 10 + 27 8 + 28 8 + 29 8 + 2a 12 } method ' (Ljava/lang/Object;Z)V' { - 1 17 - 3 17 - 4 17 - 5 17 - b 18 - 13 18 - 14 18 - 15 18 - 16 18 - 17 18 - 18 18 - 19 18 - 1a 18 - 1b 18 - 1c 20 - 1d 20 - 1e 20 - 1f 20 - 20 20 - 21 22 + 1 15 + b 15 + 13 15 + 14 15 + 15 15 + 16 15 + 17 15 + 18 15 + 19 15 + 1a 15 + 1b 15 + 1c 17 + 1d 17 + 1e 17 + 1f 17 + 20 17 + 21 19 } } Lines mapping: -5 <-> 7 -6 <-> 8 -9 <-> 11 -10 <-> 12 -11 <-> 13 -13 <-> 15 -16 <-> 21 -17 <-> 21 -19 <-> 23 +5 <-> 5 +6 <-> 6 +9 <-> 9 +10 <-> 10 +11 <-> 11 +13 <-> 13 +16 <-> 18 +17 <-> 18 +19 <-> 20 Not mapped: 4 diff --git a/testData/results/pkg/TestSwitchPatternMatchingJ21.dec b/testData/results/pkg/TestSwitchPatternMatchingJ21.dec index f578579d4..b72e28ef3 100644 --- a/testData/results/pkg/TestSwitchPatternMatchingJ21.dec +++ b/testData/results/pkg/TestSwitchPatternMatchingJ21.dec @@ -1,68 +1,197 @@ package pkg; +import java.util.function.Supplier; + public class TestSwitchPatternMatchingJ21 { public void test1(Object o) { - System.out.println(switch (o) {// 5 - case Integer i -> Integer.toString(i);// 6 - case null, default -> "null";// 7 + System.out.println(switch (o) {// 7 + case Integer i -> Integer.toString(i);// 8 + case null, default -> "null";// 9 }); - }// 9 + }// 11 + + public String test2(Object o) { + return switch (o) {// 14 + case Integer i -> Integer.toString(i);// 15 + case String s -> s;// 16 + default -> "null";// 17 + }; + } + + public String test3(Supplier o) { + return switch (o.get()) {// 22 + case Integer i -> Integer.toString(i);// 23 + case String s -> s;// 24 + default -> "null";// 25 + }; + } } class 'pkg/TestSwitchPatternMatchingJ21' { method 'test1 (Ljava/lang/Object;)V' { - 0 4 - 1 4 - 2 4 - 3 4 - 7 4 - e 4 - f 4 - 10 4 - 11 4 - 12 4 - 13 4 - 14 4 - 15 4 - 16 4 - 17 4 - 18 4 - 19 4 - 1a 4 - 1b 4 - 1c 4 - 1d 4 - 1e 4 - 1f 4 - 20 4 - 21 4 - 22 4 - 23 4 - 24 4 - 25 4 - 26 4 - 27 4 - 2c 5 - 2d 5 - 2e 5 - 2f 5 - 30 5 - 31 5 - 32 5 - 33 5 - 34 5 - 35 5 - 39 6 - 3a 6 - 3b 4 - 3c 4 - 3d 4 - 3e 8 + 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 + } + + 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 + } + + 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 } } Lines mapping: -5 <-> 5 -6 <-> 6 7 <-> 7 +8 <-> 8 9 <-> 9 +11 <-> 11 +14 <-> 14 +15 <-> 15 +16 <-> 16 +17 <-> 17 +22 <-> 22 +23 <-> 23 +24 <-> 24 +25 <-> 25 diff --git a/testData/results/pkg/TestSwitchPatternMatchingLoop.dec b/testData/results/pkg/TestSwitchPatternMatchingLoop.dec index 9d691e77f..eb324d402 100644 --- a/testData/results/pkg/TestSwitchPatternMatchingLoop.dec +++ b/testData/results/pkg/TestSwitchPatternMatchingLoop.dec @@ -1,12 +1,9 @@ package pkg; -import java.util.Objects; - public class TestSwitchPatternMatchingLoop { public void test(Object o) { while (true) { - Objects.requireNonNull(o);// 6 - switch (o) { + switch (o) {// 6 case Integer i:// 7 System.out.println(i); break; @@ -22,74 +19,71 @@ public class TestSwitchPatternMatchingLoop { class 'pkg/TestSwitchPatternMatchingLoop' { method 'test (Ljava/lang/Object;)V' { - 0 7 - 2 7 - 3 7 - 4 7 - 9 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 - 28 8 - 29 8 - 2a 8 - 2b 8 - 30 9 - 31 9 - 32 10 - 33 10 - 34 10 - 35 10 - 36 10 - 37 10 - 38 10 - 39 10 - 3a 11 - 41 12 - 42 12 - 43 13 - 44 13 - 45 13 - 46 13 - 47 13 - 48 13 - 49 13 - 4a 13 - 4b 14 - 4e 16 - 4f 16 - 50 16 - 51 16 - 52 16 - 53 16 - 54 16 - 55 16 + 0 5 + 9 5 + 10 5 + 11 5 + 12 5 + 13 5 + 14 5 + 15 5 + 16 5 + 17 5 + 18 5 + 19 5 + 1a 5 + 1b 5 + 1c 5 + 1d 5 + 1e 5 + 1f 5 + 20 5 + 21 5 + 22 5 + 23 5 + 24 5 + 25 5 + 26 5 + 27 5 + 28 5 + 29 5 + 2a 5 + 2b 5 + 30 6 + 31 6 + 32 7 + 33 7 + 34 7 + 35 7 + 36 7 + 37 7 + 38 7 + 39 7 + 3a 8 + 41 9 + 42 9 + 43 10 + 44 10 + 45 10 + 46 10 + 47 10 + 48 10 + 49 10 + 4a 10 + 4b 11 + 4e 13 + 4f 13 + 50 13 + 51 13 + 52 13 + 53 13 + 54 13 + 55 13 } } Lines mapping: -6 <-> 8 -7 <-> 10 -8 <-> 13 -9 <-> 17 +6 <-> 6 +7 <-> 7 +8 <-> 10 +9 <-> 14 diff --git a/testData/results/pkg/TestSwitchPatternMatchingReturn1.dec b/testData/results/pkg/TestSwitchPatternMatchingReturn1.dec index b648eea7b..718771719 100644 --- a/testData/results/pkg/TestSwitchPatternMatchingReturn1.dec +++ b/testData/results/pkg/TestSwitchPatternMatchingReturn1.dec @@ -1,11 +1,7 @@ package pkg; -import java.util.Objects; - public class TestSwitchPatternMatchingReturn1 { public int test(Object o) { - Objects.requireNonNull(o); - return switch (o) {// 5 case Integer i -> i;// 6 case String s -> s.length();// 7 @@ -16,60 +12,57 @@ public class TestSwitchPatternMatchingReturn1 { class 'pkg/TestSwitchPatternMatchingReturn1' { method 'test (Ljava/lang/Object;)I' { - 0 6 - 2 6 - 3 6 - 4 6 - 9 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 - 28 8 - 29 8 - 2a 8 - 2b 8 - 30 9 - 31 9 - 32 9 - 33 9 - 34 9 - 35 9 - 36 9 - 3e 10 - 3f 10 - 40 10 - 41 10 - 42 10 - 43 10 - 44 10 - 48 11 - 49 8 + 0 4 + 9 4 + 10 4 + 11 4 + 12 4 + 13 4 + 14 4 + 15 4 + 16 4 + 17 4 + 18 4 + 19 4 + 1a 4 + 1b 4 + 1c 4 + 1d 4 + 1e 4 + 1f 4 + 20 4 + 21 4 + 22 4 + 23 4 + 24 4 + 25 4 + 26 4 + 27 4 + 28 4 + 29 4 + 2a 4 + 2b 4 + 30 5 + 31 5 + 32 5 + 33 5 + 34 5 + 35 5 + 36 5 + 3e 6 + 3f 6 + 40 6 + 41 6 + 42 6 + 43 6 + 44 6 + 48 7 + 49 4 } } Lines mapping: -5 <-> 9 -6 <-> 10 -7 <-> 11 -8 <-> 12 +5 <-> 5 +6 <-> 6 +7 <-> 7 +8 <-> 8 diff --git a/testData/results/pkg/TestUnknownCastJ17.dec b/testData/results/pkg/TestUnknownCastJ17.dec index d0626a4a5..639769833 100644 --- a/testData/results/pkg/TestUnknownCastJ17.dec +++ b/testData/results/pkg/TestUnknownCastJ17.dec @@ -1,21 +1,12 @@ package pkg; import java.lang.annotation.ElementType; -import java.util.Objects; public class TestUnknownCastJ17 { - // $VF: Could not properly define all variable types! public void test() { ElementType vvv1 = ElementType.METHOD;// 8 synchronized (this) {// 9 - label91: { - System.out.println(vvv1);// 10 - Object var23; - Objects.requireNonNull(var23);// 11 - Object vvv5 = var23; - - var10000_1 = ()(new Object()); - } + System.out.println(vvv1);// 10 } try { @@ -29,13 +20,8 @@ public class TestUnknownCastJ17 { synchronized (this) {// 35 System.out.println(vvv1);// 36 System.out.println(vvv1);// 37 - Object var10000; - Objects.requireNonNull(var10000);// 38 - Object vvv5 = var10000; - - new Object(); - for (int var9 = switch (vvv5) { + for (int var9 = switch (new Object()) {// 38 default -> { ElementType var5 = ElementType.METHOD;// 40 System.out.println(vvv1);// 42 @@ -56,131 +42,122 @@ public class TestUnknownCastJ17 { class 'pkg/TestUnknownCastJ17' { method 'test ()V' { - 0 8 - 1 8 - 2 8 - 3 8 - 4 9 - 7 9 - 8 11 - 9 11 - a 11 - b 11 - c 11 - d 11 - e 11 - 17 13 - 18 13 - 19 13 - 1b 14 - a8 21 - a9 22 - aa 24 + 0 6 + 1 6 + 2 6 + 3 6 + 4 7 + 7 7 + 8 8 + 9 8 + a 8 + b 8 + c 8 + d 8 + e 8 + a8 12 + a9 13 + aa 15 } method 'test2 ()V' { - 0 27 - 1 27 - 2 27 - 3 27 - 4 28 - 7 28 - 8 29 - 9 29 - a 29 - b 29 - c 29 - d 29 - e 29 - f 30 - 10 30 - 11 30 - 12 30 - 13 30 - 14 30 - 15 30 - 1e 32 - 1f 32 - 20 32 - 22 33 - 26 37 - 2e 37 - 2f 37 - 30 37 - 31 37 - 32 37 - 33 37 - 34 37 - 35 37 - 36 37 - 37 37 - 38 39 - 39 39 - 3a 39 - 3b 39 - 3c 39 - 3d 40 - 3e 40 - 3f 40 - 40 40 - 41 40 - 42 40 - 43 40 - 44 41 - 45 41 - 46 41 - 48 43 - 49 43 - 4a 43 - 4b 43 - 4c 43 - 4d 43 - 4e 43 - 4f 43 - 50 43 - 51 43 - 52 44 - 53 44 - 54 44 - 55 44 - 56 45 - 57 45 - 58 45 - 59 45 - 5a 45 - 5b 45 - 5c 45 - 5d 43 - 5e 43 - 5f 43 - 76 50 - 77 51 - 78 53 + 0 18 + 1 18 + 2 18 + 3 18 + 4 19 + 7 19 + 8 20 + 9 20 + a 20 + b 20 + c 20 + d 20 + e 20 + f 21 + 10 21 + 11 21 + 12 21 + 13 21 + 14 21 + 15 21 + 2e 23 + 2f 23 + 30 23 + 31 23 + 32 23 + 33 23 + 34 23 + 35 23 + 36 23 + 37 23 + 38 25 + 39 25 + 3a 25 + 3b 25 + 3c 25 + 3d 26 + 3e 26 + 3f 26 + 40 26 + 41 26 + 42 26 + 43 26 + 44 27 + 45 27 + 46 27 + 48 29 + 49 29 + 4a 29 + 4b 29 + 4c 29 + 4d 29 + 4e 29 + 4f 29 + 50 29 + 51 29 + 52 30 + 53 30 + 54 30 + 55 30 + 56 31 + 57 31 + 58 31 + 59 31 + 5a 31 + 5b 31 + 5c 31 + 5d 29 + 5e 29 + 5f 29 + 76 36 + 77 37 + 78 39 } } Lines mapping: -8 <-> 9 -9 <-> 10 -10 <-> 12 -11 <-> 14 -28 <-> 22 -29 <-> 23 -31 <-> 25 -34 <-> 28 -35 <-> 29 -36 <-> 30 -37 <-> 31 -38 <-> 33 -40 <-> 40 -42 <-> 41 -43 <-> 44 -44 <-> 45 -45 <-> 46 -51 <-> 51 -52 <-> 52 -54 <-> 54 +8 <-> 7 +9 <-> 8 +10 <-> 9 +28 <-> 13 +29 <-> 14 +31 <-> 16 +34 <-> 19 +35 <-> 20 +36 <-> 21 +37 <-> 22 +38 <-> 24 +40 <-> 26 +42 <-> 27 +43 <-> 30 +44 <-> 31 +45 <-> 32 +51 <-> 37 +52 <-> 38 +54 <-> 40 Not mapped: +11 13 15 16 From 630b77416e02aa94f4903f85ac62953f528d1f5b Mon Sep 17 00:00:00 2001 From: coehlrich Date: Tue, 21 May 2024 12:43:08 +1200 Subject: [PATCH 3/3] Comments and put streams on multiple lines --- .../SwitchPatternMatchProcessor.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java index d97295de9..d429f63e6 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/SwitchPatternMatchProcessor.java @@ -266,12 +266,28 @@ private static boolean processStatement(SwitchStatement stat, Statement root) { } } + // Try to inline: + // var stackVar = ... + // Objects.requireNonNull(stackVar) + // var var1 = stackVar + // switch (var1) { + // + // to: + // switch (...) { + Exprent oldSelector = realSelector; // inline head List basicHead = stat.getBasichead().getExprents(); if (realSelector instanceof VarExprent var && basicHead != null && basicHead.size() >= 1) { if (basicHead.get(basicHead.size() - 1) instanceof AssignmentExprent assignment && assignment.getLeft() instanceof VarExprent assigned) { - if (var.equals(assigned) && !var.isVarReferenced(root, Stream.concat(Stream.of(assigned), stat.getCaseValues().stream().flatMap(List::stream).filter(exp -> exp instanceof FunctionExprent func && func.getFuncType() == FunctionType.INSTANCEOF && func.getLstOperands().get(0) instanceof VarExprent checked && checked.equals(var)).map(exp -> (VarExprent) ((FunctionExprent) exp).getLstOperands().get(0))).toArray(VarExprent[]::new))) { + if (var.equals(assigned) && !var.isVarReferenced(root, + Stream.concat( + Stream.of(assigned), + stat.getCaseValues().stream() + .flatMap(List::stream) + .filter(exp -> exp instanceof FunctionExprent func && func.getFuncType() == FunctionType.INSTANCEOF && func.getLstOperands().get(0) instanceof VarExprent checked && checked.equals(var)) + .map(exp -> (VarExprent) ((FunctionExprent) exp).getLstOperands().get(0))) + .toArray(VarExprent[]::new))) { realSelector = assignment.getRight(); basicHead.remove(basicHead.size() - 1); } @@ -298,7 +314,12 @@ private static boolean processStatement(SwitchStatement stat, Statement root) { if (oldSelector != realSelector) { Exprent finalSelector = realSelector; - stat.getCaseValues().stream().flatMap(List::stream).filter(Objects::nonNull).filter(exp -> exp instanceof FunctionExprent func && func.getFuncType() == FunctionType.INSTANCEOF && func.getLstOperands().get(0).equals(oldSelector)).forEach(exp -> ((FunctionExprent) exp).getLstOperands().set(0, finalSelector)); + // Replace the original selector with the new selector in instanceof check in case values + stat.getCaseValues().stream() + .flatMap(List::stream) + .filter(Objects::nonNull) + .filter(exp -> exp instanceof FunctionExprent func && func.getFuncType() == FunctionType.INSTANCEOF && func.getLstOperands().get(0).equals(oldSelector)) + .forEach(exp -> ((FunctionExprent) exp).getLstOperands().set(0, finalSelector)); } head.setValue(realSelector); // SwitchBootstraps.typeSwitch(o, var1) -> o