From 151c171616d0ce99047d702d815b665d3facafb4 Mon Sep 17 00:00:00 2001 From: Skylot Date: Fri, 23 Sep 2022 20:16:28 +0100 Subject: [PATCH] fix: handle empty block at end of `else-if` chain (#1674) --- .../dex/visitors/regions/IfRegionVisitor.java | 14 +++++-- .../java/jadx/core/utils/RegionUtils.java | 14 ------- .../conditions/TestElseIfCodeStyle.java | 37 +++++++++++++++++++ 3 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/conditions/TestElseIfCodeStyle.java diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfRegionVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfRegionVisitor.java index ec0d60a9..75728502 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfRegionVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfRegionVisitor.java @@ -3,8 +3,10 @@ package jadx.core.dex.visitors.regions; import java.util.List; import jadx.core.dex.attributes.AFlag; +import jadx.core.dex.instructions.InsnType; import jadx.core.dex.nodes.IContainer; import jadx.core.dex.nodes.IRegion; +import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.regions.Region; import jadx.core.dex.regions.conditions.IfCondition; @@ -45,7 +47,7 @@ public class IfRegionVisitor extends AbstractVisitor { } } - @SuppressWarnings("UnnecessaryReturnStatement") + @SuppressWarnings({ "UnnecessaryReturnStatement", "StatementWithEmptyBody" }) private static void orderBranches(MethodNode mth, IfRegion ifRegion) { if (RegionUtils.isEmpty(ifRegion.getElseRegion())) { return; @@ -79,9 +81,15 @@ public class IfRegionVisitor extends AbstractVisitor { return; } } - boolean lastRegion = ifRegion == RegionUtils.getLastRegion(mth.getRegion()); + boolean lastRegion = RegionUtils.hasExitEdge(ifRegion); if (elseSize == 1 && lastRegion && mth.isVoidReturn()) { - // single return at method end will be removed later + InsnNode lastElseInsn = RegionUtils.getLastInsn(ifRegion.getElseRegion()); + if (lastElseInsn != null && lastElseInsn.getType() == InsnType.THROW) { + // move `throw` into `then` block + invertIfRegion(ifRegion); + } else { + // single return at method end will be removed later + } return; } if (!lastRegion) { diff --git a/jadx-core/src/main/java/jadx/core/utils/RegionUtils.java b/jadx-core/src/main/java/jadx/core/utils/RegionUtils.java index aa0ffc90..b521dc64 100644 --- a/jadx-core/src/main/java/jadx/core/utils/RegionUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/RegionUtils.java @@ -146,20 +146,6 @@ public class RegionUtils { } } - @Nullable - public static IContainer getLastRegion(@Nullable IContainer container) { - if (container == null) { - return null; - } - if (container instanceof IBlock || container instanceof IBranchRegion) { - return container; - } - if (container instanceof IRegion) { - return getLastRegion(Utils.last(((IRegion) container).getSubBlocks())); - } - throw new JadxRuntimeException(unknownContainerType(container)); - } - public static boolean isExitBlock(MethodNode mth, IContainer container) { if (container instanceof BlockNode) { return BlockUtils.isExitBlock(mth, (BlockNode) container); diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestElseIfCodeStyle.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestElseIfCodeStyle.java new file mode 100644 index 00000000..e1133cc7 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestElseIfCodeStyle.java @@ -0,0 +1,37 @@ +package jadx.tests.integration.conditions; + +import org.junit.jupiter.api.Test; + +import jadx.api.ICodeWriter; +import jadx.tests.api.IntegrationTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestElseIfCodeStyle extends IntegrationTest { + + @SuppressWarnings("unused") + public static class TestCls { + + public void test(String str) { + if ("a".equals(str)) { + call(1); + } else if ("b".equals(str)) { + call(2); + } else if ("c".equals(str)) { + call(3); + } + } + + private void call(int i) { + } + } + + @Test + public void test() { + noDebugInfo(); + assertThat(getClassNode(TestCls.class)) + .code() + .doesNotContain("!\"c\".equals(str)") + .doesNotContain("{" + ICodeWriter.NL + indent(2) + "} else {"); // no empty `then` block + } +} -- GitLab