diff --git a/jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java b/jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java index 76383db75..009da3490 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java +++ b/jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java @@ -50,30 +50,20 @@ public class CodeWriter { public CodeWriter startLine() { addLine(); - addIndent(); + addLineIndent(); return this; } public CodeWriter startLine(char c) { addLine(); - addIndent(); + addLineIndent(); add(c); return this; } public CodeWriter startLine(String str) { addLine(); - addIndent(); - add(str); - return this; - } - - public CodeWriter startLine(int ind, String str) { - addLine(); - addIndent(); - for (int i = 0; i < ind; i++) { - addIndent(); - } + addLineIndent(); add(str); return this; } @@ -118,12 +108,17 @@ public class CodeWriter { offset = 0; } - public CodeWriter addIndent() { + private CodeWriter addLineIndent() { buf.append(indentStr); offset += indentStr.length(); return this; } + public CodeWriter addIndent() { + add(INDENT); + return this; + } + private void updateIndent() { int curIndent = indent; if (curIndent < INDENT_CACHE.length) { @@ -137,14 +132,6 @@ public class CodeWriter { } } - public int getLine() { - return line; - } - - public int getIndent() { - return indent; - } - public void incIndent() { incIndent(1); } @@ -167,6 +154,10 @@ public class CodeWriter { updateIndent(); } + public int getLine() { + return line; + } + private static class DefinitionWrapper { private final LineAttrNode node; diff --git a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java index 4c3108c7c..1b9490634 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java @@ -203,6 +203,7 @@ public class RegionGen extends InsnGen { code.startLine("switch ("); addArg(code, arg); code.add(") {"); + code.incIndent(); int size = sw.getKeys().size(); for (int i = 0; i < size; i++) { @@ -223,18 +224,21 @@ public class RegionGen extends InsnGen { code.startLine("default:"); makeCaseBlock(sw.getDefaultCase(), code); } + code.decIndent(); code.startLine('}'); return code; } private void makeCaseBlock(IContainer c, CodeWriter code) throws CodegenException { + boolean addBreak = true; if (RegionUtils.notEmpty(c)) { makeRegionIndent(code, c); - if (RegionUtils.hasExitEdge(c)) { - code.startLine(1, "break;"); + if (!RegionUtils.hasExitEdge(c)) { + addBreak = false; } - } else { - code.startLine(1, "break;"); + } + if (addBreak) { + code.startLine().addIndent().add("break;"); } } diff --git a/jadx-core/src/test/java/jadx/api/InternalJadxTest.java b/jadx-core/src/test/java/jadx/api/InternalJadxTest.java index 2c794e79d..ff9592a00 100644 --- a/jadx-core/src/test/java/jadx/api/InternalJadxTest.java +++ b/jadx-core/src/test/java/jadx/api/InternalJadxTest.java @@ -1,7 +1,6 @@ package jadx.api; import jadx.core.Jadx; -import jadx.core.codegen.CodeWriter; import jadx.core.dex.attributes.AttributeFlag; import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.MethodNode; @@ -25,7 +24,7 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.fail; -public abstract class InternalJadxTest { +public abstract class InternalJadxTest extends TestUtils { protected boolean outputCFG = false; protected boolean deleteTmpJar = true; @@ -151,14 +150,6 @@ public abstract class InternalJadxTest { } } - protected String makeIndent(int indent) { - StringBuilder sb = new StringBuilder(indent * CodeWriter.INDENT.length()); - for (int i = 0; i < indent; i++) { - sb.append(CodeWriter.INDENT); - } - return sb.toString(); - } - // Use only for debug purpose @Deprecated protected void setOutputCFG() { diff --git a/jadx-core/src/test/java/jadx/api/TestUtils.java b/jadx-core/src/test/java/jadx/api/TestUtils.java new file mode 100644 index 000000000..09ec769d8 --- /dev/null +++ b/jadx-core/src/test/java/jadx/api/TestUtils.java @@ -0,0 +1,25 @@ +package jadx.api; + +import jadx.core.codegen.CodeWriter; + +public class TestUtils { + + public static String indent(int indent) { + StringBuilder sb = new StringBuilder(indent * CodeWriter.INDENT.length()); + for (int i = 0; i < indent; i++) { + sb.append(CodeWriter.INDENT); + } + return sb.toString(); + } + + public static int count(String string, String substring) { + int count = 0; + int idx = 0; + while ((idx = string.indexOf(substring, idx)) != -1) { + idx++; + count++; + } + return count; + } + +} diff --git a/jadx-core/src/test/java/jadx/tests/internal/TestSwitch.java b/jadx-core/src/test/java/jadx/tests/internal/TestSwitch.java new file mode 100644 index 000000000..f8281ea3c --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/internal/TestSwitch.java @@ -0,0 +1,49 @@ +package jadx.tests.internal; + +import jadx.api.InternalJadxTest; +import jadx.core.dex.nodes.ClassNode; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +public class TestSwitch extends InternalJadxTest { + public static class TestCls { + public String escape(String str) { + int len = str.length(); + StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; i++) { + char c = str.charAt(i); + switch (c) { + case '.': + case '/': + sb.append('_'); + break; + + case ']': + sb.append('A'); + break; + + case '?': + break; + + default: + sb.append(c); + break; + } + } + return sb.toString(); + } + } + + @Test + public void test() { + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + System.out.println(code); + + assertThat(code, containsString("case '/':")); + assertThat(code, containsString(indent(5) + "break;")); + } +} diff --git a/jadx-core/src/test/java/jadx/tests/internal/TestSynchronized.java b/jadx-core/src/test/java/jadx/tests/internal/TestSynchronized.java index cabafee70..5a126ffcf 100644 --- a/jadx-core/src/test/java/jadx/tests/internal/TestSynchronized.java +++ b/jadx-core/src/test/java/jadx/tests/internal/TestSynchronized.java @@ -38,6 +38,6 @@ public class TestSynchronized extends InternalJadxTest { assertThat(code, containsString("return this.f")); assertThat(code, containsString("synchronized (this.o) {")); - assertThat(code, not(containsString(makeIndent(3) + ";"))); + assertThat(code, not(containsString(indent(3) + ";"))); } } diff --git a/jadx-core/src/test/java/jadx/tests/internal/TestVariablesDefinitions.java b/jadx-core/src/test/java/jadx/tests/internal/TestVariablesDefinitions.java index e8dec632a..b1cdfad8e 100644 --- a/jadx-core/src/test/java/jadx/tests/internal/TestVariablesDefinitions.java +++ b/jadx-core/src/test/java/jadx/tests/internal/TestVariablesDefinitions.java @@ -43,7 +43,7 @@ public class TestVariablesDefinitions extends InternalJadxTest { System.out.println(code); // 'iterator' variable must be declared inside 'try' block - assertThat(code, containsString(makeIndent(3) + "Iterator iterator = ")); + assertThat(code, containsString(indent(3) + "Iterator iterator = ")); assertThat(code, not(containsString("iterator;"))); } } diff --git a/jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass3.java b/jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass3.java index 8cc893669..e5f1688eb 100644 --- a/jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass3.java +++ b/jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass3.java @@ -44,8 +44,8 @@ public class TestAnonymousClass3 extends InternalJadxTest { String code = cls.getCode().toString(); System.out.println(code); - assertThat(code, containsString(makeIndent(4) + "public void run() {")); - assertThat(code, containsString(makeIndent(3) + "}.start();")); + assertThat(code, containsString(indent(4) + "public void run() {")); + assertThat(code, containsString(indent(3) + "}.start();")); // assertThat(code, not(containsString("synthetic"))); // assertThat(code, not(containsString("AnonymousClass_")));