提交 33f2c3f2 编写于 作者: S Skylot

fix: transform loop to `for` with branching at end

Signed-off-by: NSkylot <skylot@gmail.com>
上级 dcca0133
......@@ -73,4 +73,6 @@ public enum AFlag {
SOFT_CAST, // synthetic cast to help type inference
INCONSISTENT_CODE, // warning about incorrect decompilation
REQUEST_IF_REGION_OPTIMIZE, // run if region visitor again
}
......@@ -26,7 +26,10 @@ public class IfRegionVisitor extends AbstractVisitor {
if (mth.isNoCode()) {
return;
}
process(mth);
}
public static void process(MethodNode mth) {
DepthRegionTraversal.traverseIterative(mth, TERNARY_VISITOR);
DepthRegionTraversal.traverse(mth, PROCESS_IF_REGION_VISITOR);
DepthRegionTraversal.traverseIterative(mth, REMOVE_REDUNDANT_ELSE_VISITOR);
......
......@@ -53,35 +53,43 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor
@Override
public void visit(MethodNode mth) {
DepthRegionTraversal.traverse(mth, this);
if (mth.contains(AFlag.REQUEST_IF_REGION_OPTIMIZE)) {
IfRegionVisitor.process(mth);
mth.remove(AFlag.REQUEST_IF_REGION_OPTIMIZE);
}
}
@Override
public boolean enterRegion(MethodNode mth, IRegion region) {
if (region instanceof LoopRegion) {
processLoopRegion(mth, (LoopRegion) region);
if (processLoopRegion(mth, (LoopRegion) region)) {
// optimize `if` block after instructions remove
mth.add(AFlag.REQUEST_IF_REGION_OPTIMIZE);
}
}
return true;
}
private static void processLoopRegion(MethodNode mth, LoopRegion loopRegion) {
private static boolean processLoopRegion(MethodNode mth, LoopRegion loopRegion) {
if (loopRegion.isConditionAtEnd()) {
return;
return false;
}
IfCondition condition = loopRegion.getCondition();
if (condition == null) {
return;
return false;
}
if (checkForIndexedLoop(mth, loopRegion, condition)) {
return;
return true;
}
checkIterableForEach(mth, loopRegion, condition);
return checkIterableForEach(mth, loopRegion, condition);
}
/**
* Check for indexed loop.
*/
private static boolean checkForIndexedLoop(MethodNode mth, LoopRegion loopRegion, IfCondition condition) {
InsnNode incrInsn = RegionUtils.getLastInsn(loopRegion);
BlockNode loopEndBlock = loopRegion.getInfo().getEnd();
InsnNode incrInsn = BlockUtils.getLastInsn(BlockUtils.skipSyntheticPredecessor(loopEndBlock));
if (incrInsn == null) {
return false;
}
......
package jadx.tests.integration.loops;
import org.junit.jupiter.api.Test;
import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
/**
* Issue #977
*/
public class TestArrayForEach3 extends IntegrationTest {
public static class TestCls {
public void test(String[] arr) {
for (String s : arr) {
if (s.length() > 0) {
return;
}
}
throw new IllegalArgumentException("All strings are empty");
}
public void check() {
test(new String[] { "", "a" }); // no exception
try {
test(new String[] { "", "" });
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e) {
// expected
}
}
}
@Test
public void test() {
noDebugInfo();
assertThat(getClassNode(TestCls.class))
.code()
.doesNotContain("while")
.containsOne("for (String str : strArr) {");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册