core: fix variables inline (#86)
This commit is contained in:
@@ -23,8 +23,6 @@ import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CodeShrinker extends AbstractVisitor {
|
||||
|
||||
@Override
|
||||
@@ -38,6 +36,7 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
}
|
||||
for (BlockNode block : mth.getBasicBlocks()) {
|
||||
shrinkBlock(mth, block);
|
||||
simplifyMoveInsns(block);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,53 +230,28 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
if (assignBlock != null
|
||||
&& assignInsn != arg.getParentInsn()
|
||||
&& canMoveBetweenBlocks(assignInsn, assignBlock, block, argsInfo.getInsn())) {
|
||||
if (inline(arg, assignInsn, assignBlock, mth)) {
|
||||
InsnList.remove(assignBlock, assignInsn);
|
||||
}
|
||||
inline(arg, assignInsn, assignBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!wrapList.isEmpty()) {
|
||||
for (WrapInfo wrapInfo : wrapList) {
|
||||
inline(wrapInfo.getArg(), wrapInfo.getInsn(), block, mth);
|
||||
}
|
||||
for (WrapInfo wrapInfo : wrapList) {
|
||||
insnList.remove(wrapInfo.getInsn());
|
||||
inline(wrapInfo.getArg(), wrapInfo.getInsn(), block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean inline(RegisterArg arg, InsnNode insn, @Nullable BlockNode block, MethodNode mth) {
|
||||
private static boolean inline(RegisterArg arg, InsnNode insn, BlockNode block) {
|
||||
InsnNode parentInsn = arg.getParentInsn();
|
||||
// replace move instruction if needed
|
||||
if (parentInsn != null) {
|
||||
switch (parentInsn.getType()) {
|
||||
case MOVE: {
|
||||
if (block == null) {
|
||||
block = BlockUtils.getBlockByInsn(mth, parentInsn);
|
||||
}
|
||||
if (block != null) {
|
||||
int index = InsnList.getIndex(block.getInstructions(), parentInsn);
|
||||
if (index != -1) {
|
||||
insn.setResult(parentInsn.getResult());
|
||||
insn.copyAttributesFrom(parentInsn);
|
||||
insn.setOffset(parentInsn.getOffset());
|
||||
|
||||
block.getInstructions().set(index, insn);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RETURN: {
|
||||
parentInsn.setSourceLine(insn.getSourceLine());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parentInsn != null && parentInsn.getType() == InsnType.RETURN) {
|
||||
parentInsn.setSourceLine(insn.getSourceLine());
|
||||
}
|
||||
// simple case
|
||||
return arg.wrapInstruction(insn) != null;
|
||||
boolean replaced = arg.wrapInstruction(insn) != null;
|
||||
if (replaced) {
|
||||
InsnList.remove(block, insn);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
private static boolean canMoveBetweenBlocks(InsnNode assignInsn, BlockNode assignBlock,
|
||||
@@ -320,4 +294,24 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
}
|
||||
throw new JadxRuntimeException("Can't process instruction move : " + assignBlock);
|
||||
}
|
||||
|
||||
private static void simplifyMoveInsns(BlockNode block) {
|
||||
List<InsnNode> insns = block.getInstructions();
|
||||
int size = insns.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
InsnNode insn = insns.get(i);
|
||||
if (insn.getType() == InsnType.MOVE) {
|
||||
// replace 'move' with wrapped insn
|
||||
InsnArg arg = insn.getArg(0);
|
||||
if (arg.isInsnWrap()) {
|
||||
InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
|
||||
wrapInsn.setResult(insn.getResult());
|
||||
wrapInsn.copyAttributesFrom(insn);
|
||||
wrapInsn.setOffset(insn.getOffset());
|
||||
wrapInsn.remove(AFlag.WRAPPED);
|
||||
block.getInstructions().set(i, wrapInsn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package jadx.tests.integration.inline;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static jadx.tests.api.utils.JadxMatchers.containsOne;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class TestIssue86 extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
private static final String SERVER_ERR = "server-err";
|
||||
private static final String NOT_FOUND = "not-found";
|
||||
private static final String LIST_TAG = "list-tag";
|
||||
private static final String TEMP_TAG = "temp-tag";
|
||||
private static final String MIN_TAG = "min-tag";
|
||||
private static final String MAX_TAG = "max-tag";
|
||||
private static final String MILLIS_TAG = "millis-tag";
|
||||
private static final String WEATHER_TAG = "weather-tag";
|
||||
private static final String DESC_TAG = "desc-tag";
|
||||
|
||||
private List<Day> test(String response) {
|
||||
List<Day> reportList = new ArrayList<Day>();
|
||||
try {
|
||||
System.out.println(response);
|
||||
if (response != null
|
||||
&& (response.startsWith(SERVER_ERR)
|
||||
|| response.startsWith(NOT_FOUND))) {
|
||||
return reportList;
|
||||
}
|
||||
JSONObject jsonObj = new JSONObject(response);
|
||||
JSONArray days = jsonObj.getJSONArray(LIST_TAG);
|
||||
for (int i = 0; i < days.length(); i++) {
|
||||
JSONObject c = days.getJSONObject(i);
|
||||
long millis = c.getLong(MILLIS_TAG);
|
||||
JSONObject temp = c.getJSONObject(TEMP_TAG);
|
||||
String max = temp.getString(MAX_TAG);
|
||||
String min = temp.getString(MIN_TAG);
|
||||
JSONArray weather = c.getJSONArray(WEATHER_TAG);
|
||||
String weatherDesc = weather.getJSONObject(0).getString(DESC_TAG);
|
||||
Day d = new Day();
|
||||
d.setMilis(millis);
|
||||
d.setMinTmp(min);
|
||||
d.setMaxTmp(max);
|
||||
d.setWeatherDesc(weatherDesc);
|
||||
reportList.add(d);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return reportList;
|
||||
}
|
||||
|
||||
private static class Day {
|
||||
public void setMilis(long milis) {
|
||||
}
|
||||
|
||||
public void setMinTmp(String min) {
|
||||
}
|
||||
|
||||
public void setMaxTmp(String max) {
|
||||
}
|
||||
|
||||
public void setWeatherDesc(String weatherDesc) {
|
||||
}
|
||||
}
|
||||
|
||||
private static class JSONObject {
|
||||
public JSONObject(String response) {
|
||||
}
|
||||
|
||||
public JSONArray getJSONArray(String tag) throws JSONException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JSONObject getJSONObject(String tag) throws JSONException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getString(String tag) throws JSONException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public long getLong(String tag) throws JSONException {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private class JSONArray {
|
||||
public JSONObject getJSONObject(int i) throws JSONException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private class JSONException extends Exception {
|
||||
private static final long serialVersionUID = -4358405506584551910L;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("response.startsWith(NOT_FOUND)"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user