Skip to content

Commit

Permalink
fix: check variable usage before convert indexed loop to for-each var…
Browse files Browse the repository at this point in the history
…iant (#483)
  • Loading branch information
skylot committed Mar 22, 2019
1 parent 5a940a3 commit 2c07253
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private static boolean checkForIndexedLoop(MethodNode mth, LoopRegion loopRegion
// all checks passed
initInsn.add(AFlag.SKIP);
incrInsn.add(AFlag.SKIP);
LoopType arrForEach = checkArrayForEach(mth, initInsn, incrInsn, condition);
LoopType arrForEach = checkArrayForEach(mth, loopRegion, initInsn, incrInsn, condition);
if (arrForEach != null) {
loopRegion.setType(arrForEach);
return true;
Expand All @@ -125,7 +125,7 @@ private static boolean checkForIndexedLoop(MethodNode mth, LoopRegion loopRegion
return true;
}

private static LoopType checkArrayForEach(MethodNode mth, InsnNode initInsn, InsnNode incrInsn,
private static LoopType checkArrayForEach(MethodNode mth, LoopRegion loopRegion, InsnNode initInsn, InsnNode incrInsn,
IfCondition condition) {
if (!(incrInsn instanceof ArithNode)) {
return null;
Expand Down Expand Up @@ -186,6 +186,9 @@ private static LoopType checkArrayForEach(MethodNode mth, InsnNode initInsn, Ins
if (iterVar == null) {
return null;
}
if (!usedOnlyInLoop(mth, loopRegion, iterVar)) {
return null;
}

// array for each loop confirmed
len.add(AFlag.SKIP);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package jadx.tests.integration.loops;

import java.io.File;

import org.junit.Test;

import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;

import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;

public class TestIndexedLoop extends IntegrationTest {

public static class TestCls {

public File test(File[] files) {
File file = null;
if (files != null) {
int length = files.length;
if (length == 0) {
file = null;
} else {
for (int i = 0; i < length; i++) {
file = files[i];
if (file.getName().equals("f")) {
break;
}
}
}
} else {
file = null;
}
if (file != null) {
file.deleteOnExit();
}
return file;
}

public void check() {
assertThat(test(null), nullValue());
assertThat(test(new File[]{}), nullValue());

File file = new File("f");
assertThat(test(new File[]{new File("a"), file}), is(file));
}
}

@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();

assertThat(code, not(containsString("for (File file :")));
assertThat(code, containsOne("for (int i = 0; i < length; i++) {"));
}

@Test
public void testNoDebug() {
noDebugInfo();
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();

assertThat(code, not(containsString("for (File file :")));
assertThat(code, containsOne("for (int i = 0; i < length; i++) {"));
}
}

0 comments on commit 2c07253

Please sign in to comment.