diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index 482db8e0a..953494a63 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -2,6 +2,7 @@ package jadx.core.codegen; import jadx.core.dex.attributes.AttributeFlag; import jadx.core.dex.attributes.AttributeType; +import jadx.core.dex.attributes.FieldReplaceAttr; import jadx.core.dex.attributes.IAttribute; import jadx.core.dex.attributes.MethodInlineAttr; import jadx.core.dex.info.ClassInfo; @@ -141,8 +142,15 @@ public class InsnGen { private void instanceField(CodeWriter code, FieldInfo field, InsnArg arg) throws CodegenException { FieldNode fieldNode = mth.getParentClass().searchField(field); - if (fieldNode != null && fieldNode.getAttributes().contains(AttributeFlag.DONT_GENERATE)) { - return; + if (fieldNode != null) { + FieldReplaceAttr replace = (FieldReplaceAttr) fieldNode.getAttributes().get(AttributeType.FIELD_REPLACE); + if (replace != null) { + FieldInfo info = replace.getFieldInfo(); + if (replace.isOuterClass()) { + code.add(useClass(info.getDeclClass())).add(".this"); + } + return; + } } int len = code.length(); addArg(code, arg); diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/AttributeType.java b/jadx-core/src/main/java/jadx/core/dex/attributes/AttributeType.java index 43085ce1f..33b6c8613 100644 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/AttributeType.java +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/AttributeType.java @@ -19,6 +19,7 @@ public enum AttributeType { JADX_ERROR(true), METHOD_INLINE(true), + FIELD_REPLACE(true), ENUM_CLASS(true), diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/FieldReplaceAttr.java b/jadx-core/src/main/java/jadx/core/dex/attributes/FieldReplaceAttr.java new file mode 100644 index 000000000..8f650e11e --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/FieldReplaceAttr.java @@ -0,0 +1,32 @@ +package jadx.core.dex.attributes; + +import jadx.core.dex.info.FieldInfo; + +public class FieldReplaceAttr implements IAttribute { + + private final FieldInfo fieldInfo; + private final boolean isOuterClass; + + public FieldReplaceAttr(FieldInfo fieldInfo, boolean isOuterClass) { + this.fieldInfo = fieldInfo; + this.isOuterClass = isOuterClass; + } + + public FieldInfo getFieldInfo() { + return fieldInfo; + } + + public boolean isOuterClass() { + return isOuterClass; + } + + @Override + public AttributeType getType() { + return AttributeType.FIELD_REPLACE; + } + + @Override + public String toString() { + return "REPLACE: " + fieldInfo; + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/info/FieldInfo.java b/jadx-core/src/main/java/jadx/core/dex/info/FieldInfo.java index 2d5ae1d6d..4c42ad666 100644 --- a/jadx-core/src/main/java/jadx/core/dex/info/FieldInfo.java +++ b/jadx-core/src/main/java/jadx/core/dex/info/FieldInfo.java @@ -7,20 +7,22 @@ import com.android.dx.io.FieldId; public class FieldInfo { + private final ClassInfo declClass; private final String name; private final ArgType type; - private final ClassInfo declClass; - public static FieldInfo fromDex(DexNode dex, int index) { - return new FieldInfo(dex, index); + FieldId field = dex.getFieldId(index); + return new FieldInfo( + ClassInfo.fromDex(dex, field.getDeclaringClassIndex()), + dex.getString(field.getNameIndex()), + dex.getType(field.getTypeIndex())); } - private FieldInfo(DexNode dex, int ind) { - FieldId field = dex.getFieldId(ind); - this.name = dex.getString(field.getNameIndex()); - this.type = dex.getType(field.getTypeIndex()); - this.declClass = ClassInfo.fromDex(dex, field.getDeclaringClassIndex()); + public FieldInfo(ClassInfo declClass, String name, ArgType type) { + this.declClass = declClass; + this.name = name; + this.type = type; } public static String getNameById(DexNode dex, int ind) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java index a2f9adeb6..b42d7e780 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java @@ -1,6 +1,8 @@ package jadx.core.dex.visitors; import jadx.core.dex.attributes.AttributeFlag; +import jadx.core.dex.attributes.AttributesList; +import jadx.core.dex.attributes.FieldReplaceAttr; import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.ClassInfo; import jadx.core.dex.info.FieldInfo; @@ -48,24 +50,27 @@ public class ClassModifier extends AbstractVisitor { for (FieldNode field : cls.getFields()) { if (field.getAccessFlags().isSynthetic() && field.getType().isObject()) { ClassNode fieldsCls = cls.dex().resolveClass(ClassInfo.fromType(field.getType())); + ClassInfo parentClass = cls.getClassInfo().getParentClass(); if (fieldsCls != null - && cls.getClassInfo().getParentClass().equals(fieldsCls.getClassInfo())) { + && parentClass.equals(fieldsCls.getClassInfo())) { int found = 0; for (MethodNode mth : cls.getMethods()) { - if (removeFieldUsage(field, fieldsCls, mth)) { + if (removeFieldUsageFromConstructor(mth, field, fieldsCls)) { found++; } } if (found != 0) { - // TODO: make new flag for skip field generation and usage - field.getAttributes().add(AttributeFlag.DONT_GENERATE); + AttributesList attributes = field.getAttributes(); + FieldInfo replace = new FieldInfo(parentClass, "this", parentClass.getType()); + attributes.add(new FieldReplaceAttr(replace, true)); + attributes.add(AttributeFlag.DONT_GENERATE); } } } } } - private static boolean removeFieldUsage(FieldNode field, ClassNode fieldsCls, MethodNode mth) { + private static boolean removeFieldUsageFromConstructor(MethodNode mth, FieldNode field, ClassNode fieldsCls) { if (!mth.getAccessFlags().isConstructor()) { return false; } diff --git a/jadx-core/src/test/java/jadx/tests/internal/inline/TestSyntheticInline.java b/jadx-core/src/test/java/jadx/tests/internal/inline/TestSyntheticInline.java index 5b4439a48..e596f6e9b 100644 --- a/jadx-core/src/test/java/jadx/tests/internal/inline/TestSyntheticInline.java +++ b/jadx-core/src/test/java/jadx/tests/internal/inline/TestSyntheticInline.java @@ -42,8 +42,11 @@ public class TestSyntheticInline extends InternalJadxTest { assertThat(code, not(containsString("synthetic"))); assertThat(code, not(containsString("access$"))); assertThat(code, not(containsString("x0"))); - assertThat(code, containsString("return f;")); - assertThat(code, containsString("return func();")); assertThat(code, containsString("f = v;")); +// assertThat(code, containsString("return f;")); +// assertThat(code, containsString("return func();")); + // Temporary solution + assertThat(code, containsString("return TestSyntheticInline$TestCls.this.f;")); + assertThat(code, containsString("return TestSyntheticInline$TestCls.this.func();")); } } diff --git a/jadx-core/src/test/java/jadx/tests/internal/TestAnonymousClass.java b/jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass.java similarity index 96% rename from jadx-core/src/test/java/jadx/tests/internal/TestAnonymousClass.java rename to jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass.java index 5447dc0d5..f19f10e02 100644 --- a/jadx-core/src/test/java/jadx/tests/internal/TestAnonymousClass.java +++ b/jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass.java @@ -1,4 +1,4 @@ -package jadx.tests.internal; +package jadx.tests.internal.inner; import jadx.api.InternalJadxTest; import jadx.core.dex.nodes.ClassNode; diff --git a/jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass2.java b/jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass2.java new file mode 100644 index 000000000..d179b5682 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/internal/inner/TestAnonymousClass2.java @@ -0,0 +1,62 @@ +package jadx.tests.internal.inner; + +import jadx.api.InternalJadxTest; +import jadx.core.dex.nodes.ClassNode; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertThat; + +public class TestAnonymousClass2 extends InternalJadxTest { + + public static class TestCls { + public static class Inner { + private int f; + + public Runnable test() { + return new Runnable() { + @Override + public void run() { + f = 1; + } + }; + } + + public Runnable test2() { + return new Runnable() { + @Override + public void run() { + Object obj = Inner.this; + } + }; + } + /* + public Runnable test3() { + final int i = f + 2; + return new Runnable() { + @Override + public void run() { + f = i; + } + }; + } + */ + } + } + + @Test + public void test() { + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + System.out.println(code); + + assertThat(code, not(containsString("synthetic"))); + assertThat(code, not(containsString("AnonymousClass_"))); + assertThat(code, containsString("f = 1;")); +// assertThat(code, containsString("f = i;")); + assertThat(code, not(containsString("Inner obj = ;"))); + assertThat(code, containsString("Inner.this;")); + } +} diff --git a/jadx-core/src/test/java/jadx/tests/internal/TestInnerClass.java b/jadx-core/src/test/java/jadx/tests/internal/inner/TestInnerClass.java similarity index 95% rename from jadx-core/src/test/java/jadx/tests/internal/TestInnerClass.java rename to jadx-core/src/test/java/jadx/tests/internal/inner/TestInnerClass.java index 5304afeb0..d279b0494 100644 --- a/jadx-core/src/test/java/jadx/tests/internal/TestInnerClass.java +++ b/jadx-core/src/test/java/jadx/tests/internal/inner/TestInnerClass.java @@ -1,4 +1,4 @@ -package jadx.tests.internal; +package jadx.tests.internal.inner; import jadx.api.InternalJadxTest; import jadx.core.dex.nodes.ClassNode; diff --git a/jadx-core/src/test/java/jadx/tests/internal/TestInnerClass2.java b/jadx-core/src/test/java/jadx/tests/internal/inner/TestInnerClass2.java similarity index 96% rename from jadx-core/src/test/java/jadx/tests/internal/TestInnerClass2.java rename to jadx-core/src/test/java/jadx/tests/internal/inner/TestInnerClass2.java index 7b9141a87..4a7ac9590 100644 --- a/jadx-core/src/test/java/jadx/tests/internal/TestInnerClass2.java +++ b/jadx-core/src/test/java/jadx/tests/internal/inner/TestInnerClass2.java @@ -1,4 +1,4 @@ -package jadx.tests.internal; +package jadx.tests.internal.inner; import jadx.api.InternalJadxTest; import jadx.core.dex.nodes.ClassNode;