diff --git a/CHANGELOG.md b/CHANGELOG.md index dc76cc9ad..ff0b01ad1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ### Fixed - [#1888] AS3 - missing casts in declarations +- [#1894] Switch inside loop ## [18.3.2] - 2023-01-10 ### Removed diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 3844acb42..24396db1b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -446,11 +446,11 @@ public class Graph { commonSet.add(new PartCommon(r, commonLevel)); } - Set partsLeadingToStopPart = new LinkedHashSet<>(); + /*Set partsLeadingToStopPart = new LinkedHashSet<>(); if (stopPart != null) { for (GraphPart p : parts) { for (GraphPart sp : stopPart) { - if (sp == p || p.leadsTo(localData, this, code, sp, new ArrayList() /*IGNORE LOOPS*/, throwStates, false)) { + if (sp == p || p.leadsTo(localData, this, code, sp, new ArrayList(), throwStates, false)) { partsLeadingToStopPart.add(p); } } @@ -478,23 +478,19 @@ public class Graph { System.err.println("partsLeadingToStopPart:"); for (GraphPart p : partsLeadingToStopPart) { System.err.println("- " + p); - } - - /*if (partsLeadingToStopPart.isEmpty()) { - return null; //? - }*/ - } + } + }*/ loopc: for (PartCommon pc : commonSet) { - for (GraphPart p : partsLeadingToStopPart) { + /*for (GraphPart p : partsLeadingToStopPart) { if (p != pc.part && !p.leadsTo(localData, this, code, pc.part, loops, throwStates, false)) { if (debugPrintLoopList) { System.err.println("ignoring " + pc.part + ", " + p + " does not lead to it"); } continue loopc; } - } + }*/ if (pc.level <= 1) { return null; } @@ -823,9 +819,10 @@ public class Graph { } } } - if (hasContinues && breakCaseIndex > -1 && i + 1 < list.size() && (list.get(list.size() - 1) instanceof ContinueItem)) { + if (hasContinues && breakCaseIndex > -1 && i + 1 < list.size()) { List toAdd = new ArrayList<>(); - for (int j = i + 1; j < list.size() - 1; j++) { + boolean continueOnEnd = list.get(list.size() - 1 ) instanceof ContinueItem; + for (int j = i + 1; j < list.size() - (continueOnEnd ? 1 : 0); j++) { toAdd.add(list.remove(i + 1)); } List targetCommands = swi.caseCommands.get(breakCaseIndex); @@ -833,7 +830,9 @@ public class Graph { targetCommands.remove(targetCommands.size() - 1); } targetCommands.addAll(toAdd); - targetCommands.add(new BreakItem(null, null, swi.loop.id)); + if (toAdd.isEmpty() || (!((toAdd.get(toAdd.size()-1) instanceof ExitItem)||(toAdd.get(toAdd.size()-1) instanceof BreakItem)))) { + targetCommands.add(new BreakItem(null, null, swi.loop.id)); + } } } } @@ -3378,6 +3377,44 @@ public class Graph { } caseCommands.add(currentCaseCommands); } + + + /* + switch(a) + { + case 0: + case 1: + break; + case 2: + break; + } + + => + + switch(a) + { + case 0: + case 1: + case 2: + break; + } + + */ + for (int i = 0; i < caseCommands.size(); i++) { + if (caseCommands.get(i).size() == 1 && + (caseCommands.get(i).get(0) instanceof BreakItem) && + (((BreakItem)caseCommands.get(i).get(0)).loopId == currentLoop.id)) { + for (int j = i + 1; j < caseCommands.size(); j++) { + if (caseCommands.get(j).size() == 1 && + (caseCommands.get(j).get(0) instanceof BreakItem) && + (((BreakItem)caseCommands.get(j).get(0)).loopId == currentLoop.id)) { + caseCommands.get(j - 1).remove(0); + } else { + break; + } + } + } + } //If the lastone is default empty and alone, remove it if (!caseCommands.isEmpty()) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java index e0f153e56..1c25077c6 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java @@ -1506,6 +1506,34 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile false); } + @Test + public void testSwitchContinue() { + decompileMethod("classic_air", "testSwitchContinue", "var i:int = 0;\r\n" + + "var r:int = Math.random() % 10;\r\n" + + "if(r > 5)\r\n" + + "{\r\n" + + "for(i = 0; i < 10; i++)\r\n" + + "{\r\n" + + "switch(i)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "trace(\"hello\");\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "trace(\"hi\");\r\n" + + "break;\r\n" + + "case 2:\r\n" + + "trace(\"howdy\");\r\n" + + "break;\r\n" + + "default:\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"message shown\");\r\n" + + "}\r\n" + + "}\r\n", + false); + } + @Test public void testSwitchDefault() { decompileMethod("classic_air", "testSwitchDefault", "var a:int = 5;\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java index 091c46370..d68685465 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java @@ -1502,6 +1502,34 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes false); } + @Test + public void testSwitchContinue() { + decompileMethod("classic", "testSwitchContinue", "var i:int = 0;\r\n" + + "var r:int = Math.random() % 10;\r\n" + + "if(r > 5)\r\n" + + "{\r\n" + + "for(i = 0; i < 10; i++)\r\n" + + "{\r\n" + + "switch(i)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "trace(\"hello\");\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "trace(\"hi\");\r\n" + + "break;\r\n" + + "case 2:\r\n" + + "trace(\"howdy\");\r\n" + + "break;\r\n" + + "default:\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"message shown\");\r\n" + + "}\r\n" + + "}\r\n", + false); + } + @Test public void testSwitchDefault() { decompileMethod("classic", "testSwitchDefault", "var a:* = 5;\r\n" diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf index cfdf1775b..d405638c4 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf index ef8d15b41..1f943e3d8 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as index 03ba395f2..d695fddef 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as @@ -96,6 +96,7 @@ package TestStringConcat; TestStrings; TestSwitch; + TestSwitchContinue; TestSwitchComma; TestSwitchDefault; TestSwitchIf; diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestSwitchContinue.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestSwitchContinue.as new file mode 100644 index 000000000..597d1aec6 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestSwitchContinue.as @@ -0,0 +1,33 @@ +package tests +{ + + public class TestSwitchContinue + { + public function run():* + { + var r:int = Math.random() % 10; + + if (r > 5) + { + for(var i:int = 0; i < 10; i++) + { + switch(i) + { + case 0: + trace("hello"); + break; + case 1: + trace("hi"); + break; + case 2: + trace("howdy"); + break; + default: + continue; + } + trace("message shown"); + } + } + } + } +}