From f8d38e4fdd27e0bc751f11a0b6a8fe41d28a80b2 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Sat, 15 Jul 2023 10:03:48 -0400 Subject: [PATCH 01/18] Version bump --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3aba3e2a8a..051b5c2622 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ compileJava { group = 'org.vineflower' archivesBaseName = 'vineflower' -version = '1.9.1' +version = '1.9.2' def ENV = System.getenv() version = version + (ENV.GITHUB_ACTIONS ? "" : "+local") From 0690cf272f969fb8ccb747702fd1d807a152c116 Mon Sep 17 00:00:00 2001 From: SuperCoder79 <25208576+SuperCoder7979@users.noreply.github.com> Date: Mon, 9 Jan 2023 11:26:06 -0500 Subject: [PATCH 02/18] Hackfix to stop inconsistent decompilation of pi constants --- .../modules/decompiler/exps/ArrayExprent.java | 2 +- .../decompiler/exps/AssignmentExprent.java | 2 +- .../modules/decompiler/exps/ConstExprent.java | 9 +- .../modules/decompiler/exps/FieldExprent.java | 2 +- .../decompiler/exps/FunctionExprent.java | 2 +- .../decompiler/exps/InvocationExprent.java | 2 +- .../java/decompiler/util/TextBuffer.java | 20 +++++ testData/results/pkg/TestPiDivision.dec | 89 +++++++++++++++++++ .../src/java8/pkg/TestConstantUninlining.java | 1 - testData/src/java8/pkg/TestPiDivision.java | 24 +++++ 10 files changed, 143 insertions(+), 10 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java index db93dcc9ef..569654bf85 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java @@ -76,7 +76,7 @@ public TextBuffer toJava(int indent) { TextBuffer res = array.toJava(indent); if (array.getPrecedence() > getPrecedence() && !canSkipParenEnclose(array)) { // array precedence equals 0 - res.enclose("(", ")"); + res.encloseWithParens(); } VarType arrType = array.getExprType(); diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java index 808346e1c3..556f289c3c 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java @@ -297,7 +297,7 @@ private void wrapInCast(VarType left, VarType right, TextBuffer buf, int precede } if (precedence >= FunctionExprent.FunctionType.CAST.precedence) { - buf.enclose("(", ")"); + buf.encloseWithParens(); } buf.prepend("(" + ExprProcessor.getCastTypeName(left) + ")"); diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java index dfba0bc2d8..b0ad986873 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java @@ -104,8 +104,7 @@ public class ConstExprent extends Exprent { UNINLINED_FLOATS.put(key.floatValue(), bytecode -> { TextBuffer doubleValue = valueFunction.apply(bytecode); if (doubleValue.count(" ", 0) > 0) { // As long as all uninlined double values with more than one expression have a space in it, this'll work. - NO_PAREN_VALUES.add(key.floatValue()); - doubleValue.prepend("(").append(")"); + doubleValue.encloseWithParens(); } return doubleValue.prepend("(float) "); }); @@ -369,18 +368,20 @@ public int getPrecedence() { VarType unboxed = VarType.UNBOXING_TYPES.getOrDefault(constType, constType); + // FIXME: this entire system is terrible, and pi constants need to be fixed to not create field exprents + switch (unboxed.type) { case CodeConstants.TYPE_FLOAT: float floatVal = (Float)value; - if (UNINLINED_FLOATS.containsKey(floatVal) && !NO_PAREN_VALUES.contains(floatVal)) { + if (UNINLINED_FLOATS.containsKey(floatVal) && !NO_PAREN_VALUES.contains(floatVal) && UNINLINED_FLOATS.get(floatVal).apply(bytecode).countChars('(') < 2) { return 4; } break; case CodeConstants.TYPE_DOUBLE: double doubleVal = (Double)value; - if (UNINLINED_DOUBLES.containsKey(doubleVal) && !NO_PAREN_VALUES.contains(doubleVal)) { + if (UNINLINED_DOUBLES.containsKey(doubleVal) && !NO_PAREN_VALUES.contains(doubleVal) && UNINLINED_DOUBLES.get(doubleVal).apply(bytecode).countChars('(') < 2) { return 4; } break; diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java index 3caa561ff9..19752886b5 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java @@ -186,7 +186,7 @@ public TextBuffer toJava(int indent) { boolean casted = ExprProcessor.getCastedExprent(instance, new VarType(CodeConstants.TYPE_OBJECT, 0, classname), buff, indent, true); if (casted || instance.getPrecedence() > getPrecedence()) { - buff.enclose("(", ")"); + buff.encloseWithParens(); } buf.append(buff); diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java index 01036fb9a1..c20b6d9aa4 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java @@ -546,7 +546,7 @@ else if (left instanceof ConstExprent) { if (!needsCast) { return buf.append(lstOperands.get(0).toJava(indent)); } - return buf.append(lstOperands.get(1).toJava(indent)).enclose("(", ")").append(wrapOperandString(lstOperands.get(0), true, indent)); + return buf.append(lstOperands.get(1).toJava(indent)).encloseWithParens().append(wrapOperandString(lstOperands.get(0), true, indent)); case ARRAY_LENGTH: Exprent arr = lstOperands.get(0); diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java index 2460419b8b..ff1bbf33e5 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java @@ -649,7 +649,7 @@ else if (instance != null) { buf.append("((").append(ExprProcessor.getCastTypeName(leftType)).append(")"); if (instance.getPrecedence() >= FunctionType.CAST.precedence) { - res.enclose("(", ")"); + res.encloseWithParens(); } buf.append(res).append(")"); } diff --git a/src/org/jetbrains/java/decompiler/util/TextBuffer.java b/src/org/jetbrains/java/decompiler/util/TextBuffer.java index 4260b7f88d..1e1688318e 100644 --- a/src/org/jetbrains/java/decompiler/util/TextBuffer.java +++ b/src/org/jetbrains/java/decompiler/util/TextBuffer.java @@ -139,6 +139,10 @@ public TextBuffer enclose(String left, String right) { return this; } + public TextBuffer encloseWithParens() { + return enclose("(", ")"); + } + public boolean containsOnlyWhitespaces() { for (int i = 0; i < myStringBuilder.length(); i++) { if (myStringBuilder.charAt(i) != ' ') { @@ -536,6 +540,22 @@ public int count(String substring, int from) { return count; } + @Deprecated + public int countChars(char c) { + convertToStringAndAllowDataDiscard(); + + int count = 0; + + CharSequence chars = myStringBuilder.subSequence(0, myStringBuilder.length()); + for (int i = 0; i < chars.length(); i++) { + if (chars.charAt(i) == c) { + count++; + } + } + + return count; + } + private static List compactLines(List srcLines, int requiredLineNumber) { if (srcLines.size() < 2 || srcLines.size() <= requiredLineNumber) { return srcLines; diff --git a/testData/results/pkg/TestPiDivision.dec b/testData/results/pkg/TestPiDivision.dec index 53c2644839..588a72f491 100644 --- a/testData/results/pkg/TestPiDivision.dec +++ b/testData/results/pkg/TestPiDivision.dec @@ -4,6 +4,30 @@ public class TestPiDivision { public double div(double val) { return val / (180.0 / Math.PI);// 5 } + + public float mul(float f) { + return f * (float) (Math.PI / 180.0);// 9 + } + + public float mul2(float f) { + return f * (180.0F / (float)Math.PI);// 13 + } + + public float mul2_ok(float f) { + return f * 180.0F / (float) Math.PI;// 17 + } + + public double mul3(double val) { + return val * (180.0 / Math.PI);// 21 + } + + public double mul3_ok(double val) { + return val * 180.0 / Math.PI;// 25 + } + + public boolean isInf(double d) { + return d == Double.POSITIVE_INFINITY;// 29 + } } class 'pkg/TestPiDivision' { @@ -15,7 +39,72 @@ class 'pkg/TestPiDivision' { 4 4 5 4 } + + method 'mul (F)F' { + 0 8 + 1 8 + 2 8 + 3 8 + 4 8 + } + + method 'mul2 (F)F' { + 0 12 + 1 12 + 2 12 + 3 12 + 4 12 + } + + method 'mul2_ok (F)F' { + 0 16 + 1 16 + 2 16 + 3 16 + 4 16 + 5 16 + 6 16 + 7 16 + } + + method 'mul3 (D)D' { + 0 20 + 1 20 + 2 20 + 3 20 + 4 20 + 5 20 + } + + method 'mul3_ok (D)D' { + 0 24 + 1 24 + 2 24 + 3 24 + 4 24 + 5 24 + 6 24 + 7 24 + 8 24 + 9 24 + } + + method 'isInf (D)Z' { + 0 28 + 1 28 + 2 28 + 3 28 + 4 28 + 5 28 + d 28 + } } Lines mapping: 5 <-> 5 +9 <-> 9 +13 <-> 13 +17 <-> 17 +21 <-> 21 +25 <-> 25 +29 <-> 29 diff --git a/testData/src/java8/pkg/TestConstantUninlining.java b/testData/src/java8/pkg/TestConstantUninlining.java index 1e1609402a..1dbb2e8ee2 100644 --- a/testData/src/java8/pkg/TestConstantUninlining.java +++ b/testData/src/java8/pkg/TestConstantUninlining.java @@ -40,5 +40,4 @@ class TestConstantUninlining { static final double DE = Math.E; static final double DENeg = -Math.E; - } \ No newline at end of file diff --git a/testData/src/java8/pkg/TestPiDivision.java b/testData/src/java8/pkg/TestPiDivision.java index 4125bc4ab1..986f47dce4 100644 --- a/testData/src/java8/pkg/TestPiDivision.java +++ b/testData/src/java8/pkg/TestPiDivision.java @@ -4,4 +4,28 @@ public class TestPiDivision { public double div(double val) { return val / (180 / Math.PI); } + + public float mul(float f) { + return f * (float) (Math.PI / 180.0); + } + + public float mul2(float f) { + return f * (180.0F / (float)Math.PI); + } + + public float mul2_ok(float f) { + return f * 180.0F / (float)Math.PI; + } + + public double mul3(double val) { + return val * (180 / Math.PI); + } + + public double mul3_ok(double val) { + return val * 180 / Math.PI; + } + + public boolean isInf(double d) { + return d == Double.POSITIVE_INFINITY; + } } From ff1686efd818ffc8567e9bc0e71003b5a2e35d42 Mon Sep 17 00:00:00 2001 From: SuperCoder79 <25208576+SuperCoder7979@users.noreply.github.com> Date: Wed, 23 Nov 2022 11:56:48 -0500 Subject: [PATCH 03/18] Fix try with resources being matched in improper cases --- .../decompiler/TryWithResourcesProcessor.java | 21 +++++++++++++++++++ .../pkg/TestTryWithResourcesFakeTrigger.dec | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/TryWithResourcesProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/TryWithResourcesProcessor.java index 19c3bcb2e9..84cbd2fa9c 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/TryWithResourcesProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/TryWithResourcesProcessor.java @@ -109,6 +109,10 @@ public static boolean makeTryWithResourceJ11(CatchStatement tryStatement) { return false; } + if (!tryStatement.getVars().get(0).getVarType().value.equals("java/lang/Throwable")) { + return false; + } + Statement inner = tryStatement.getStats().get(1); // Get catch block VarExprent closeable = null; @@ -125,6 +129,11 @@ public static boolean makeTryWithResourceJ11(CatchStatement tryStatement) { return false; } + CatchStatement innerTry = (CatchStatement)inner; + if (!innerTry.getVars().get(0).getVarType().value.equals("java/lang/Throwable")) { + return false; + } + Statement inTry = inner.getStats().get(0); // Catch block contains a basic block inside which has the closeable invocation @@ -164,6 +173,15 @@ public static boolean makeTryWithResourceJ11(CatchStatement tryStatement) { // Process try catch inside of if statement if (inner instanceof CatchStatement && !inner.getStats().isEmpty()) { + if (inner.getStats().isEmpty()) { + return false; + } + + CatchStatement innerTry = (CatchStatement)inner; + if (!innerTry.getVars().get(0).getVarType().value.equals("java/lang/Throwable")) { + return false; + } + Statement inTry = inner.getStats().get(0); if (inTry instanceof BasicBlockStatement && !inTry.getExprents().isEmpty()) { @@ -192,6 +210,9 @@ public static boolean makeTryWithResourceJ11(CatchStatement tryStatement) { } Set destinations = findExitpoints(tryStatement); + if (destinations.isEmpty()) { + return false; + } Statement check = tryStatement; List preds = new ArrayList<>(); diff --git a/testData/results/pkg/TestTryWithResourcesFakeTrigger.dec b/testData/results/pkg/TestTryWithResourcesFakeTrigger.dec index b2f9dcf516..8f73334e01 100644 --- a/testData/results/pkg/TestTryWithResourcesFakeTrigger.dec +++ b/testData/results/pkg/TestTryWithResourcesFakeTrigger.dec @@ -96,4 +96,4 @@ Not mapped: 16 18 30 -33 +33 \ No newline at end of file From 2dd839ec8432b9dec63bf8dc7397918bf2ebc844 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Sat, 15 Jul 2023 14:10:22 -0400 Subject: [PATCH 04/18] Fix switch statements losing their default case in IdentifyLabels --- .../java/decompiler/modules/decompiler/LabelHelper.java | 3 ++- .../decompiler/modules/decompiler/stats/SwitchStatement.java | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java index 02af808ee2..427c1ad15e 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/LabelHelper.java @@ -30,7 +30,8 @@ public static void identifyLabels(RootStatement root) { setExplicitEdges(root); - hideDefaultSwitchEdges(root); + // TODO: is this correct? we don't want to mess with case statements while processing still happens! +// hideDefaultSwitchEdges(root); processStatementLabel(root); diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java index 2e2b014ab3..84d8cbc52b 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java @@ -9,6 +9,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; +import org.jetbrains.java.decompiler.modules.decompiler.ValidationHelper; import org.jetbrains.java.decompiler.modules.decompiler.exps.*; import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent.FunctionType; import org.jetbrains.java.decompiler.struct.gen.VarType; @@ -308,12 +309,16 @@ public void replaceExprent(Exprent oldexpr, Exprent newexpr) { @Override public void replaceStatement(Statement oldstat, Statement newstat) { + boolean changedAny = false; for (int i = 0; i < caseStatements.size(); i++) { if (caseStatements.get(i) == oldstat) { caseStatements.set(i, newstat); + changedAny = true; } } + ValidationHelper.assertTrue(changedAny, "Replaced statement in switch without changing any case statements!"); + super.replaceStatement(oldstat, newstat); } From e2abac12cf47d19baffddc809d33485eb9ef6031 Mon Sep 17 00:00:00 2001 From: ByMartrixx Date: Sat, 15 Jul 2023 21:35:53 -0400 Subject: [PATCH 05/18] Test for the switch statement losing its default case + extra test Fixes #287 --- .../java/decompiler/SingleClassesTest.java | 5 +- .../results/pkg/TestSingleCaseStrSwitch.dec | 51 ++++++++ .../pkg/TestSwitchDefaultCaseReturn.dec | 117 ++++++++++++++++++ .../java17/pkg/TestSingleCaseStrSwitch.java | 10 ++ .../pkg/TestSwitchDefaultCaseReturn.java | 33 +++++ 5 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 testData/results/pkg/TestSingleCaseStrSwitch.dec create mode 100644 testData/results/pkg/TestSwitchDefaultCaseReturn.dec create mode 100644 testData/src/java17/pkg/TestSingleCaseStrSwitch.java create mode 100644 testData/src/java17/pkg/TestSwitchDefaultCaseReturn.java diff --git a/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 7b1652ef38..4dcd9d121f 100644 --- a/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -445,7 +445,7 @@ private void registerDefault() { register(JAVA_17_PREVIEW, "TestSwitchPatternMatchingWithNull"); register(JAVA_17_PREVIEW, "TestSwitchPatternMatchingFuzz1"); - + // TODO: non-resugared record patterns reference hidden proxy methods register(JAVA_19_PREVIEW, "TestRecordPattern1"); register(JAVA_19_PREVIEW, "TestRecordPattern2"); @@ -642,6 +642,9 @@ private void registerDefault() { register(JAVA_17_PREVIEW, "TestUnknownCastJ17"); // TODO: These variables shouldn't be merged, and should be split because each version is used once and has a different type use register(JAVA_8_NODEBUG, "TestVarIndex"); + register(JAVA_17, "TestSwitchDefaultCaseReturn"); + // TODO: switch (s) decompiled as switch (s.hashCode()) + register(JAVA_17, "TestSingleCaseStrSwitch"); } private void registerEntireClassPath() { diff --git a/testData/results/pkg/TestSingleCaseStrSwitch.dec b/testData/results/pkg/TestSingleCaseStrSwitch.dec new file mode 100644 index 0000000000..fa50e19b65 --- /dev/null +++ b/testData/results/pkg/TestSingleCaseStrSwitch.dec @@ -0,0 +1,51 @@ +package pkg; + +public class TestSingleCaseStrSwitch { + public String test(String s) { + byte var3 = -1; + switch(s.hashCode()) { + case 0: + if (s.equals("")) { + var3 = 0; + } + default: + return switch(var3) {// 5 + case 0 -> "foo bar";// 6 + default -> s;// 7 + }; + } + } +} + +class 'pkg/TestSingleCaseStrSwitch' { + method 'test (Ljava/lang/String;)Ljava/lang/String;' { + 0 5 + 2 4 + 3 4 + 4 5 + 5 5 + 6 5 + 7 5 + 8 5 + 1c 7 + 1d 7 + 1e 7 + 1f 7 + 20 7 + 21 7 + 22 7 + 25 8 + 26 8 + 27 11 + 28 11 + 3c 12 + 3d 12 + 41 13 + 42 11 + } +} + +Lines mapping: +5 <-> 12 +6 <-> 13 +7 <-> 14 diff --git a/testData/results/pkg/TestSwitchDefaultCaseReturn.dec b/testData/results/pkg/TestSwitchDefaultCaseReturn.dec new file mode 100644 index 0000000000..871ff9b285 --- /dev/null +++ b/testData/results/pkg/TestSwitchDefaultCaseReturn.dec @@ -0,0 +1,117 @@ +package pkg; + +public class TestSwitchDefaultCaseReturn { + public static String test(String s) { + if (s.hashCode() == 0) {// 5 + return switch(s) {// 6 + case "", " " -> "";// 7 + default -> s;// 8 + }; + } else { + int i = s.indexOf(97);// 12 + boolean bl = false;// 13 + + while(true) { + switch(s) {// 16 + case "": + case " ": + return "";// 19 + } + + if (!bl && i != 0) {// 21 + return "";// 22 + } + + if (bl) {// 23 + return "";// 24 + } + + if (s.indexOf(65 + i) == -1) {// 27 + bl = true;// 28 + } + } + } + } +} + +class 'pkg/TestSwitchDefaultCaseReturn' { + method 'test (Ljava/lang/String;)Ljava/lang/String;' { + 0 4 + 1 4 + 2 4 + 3 4 + 4 4 + 7 5 + b 5 + 29 6 + 2a 6 + 37 6 + 38 6 + 42 5 + 5c 6 + 5d 6 + 61 7 + 62 5 + 63 10 + 64 10 + 65 10 + 66 10 + 67 10 + 68 10 + 69 10 + 6a 11 + 6b 11 + 6c 14 + 71 14 + 91 15 + 92 15 + a0 16 + a1 16 + ad 14 + c8 17 + c9 17 + ca 17 + cb 20 + cc 20 + cf 20 + d0 20 + d3 21 + d4 21 + d5 21 + d6 24 + d7 24 + da 25 + db 25 + dc 25 + dd 28 + de 28 + df 28 + e0 28 + e1 28 + e2 28 + e3 28 + e4 28 + e5 28 + e6 28 + e9 29 + ea 29 + } +} + +Lines mapping: +5 <-> 5 +6 <-> 6 +7 <-> 7 +8 <-> 8 +12 <-> 11 +13 <-> 12 +16 <-> 15 +19 <-> 18 +21 <-> 21 +22 <-> 22 +23 <-> 25 +24 <-> 26 +27 <-> 29 +28 <-> 30 +Not mapped: +30 diff --git a/testData/src/java17/pkg/TestSingleCaseStrSwitch.java b/testData/src/java17/pkg/TestSingleCaseStrSwitch.java new file mode 100644 index 0000000000..14cd3b3fe7 --- /dev/null +++ b/testData/src/java17/pkg/TestSingleCaseStrSwitch.java @@ -0,0 +1,10 @@ +package pkg; + +public class TestSingleCaseStrSwitch { + public String test(String s) { + return switch (s) { + case "" -> "foo bar"; + default -> s; + }; + } +} diff --git a/testData/src/java17/pkg/TestSwitchDefaultCaseReturn.java b/testData/src/java17/pkg/TestSwitchDefaultCaseReturn.java new file mode 100644 index 0000000000..3470a9ed37 --- /dev/null +++ b/testData/src/java17/pkg/TestSwitchDefaultCaseReturn.java @@ -0,0 +1,33 @@ +package pkg; + +public class TestSwitchDefaultCaseReturn { + public static String test(String s) { + if (s.hashCode() == 0) { + return switch (s) { + case "", " " -> ""; + default -> s; + }; + } + + int i = s.indexOf('a'); + boolean bl = false; + + while (true) { + switch (s) { + case "": + case " ": + return ""; + default: + if (!bl && i != 0) { + return ""; + } else if (bl) { + return ""; + } + + if (s.indexOf('A' + i) == -1) { + bl = true; + } + } + } + } +} From 8c96d8bcfb6d660ab8ac92d87a86945bccc08765 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Wed, 19 Jul 2023 20:27:12 -0400 Subject: [PATCH 06/18] Fix maven local publishing --- build.gradle | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 051b5c2622..8594dcbc98 100644 --- a/build.gradle +++ b/build.gradle @@ -242,9 +242,11 @@ nexusPublishing { } signing { - def signingKey = ENV.SIGNING_KEY - def signingPassword = ENV.SIGNING_KEY_PASSPHRASE + if (ENV.SIGNING_KEY) { + def signingKey = ENV.SIGNING_KEY + def signingPassword = ENV.SIGNING_KEY_PASSPHRASE - useInMemoryPgpKeys(signingKey, signingPassword) - sign publishing.publications.mavenJava + useInMemoryPgpKeys(signingKey, signingPassword) + sign publishing.publications.mavenJava + } } From b16b4592de64df694283e133516274af0db9cc08 Mon Sep 17 00:00:00 2001 From: coehlrich Date: Thu, 20 Jul 2023 13:18:50 +1200 Subject: [PATCH 07/18] Fix local variable jad name and type where the debug name conflicts (#291) * Fix local variable names and types where the debug var name conflicts * rename the lvt as well --- .../main/rels/NestedClassProcessor.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java b/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java index 458b568b84..0b538bdc8d 100644 --- a/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java +++ b/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java @@ -270,9 +270,20 @@ private static void setLambdaVars(ClassNode parent, ClassNode child) { // rename colliding local variables for (VarVersionPair local : varProc.getUsedVarVersions()) { - String name = varProc.getVarName(local); + String name = null; + LocalVariable lvt = varProc.getVarLVT(local); + if (lvt != null) { + name = lvt.getName(); + } + if (name == null) { + name = varProc.getVarName(local); + } if (usedBefore.contains(name) && !"this".equals(name)) { - mapNewNames.put(local, enclosingCollector.getFreeName(name)); + name = enclosingCollector.getFreeName(name); + mapNewNames.put(local, name); + if (lvt != null) { + lvts.put(local, lvt.rename(name)); + } } } From d88f743cbe3f18bbe7f54fe7b8d209e56c4fd51b Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Mon, 31 Jul 2023 22:28:49 -0400 Subject: [PATCH 08/18] Downstream ForgeFlower#105 Co-authored-by: coehlrich --- .../modules/decompiler/FinallyProcessor.java | 7 +++ .../java/decompiler/SingleClassesTest.java | 1 + testData/results/TestHotjava.dec | 19 +++--- testData/results/TestJsr.dec | 10 +-- testData/results/pkg/TestClassLoop.dec | 4 +- .../pkg/TestClassSimpleBytecodeMapping.dec | 2 +- testData/results/pkg/TestClassVar.dec | 2 +- .../results/pkg/TestComplexIfElseChain.dec | 22 +++---- .../pkg/TestFinallyBlockVariableUse.dec | 5 +- testData/results/pkg/TestFinallyThrow.dec | 3 +- testData/results/pkg/TestIfElseTernary1.dec | 18 +++--- .../results/pkg/TestIfElseTernary1J17.dec | 18 +++--- testData/results/pkg/TestLoopFinally.dec | 47 +++++++------- testData/results/pkg/TestSwitchFinally.dec | 46 ++++++-------- .../pkg/TestSwitchPatternMatching22.dec | 18 ++---- testData/results/pkg/TestSynchronizedLoop.dec | 8 +-- testData/results/pkg/TestSynchronizedTry.dec | 6 +- testData/results/pkg/TestTryCatchFinally.dec | 13 ++-- testData/results/pkg/TestTryFinally.dec | 3 +- .../results/pkg/TestTryLoopReturnFinally.dec | 2 +- .../results/pkg/TestTryLoopSimpleFinally.dec | 5 +- testData/results/pkg/TestTryReturn.dec | 62 +++++++++---------- .../pkg/TestTryWithResourcesAfterSwitch.dec | 3 +- .../TestTryWithResourcesCatchFinallyJ16.dec | 6 +- .../pkg/TestTryWithResourcesFakeTrigger.dec | 2 +- .../pkg/TestTryWithResourcesFinallyJ16.dec | 6 +- .../pkg/TestTryWithResourcesNestedJ16.dec | 12 ++-- 27 files changed, 159 insertions(+), 191 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java index 3287e1e426..09cbe62ee9 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java @@ -780,6 +780,7 @@ private boolean compareBasicBlocksEx(ControlFlowGraph graph, List lstStoreVars) { InstructionSequence seqPattern = pattern.getSeq(); InstructionSequence seqSample = sample.getSeq(); + List instrOldOffsetsSample = sample.getInstrOldOffsets(); if (type != 0) { seqPattern = seqPattern.clone(); @@ -822,6 +823,7 @@ private boolean compareBasicBlocksEx(ControlFlowGraph graph, seq.addInstruction(0, seqSample.getInstr(i), -1); oldOffsets.addFirst(sample.getOldOffset(i)); seqSample.removeInstruction(i); + instrOldOffsetsSample.remove(i); } BasicBlock newblock = new BasicBlock(++graph.last_id); @@ -1010,26 +1012,31 @@ private static void deleteArea(ControlFlowGraph graph, Area area) { private static void removeExceptionInstructionsEx(BasicBlock block, int blocktype, int finallytype) { InstructionSequence seq = block.getSeq(); + List instrOldOffsets = block.getInstrOldOffsets(); if (finallytype == 3) { // empty finally handler for (int i = seq.length() - 1; i >= 0; i--) { seq.removeInstruction(i); + instrOldOffsets.remove(i); } } else { if ((blocktype & 1) > 0) { // first if (finallytype == 2 || finallytype == 1) { // astore or pop seq.removeInstruction(0); + instrOldOffsets.remove(0); } } if ((blocktype & 2) > 0) { // last if (finallytype == 2 || finallytype == 0) { seq.removeLast(); + instrOldOffsets.remove(instrOldOffsets.size() - 1); } if (finallytype == 2) { // astore seq.removeLast(); + instrOldOffsets.remove(instrOldOffsets.size() - 1); } } } diff --git a/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 4dcd9d121f..da97cfd744 100644 --- a/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -153,6 +153,7 @@ private void registerDefault() { register(JAVA_8, "TestAnonymousClassConstructor"); register(JAVA_8, "TestInnerClassConstructor"); register(CUSTOM, "v11/TestInnerClassConstructor"); + // [minor] todo: the linenumbers are incorrect on the finally block register(JAVA_8, "TestTryCatchFinally"); register(JAVA_8, "TestTryFinally"); register(JAVA_8, "TestAmbiguousCall"); diff --git a/testData/results/TestHotjava.dec b/testData/results/TestHotjava.dec index bcdebb4f8b..cd8d81230c 100644 --- a/testData/results/TestHotjava.dec +++ b/testData/results/TestHotjava.dec @@ -7,9 +7,9 @@ public class TestHotjava { try { System.out.println("Try");// 7 8 } finally { - System.out.println("Jsr"); + System.out.println("Jsr");// 10 } - }// 10 + } // $VF: Could not inline inconsistent finally blocks // $VF: Could not create synchronized statement, marking monitor enters and exits @@ -50,7 +50,7 @@ public class TestHotjava { try { System.out.println("Try");// 28 29 } finally { - System.out.println("Jsr"); + System.out.println("Jsr");// 31 } } catch (Throwable var10) { // $VF: monitorexit @@ -81,13 +81,15 @@ class 'TestHotjava' { 3 7 4 7 5 7 - c 9 d 9 e 9 f 9 10 9 11 9 12 9 + 13 9 + 14 9 + 15 9 18 11 } @@ -133,7 +135,6 @@ class 'TestHotjava' { 7 50 8 50 9 50 - 12 52 13 52 14 52 15 52 @@ -141,6 +142,9 @@ class 'TestHotjava' { 17 52 18 52 19 52 + 1a 52 + 1b 52 + 1c 52 25 59 26 60 28 55 @@ -153,7 +157,7 @@ Lines mapping: 3 <-> 3 7 <-> 8 8 <-> 8 -10 <-> 12 +10 <-> 10 15 <-> 17 16 <-> 20 21 <-> 32 @@ -161,5 +165,4 @@ Lines mapping: 27 <-> 47 28 <-> 51 29 <-> 51 -Not mapped: -31 +31 <-> 53 diff --git a/testData/results/TestJsr.dec b/testData/results/TestJsr.dec index fafc379fa9..048ee69efd 100644 --- a/testData/results/TestJsr.dec +++ b/testData/results/TestJsr.dec @@ -3,9 +3,9 @@ public class TestJsr { try { System.out.println("Test");// 3 4 } finally { - System.out.println("Jsr"); + System.out.println("Jsr");// 6 } - }// 6 + } } class 'TestJsr' { @@ -16,13 +16,15 @@ class 'TestJsr' { 3 3 4 3 5 3 - c 5 d 5 e 5 f 5 10 5 11 5 12 5 + 13 5 + 14 5 + 15 5 18 7 } } @@ -30,4 +32,4 @@ class 'TestJsr' { Lines mapping: 3 <-> 4 4 <-> 4 -6 <-> 8 +6 <-> 6 diff --git a/testData/results/pkg/TestClassLoop.dec b/testData/results/pkg/TestClassLoop.dec index 3727b42140..28d8793fda 100644 --- a/testData/results/pkg/TestClassLoop.dec +++ b/testData/results/pkg/TestClassLoop.dec @@ -124,12 +124,12 @@ class 'pkg/TestClassLoop' { e 14 f 14 1a 15 - 26 18 27 18 28 18 29 18 2a 18 2b 18 + 2c 18 } method 'testCatch ()V' { @@ -168,8 +168,8 @@ class 'pkg/TestClassLoop' { 11 43 12 43 13 43 - 25 46 26 46 + 27 46 2a 47 2b 47 2c 47 diff --git a/testData/results/pkg/TestClassSimpleBytecodeMapping.dec b/testData/results/pkg/TestClassSimpleBytecodeMapping.dec index 8d02210c45..67ebc91954 100644 --- a/testData/results/pkg/TestClassSimpleBytecodeMapping.dec +++ b/testData/results/pkg/TestClassSimpleBytecodeMapping.dec @@ -105,12 +105,12 @@ class 'pkg/TestClassSimpleBytecodeMapping' { 13 25 14 25 15 25 - 23 27 24 27 25 27 26 27 27 27 28 27 + 29 27 2e 29 } diff --git a/testData/results/pkg/TestClassVar.dec b/testData/results/pkg/TestClassVar.dec index 7bac467148..10b710be00 100644 --- a/testData/results/pkg/TestClassVar.dec +++ b/testData/results/pkg/TestClassVar.dec @@ -49,11 +49,11 @@ class 'pkg/TestClassVar' { 9 9 a 9 b 9 - 1e 11 1f 11 20 11 21 11 22 11 + 23 11 26 12 27 12 28 12 diff --git a/testData/results/pkg/TestComplexIfElseChain.dec b/testData/results/pkg/TestComplexIfElseChain.dec index 6b7c79243d..057614e213 100644 --- a/testData/results/pkg/TestComplexIfElseChain.dec +++ b/testData/results/pkg/TestComplexIfElseChain.dec @@ -1036,8 +1036,8 @@ class 'pkg/TestComplexIfElseChain' { 12 201 13 201 14 201 - 83 203 84 203 + 85 203 88 203 89 203 8a 203 @@ -1125,8 +1125,8 @@ class 'pkg/TestComplexIfElseChain' { 12 222 13 222 14 222 - 83 224 84 224 + 85 224 88 224 89 224 8a 224 @@ -1285,9 +1285,8 @@ class 'pkg/TestComplexIfElseChain' { 12 255 13 255 14 255 - f9 257 - fa 257 fb 257 + fc 257 ff 257 100 257 101 257 @@ -1297,13 +1296,12 @@ class 'pkg/TestComplexIfElseChain' { 107 259 108 259 109 259 - 117 261 - 118 261 119 261 11a 261 11b 261 11c 261 11d 261 + 11e 261 127 263 128 263 129 263 @@ -1316,13 +1314,12 @@ class 'pkg/TestComplexIfElseChain' { 134 265 135 265 136 265 - 144 267 - 145 267 146 267 147 267 148 267 149 267 14a 267 + 14b 267 154 269 155 269 156 269 @@ -1335,13 +1332,12 @@ class 'pkg/TestComplexIfElseChain' { 161 271 162 271 163 271 - 171 273 - 172 273 173 273 174 273 175 273 176 273 177 273 + 178 273 181 275 182 275 183 275 @@ -1356,13 +1352,12 @@ class 'pkg/TestComplexIfElseChain' { 190 277 191 277 192 277 - 1a0 279 - 1a1 279 1a2 279 1a3 279 1a4 279 1a5 279 1a6 279 + 1a7 279 1b0 281 1b1 281 1b2 281 @@ -1377,13 +1372,12 @@ class 'pkg/TestComplexIfElseChain' { 1bf 283 1c0 283 1c1 283 - 1cf 285 - 1d0 285 1d1 285 1d2 285 1d3 285 1d4 285 1d5 285 + 1d6 285 1df 289 } } diff --git a/testData/results/pkg/TestFinallyBlockVariableUse.dec b/testData/results/pkg/TestFinallyBlockVariableUse.dec index 63325ea82c..c93d4449ee 100644 --- a/testData/results/pkg/TestFinallyBlockVariableUse.dec +++ b/testData/results/pkg/TestFinallyBlockVariableUse.dec @@ -66,15 +66,14 @@ class 'pkg/TestFinallyBlockVariableUse' { 4d 15 4e 15 4f 15 - 50 18 - 51 18 52 18 53 18 54 18 55 18 - 56 19 + 56 18 57 19 58 19 + 59 19 5c 20 63 20 64 20 diff --git a/testData/results/pkg/TestFinallyThrow.dec b/testData/results/pkg/TestFinallyThrow.dec index a778f92a16..392b1ed5e1 100644 --- a/testData/results/pkg/TestFinallyThrow.dec +++ b/testData/results/pkg/TestFinallyThrow.dec @@ -64,12 +64,11 @@ class 'pkg/TestFinallyThrow' { 47 14 48 14 49 14 - 4a 16 - 4b 16 4c 16 4d 16 4e 16 4f 16 + 50 16 } method 'test1 (Ljava/lang/RuntimeException;)V' { diff --git a/testData/results/pkg/TestIfElseTernary1.dec b/testData/results/pkg/TestIfElseTernary1.dec index 561ddfcd9d..fb1ce28e2b 100644 --- a/testData/results/pkg/TestIfElseTernary1.dec +++ b/testData/results/pkg/TestIfElseTernary1.dec @@ -605,22 +605,22 @@ class 'pkg/TestIfElseTernary1' { a3 108 a4 108 ae 111 - af 113 - b0 113 b1 113 b2 113 - b4 114 - b5 114 - b9 114 + b3 113 + b6 114 + b7 114 + b8 114 ba 114 - bb 115 + bb 114 bc 115 bd 115 be 115 bf 115 - c7 116 - c8 116 - c9 116 + c0 115 + c1 115 + c2 115 + ca 116 } } diff --git a/testData/results/pkg/TestIfElseTernary1J17.dec b/testData/results/pkg/TestIfElseTernary1J17.dec index 3fa30435ed..0d81742d1d 100644 --- a/testData/results/pkg/TestIfElseTernary1J17.dec +++ b/testData/results/pkg/TestIfElseTernary1J17.dec @@ -605,22 +605,22 @@ class 'pkg/TestIfElseTernary1J17' { a3 108 a4 108 ae 111 - af 113 - b0 113 b1 113 b2 113 - b4 114 - b5 114 - b9 114 + b3 113 + b6 114 + b7 114 + b8 114 ba 114 - bb 115 + bb 114 bc 115 bd 115 be 115 bf 115 - c7 116 - c8 116 - c9 116 + c0 115 + c1 115 + c2 115 + ca 116 } } diff --git a/testData/results/pkg/TestLoopFinally.dec b/testData/results/pkg/TestLoopFinally.dec index fb0e5c85d7..5246bb57cb 100644 --- a/testData/results/pkg/TestLoopFinally.dec +++ b/testData/results/pkg/TestLoopFinally.dec @@ -109,7 +109,7 @@ public class TestLoopFinally { return var2 + var3;// 128 } } finally { - if (x > 3) {// 119 120 + if (x > 3) {// 120 return 1;// 126 } } @@ -191,25 +191,23 @@ class 'pkg/TestLoopFinally' { b 6 c 6 27 4 - 2a 8 2b 8 2c 8 2d 8 2e 8 2f 8 - 30 9 - 31 9 - 32 9 + 30 8 + 31 8 + 32 8 33 9 34 9 + 35 9 3b 13 3c 13 3d 13 3e 13 3f 13 40 13 - 41 13 - 42 13 4b 17 4c 17 4d 17 @@ -233,17 +231,17 @@ class 'pkg/TestLoopFinally' { a 23 b 23 c 23 - 42 25 43 25 44 25 45 25 46 25 47 25 - 48 26 - 49 26 - 4a 26 + 48 25 + 49 25 + 4a 25 4b 26 4c 26 + 4d 26 50 35 51 35 52 35 @@ -271,8 +269,6 @@ class 'pkg/TestLoopFinally' { 6e 32 6f 32 70 32 - 71 32 - 72 32 75 21 76 21 77 21 @@ -299,17 +295,17 @@ class 'pkg/TestLoopFinally' { a 46 b 46 c 46 - 1f 48 20 48 21 48 22 48 23 48 24 48 - 25 49 - 26 49 - 27 49 + 25 48 + 26 48 + 27 48 28 49 29 49 + 2a 49 30 44 31 44 32 44 @@ -358,9 +354,9 @@ class 'pkg/TestLoopFinally' { 36 72 39 73 44 73 - 4d 76 4e 76 4f 76 + 50 76 58 80 59 80 5a 80 @@ -383,9 +379,9 @@ class 'pkg/TestLoopFinally' { 3 89 6 90 11 90 - 1a 93 1b 93 1c 93 + 1d 93 25 97 26 97 27 97 @@ -401,9 +397,9 @@ class 'pkg/TestLoopFinally' { 3 105 6 106 7 106 - 1f 111 20 111 21 111 + 22 111 2b 115 2c 115 2d 115 @@ -431,13 +427,12 @@ class 'pkg/TestLoopFinally' { b 128 16 129 17 130 - 24 136 - 25 136 26 136 27 136 28 136 29 136 2a 136 + 2b 136 } method 'testConditionalBreakInFinally ()V' { @@ -457,11 +452,11 @@ class 'pkg/TestLoopFinally' { 1e 147 1f 147 20 147 - 2d 149 2e 149 2f 149 30 149 31 149 + 32 149 38 154 39 154 43 150 @@ -485,11 +480,11 @@ class 'pkg/TestLoopFinally' { 6 165 19 176 2f 167 - 30 170 - 31 170 32 170 33 170 34 170 + 35 170 + 36 170 37 172 38 172 39 172 @@ -548,7 +543,6 @@ Lines mapping: 104 <-> 95 114 <-> 106 115 <-> 107 -119 <-> 112 120 <-> 112 124 <-> 116 126 <-> 113 @@ -582,6 +576,7 @@ Not mapped: 83 99 101 +119 121 123 140 diff --git a/testData/results/pkg/TestSwitchFinally.dec b/testData/results/pkg/TestSwitchFinally.dec index 03b718c234..c45fa10267 100644 --- a/testData/results/pkg/TestSwitchFinally.dec +++ b/testData/results/pkg/TestSwitchFinally.dec @@ -49,7 +49,7 @@ public class TestSwitchFinally { try { System.out.println(1);// 57 } finally { - System.out.println("finally");// 59 + System.out.println("finally"); switch(i) {// 61 case 0: System.out.println("0");// 63 @@ -65,7 +65,7 @@ public class TestSwitchFinally { System.out.println("b"); } - System.out.println("d"); + System.out.println("d");// 59 return 1; } } @@ -78,16 +78,16 @@ class 'pkg/TestSwitchFinally' { 3 5 4 5 34 15 - 37 7 38 7 39 7 3a 7 3b 7 3c 7 - 3d 8 - 3e 8 - 3f 8 + 3d 7 + 3e 7 + 3f 7 40 8 + 41 8 54 10 55 10 56 10 @@ -100,8 +100,6 @@ class 'pkg/TestSwitchFinally' { 5f 13 60 13 61 13 - 62 13 - 63 13 } method 'test1 (I)V' { @@ -111,16 +109,16 @@ class 'pkg/TestSwitchFinally' { 3 19 4 19 47 32 - 4a 21 4b 21 4c 21 4d 21 4e 21 4f 21 - 50 22 - 51 22 - 52 22 + 50 21 + 51 21 + 52 21 53 22 + 54 22 70 24 71 24 72 24 @@ -142,8 +140,6 @@ class 'pkg/TestSwitchFinally' { 86 30 87 30 88 30 - 89 30 - 8a 30 } method 'test2 (I)V' { @@ -153,16 +149,16 @@ class 'pkg/TestSwitchFinally' { 3 36 4 36 2c 45 - 2f 38 30 38 31 38 32 38 33 38 34 38 - 35 39 - 36 39 - 37 39 + 35 38 + 36 38 + 37 38 38 39 + 39 39 44 41 45 41 46 41 @@ -177,8 +173,6 @@ class 'pkg/TestSwitchFinally' { 4f 42 50 42 51 42 - 52 42 - 53 42 } method 'test3 (I)I' { @@ -190,17 +184,17 @@ class 'pkg/TestSwitchFinally' { 52 67 53 67 54 67 - 55 51 + 55 67 56 51 57 51 58 51 59 51 5a 51 - 5b 52 - 5c 52 - 5d 52 + 5b 51 + 5c 51 + 5d 51 5e 52 - 5f 67 + 5f 52 60 67 61 67 62 67 @@ -309,7 +303,7 @@ Lines mapping: 50 <-> 43 51 <-> 46 57 <-> 50 -59 <-> 52 +59 <-> 68 61 <-> 53 63 <-> 55 64 <-> 56 diff --git a/testData/results/pkg/TestSwitchPatternMatching22.dec b/testData/results/pkg/TestSwitchPatternMatching22.dec index 28ab7c8a59..c0adc31dcc 100644 --- a/testData/results/pkg/TestSwitchPatternMatching22.dec +++ b/testData/results/pkg/TestSwitchPatternMatching22.dec @@ -118,13 +118,12 @@ class 'pkg/TestSwitchPatternMatching22' { 4b 17 50 13 51 13 - 5d 20 - 5e 20 5f 20 60 20 61 20 62 20 63 20 + 64 20 6a 22 } @@ -153,9 +152,7 @@ class 'pkg/TestSwitchPatternMatching22' { 47 35 4c 32 4d 32 - 5c 38 - 5d 38 - 5e 38 + 5f 38 } method 'test1Null ()V' { @@ -180,13 +177,12 @@ class 'pkg/TestSwitchPatternMatching22' { 4f 53 54 48 55 48 - 61 56 - 62 56 63 56 64 56 65 56 66 56 67 56 + 68 56 6e 58 } @@ -212,9 +208,7 @@ class 'pkg/TestSwitchPatternMatching22' { 4b 70 50 66 51 66 - 60 73 - 61 73 - 62 73 + 63 73 } method 'testNonPattern ()V' { @@ -236,9 +230,7 @@ class 'pkg/TestSwitchPatternMatching22' { 32 85 33 85 3b 86 - 49 89 - 4a 89 - 4b 89 + 4c 89 } } diff --git a/testData/results/pkg/TestSynchronizedLoop.dec b/testData/results/pkg/TestSynchronizedLoop.dec index c25efae915..aa3d3f56e8 100644 --- a/testData/results/pkg/TestSynchronizedLoop.dec +++ b/testData/results/pkg/TestSynchronizedLoop.dec @@ -162,18 +162,18 @@ class 'pkg/TestSynchronizedLoop' { 1f 47 20 47 21 47 - 37 49 38 49 39 49 3a 49 3b 49 3c 49 3d 49 - 3e 50 - 3f 50 - 40 50 + 3e 49 + 3f 49 + 40 49 41 50 42 50 + 43 50 50 56 51 56 52 56 diff --git a/testData/results/pkg/TestSynchronizedTry.dec b/testData/results/pkg/TestSynchronizedTry.dec index ab3a62f671..4c6f893b9a 100644 --- a/testData/results/pkg/TestSynchronizedTry.dec +++ b/testData/results/pkg/TestSynchronizedTry.dec @@ -93,10 +93,8 @@ class 'pkg/TestSynchronizedTry' { 6 6 7 6 9 7 - 27 9 - 28 9 - 2b 9 - 2c 9 + 29 9 + 2d 9 2e 10 2f 10 30 10 diff --git a/testData/results/pkg/TestTryCatchFinally.dec b/testData/results/pkg/TestTryCatchFinally.dec index ca4ddaa375..07e8bb2a6b 100644 --- a/testData/results/pkg/TestTryCatchFinally.dec +++ b/testData/results/pkg/TestTryCatchFinally.dec @@ -30,10 +30,10 @@ public class TestTryCatchFinally { } catch (Exception var6) {// 52 System.out.println("Error" + var6);// 53 } finally { - System.out.println("Finally");// 55 + System.out.println("Finally"); } - return -1;// 56 57 + return -1;// 55 56 57 } } @@ -52,13 +52,12 @@ class 'pkg/TestTryCatchFinally' { 18 8 19 8 1f 9 - 2b 12 - 2c 12 2d 12 2e 12 2f 12 30 12 31 12 + 32 12 38 14 } @@ -95,13 +94,13 @@ class 'pkg/TestTryCatchFinally' { 31 35 32 35 33 35 - 34 32 + 34 35 35 32 36 32 37 32 38 32 39 32 - 3a 35 + 3a 32 3b 35 3c 35 3d 35 @@ -124,7 +123,7 @@ Lines mapping: 51 <-> 29 52 <-> 30 53 <-> 31 -55 <-> 33 +55 <-> 36 56 <-> 36 57 <-> 36 Not mapped: diff --git a/testData/results/pkg/TestTryFinally.dec b/testData/results/pkg/TestTryFinally.dec index 61c6040e06..7e8d905f1b 100644 --- a/testData/results/pkg/TestTryFinally.dec +++ b/testData/results/pkg/TestTryFinally.dec @@ -19,10 +19,11 @@ class 'pkg/TestTryFinally' { 4 5 5 5 c 9 - f 7 10 7 11 7 12 7 + 13 7 + 14 7 } } diff --git a/testData/results/pkg/TestTryLoopReturnFinally.dec b/testData/results/pkg/TestTryLoopReturnFinally.dec index d3ccd694e6..5e6a7d96c7 100644 --- a/testData/results/pkg/TestTryLoopReturnFinally.dec +++ b/testData/results/pkg/TestTryLoopReturnFinally.dec @@ -36,12 +36,12 @@ class 'pkg/TestTryLoopReturnFinally' { 18 16 2c 19 2d 19 - 3b 21 3c 21 3d 21 3e 21 3f 21 40 21 + 41 21 46 23 } } diff --git a/testData/results/pkg/TestTryLoopSimpleFinally.dec b/testData/results/pkg/TestTryLoopSimpleFinally.dec index 8790c177b4..8f2d9098e4 100644 --- a/testData/results/pkg/TestTryLoopSimpleFinally.dec +++ b/testData/results/pkg/TestTryLoopSimpleFinally.dec @@ -48,12 +48,12 @@ class 'pkg/TestTryLoopSimpleFinally' { 1e 16 1f 17 20 17 - 2e 19 2f 19 30 19 31 19 32 19 33 19 + 34 19 39 21 } @@ -80,13 +80,12 @@ class 'pkg/TestTryLoopSimpleFinally' { 29 28 2b 28 37 37 - 3a 35 - 3b 35 3c 35 3d 35 3e 35 3f 35 40 35 + 41 35 } } diff --git a/testData/results/pkg/TestTryReturn.dec b/testData/results/pkg/TestTryReturn.dec index 25708ee61c..4d283a6e06 100644 --- a/testData/results/pkg/TestTryReturn.dec +++ b/testData/results/pkg/TestTryReturn.dec @@ -32,13 +32,13 @@ public class TestTryReturn { break label27; } } finally { - System.out.println("Finally");// 31 + System.out.println("Finally"); } return;// 28 } - System.out.println("suc");// 32 34 + System.out.println("suc");// 31 32 34 } public boolean testFinally2(Supplier supplier) { @@ -46,10 +46,10 @@ public class TestTryReturn { try { b = supplier.get();// 40 } finally { - System.out.println("Finally");// 42 + System.out.println("Finally"); } - return b;// 43 45 + return b;// 42 43 45 } public boolean testFinally3(boolean b, boolean c, int a, Supplier supplier) { @@ -77,10 +77,10 @@ public class TestTryReturn { try { b = supplier.get();// 67 } finally { - System.out.println("Finally");// 69 + System.out.println("Finally"); } - return b;// 70 72 + return b;// 69 70 72 } public boolean testFinally5(Supplier supplier) { @@ -178,7 +178,7 @@ public class TestTryReturn { } catch (Exception var14) {// 149 System.out.println(3);// 150 } finally { - continue;// 153 + continue; } } finally { boolean var7 = true;// 156 @@ -256,12 +256,12 @@ class 'pkg/TestTryReturn' { c 17 15 22 16 22 - 17 19 18 19 19 19 1a 19 1b 19 1c 19 + 1d 19 } method 'testFinally1 (Ljava/util/function/Supplier;)V' { @@ -285,13 +285,13 @@ class 'pkg/TestTryReturn' { 28 40 29 40 2a 40 - 2b 34 + 2b 40 2c 34 2d 34 2e 34 2f 34 30 34 - 31 40 + 31 34 32 40 33 40 34 40 @@ -318,13 +318,13 @@ class 'pkg/TestTryReturn' { 15 51 16 51 17 51 - 18 48 + 18 51 19 48 1a 48 1b 48 1c 48 1d 48 - 1e 51 + 1e 48 1f 51 20 51 21 51 @@ -370,13 +370,12 @@ class 'pkg/TestTryReturn' { 50 62 51 62 5e 62 - 5f 67 - 60 67 61 67 62 67 63 67 64 67 65 67 + 66 67 } method 'testFinally4 (Ljava/util/function/Supplier;)Z' { @@ -395,13 +394,13 @@ class 'pkg/TestTryReturn' { 17 82 18 82 19 82 - 1a 79 + 1a 82 1b 79 1c 79 1d 79 1e 79 1f 79 - 20 82 + 20 79 21 82 22 82 23 82 @@ -441,13 +440,12 @@ class 'pkg/TestTryReturn' { 2d 92 2e 92 2f 92 - 3b 94 - 3c 94 3d 94 3e 94 3f 94 40 94 41 94 + 42 94 48 97 49 97 } @@ -494,13 +492,12 @@ class 'pkg/TestTryReturn' { 3c 112 3d 112 3e 112 - 4a 114 - 4b 114 4c 114 4d 114 4e 114 4f 114 50 114 + 51 114 57 117 58 117 } @@ -511,12 +508,12 @@ class 'pkg/TestTryReturn' { 2 125 3 125 e 126 - 1a 129 1b 129 1c 129 1d 129 1e 129 1f 129 + 20 129 } method 'testPostdomFailure ()V' { @@ -539,11 +536,10 @@ class 'pkg/TestTryReturn' { 24 178 25 178 26 178 - 2f 180 - 38 183 - 39 183 3a 183 3b 183 + 3c 183 + 3d 183 41 186 } @@ -565,10 +561,10 @@ class 'pkg/TestTryReturn' { 1a 194 1b 194 21 195 - 22 198 - 23 198 24 198 25 198 + 26 198 + 27 198 } method 'testInvalidUse ()V' { @@ -591,19 +587,17 @@ class 'pkg/TestTryReturn' { 19 216 26 218 36 225 - 37 220 - 38 220 39 220 3a 220 3b 220 3c 220 + 3d 220 4a 217 - 4d 223 - 4e 223 4f 223 50 223 51 223 52 223 + 53 223 } } @@ -616,11 +610,11 @@ Lines mapping: 24 <-> 27 27 <-> 31 28 <-> 38 -31 <-> 35 +31 <-> 41 32 <-> 41 34 <-> 41 40 <-> 47 -42 <-> 49 +42 <-> 52 43 <-> 52 45 <-> 52 50 <-> 58 @@ -631,7 +625,7 @@ Lines mapping: 60 <-> 68 65 <-> 75 67 <-> 78 -69 <-> 80 +69 <-> 83 70 <-> 83 72 <-> 83 76 <-> 87 @@ -660,7 +654,6 @@ Lines mapping: 148 <-> 177 149 <-> 178 150 <-> 179 -153 <-> 181 156 <-> 184 159 <-> 187 164 <-> 191 @@ -689,6 +682,7 @@ Not mapped: 84 103 118 +153 157 175 191 diff --git a/testData/results/pkg/TestTryWithResourcesAfterSwitch.dec b/testData/results/pkg/TestTryWithResourcesAfterSwitch.dec index 00bed8889f..1d3a905ed1 100644 --- a/testData/results/pkg/TestTryWithResourcesAfterSwitch.dec +++ b/testData/results/pkg/TestTryWithResourcesAfterSwitch.dec @@ -142,13 +142,12 @@ class 'pkg/TestTryWithResourcesAfterSwitch' { 62 18 63 18 bf 24 - c2 20 - c3 20 c4 20 c5 20 c6 20 c7 20 c8 20 + c9 20 } } diff --git a/testData/results/pkg/TestTryWithResourcesCatchFinallyJ16.dec b/testData/results/pkg/TestTryWithResourcesCatchFinallyJ16.dec index ef7c945b84..bd6ed208b9 100644 --- a/testData/results/pkg/TestTryWithResourcesCatchFinallyJ16.dec +++ b/testData/results/pkg/TestTryWithResourcesCatchFinallyJ16.dec @@ -41,13 +41,12 @@ class 'pkg/TestTryWithResourcesCatchFinallyJ16' { 32 10 33 11 34 11 - 42 13 - 43 13 44 13 45 13 46 13 47 13 48 13 + 49 13 4f 15 } @@ -65,13 +64,12 @@ class 'pkg/TestTryWithResourcesCatchFinallyJ16' { 37 20 38 21 39 21 - 47 23 - 48 23 49 23 4a 23 4b 23 4c 23 4d 23 + 4e 23 54 25 } diff --git a/testData/results/pkg/TestTryWithResourcesFakeTrigger.dec b/testData/results/pkg/TestTryWithResourcesFakeTrigger.dec index 8f73334e01..b2f9dcf516 100644 --- a/testData/results/pkg/TestTryWithResourcesFakeTrigger.dec +++ b/testData/results/pkg/TestTryWithResourcesFakeTrigger.dec @@ -96,4 +96,4 @@ Not mapped: 16 18 30 -33 \ No newline at end of file +33 diff --git a/testData/results/pkg/TestTryWithResourcesFinallyJ16.dec b/testData/results/pkg/TestTryWithResourcesFinallyJ16.dec index c7fba8e88b..5f1f03eacc 100644 --- a/testData/results/pkg/TestTryWithResourcesFinallyJ16.dec +++ b/testData/results/pkg/TestTryWithResourcesFinallyJ16.dec @@ -35,13 +35,12 @@ class 'pkg/TestTryWithResourcesFinallyJ16' { b 9 c 9 2f 13 - 32 11 - 33 11 34 11 35 11 36 11 37 11 38 11 + 39 11 } method 'testFunc (Ljava/io/File;)V' { @@ -56,13 +55,12 @@ class 'pkg/TestTryWithResourcesFinallyJ16' { 8 17 9 17 34 21 - 37 19 - 38 19 39 19 3a 19 3b 19 3c 19 3d 19 + 3e 19 } method 'create (Ljava/io/File;)Ljava/util/Scanner;' { diff --git a/testData/results/pkg/TestTryWithResourcesNestedJ16.dec b/testData/results/pkg/TestTryWithResourcesNestedJ16.dec index a14278595a..9d2de4e9cc 100644 --- a/testData/results/pkg/TestTryWithResourcesNestedJ16.dec +++ b/testData/results/pkg/TestTryWithResourcesNestedJ16.dec @@ -91,31 +91,27 @@ class 'pkg/TestTryWithResourcesNestedJ16' { 27 23 28 23 29 23 - 53 25 - 54 25 55 25 56 25 57 25 58 25 - 87 28 - 88 28 + 59 25 89 28 8a 28 8b 28 8c 28 - b9 31 - ba 31 + 8d 28 bb 31 bc 31 bd 31 be 31 + bf 31 e5 36 - e8 34 - e9 34 ea 34 eb 34 ec 34 ed 34 + ee 34 } } From eb95dad022803611bab64cb9b7ac035a33aab8a0 Mon Sep 17 00:00:00 2001 From: MiniDigger | Martin Date: Tue, 1 Aug 2023 04:31:26 +0200 Subject: [PATCH 09/18] fix: consider method params when checking for clashing names (#292) * fix: consider method params when checking for clashing names * temp: push test for loop case --- .../decompiler/vars/VarDefinitionHelper.java | 15 +++ .../java/decompiler/SingleClassesTest.java | 2 + .../classes/custom/TestJadLvtCollision.class | Bin 0 -> 1361 bytes testData/results/TestJadLvtCollision.dec | 94 ++++++++++++++++++ 4 files changed, 111 insertions(+) create mode 100644 testData/classes/custom/TestJadLvtCollision.class create mode 100644 testData/results/TestJadLvtCollision.dec diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java index 3c2fe9217c..4b297bdc80 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java @@ -12,7 +12,10 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor.FinalType; import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructMethod; +import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; +import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute; import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute.LocalVariable; +import org.jetbrains.java.decompiler.struct.attr.StructMethodParametersAttribute; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.generics.GenericType; @@ -1352,6 +1355,18 @@ public void remapClashingNames(Statement root) { Set liveVarDefs = new HashSet<>(); Map nameMap = new HashMap<>(); + if (root instanceof RootStatement) { + StructMethodParametersAttribute paramAttribute = ((RootStatement) root).mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_METHOD_PARAMETERS); + StructLocalVariableTableAttribute lvtAttribute = ((RootStatement) root).mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE); + if (paramAttribute != null && lvtAttribute != null) { + for (StructMethodParametersAttribute.Entry entry : paramAttribute.getEntries()) { + // for every method param, find lvt entry and put it into the name map + Optional lvtEntry = lvtAttribute.getVariables().filter(s -> s.getName().equals(entry.myName)).findFirst(); + lvtEntry.ifPresent(localVariable -> nameMap.put(localVariable.getVersion(), entry.myName)); + } + } + } + iterateClashingNames(root, varDefinitions, liveVarDefs, nameMap); } diff --git a/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/test/org/jetbrains/java/decompiler/SingleClassesTest.java index da97cfd744..15ff4a62d5 100644 --- a/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -75,6 +75,8 @@ protected void registerAll() { ); registerSet("JAD Naming", () -> { register(JAVA_8, "TestJADNaming"); + // TODO: loop part fails + registerRaw(CUSTOM, "TestJadLvtCollision"); // created by placing a class in java8 sources and remapping its param using tinyremapper },IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1", IFernflowerPreferences.DUMP_ORIGINAL_LINES, "1", IFernflowerPreferences.DUMP_EXCEPTION_ON_ERROR, "0", diff --git a/testData/classes/custom/TestJadLvtCollision.class b/testData/classes/custom/TestJadLvtCollision.class new file mode 100644 index 0000000000000000000000000000000000000000..c1f73a8d119d629da6714e1151828acb025a1834 GIT binary patch literal 1361 zcmZ`&T~8B16g{(T*-{E3pB0r4KcIy|6%nQ7Lm@HIv`A7yqHjYxfx+!=vz-$CAwKvE zd{rMxl*IV#i~q+M_0H}VTB&I=bN9}jbI&<*`~CNquK<>?#W1)lYU&v;=a1EvV_C8$ z9oqzBSj!*rW1g|NeUN#+ePY+i7>;!dA12*qKhHX z0cJthGIXsk?IM9{+!R)@02Fx-)XJ|<;^oa}g>+9U0{;)s{6V^wNu zkHOH`E$oYLYD!d03=#vUPKd+457No(xYAZdz>6!Gy-~01tKDigqjT zrVaf60~_9Q%7WoiUfN>2UfCD!uAXqBn0HFt+T*U&-$Am!Ak?8#-r+8<2og+#*jrS* z^s2zCK}mN}9@t#fUBZYJow{2RPoyOneR^XlJxXW=|0RNP&Sh zTD$xt)+vq$aWDGli|C@Cs`TXwLi7V>PGP(_!9d{?5~moW@akLx6Aj!<`&$FI8kjwY z@AIxj5hW(m#6`E6^r7IlAy8bVhV;0Yz#K&eHmEAXD6Ltf&se;ri($%Tspp+S`ZJap z-eG})EW%zeiXu{mx=xbyO%Ez literal 0 HcmV?d00001 diff --git a/testData/results/TestJadLvtCollision.dec b/testData/results/TestJadLvtCollision.dec new file mode 100644 index 0000000000..cefae34980 --- /dev/null +++ b/testData/results/TestJadLvtCollision.dec @@ -0,0 +1,94 @@ +import java.util.Iterator; + +public class TestJadLvtCollision implements Iterable { + public void test(TestJadLvtCollision testjadlvtcollision) { + TestJadLvtCollision testjadlvtcollisionx = new TestJadLvtCollision();// 8 + System.out.println(testjadlvtcollision.toString() + testjadlvtcollisionx.toString());// 9 + }// 10 + + public void testLoop(TestJadLvtCollision testjadlvtcollision) { + for(TestJadLvtCollision testjadlvtcollision : testjadlvtcollision) {// 13 + System.out.println(testjadlvtcollision.toString() + testjadlvtcollision.toString());// 14 + } + }// 16 + + public Iterator iterator() { + return null;// 20 + } +} + +class 'TestJadLvtCollision' { + method 'test (LTestJadLvtCollision;)V' { + 7 4 + 8 5 + 9 5 + a 5 + 12 5 + 13 5 + 14 5 + 15 5 + 19 5 + 1a 5 + 1b 5 + 1c 5 + 20 5 + 21 5 + 22 5 + 23 5 + 24 5 + 25 5 + 26 6 + } + + method 'testLoop (LTestJadLvtCollision;)V' { + 0 9 + 1 9 + 2 9 + 3 9 + 4 9 + e 9 + f 9 + 10 9 + 11 9 + 12 9 + 13 9 + 14 9 + 15 9 + 16 9 + 17 9 + 18 10 + 19 10 + 1a 10 + 22 10 + 23 10 + 24 10 + 25 10 + 29 10 + 2a 10 + 2b 10 + 2c 10 + 30 10 + 31 10 + 32 10 + 33 10 + 34 10 + 35 10 + 39 12 + } + + method 'iterator ()Ljava/util/Iterator;' { + 0 15 + 1 15 + } +} + +Lines mapping: +8 <-> 5 +9 <-> 6 +10 <-> 7 +13 <-> 10 +14 <-> 11 +16 <-> 13 +20 <-> 16 +Not mapped: +15 From 7f65ce72c2d940eee6ef501c40e6daca59141d83 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Mon, 31 Jul 2023 23:08:08 -0400 Subject: [PATCH 10/18] Fix var clashing not processing foreach properly --- .../modules/decompiler/exps/VarExprent.java | 2 +- .../decompiler/vars/VarDefinitionHelper.java | 18 ++++++++---------- testData/results/TestJadLvtCollision.dec | 6 +++--- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java index dfd7278f0f..e8602c8f58 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java @@ -439,7 +439,7 @@ public boolean allowNewlineAfterQualifier() { @Override public String toString() { - return "VarExprent[" + index + ',' + version +"]: {" + super.toString() + "}"; + return "VarExprent[" + index + ',' + version + (definition ? " Def" : "") + "]: {" + super.toString() + "}"; } // ***************************************************************************** diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java index 4b297bdc80..23824a61f4 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java @@ -1355,15 +1355,13 @@ public void remapClashingNames(Statement root) { Set liveVarDefs = new HashSet<>(); Map nameMap = new HashMap<>(); - if (root instanceof RootStatement) { - StructMethodParametersAttribute paramAttribute = ((RootStatement) root).mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_METHOD_PARAMETERS); - StructLocalVariableTableAttribute lvtAttribute = ((RootStatement) root).mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE); - if (paramAttribute != null && lvtAttribute != null) { - for (StructMethodParametersAttribute.Entry entry : paramAttribute.getEntries()) { - // for every method param, find lvt entry and put it into the name map - Optional lvtEntry = lvtAttribute.getVariables().filter(s -> s.getName().equals(entry.myName)).findFirst(); - lvtEntry.ifPresent(localVariable -> nameMap.put(localVariable.getVersion(), entry.myName)); - } + StructMethodParametersAttribute paramAttribute = ((RootStatement) root).mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_METHOD_PARAMETERS); + StructLocalVariableTableAttribute lvtAttribute = ((RootStatement) root).mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE); + if (paramAttribute != null && lvtAttribute != null) { + for (StructMethodParametersAttribute.Entry entry : paramAttribute.getEntries()) { + // for every method param, find lvt entry and put it into the name map + Optional lvtEntry = lvtAttribute.getVariables().filter(s -> s.getName().equals(entry.myName)).findFirst(); + lvtEntry.ifPresent(localVariable -> nameMap.put(localVariable.getVersion(), entry.myName)); } } @@ -1389,7 +1387,7 @@ private void iterateClashingNames(Statement stat, Map exprents = ((Exprent) obj).getAllExprents(true); + List exprents = ((Exprent) obj).getAllExprents(true, true); for (Exprent exprent : exprents) { iterateClashingExprent(stat, varDefinitions, exprent, curVarDefs, nameMap); diff --git a/testData/results/TestJadLvtCollision.dec b/testData/results/TestJadLvtCollision.dec index cefae34980..e0ae532329 100644 --- a/testData/results/TestJadLvtCollision.dec +++ b/testData/results/TestJadLvtCollision.dec @@ -7,8 +7,8 @@ public class TestJadLvtCollision implements Iterable { }// 10 public void testLoop(TestJadLvtCollision testjadlvtcollision) { - for(TestJadLvtCollision testjadlvtcollision : testjadlvtcollision) {// 13 - System.out.println(testjadlvtcollision.toString() + testjadlvtcollision.toString());// 14 + for(TestJadLvtCollision testjadlvtcollisionx : testjadlvtcollision) {// 13 + System.out.println(testjadlvtcollision.toString() + testjadlvtcollisionx.toString());// 14 } }// 16 @@ -91,4 +91,4 @@ Lines mapping: 16 <-> 13 20 <-> 16 Not mapped: -15 +15 \ No newline at end of file From 348363b47ee6a8f83151160a42637b52dbdce828 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:54:16 -0400 Subject: [PATCH 11/18] Downstream constant fixes, ForgeFlower#130 Co-authored-by SizableShrimp --- .../modules/decompiler/exps/ConstExprent.java | 103 ++++++++++++++++-- testData/results/pkg/TestConstants.dec | 62 ++++++----- testData/src/java8/pkg/TestConstants.java | 2 + 3 files changed, 127 insertions(+), 40 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java index b0ad986873..dbad4f93fb 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java @@ -303,7 +303,7 @@ else if (floatVal == Float.NEGATIVE_INFINITY) { return buf.append("-1.0F / 0.0F"); } } - return buf.append(trimZeros(Float.toString(floatVal))).append('F'); + return buf.append(trimFloat(Float.toString(floatVal), floatVal)).append('F'); case CodeConstants.TYPE_DOUBLE: double doubleVal = (Double)value; @@ -325,7 +325,7 @@ else if (UNINLINED_DOUBLES.containsKey(doubleVal)) { return buf.append(UNINLINED_FLOATS.get(floatRepresentation).apply(bytecode)); } else { // Return the standard representation if the value is not able to be uninlined - return buf.append(Float.toString(floatRepresentation)).append("F"); + return buf.append(trimFloat(Float.toString(floatRepresentation), floatRepresentation)).append("F"); } } } @@ -339,7 +339,7 @@ else if (doubleVal == Double.POSITIVE_INFINITY) { else if (doubleVal == Double.NEGATIVE_INFINITY) { return buf.append("-1.0 / 0.0"); } - return buf.append(trimZeros(value.toString())); + return buf.append(trimDouble(Double.toString(doubleVal), doubleVal)); case CodeConstants.TYPE_NULL: return buf.append("null"); @@ -404,14 +404,97 @@ private static TextBuffer getFloat(BitSet bytecode, String name, String classNam // Different JVM implementations/version display Floats and Doubles with different number of trailing zeros. // This trims them all down to only the necessary amount. - private static String trimZeros(String value) { - int i = value.length() - 1; - while (i >= 0 && value.charAt(i) == '0') { - i--; + private static String trimFloat(String value, float start) { + // Includes NaN and simple numbers + if (value.length() <= 3) { + return value; + } + + String exp = ""; + int eIdx = value.indexOf('E'); + if (eIdx != -1) { + exp = value.substring(eIdx); + value = value.substring(0, eIdx); + } + + if (!exp.isEmpty()) { + return value + exp; + } + + // Cut off digits that don't affect the value + String temp = value; + int dotIdx = value.indexOf('.'); + do { + value = temp; + temp = value.substring(0, value.length() - 1); + } while (!temp.isEmpty() && !"-".equals(temp) && Float.parseFloat(temp + exp) == start); + + if (dotIdx != -1 && value.indexOf('.') == -1) { + value += ".0"; + } else if (dotIdx != -1) { + String integer = value.substring(0, dotIdx); + String decimal = value.substring(dotIdx + 1); + + String rounded = (Integer.parseInt(integer) + 1) + ".0" + exp; + if (Float.parseFloat(rounded) == start) + return rounded; + + long decimalVal = 1; + for (int i = 0; i < decimal.length() - 1; i++) { + decimalVal = (decimalVal - 1) * 10 + decimal.charAt(i) - '0' + 1; + rounded = integer + '.' + decimalVal + exp; + if (Float.parseFloat(rounded) == start) + return rounded; + } + } + + return value + exp; + } + + private static String trimDouble(String value, double start) { + // Includes NaN and simple numbers + if (value.length() <= 3) { + return value; + } + + String exp = ""; + int eIdx = value.indexOf('E'); + if (eIdx != -1) { + exp = value.substring(eIdx); + value = value.substring(0, eIdx); + } + if (!exp.isEmpty()) { + return value + exp; + } + + // Cut off digits that don't affect the value + String temp = value; + int dotIdx = value.indexOf('.'); + do { + value = temp; + temp = value.substring(0, value.length() - 1); + } while (!temp.isEmpty() && !"-".equals(temp) && Double.parseDouble(temp) == start); + + if (dotIdx != -1 && value.indexOf('.') == -1) { + value += ".0"; + } else if (dotIdx != -1) { + String integer = value.substring(0, dotIdx); + String decimal = value.substring(dotIdx + 1); + + String rounded = (Long.parseLong(integer) + 1) + ".0" + exp; + if (Double.parseDouble(rounded) == start) + return rounded; + + long decimalVal = 1; + for (int i = 0; i < decimal.length() - 1; i++) { + decimalVal = (decimalVal - 1) * 10 + decimal.charAt(i) - '0' + 1; + rounded = integer + '.' + decimalVal + exp; + if (Double.parseDouble(rounded) == start) + return rounded; } - if (value.charAt(i) == '.') - i++; - return value.substring(0, i + 1); + } + + return value + exp; } public boolean isNull() { diff --git a/testData/results/pkg/TestConstants.dec b/testData/results/pkg/TestConstants.dec index 3a7f857457..ef2731eb85 100644 --- a/testData/results/pkg/TestConstants.dec +++ b/testData/results/pkg/TestConstants.dec @@ -26,46 +26,48 @@ public class TestConstants { static final double DPos = 1.0 / 0.0; static final double DMin = 4.9E-324; static final double DMax = 1.7976931348623157E308; + static final double D10 = 1.0E10; + static final double DN10 = 1.0E-10; @TestConstants.A(byte.class) void m1() { - }// 54 + }// 56 @TestConstants.A(char.class) void m2() { - }// 55 + }// 57 @TestConstants.A(double.class) void m3() { - }// 56 + }// 58 @TestConstants.A(float.class) void m4() { - }// 57 + }// 59 @TestConstants.A(int.class) void m5() { - }// 58 + }// 60 @TestConstants.A(long.class) void m6() { - }// 59 + }// 61 @TestConstants.A(short.class) void m7() { - }// 60 + }// 62 @TestConstants.A(boolean.class) void m8() { - }// 61 + }// 63 @TestConstants.A(void.class) void m9() { - }// 62 + }// 64 @TestConstants.A(Date.class) void m10() { - }// 63 + }// 65 @interface A { Class value(); @@ -74,54 +76,54 @@ public class TestConstants { class 'pkg/TestConstants' { method 'm1 ()V' { - 0 31 + 0 33 } method 'm2 ()V' { - 0 35 + 0 37 } method 'm3 ()V' { - 0 39 + 0 41 } method 'm4 ()V' { - 0 43 + 0 45 } method 'm5 ()V' { - 0 47 + 0 49 } method 'm6 ()V' { - 0 51 + 0 53 } method 'm7 ()V' { - 0 55 + 0 57 } method 'm8 ()V' { - 0 59 + 0 61 } method 'm9 ()V' { - 0 63 + 0 65 } method 'm10 ()V' { - 0 67 + 0 69 } } Lines mapping: -54 <-> 32 -55 <-> 36 -56 <-> 40 -57 <-> 44 -58 <-> 48 -59 <-> 52 -60 <-> 56 -61 <-> 60 -62 <-> 64 -63 <-> 68 +56 <-> 34 +57 <-> 38 +58 <-> 42 +59 <-> 46 +60 <-> 50 +61 <-> 54 +62 <-> 58 +63 <-> 62 +64 <-> 66 +65 <-> 70 \ No newline at end of file diff --git a/testData/src/java8/pkg/TestConstants.java b/testData/src/java8/pkg/TestConstants.java index 09b5419fc3..4383103b74 100644 --- a/testData/src/java8/pkg/TestConstants.java +++ b/testData/src/java8/pkg/TestConstants.java @@ -46,6 +46,8 @@ public class TestConstants { static final double DPos = Double.POSITIVE_INFINITY; static final double DMin = Double.MIN_VALUE; static final double DMax = Double.MAX_VALUE; + static final double D10 = 1.0E10; + static final double DN10 = 1.0E-10; static @interface A { Class value(); From 2eb9c61de56c815597f44633cda843295325ab6e Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Thu, 3 Aug 2023 11:46:39 -0400 Subject: [PATCH 12/18] Properly fix floating exp issues --- .../modules/decompiler/exps/ConstExprent.java | 7 ------- testData/results/pkg/MoreAnnotations.dec | 11 +++++------ testData/results/pkg/TestConstants.dec | 4 ++-- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java index dbad4f93fb..730c0e6c01 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java @@ -417,10 +417,6 @@ private static String trimFloat(String value, float start) { value = value.substring(0, eIdx); } - if (!exp.isEmpty()) { - return value + exp; - } - // Cut off digits that don't affect the value String temp = value; int dotIdx = value.indexOf('.'); @@ -463,9 +459,6 @@ private static String trimDouble(String value, double start) { exp = value.substring(eIdx); value = value.substring(0, eIdx); } - if (!exp.isEmpty()) { - return value + exp; - } // Cut off digits that don't affect the value String temp = value; diff --git a/testData/results/pkg/MoreAnnotations.dec b/testData/results/pkg/MoreAnnotations.dec index 67ba6bfb40..47bc814d4c 100644 --- a/testData/results/pkg/MoreAnnotations.dec +++ b/testData/results/pkg/MoreAnnotations.dec @@ -34,8 +34,8 @@ public @interface MoreAnnotations { @MoreAnnotations( intArray = {1, 0, 2147483647, -2147483648}, byteArray = {1, 0, 127, -128, -1}, - floatArray = {1.0F, 0.0F, 3.4028235E38F, 1.4E-45F, 0.0F / 0.0F, 1.0F / 0.0F, -1.0F / 0.0F}, - doubleArray = {1.0, 0.0, 1.7976931348623157E308, 4.9E-324, 0.0 / 0.0, 1.0 / 0.0, -1.0 / 0.0}, + floatArray = {1.0F, 0.0F, 3.4028235E38F, 1.0E-45F, 0.0F / 0.0F, 1.0F / 0.0F, -1.0F / 0.0F}, + doubleArray = {1.0, 0.0, 1.7976931348623157E308, 5.0E-324, 0.0 / 0.0, 1.0 / 0.0, -1.0 / 0.0}, booleanArray = {true, false}, shortArray = {1, 0, 32767, -32768, -1}, longArray = {1L, 0L, 9223372036854775807L, -9223372036854775808L}, @@ -75,9 +75,9 @@ public @interface MoreAnnotations { byte[] byteArray() default {1, 0, 127, -128, -1}; - float[] floatArray() default {1.0F, 0.0F, 3.4028235E38F, 1.4E-45F, 0.0F / 0.0F, 1.0F / 0.0F, -1.0F / 0.0F}; + float[] floatArray() default {1.0F, 0.0F, 3.4028235E38F, 1.0E-45F, 0.0F / 0.0F, 1.0F / 0.0F, -1.0F / 0.0F}; - double[] doubleArray() default {1.0, 0.0, 1.7976931348623157E308, 4.9E-324, 0.0 / 0.0, 1.0 / 0.0, -1.0 / 0.0}; + double[] doubleArray() default {1.0, 0.0, 1.7976931348623157E308, 5.0E-324, 0.0 / 0.0, 1.0 / 0.0, -1.0 / 0.0}; boolean[] booleanArray() default {true, false}; @@ -103,5 +103,4 @@ public @interface MoreAnnotations { FirstValue, SecondValue; } -} - +} \ No newline at end of file diff --git a/testData/results/pkg/TestConstants.dec b/testData/results/pkg/TestConstants.dec index ef2731eb85..dd40fc2ce4 100644 --- a/testData/results/pkg/TestConstants.dec +++ b/testData/results/pkg/TestConstants.dec @@ -19,12 +19,12 @@ public class TestConstants { static final float FNan = 0.0F / 0.0F; static final float FNeg = -1.0F / 0.0F; static final float FPos = 1.0F / 0.0F; - static final float FMin = 1.4E-45F; + static final float FMin = 1.0E-45F; static final float FMax = 3.4028235E38F; static final double DNan = 0.0 / 0.0; static final double DNeg = -1.0 / 0.0; static final double DPos = 1.0 / 0.0; - static final double DMin = 4.9E-324; + static final double DMin = 5.0E-324; static final double DMax = 1.7976931348623157E308; static final double D10 = 1.0E10; static final double DN10 = 1.0E-10; From ab6fa1f18d77b769275311dc509092b1e1b92dd8 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Thu, 3 Aug 2023 12:45:41 -0400 Subject: [PATCH 13/18] Downstream JAD param renaming patches --- .../java/decompiler/main/ClassWriter.java | 21 +++++-- .../java/decompiler/main/Fernflower.java | 3 +- .../main/extern/IFernflowerPreferences.java | 7 ++- .../main/extern/IVariableNameProvider.java | 13 ++++- .../java/decompiler/util/JADNameProvider.java | 56 +++++++++++-------- 5 files changed, 69 insertions(+), 31 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 326bb804ba..bf2e07da24 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -189,9 +189,14 @@ public void classLambdaToJava(ClassNode node, TextBuffer buffer, Exprent method_ if (!firstParameter) { buffer.append(", "); } + VarType type = md_content.params[i]; String parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0)); - buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors + if (parameterName == null) { + parameterName = "param" + index; // null iff decompiled with errors + } + parameterName = methodWrapper.methodStruct.getVariableNamer().renameParameter(mt.getAccessFlags(), ExprProcessor.getCastTypeName(type), parameterName, index); + buffer.append(parameterName); firstParameter = false; } @@ -835,7 +840,11 @@ private static void methodLambdaToJava(ClassNode lambdaNode, buffer.append(" "); String parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0)); - buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors + if (parameterName == null) { + parameterName = "param" + index; // null iff decompiled with errors + } + parameterName = methodWrapper.methodStruct.getVariableNamer().renameParameter(mt.getAccessFlags(), typeName, parameterName, index); + buffer.append(parameterName); firstParameter = false; } @@ -1104,11 +1113,11 @@ else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarT parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0)); } - if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0) { - String newParameterName = methodWrapper.methodStruct.getVariableNamer().renameAbstractParameter(parameterName, index); - parameterName = !newParameterName.equals(parameterName) ? newParameterName : DecompilerContext.getStructContext().renameAbstractParameter(methodWrapper.methodStruct.getClassQualifiedName(), mt.getName(), mt.getDescriptor(), index - (((flags & CodeConstants.ACC_STATIC) == 0) ? 1 : 0), parameterName); - + String newParameterName = methodWrapper.methodStruct.getVariableNamer().renameParameter(flags, typeName, parameterName, index); + if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0 && newParameterName.equals(parameterName)) { + newParameterName = DecompilerContext.getStructContext().renameAbstractParameter(methodWrapper.methodStruct.getClassQualifiedName(), mt.getName(), mt.getDescriptor(), index - (((flags & CodeConstants.ACC_STATIC) == 0) ? 1 : 0), parameterName); } + parameterName = newParameterName; buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors diff --git a/src/org/jetbrains/java/decompiler/main/Fernflower.java b/src/org/jetbrains/java/decompiler/main/Fernflower.java index e688ddae96..3a89417208 100644 --- a/src/org/jetbrains/java/decompiler/main/Fernflower.java +++ b/src/org/jetbrains/java/decompiler/main/Fernflower.java @@ -72,7 +72,8 @@ public Fernflower(IBytecodeProvider provider, IResultSaver saver, Map_A.") + @Description("Use JAD-style variable naming for local variables, instead of var_.") String USE_JAD_VARNAMING = "jvn"; + @Name("JAD-Style Parameter Naming") + @Description("Use JAD-style variable naming for parameters.") + String USE_JAD_PARAMETER_NAMING = "jpr"; + @Name("Skip Extra Files") @Description("Skip copying non-class files from the input folder or file to the output") String SKIP_EXTRA_FILES = "sef"; @@ -319,6 +323,7 @@ static Map getDefaults() { defaults.put(DUMP_ORIGINAL_LINES, "0"); defaults.put(THREADS, String.valueOf(Runtime.getRuntime().availableProcessors())); defaults.put(USE_JAD_VARNAMING, "0"); + defaults.put(USE_JAD_PARAMETER_NAMING, "0"); defaults.put(SKIP_EXTRA_FILES, "0"); defaults.put(WARN_INCONSISTENT_INNER_CLASSES, "1"); defaults.put(DUMP_BYTECODE_ON_ERROR, "1"); diff --git a/src/org/jetbrains/java/decompiler/main/extern/IVariableNameProvider.java b/src/org/jetbrains/java/decompiler/main/extern/IVariableNameProvider.java index 8e6ab2bfc6..f2c3527cf9 100644 --- a/src/org/jetbrains/java/decompiler/main/extern/IVariableNameProvider.java +++ b/src/org/jetbrains/java/decompiler/main/extern/IVariableNameProvider.java @@ -17,10 +17,21 @@ import java.util.Map; +import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair; public interface IVariableNameProvider { public Map rename(Map variables); - public String renameAbstractParameter(String abstractParam, int index); + default String renameAbstractParameter(String name, int index) { + return name; + } + + default String renameParameter(int flags, String type, String name, int index) { + if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0) { + return renameAbstractParameter(name, index); + } + + return name; + } public void addParentContext(IVariableNameProvider renamer); } diff --git a/src/org/jetbrains/java/decompiler/util/JADNameProvider.java b/src/org/jetbrains/java/decompiler/util/JADNameProvider.java index b29e693b22..c3168adff5 100644 --- a/src/org/jetbrains/java/decompiler/util/JADNameProvider.java +++ b/src/org/jetbrains/java/decompiler/util/JADNameProvider.java @@ -37,13 +37,14 @@ public class JADNameProvider implements IVariableNameProvider { private HashMap last = null; private HashMap remap = null; + private final HashMap parameters = new HashMap<>(); private StructMethod method = null; private boolean renameParameters = false; private static final Pattern CAPS_START = Pattern.compile("^[A-Z]"); private static final Pattern ARRAY = Pattern.compile("(\\[|\\.\\.\\.)"); - public JADNameProvider(StructMethod wrapper) { - last = new HashMap(); + public JADNameProvider(boolean renameParameters, StructMethod wrapper) { + last = new HashMap<>(); last.put("int", new Holder(0, true, "i", "j", "k", "l")); last.put("byte", new Holder(0, false, "b" )); last.put("char", new Holder(0, false, "c" )); @@ -65,6 +66,7 @@ public JADNameProvider(StructMethod wrapper) { remap.put("long", "int"); this.method = wrapper; + this.renameParameters = renameParameters; } @Override @@ -109,34 +111,34 @@ public Map rename(Map entries) { params += param.stackSize; } - List keys = new ArrayList(entries.keySet()); - Collections.sort(keys, new Comparator(){ - @Override - public int compare(VarVersionPair o1, VarVersionPair o2) { - if (o1.var != o2.var) return o1.var - o2.var; - return o1.version - o2.version; - } - }); + List keys = new ArrayList<>(entries.keySet()); + Collections.sort(keys, (o1, o2) -> (o1.var != o2.var) ? o1.var - o2.var : o1.version - o2.version); - Map result = new LinkedHashMap(); + Map result = new LinkedHashMap<>(); for (VarVersionPair ver : keys) { - String type = entries.get(ver); + String type = cleanType(entries.get(ver)); if ("this".equals(type)) { continue; } - if (type.indexOf('<') != -1) { - type = type.substring(0, type.indexOf('<')); - } - if (type.indexOf('.') != -1) { - type = type.substring(type.lastIndexOf('.') + 1); - } - if (renameParameters || ver.var >= params) { + if (ver.var >= params) { result.put(ver, getNewName(type)); + } else if (renameParameters) { + result.put(ver, this.parameters.computeIfAbsent(ver.var, k -> getNewName(type))); } } return result; } + private String cleanType(String type) { + if (type.indexOf('<') != -1) { + type = type.substring(0, type.indexOf('<')); + } + if (type.indexOf('.') != -1) { + type = type.substring(type.lastIndexOf('.') + 1); + } + return type; + } + protected synchronized String getNewName(String type) { String index = null; String findtype = type; @@ -199,14 +201,24 @@ else if (remap.containsKey(type)) { } @Override - public String renameAbstractParameter(String abstractParam, int index) { - return abstractParam; + public String renameParameter(int flags, String type, String name, int index) { + if (!this.renameParameters) { + return IVariableNameProvider.super.renameParameter(flags, type, name, index); + } + + return this.parameters.computeIfAbsent(index, k -> getNewName(cleanType(type))); } public static class JADNameProviderFactory implements IVariableNamingFactory { + private final boolean renameParameters; + + public JADNameProviderFactory(boolean renameParameters) { + this.renameParameters = renameParameters; + } + @Override public IVariableNameProvider createFactory(StructMethod method) { - return new JADNameProvider(method); + return new JADNameProvider(renameParameters, method); } } } From 799faebb03806ff878bcace7226bcd80d601fdf0 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Thu, 3 Aug 2023 13:58:02 -0400 Subject: [PATCH 14/18] Fix classes inheriting names from enclosed methods --- .../java/decompiler/main/ClassWriter.java | 7 ++++++ .../decompiler/main/ClassesProcessor.java | 5 +++++ .../main/rels/NestedClassProcessor.java | 4 ++-- .../decompiler/stats/RootStatement.java | 1 - .../decompiler/vars/VarDefinitionHelper.java | 1 + .../modules/decompiler/vars/VarProcessor.java | 22 +++++++++++++++++++ testData/results/pkg/TestDuplicateLocals.dec | 4 ++-- 7 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java index bf2e07da24..5d0c9c7e6f 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -101,6 +101,13 @@ private static boolean invokeProcessors(TextBuffer buffer, ClassNode node) { EnumProcessor.clearEnum(wrapper); } + // FIXME: when 1.10 merge, this needs to be removed + for (MethodWrapper mw : wrapper.getMethods()) { + if (mw.root != null) { + mw.varproc.rerunClashing(mw.root); + } + } + if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ASSERTIONS)) { AssertProcessor.buildAssertions(node); } diff --git a/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java b/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java index 1a991e7cc0..940f569a1a 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java +++ b/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java @@ -686,6 +686,11 @@ public int compareTo(ClassNode o) { return this.classStruct.qualifiedName.compareTo(o.classStruct.qualifiedName); } + @Override + public String toString() { + return type + " class " + classStruct.qualifiedName; + } + public static class LambdaInformation { public String method_name; public String method_descriptor; diff --git a/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java b/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java index 0b538bdc8d..70dc8094cd 100644 --- a/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java +++ b/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java @@ -343,7 +343,7 @@ else if (!mapNewNames.containsKey(varVersion)) { VarVersionPair pair = entry.getKey(); LocalVariable lvt = lvts.get(pair); - varProc.setVarName(pair, entry.getValue()); + varProc.setInheritedName(pair, entry.getValue()); if (lvt != null) { varProc.setVarLVT(pair, lvt); } @@ -734,7 +734,7 @@ private static void insertLocalVars(ClassNode parent, ClassNode child) { VarType type = mapNewTypes.get(pair); LocalVariable lvt = mapNewLVTs.get(pair); - method.varproc.setVarName(pair, entry.getValue()); + method.varproc.setInheritedName(pair, entry.getValue()); if (type != null) { method.varproc.setVarType(pair, type); } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java index 48c337448e..fe7f33a62f 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java @@ -23,7 +23,6 @@ public RootStatement(Statement head, DummyExitStatement dummyExit, StructMethod first = head; this.dummyExit = dummyExit; this.mt = mt; - if (this.first == null) { throw new IllegalStateException("Root statement has no content!"); } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java index 23824a61f4..fa473d3983 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java @@ -1354,6 +1354,7 @@ public void remapClashingNames(Statement root) { Map> varDefinitions = new HashMap<>(); Set liveVarDefs = new HashSet<>(); Map nameMap = new HashMap<>(); + nameMap.putAll(this.varproc.getInheritedNames()); StructMethodParametersAttribute paramAttribute = ((RootStatement) root).mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_METHOD_PARAMETERS); StructLocalVariableTableAttribute lvtAttribute = ((RootStatement) root).mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE); diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java index 2f79d43e36..67f50789a3 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java @@ -28,6 +28,7 @@ public class VarProcessor { private final Map thisVars = new HashMap<>(); private final Set externalVars = new HashSet<>(); private final Map clashingNames = new HashMap<>(); + private final Map inheritedNames = new HashMap<>(); private final Set syntheticSemaphores = new HashSet<>(); public boolean nestedProcessed; @@ -96,6 +97,17 @@ public void setDebugVarNames(RootStatement root, Map map } } + public void rerunClashing(RootStatement root) { + VarDefinitionHelper vardef = new VarDefinitionHelper(root, method, this, false); + vardef.remapClashingNames(root); + + for (Entry e : vardef.getClashingNames().entrySet()) { + if (!params.contains(e.getKey())) { + this.clashingNames.put(e.getKey(), e.getValue()); + } + } + } + public Integer getVarOriginalIndex(int index) { if (varVersions == null) { return null; @@ -145,6 +157,16 @@ public void setVarName(VarVersionPair pair, String name) { mapVarNames.put(pair, name); } + public void setInheritedName(VarVersionPair pair, String name) { + setVarName(pair, name); + + inheritedNames.put(pair, name); + } + + public Map getInheritedNames() { + return this.inheritedNames; + } + public Set getUsedVarVersions() { return mapVarNames != null ? mapVarNames.keySet() : Collections.emptySet(); } diff --git a/testData/results/pkg/TestDuplicateLocals.dec b/testData/results/pkg/TestDuplicateLocals.dec index ab89fcb786..a38212a4e1 100644 --- a/testData/results/pkg/TestDuplicateLocals.dec +++ b/testData/results/pkg/TestDuplicateLocals.dec @@ -30,7 +30,7 @@ public class TestDuplicateLocals { public void test3(List> var1) { System.out.println(var1); var1.forEach(var0 -> { - int var1x = var0.size(); + int var1xx = var0.size(); System.out.println(var0); var0.forEach(var1xx -> System.out.println(var1x)); }); @@ -386,4 +386,4 @@ class 'pkg/TestDuplicateLocals$Inner2' { } } -Lines mapping: +Lines mapping: \ No newline at end of file From 97066f2b26ed7588540fb91cd4d97e2e30042e61 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Thu, 3 Aug 2023 14:03:28 -0400 Subject: [PATCH 15/18] Fix #296 --- src/org/jetbrains/java/decompiler/main/ClassWriter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 5d0c9c7e6f..dae656f98c 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -1121,7 +1121,7 @@ else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarT } String newParameterName = methodWrapper.methodStruct.getVariableNamer().renameParameter(flags, typeName, parameterName, index); - if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0 && newParameterName.equals(parameterName)) { + if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0 && Objects.equals(newParameterName, parameterName)) { newParameterName = DecompilerContext.getStructContext().renameAbstractParameter(methodWrapper.methodStruct.getClassQualifiedName(), mt.getName(), mt.getDescriptor(), index - (((flags & CodeConstants.ACC_STATIC) == 0) ? 1 : 0), parameterName); } parameterName = newParameterName; From 6722ca4b510a48885ff5dc55d2d7f91d7253e7db Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Thu, 3 Aug 2023 15:05:11 -0400 Subject: [PATCH 16/18] Add test for incorrect switch statement generation --- .../java/decompiler/SingleClassesTest.java | 1 + .../results/pkg/TestSwitchExprString1.dec | 69 +++++++++++++++++++ .../src/java16/pkg/TestSwitchExprString1.java | 18 +++++ 3 files changed, 88 insertions(+) create mode 100644 testData/results/pkg/TestSwitchExprString1.dec create mode 100644 testData/src/java16/pkg/TestSwitchExprString1.java diff --git a/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 15ff4a62d5..1ab89dd962 100644 --- a/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -372,6 +372,7 @@ private void registerDefault() { register(JAVA_16, "TestReturnSwitchExpression2"); register(JAVA_16, "TestReturnSwitchExpression3"); register(JAVA_16, "TestReturnSwitchExpression4"); + register(JAVA_16, "TestSwitchExprString1"); register(JAVA_16, "TestConstructorSwitchExpression1"); register(JAVA_16, "TestConstructorSwitchExpression2"); diff --git a/testData/results/pkg/TestSwitchExprString1.dec b/testData/results/pkg/TestSwitchExprString1.dec new file mode 100644 index 0000000000..94e75f4a78 --- /dev/null +++ b/testData/results/pkg/TestSwitchExprString1.dec @@ -0,0 +1,69 @@ +package pkg; + +public class TestSwitchExprString1 { + public TestSwitchExprString1.Type get(String s) { + if (s == null) {// 9 + return TestSwitchExprString1.Type.B;// 10 + } else { + byte var3 = -1; + switch(s.hashCode()) { + case 97: + if (s.equals("a")) { + var3 = 0; + } + default: + return switch(var3) {// 13 + case 0 -> TestSwitchExprString1.Type.A;// 14 + default -> TestSwitchExprString1.Type.B;// 15 + }; + } + } + } + + static enum Type { + A, + B; + } +} + +class 'pkg/TestSwitchExprString1' { + method 'get (Ljava/lang/String;)Lpkg/TestSwitchExprString1$Type;' { + 0 4 + 1 4 + 4 5 + 5 5 + 6 5 + 7 5 + 8 8 + a 7 + b 7 + c 8 + d 8 + e 8 + f 8 + 10 8 + 24 10 + 25 10 + 26 10 + 27 10 + 28 10 + 29 10 + 2a 10 + 2d 11 + 2e 11 + 2f 14 + 30 14 + 44 15 + 45 15 + 46 15 + 4a 16 + 4d 14 + } +} + +Lines mapping: +9 <-> 5 +10 <-> 6 +13 <-> 15 +14 <-> 16 +15 <-> 17 diff --git a/testData/src/java16/pkg/TestSwitchExprString1.java b/testData/src/java16/pkg/TestSwitchExprString1.java new file mode 100644 index 0000000000..ff9b11d9c6 --- /dev/null +++ b/testData/src/java16/pkg/TestSwitchExprString1.java @@ -0,0 +1,18 @@ +package pkg; + +public class TestSwitchExprString1 { + enum Type { + A, B + } + + public Type get(String s) { + if (s == null) { + return Type.B; + } + + return switch (s) { + case "a" -> Type.A; + default -> Type.B; + }; + } +} From f98b4edab513a537b90c8be897d412a778250632 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Thu, 3 Aug 2023 16:10:08 -0400 Subject: [PATCH 17/18] Fix IOOBE with finally var remapping --- .../java/decompiler/modules/decompiler/FinallyProcessor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java index 09cbe62ee9..509666d4c8 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java @@ -823,7 +823,9 @@ private boolean compareBasicBlocksEx(ControlFlowGraph graph, seq.addInstruction(0, seqSample.getInstr(i), -1); oldOffsets.addFirst(sample.getOldOffset(i)); seqSample.removeInstruction(i); - instrOldOffsetsSample.remove(i); + if (i < instrOldOffsetsSample.size()) { + instrOldOffsetsSample.remove(i); + } } BasicBlock newblock = new BasicBlock(++graph.last_id); From f79b26326972535ba787fbf659c4821865459dd8 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan <25208576+jaskarth@users.noreply.github.com> Date: Thu, 3 Aug 2023 20:12:47 -0400 Subject: [PATCH 18/18] Fix test --- .../pkg/TestSwitchPatternMatching22_1.dec | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/testData/results/pkg/TestSwitchPatternMatching22_1.dec b/testData/results/pkg/TestSwitchPatternMatching22_1.dec index 7f465a407d..c15e39c4f8 100644 --- a/testData/results/pkg/TestSwitchPatternMatching22_1.dec +++ b/testData/results/pkg/TestSwitchPatternMatching22_1.dec @@ -111,13 +111,12 @@ class 'pkg/TestSwitchPatternMatching22' { 4f 14 54 9 55 9 - 61 17 - 62 17 63 17 64 17 65 17 66 17 67 17 + 68 17 6e 19 } @@ -143,9 +142,7 @@ class 'pkg/TestSwitchPatternMatching22' { 4b 31 50 27 51 27 - 60 34 - 61 34 - 62 34 + 63 34 } method 'test1Null ()V' { @@ -170,13 +167,12 @@ class 'pkg/TestSwitchPatternMatching22' { 4f 49 54 44 55 44 - 61 52 - 62 52 63 52 64 52 65 52 66 52 67 52 + 68 52 6e 54 } @@ -202,9 +198,7 @@ class 'pkg/TestSwitchPatternMatching22' { 4b 66 50 62 51 62 - 60 69 - 61 69 - 62 69 + 63 69 } method 'testNonPattern ()V' { @@ -226,9 +220,7 @@ class 'pkg/TestSwitchPatternMatching22' { 32 81 33 81 3b 82 - 49 85 - 4a 85 - 4b 85 + 4c 85 } }