fix: inline anonymous classes with not default constructor (#450)

This commit is contained in:
Skylot
2019-04-14 19:02:16 +03:00
parent 0aa7173e83
commit 4cb9f23a7d
11 changed files with 319 additions and 45 deletions
@@ -0,0 +1,58 @@
package jadx.tests.integration.inner;
import org.junit.jupiter.api.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
public class TestAnonymousClass14 extends SmaliTest {
/*
public class OuterCls implements Runnable {
class AnonymousClass1 {
AnonymousClass1(Runnable runnable) {
}
public void someMethod() {
}
}
class TestCls {
private TestCls() {
ArrayList arrayList = new ArrayList();
}
synthetic TestCls(OuterCls outerCls, AnonymousClass1 anonymousClass1) {
this();
}
}
public void makeAnonymousCls() {
AnonymousClass1 anonymousClass1 = new AnonymousClass1(this);
}
public void makeTestCls() {
TestCls testCls = new TestCls(this, null);
}
public void run() {
}
public void use(AnonymousClass1 anonymousClass1) {
}
}
*/
@Test
public void test() {
ClassNode clsNode = getClassNodeFromSmaliFiles("inner", "TestAnonymousClass14", "OuterCls");
String code = clsNode.getCode().toString();
assertThat(code, not(containsString("AnonymousClass1")));
assertThat(code, not(containsString("synthetic")));
}
}
@@ -0,0 +1,48 @@
package jadx.tests.integration.inner;
import org.junit.jupiter.api.Test;
import jadx.NotYetImplemented;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static jadx.tests.api.utils.JadxMatchers.countString;
import static org.hamcrest.MatcherAssert.assertThat;
public class TestAnonymousClass15 extends IntegrationTest {
public static class TestCls {
public Thread test(Runnable run) {
return new Thread(run) {
@Override
public void run() {
System.out.println("run");
super.run();
}
};
}
public Thread test2(Runnable run) {
return new Thread(run) {
{
setName("run");
}
@Override
public void run() {
}
};
}
}
@Test
public void test() {
ClassNode classNode = getClassNode(TestCls.class);
String code = classNode.getCode().toString();
assertThat(code, countString(2, "return new Thread(run) {"));
assertThat(code, containsOne("setName(\"run\");"));
}
}
@@ -0,0 +1,28 @@
.class Linner/OuterCls$1;
.super Ljava/lang/Thread;
.source "SourceFile"
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x0
name = null
.end annotation
.field final synthetic this$0:Linner/OuterCls;
# direct methods
.method constructor <init>(Linner/OuterCls;Ljava/lang/Runnable;)V
.locals 0
iput-object p1, p0, Linner/OuterCls$1;->this$0:Linner/OuterCls;
return-void
.end method
# virtual methods
.method public someMethod()V
.locals 3
return-void
.end method
@@ -0,0 +1,39 @@
.class Linner/OuterCls$TestCls;
.super Ljava/lang/Object;
.source "SourceFile"
# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
value = Linner/OuterCls;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x0
name = "TestCls"
.end annotation
.field final synthetic this$0:Linner/OuterCls;
# direct methods
.method private constructor <init>(Linner/OuterCls;)V
.locals 0
iput-object p1, p0, Linner/OuterCls$TestCls;->this$0:Linner/OuterCls;
new-instance p1, Ljava/util/ArrayList;
invoke-direct {p1}, Ljava/util/ArrayList;-><init>()V
return-void
.end method
.method synthetic constructor <init>(Linner/OuterCls;Linner/OuterCls$1;)V
.locals 0
invoke-direct {p0, p1}, Linner/OuterCls$TestCls;-><init>(Linner/OuterCls;)V
return-void
.end method
@@ -0,0 +1,65 @@
.class public Linner/OuterCls;
.super Ljava/lang/Object;
.source "SourceFile"
# interfaces
.implements Ljava/lang/Runnable;
# annotations
.annotation system Ldalvik/annotation/MemberClasses;
value = {
Linner/OuterCls$TestCls;
}
.end annotation
# direct methods
.method static constructor <clinit>()V
.locals 0
return-void
.end method
.method public constructor <init>()V
.locals 1
return-void
.end method
.method public makeTestCls()V
.locals 2
new-instance v1, Linner/OuterCls$TestCls;
const/4 v0, 0x0
invoke-direct {v1, p0, v0}, Linner/OuterCls$TestCls;-><init>(Linner/OuterCls;Linner/OuterCls$1;)V
return-void
.end method
.method public makeAnonymousCls()V
.locals 2
new-instance v1, Linner/OuterCls$1;
invoke-direct {v1, p0, p0}, Linner/OuterCls$1;-><init>(Linner/OuterCls;Ljava/lang/Runnable;)V
invoke-direct {p0, v1}, Linner/OuterCls;->use(Ljava/lang/Thread;)V
return-void
.end method
.method public run()V
.locals 2
return-void
.end method
.method public use(Ljava/lang/Thread;)V
.locals 2
return-void
.end method