Commit 195eeceb authored by Skylot's avatar Skylot

core: restore simple indexed loops

parent ec8309af
......@@ -18,6 +18,7 @@ import jadx.core.dex.visitors.ReSugarCode;
import jadx.core.dex.visitors.SimplifyVisitor;
import jadx.core.dex.visitors.regions.CheckRegions;
import jadx.core.dex.visitors.regions.IfRegionVisitor;
import jadx.core.dex.visitors.regions.LoopRegionVisitor;
import jadx.core.dex.visitors.regions.ProcessVariables;
import jadx.core.dex.visitors.regions.RegionMakerVisitor;
import jadx.core.dex.visitors.regions.ReturnVisitor;
......@@ -91,6 +92,7 @@ public class Jadx {
passes.add(new MethodInlineVisitor());
passes.add(new ClassModifier());
passes.add(new PrepareForCodeGen());
passes.add(new LoopRegionVisitor());
}
passes.add(new CodeGen(args));
return passes;
......
......@@ -8,9 +8,9 @@ import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.InsnWrapArg;
import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.regions.Compare;
import jadx.core.dex.regions.IfCondition;
import jadx.core.dex.regions.IfCondition.Mode;
import jadx.core.dex.regions.conditions.Compare;
import jadx.core.dex.regions.conditions.IfCondition;
import jadx.core.dex.regions.conditions.IfCondition.Mode;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.JadxRuntimeException;
......
......@@ -58,9 +58,10 @@ public class InsnGen {
protected final RootNode root;
protected final boolean fallback;
private enum Flags {
protected enum Flags {
BODY_ONLY,
BODY_ONLY_NOWRAP,
INLINE
}
public InsnGen(MethodGen mgen, boolean fallback) {
......@@ -186,7 +187,7 @@ public class InsnGen {
return makeInsn(insn, code, null);
}
private boolean makeInsn(InsnNode insn, CodeWriter code, Flags flag) throws CodegenException {
protected boolean makeInsn(InsnNode insn, CodeWriter code, Flags flag) throws CodegenException {
try {
if (insn.getType() == InsnType.NOP) {
return false;
......@@ -196,13 +197,17 @@ public class InsnGen {
state.add(flag);
makeInsnBody(code, insn, state);
} else {
code.startLineWithNum(insn.getSourceLine());
if (flag != Flags.INLINE) {
code.startLineWithNum(insn.getSourceLine());
}
if (insn.getResult() != null && insn.getType() != InsnType.ARITH_ONEARG) {
assignVar(code, insn);
code.add(" = ");
}
makeInsnBody(code, insn, state);
code.add(';');
if (flag != Flags.INLINE) {
code.add(';');
}
}
} catch (Throwable th) {
throw new CodegenException(mth, "Error generate insn: " + insn, th);
......
......@@ -14,17 +14,20 @@ import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.regions.IfCondition;
import jadx.core.dex.regions.IfRegion;
import jadx.core.dex.regions.LoopRegion;
import jadx.core.dex.regions.Region;
import jadx.core.dex.regions.SwitchRegion;
import jadx.core.dex.regions.SynchronizedRegion;
import jadx.core.dex.regions.conditions.IfCondition;
import jadx.core.dex.regions.conditions.IfRegion;
import jadx.core.dex.regions.loops.IndexLoop;
import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.regions.loops.LoopType;
import jadx.core.dex.trycatch.CatchAttr;
import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.JadxRuntimeException;
import java.util.List;
......@@ -92,7 +95,9 @@ public class RegionGen extends InsnGen {
private void makeSimpleBlock(IBlock block, CodeWriter code) throws CodegenException {
for (InsnNode insn : block.getInstructions()) {
makeInsn(insn, code);
if (!insn.contains(AFlag.SKIP)) {
makeInsn(insn, code);
}
}
ForceReturnAttr retAttr = block.get(AType.FORCE_RETURN);
if (retAttr != null) {
......@@ -166,8 +171,24 @@ public class RegionGen extends InsnGen {
code.startLine('}');
return code;
}
ConditionGen conditionGen = new ConditionGen(this);
LoopType type = region.getType();
if (type != null) {
if (type instanceof IndexLoop) {
IndexLoop indexLoop = (IndexLoop) type;
code.startLine("for (");
makeInsn(indexLoop.getInitInsn(), code, Flags.INLINE);
code.add("; ");
conditionGen.add(code, condition);
code.add("; ");
makeInsn(indexLoop.getIncrInsn(), code, Flags.INLINE);
code.add(") {");
makeRegionIndent(code, region.getBody());
code.startLine('}');
return code;
}
throw new JadxRuntimeException("Unknown loop type: " + type.getClass());
}
if (region.isConditionAtEnd()) {
code.startLine("do {");
makeRegionIndent(code, region.getBody());
......
......@@ -23,5 +23,7 @@ public enum AFlag {
ELSE_IF_CHAIN,
WRAPPED,
INCONSISTENT_CODE, // warning about incorrect decompilation
}
package jadx.core.dex.instructions.args;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.utils.InsnUtils;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -76,18 +80,36 @@ public abstract class InsnArg extends Typed {
return null;
}
if (parent == insn) {
LOG.debug("Can't wrap instruction info itself: " + insn);
LOG.debug("Can't wrap instruction info itself: {}", insn);
Thread.dumpStack();
return null;
}
int i = getArgIndex(parent, this);
if (i == -1) {
return null;
}
insn.add(AFlag.WRAPPED);
InsnArg arg = wrapArg(insn);
parent.setArg(i, arg);
return arg;
}
public static void updateParentInsn(InsnNode fromInsn, InsnNode toInsn) {
List<RegisterArg> args = new ArrayList<RegisterArg>();
fromInsn.getRegisterArgs(args);
for (RegisterArg reg : args) {
reg.setParentInsn(toInsn);
}
}
private static int getArgIndex(InsnNode parent, InsnArg arg) {
int count = parent.getArgsCount();
for (int i = 0; i < count; i++) {
if (parent.getArg(i) == this) {
InsnArg arg = wrapArg(insn);
parent.setArg(i, arg);
return arg;
if (parent.getArg(i) == arg) {
return i;
}
}
return null;
return -1;
}
public static InsnArg wrapArg(InsnNode insn) {
......
......@@ -5,7 +5,7 @@ import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.regions.IfCondition;
import jadx.core.dex.regions.conditions.IfCondition;
import jadx.core.utils.InsnUtils;
import jadx.core.utils.Utils;
......
package jadx.core.dex.regions;
package jadx.core.dex.regions.conditions;
import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.IfOp;
......
package jadx.core.dex.regions;
package jadx.core.dex.regions.conditions;
import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.IfOp;
......
package jadx.core.dex.regions;
package jadx.core.dex.regions.conditions;
import jadx.core.dex.nodes.BlockNode;
......
package jadx.core.dex.regions;
package jadx.core.dex.regions.conditions;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.regions.AbstractRegion;
import java.util.ArrayList;
import java.util.Collections;
......@@ -77,7 +78,7 @@ public final class IfRegion extends AbstractRegion {
@Override
public List<IContainer> getSubBlocks() {
ArrayList<IContainer> all = new ArrayList<IContainer>(3);
List<IContainer> all = new ArrayList<IContainer>(3);
all.add(header);
if (thenRegion != null) {
all.add(thenRegion);
......
package jadx.core.dex.regions.loops;
import jadx.core.dex.nodes.InsnNode;
public class IndexLoop extends LoopType {
private final InsnNode initInsn;
private final InsnNode incrInsn;
public IndexLoop(InsnNode initInsn, InsnNode incrInsn) {
this.initInsn = initInsn;
this.incrInsn = incrInsn;
}
public InsnNode getInitInsn() {
return initInsn;
}
public InsnNode getIncrInsn() {
return incrInsn;
}
}
package jadx.core.dex.regions;
package jadx.core.dex.regions.loops;
import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.args.RegisterArg;
......@@ -6,6 +6,8 @@ import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.regions.AbstractRegion;
import jadx.core.dex.regions.conditions.IfCondition;
import java.util.ArrayList;
import java.util.Collections;
......@@ -21,6 +23,8 @@ public final class LoopRegion extends AbstractRegion {
private IContainer body;
private final boolean conditionAtEnd;
private LoopType type;
public LoopRegion(IRegion parent, BlockNode header, boolean reversed) {
super(parent);
this.conditionBlock = header;
......@@ -116,6 +120,15 @@ public final class LoopRegion extends AbstractRegion {
}
}
public LoopType getType() {
return type;
}
public void setType(LoopType type) {
this.type = type;
}
@Override
public List<IContainer> getSubBlocks() {
List<IContainer> all = new ArrayList<IContainer>(3);
......
package jadx.core.dex.regions.loops;
public abstract class LoopType {
}
......@@ -214,6 +214,7 @@ public class CodeShrinker extends AbstractVisitor {
// another block
BlockNode assignBlock = BlockUtils.getBlockByInsn(mth, assignInsn);
if (assignBlock != null
&& assignInsn != arg.getParentInsn()
&& canMoveBetweenBlocks(assignInsn, assignBlock, block, argsInfo.getInsn())) {
arg.wrapInstruction(assignInsn);
InsnList.remove(assignBlock, assignInsn);
......
......@@ -141,6 +141,7 @@ public class PrepareForCodeGen extends AbstractVisitor {
}
if (replace) {
ArithNode newArith = new ArithNode(arith.getOp(), res, arith.getArg(1));
InsnArg.updateParentInsn(arith, newArith);
list.set(i, newArith);
}
}
......
......@@ -19,7 +19,7 @@ import jadx.core.dex.instructions.mods.TernaryInsn;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.IfCondition;
import jadx.core.dex.regions.conditions.IfCondition;
import java.util.ArrayList;
import java.util.Collections;
......
......@@ -6,7 +6,7 @@ import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.LoopRegion;
import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.exceptions.JadxException;
......
......@@ -9,9 +9,9 @@ import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.IfCondition;
import jadx.core.dex.regions.IfCondition.Mode;
import jadx.core.dex.regions.IfInfo;
import jadx.core.dex.regions.conditions.IfCondition;
import jadx.core.dex.regions.conditions.IfCondition.Mode;
import jadx.core.dex.regions.conditions.IfInfo;
import jadx.core.utils.BlockUtils;
import java.util.Collection;
......
......@@ -6,9 +6,9 @@ import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.IfCondition;
import jadx.core.dex.regions.IfCondition.Mode;
import jadx.core.dex.regions.IfRegion;
import jadx.core.dex.regions.conditions.IfCondition;
import jadx.core.dex.regions.conditions.IfCondition.Mode;
import jadx.core.dex.regions.conditions.IfRegion;
import jadx.core.dex.regions.Region;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.RegionUtils;
......
package jadx.core.dex.visitors.regions;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.instructions.PhiInsn;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.conditions.IfCondition;
import jadx.core.dex.regions.loops.IndexLoop;
import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.RegionUtils;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor {
private static final Logger LOG = LoggerFactory.getLogger(LoopRegionVisitor.class);
@Override
public void visit(MethodNode mth) {
DepthRegionTraversal.traverseAll(mth, this);
}
@Override
public void enterRegion(MethodNode mth, IRegion region) {
if (region instanceof LoopRegion) {
processLoopRegion(mth, (LoopRegion) region);
}
}
private static void processLoopRegion(MethodNode mth, LoopRegion loopRegion) {
if (loopRegion.isConditionAtEnd()) {
return;
}
IfCondition condition = loopRegion.getCondition();
if (condition == null) {
return;
}
List<RegisterArg> args = condition.getRegisterArgs();
if (checkForIndexedLoop(mth, loopRegion, args)) {
return;
}
}
/**
* Check for indexed loop.
*/
private static boolean checkForIndexedLoop(MethodNode mth, LoopRegion loopRegion, List<RegisterArg> condArgs) {
InsnNode incrInsn = RegionUtils.getLastInsn(loopRegion);
if (incrInsn == null) {
return false;
}
RegisterArg incrArg = incrInsn.getResult();
if (incrArg == null
|| incrArg.getSVar() == null
|| !incrArg.getSVar().isUsedInPhi()) {
return false;
}
PhiInsn phiInsn = incrArg.getSVar().getUsedInPhi();
if (phiInsn.getArgsCount() != 2
|| !phiInsn.getArg(1).equals(incrArg)
|| incrArg.getSVar().getUseCount() != 1) {
return false;
}
RegisterArg arg = phiInsn.getResult();
if (!condArgs.contains(arg) || arg.getSVar().isUsedInPhi()) {
return false;
}
RegisterArg initArg = phiInsn.getArg(0);
InsnNode initInsn = initArg.getAssignInsn();
if (initInsn == null || initArg.getSVar().getUseCount() != 1) {
return false;
}
if (!usedOnlyInLoop(mth, loopRegion, arg)) {
return false;
}
initInsn.add(AFlag.SKIP);
incrInsn.add(AFlag.SKIP);
loopRegion.setType(new IndexLoop(initInsn, incrInsn));
return true;
}
private static boolean usedOnlyInLoop(MethodNode mth, LoopRegion loopRegion, RegisterArg arg) {
List<RegisterArg> useList = arg.getSVar().getUseList();
for (RegisterArg useArg : useList) {
if (!argInLoop(mth, loopRegion, useArg)) {
return false;
}
}
return true;
}
private static boolean argInLoop(MethodNode mth, LoopRegion loopRegion, RegisterArg arg) {
InsnNode parentInsn = arg.getParentInsn();
if (parentInsn == null) {
return false;
}
BlockNode block = BlockUtils.getBlockByInsn(mth, parentInsn);
if (block == null) {
LOG.debug("Instruction not found: {}, mth: {}", parentInsn, mth);
return false;
}
return RegionUtils.isRegionContainsBlock(loopRegion, block);
}
@Override
public void leaveRegion(MethodNode mth, IRegion region) {
}
@Override
public void processBlock(MethodNode mth, IBlock container) {
}
}
......@@ -12,7 +12,7 @@ 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.IfRegion;
import jadx.core.dex.regions.conditions.IfRegion;
import jadx.core.dex.regions.SwitchRegion;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.RegionUtils;
......
......@@ -13,9 +13,9 @@ import jadx.core.dex.nodes.Edge;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.IfInfo;
import jadx.core.dex.regions.IfRegion;
import jadx.core.dex.regions.LoopRegion;
import jadx.core.dex.regions.conditions.IfInfo;
import jadx.core.dex.regions.conditions.IfRegion;
import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.regions.Region;
import jadx.core.dex.regions.SwitchRegion;
import jadx.core.dex.regions.SynchronizedRegion;
......
......@@ -4,7 +4,7 @@ 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.LoopRegion;
import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.regions.Region;
import jadx.core.dex.regions.SynchronizedRegion;
import jadx.core.dex.visitors.AbstractVisitor;
......
......@@ -8,8 +8,8 @@ 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.IfRegion;
import jadx.core.dex.regions.LoopRegion;
import jadx.core.dex.regions.conditions.IfRegion;
import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.regions.SwitchRegion;
import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.exceptions.JadxException;
......
......@@ -12,7 +12,7 @@ import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.IfRegion;
import jadx.core.dex.regions.conditions.IfRegion;
import jadx.core.dex.regions.Region;
import jadx.core.dex.visitors.CodeShrinker;
import jadx.core.utils.InsnList;
......
package jadx.core.utils;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.InsnWrapArg;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
......@@ -113,7 +116,9 @@ public class BlockUtils {
}
public static BlockNode getBlockByInsn(MethodNode mth, InsnNode insn) {
assert insn != null;
if (insn.contains(AFlag.WRAPPED)) {
return getBlockByWrappedInsn(mth, insn);
}
for (BlockNode bn : mth.getBasicBlocks()) {
if (blockContains(bn, insn)) {
return bn;
......@@ -122,6 +127,29 @@ public class BlockUtils {
return null;
}
private static BlockNode getBlockByWrappedInsn(MethodNode mth, InsnNode insn) {
for (BlockNode bn : mth.getBasicBlocks()) {
for (InsnNode bi : bn.getInstructions()) {
if (bi == insn || foundWrappedInsn(bi, insn)) {
return bn;
}
}
}
return null;
}
private static boolean foundWrappedInsn(InsnNode container, InsnNode insn) {
for (InsnArg arg : container.getArguments()) {
if (arg.isInsnWrap()) {
InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
if (wrapInsn == insn || foundWrappedInsn(wrapInsn, insn)) {
return true;
}
}
}
return false;
}
public static BitSet blocksToBitSet(MethodNode mth, List<BlockNode> blocks) {
BitSet bs = new BitSet(mth.getBasicBlocks().size());
for (BlockNode block : blocks) {
......
......@@ -6,6 +6,9 @@ import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.regions.SwitchRegion;
import jadx.core.dex.regions.conditions.IfRegion;
import jadx.core.dex.trycatch.CatchAttr;
import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock;
......@@ -35,6 +38,29 @@ public class RegionUtils {
}
}
public static InsnNode getLastInsn(IContainer container) {
if (container instanceof BlockNode) {
BlockNode block = (BlockNode) container;
List<InsnNode> insnList = block.getInstructions();
if (insnList.isEmpty()) {
return null;
}
return insnList.get(insnList.size() - 1);
} else if (container instanceof IfRegion
|| container instanceof SwitchRegion) {
return null;
} else if (container instanceof IRegion) {
IRegion region = (IRegion) container;
List<IContainer> blocks = region.getSubBlocks();
if (blocks.isEmpty()) {
return null;
}
return getLastInsn(blocks.get(blocks.size() - 1));
} else {
throw new JadxRuntimeException("Unknown container type: " + container.getClass());
}
}
/**
* Return true if last block in region has no successors
*/
......
......@@ -5,15 +5,15 @@ import jadx.core.dex.instructions.IfOp;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.regions.Compare;
import jadx.core.dex.regions.IfCondition;
import jadx.core.dex.regions.conditions.Compare;
import jadx.core.dex.regions.conditions.IfCondition;
import org.junit.Test;
import static jadx.core.dex.regions.IfCondition.Mode;
import static jadx.core.dex.regions.IfCondition.merge;
import static jadx.core.dex.regions.IfCondition.not;
import static jadx.core.dex.regions.IfCondition.simplify;
import static jadx.core.dex.regions.conditions.IfCondition.Mode;
import static jadx.core.dex.regions.conditions.IfCondition.merge;
import static jadx.core.dex.regions.conditions.IfCondition.not;
import static jadx.core.dex.regions.conditions.IfCondition.simplify;
import static org.junit.Assert.assertEquals;
public class TestIfCondition {
......
......@@ -5,7 +5,7 @@ import jadx.core.dex.nodes.ClassNode;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.containsString;
import static jadx.tests.utils.JadxMatchers.containsOne;
import static org.junit.Assert.assertThat;
public class TestInline2 extends InternalJadxTest {
......@@ -30,9 +30,7 @@ public class TestInline2 extends InternalJadxTest {
String code = cls.getCode().toString();
System.out.println(code);
assertThat(code, containsString("i < a.length"));
assertThat(code, containsString("long i2 ="));
assertThat(code, containsString("+ i2"));
assertThat(code, containsString("i2--;"));
assertThat(code, containsOne("for (int i = 0; i < a.length; i++) {"));
assertThat(code, containsOne("for (long i2 = (long) b; i2 > 0; i2--) {"));
}
}
......@@ -6,6 +6,7 @@ import jadx.core.dex.nodes.ClassNode;
import org.junit.Test;
import static jadx.tests.utils.JadxMatchers.containsOne;
import static jadx.tests.utils.JadxMatchers.countString;
import static org.junit.Assert.assertThat;
public class TestBreakInLoop extends InternalJadxTest {
......@@ -14,13 +15,11 @@ public class TestBreakInLoop extends InternalJadxTest {
private int f;
private void test(int[] a, int b) {
int i = 0;
while (i < a.length) {
for (int i = 0; i < a.length; i++) {
a[i]++;
if (i < b) {
break;
}
i++;
}
this.f++;
}
......@@ -32,12 +31,12 @@ public class TestBreakInLoop extends InternalJadxTest {
String code = cls.getCode().toString();
System.out.println(code);
assertThat(code, containsOne("this.f++;"));
assertThat(code, containsOne("for (int i = 0; i < a.length; i++) {"));
// assertThat(code, containsOne("a[i]++;"));
assertThat(code, containsOne("if (i < b) {"));
assertThat(code, containsOne("break;"));
assertThat(code, containsOne("i++;"));
assertThat(code, containsOne("this.f++;"));
// assertThat(code, countString(0, "else"));
assertThat(code, countString(0, "else"));
}
}
package jadx.tests.internal.loops;
import jadx.api.InternalJadxTest;
import jadx.core.dex.nodes.ClassNode;
import org.junit.Test;
import static jadx.tests.utils.JadxMatchers.containsLines;
import static org.junit.Assert.assertThat;
public class TestIndexForLoop extends InternalJadxTest {
public static class TestCls {
private int test(int[] a, int b) {
int sum = 0;
for (int i = 0; i < b; i++) {
sum += a[i];
}
return sum;
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
System.out.println(code);
assertThat(code, containsLines(2,
"int sum = 0;",
"for (int i = 0; i < b; i++) {",
indent(1) + "sum += a[i];",
"}",
"return sum;"
));
}
}
......@@ -5,6 +5,7 @@ import jadx.core.dex.nodes.ClassNode;
import org.junit.Test;
import static jadx.tests.utils.JadxMatchers.containsOne;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
......@@ -33,9 +34,8 @@ public class TestLoopDetection2 extends InternalJadxTest {
String code = cls.getCode().toString();
System.out.println(code);
assertThat(code, containsString("while (i < b) {"));
assertThat(code, containsString("int c = a + b;"));
assertThat(code, containsOne("int c = a + b;"));
assertThat(code, containsOne("for (int i = a; i < b; i++) {"));
assertThat(code, not(containsString("c_2")));
assertThat(code, containsString("i++"));
}
}
package jadx.tests.internal.loops;
import jadx.api.InternalJadxTest;
import jadx.core.dex.nodes.ClassNode;
import java.util.List;
import org.junit.Test;
import static jadx.tests.utils.JadxMatchers.containsOne;
import static org.junit.Assert.assertThat;
public class TestNestedLoops2 extends InternalJadxTest {
public static class TestCls {
private boolean test(List<String> list) {
int j = 0;
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
while (j < s.length()) {
j++;
}
}
return j > 10;
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
System.out.println(code);
assertThat(code, containsOne("for (int i = 0; i < list.size(); i++) {"));
assertThat(code, containsOne("while (j < ((String) list.get(i)).length()) {"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment