diff --git a/src/main/java/jadx/dex/visitors/MethodInlinerVisitor.java b/src/main/java/jadx/dex/visitors/MethodInlinerVisitor.java index 43966e1b2..854239d3b 100644 --- a/src/main/java/jadx/dex/visitors/MethodInlinerVisitor.java +++ b/src/main/java/jadx/dex/visitors/MethodInlinerVisitor.java @@ -3,6 +3,7 @@ package jadx.dex.visitors; import jadx.dex.attributes.AttributeFlag; import jadx.dex.attributes.IAttribute; import jadx.dex.attributes.MethodInlineAttr; +import jadx.dex.info.AccessInfo; import jadx.dex.instructions.InsnType; import jadx.dex.nodes.BlockNode; import jadx.dex.nodes.InsnNode; @@ -13,34 +14,30 @@ public class MethodInlinerVisitor extends AbstractVisitor { @Override public void visit(MethodNode mth) throws JadxException { - if (mth.getAccessFlags().isSynthetic() && mth.getAccessFlags().isStatic()) { - if (mth.getBasicBlocks().size() == 1) { - BlockNode block = mth.getBasicBlocks().get(0); - // synthetic field getter - if (block.getInstructions().size() == 1) { - InsnNode insn = block.getInstructions().get(0); - if (insn.getType() == InsnType.RETURN) { - InsnNode inl = new InsnNode(InsnType.ARGS, 1); - inl.addArg(insn.getArg(0)); - addInlineAttr(mth, inl); - return; - } + AccessInfo accessFlags = mth.getAccessFlags(); + if (accessFlags.isSynthetic() && accessFlags.isStatic()) { + if (mth.getBasicBlocks().size() == 2) { + BlockNode block = mth.getBasicBlocks().get(1); + if (block.getAttributes().contains(AttributeFlag.RETURN)) { + inlineMth(mth); } + } + } + } - // synthetic field setter - if (block.getInstructions().size() == 2) { - if (block.getInstructions().get(1).getType() == InsnType.RETURN) { - InsnNode insn = block.getInstructions().get(0); - addInlineAttr(mth, insn); - return; - } - } - - // synthetic method invoke - if (block.getInstructions().size() == 1) { - InsnNode insn = block.getInstructions().get(0); - addInlineAttr(mth, insn); - } + private static void inlineMth(MethodNode mth) { + BlockNode firstBlock = mth.getBasicBlocks().get(0); + if (firstBlock.getInstructions().isEmpty()) { + // synthetic field getter + BlockNode block = mth.getBasicBlocks().get(1); + InsnNode insn = block.getInstructions().get(0); + InsnNode inl = new InsnNode(InsnType.ARGS, 1); + inl.addArg(insn.getArg(0)); + addInlineAttr(mth, inl); + } else { + // synthetic field setter or method invoke + if (firstBlock.getInstructions().size() == 1) { + addInlineAttr(mth, firstBlock.getInstructions().get(0)); } } } @@ -50,5 +47,4 @@ public class MethodInlinerVisitor extends AbstractVisitor { mth.getAttributes().add(attr); mth.getAttributes().add(AttributeFlag.DONT_GENERATE); } - } diff --git a/src/samples/java/jadx/samples/AbstractTest.java b/src/samples/java/jadx/samples/AbstractTest.java index 94c86aa75..d2067a861 100644 --- a/src/samples/java/jadx/samples/AbstractTest.java +++ b/src/samples/java/jadx/samples/AbstractTest.java @@ -10,6 +10,12 @@ public abstract class AbstractTest { } } + public static void assertTrue(boolean condition, String msg) { + if (!condition) { + throw new AssertionError(msg); + } + } + public static void assertEquals(int a1, int a2) { if (a1 != a2) { throw new AssertionError(a1 + " != " + a2); diff --git a/src/samples/java/jadx/samples/TestInner2.java b/src/samples/java/jadx/samples/TestInner2.java index 1edd2697e..bba7a9fdf 100644 --- a/src/samples/java/jadx/samples/TestInner2.java +++ b/src/samples/java/jadx/samples/TestInner2.java @@ -1,5 +1,7 @@ package jadx.samples; +import java.lang.reflect.Method; + public class TestInner2 extends AbstractTest { private String a; @@ -26,12 +28,56 @@ public class TestInner2 extends AbstractTest { } } + private String c; + + private void setC(String c) { + this.c = c; + } + + public class C { + public String c() { + setC("c"); + return c; + } + } + + private static String d; + + private static void setD(String s) { + d = s; + } + + public static class D { + public String d() { + setD("d"); + return d; + } + } + + // value from java.lang.reflect.Modifier + static final int SYNTHETIC = 0x00001000; + @Override public boolean testRun() throws Exception { assertTrue((new A()).a().equals("a")); assertTrue(a.equals("a")); + assertTrue((new B()).b().equals("b")); assertTrue(b.equals("b")); + + assertTrue((new C()).c().equals("c")); + assertTrue(c.equals("c")); + + assertTrue((new D()).d().equals("d")); + assertTrue(d.equals("d")); + + Method[] mths = TestInner2.class.getDeclaredMethods(); + for (Method mth : mths) { + if(mth.getName().startsWith("access$")) { + int modifiers = mth.getModifiers(); + assertTrue((modifiers & SYNTHETIC) != 0, "Synthetic methods must be removed"); + } + } return true; }