fix: allow to reuse enum fields in static fields (#1019)
This commit is contained in:
@@ -192,7 +192,14 @@ public class EnumVisitor extends AbstractVisitor {
|
||||
if (ctrMth != null) {
|
||||
markArgsForSkip(ctrMth);
|
||||
}
|
||||
InsnRemover.removeWithoutUnbind(classInitMth, staticBlock, co);
|
||||
if (co.getResult().getSVar().getUseList().size() <= 2) {
|
||||
InsnRemover.removeWithoutUnbind(classInitMth, staticBlock, co);
|
||||
} else {
|
||||
// constructor result used in other places -> replace constructor with enum field get (SGET)
|
||||
IndexInsnNode enumGet = new IndexInsnNode(InsnType.SGET, enumField.getField().getFieldInfo(), 0);
|
||||
enumGet.setResult(co.getResult().duplicate());
|
||||
BlockUtils.replaceInsn(classInitMth, staticBlock, co, enumGet);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -335,7 +342,6 @@ public class EnumVisitor extends AbstractVisitor {
|
||||
enumFieldNode = createFakeField(cls, "EF" + arg.getRegNum());
|
||||
cls.addField(enumFieldNode);
|
||||
}
|
||||
toRemove.add(constrInsn);
|
||||
return createEnumFieldByConstructor(cls, enumFieldNode, (ConstructorInsn) constrInsn);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.FieldNode;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
|
||||
import jadx.core.utils.BlockUtils;
|
||||
import jadx.core.utils.InsnRemover;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
@@ -80,8 +81,16 @@ public class ExtractFieldInit extends AbstractVisitor {
|
||||
if (classInitMth == null) {
|
||||
return;
|
||||
}
|
||||
while (processFields(cls, classInitMth)) {
|
||||
// sometimes instructions moved to field init prevent from vars inline -> inline and try again
|
||||
CodeShrinkVisitor.shrinkMethod(classInitMth);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean processFields(ClassNode cls, MethodNode classInitMth) {
|
||||
boolean changed = false;
|
||||
for (FieldNode field : cls.getFields()) {
|
||||
if (field.contains(AFlag.DONT_GENERATE)) {
|
||||
if (field.contains(AFlag.DONT_GENERATE) || field.contains(AType.FIELD_INIT)) {
|
||||
continue;
|
||||
}
|
||||
if (field.getAccessFlags().isStatic()) {
|
||||
@@ -95,10 +104,12 @@ public class ExtractFieldInit extends AbstractVisitor {
|
||||
}
|
||||
InsnRemover.remove(classInitMth, insn);
|
||||
addFieldInitAttr(classInitMth, field, insn);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
private static class InitInfo {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package jadx.tests.integration.enums;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class TestEnumWithFields extends SmaliTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
public enum SearchTimeout {
|
||||
DISABLED(0), TWO_SECONDS(2), FIVE_SECONDS(5);
|
||||
|
||||
public static final SearchTimeout DEFAULT = DISABLED;
|
||||
public static final SearchTimeout MAX = FIVE_SECONDS;
|
||||
|
||||
public final int sec;
|
||||
|
||||
SearchTimeout(int val) {
|
||||
this.sec = val;
|
||||
}
|
||||
}
|
||||
|
||||
public void check() {
|
||||
assertEquals(0, SearchTimeout.DISABLED.sec);
|
||||
assertEquals(0, SearchTimeout.DEFAULT.sec);
|
||||
assertEquals(2, SearchTimeout.TWO_SECONDS.sec);
|
||||
assertEquals(5, SearchTimeout.MAX.sec);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
noDebugInfo();
|
||||
assertThat(getClassNode(TestCls.class))
|
||||
.code();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
assertThat(getClassNodeFromSmali())
|
||||
.code();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
.class public final enum Lenums/TestEnumWithFields;
|
||||
.super Ljava/lang/Enum;
|
||||
|
||||
|
||||
# annotations
|
||||
.annotation system Ldalvik/annotation/Signature;
|
||||
value = {
|
||||
"Ljava/lang/Enum<",
|
||||
"Lenums/TestEnumWithFields;",
|
||||
">;"
|
||||
}
|
||||
.end annotation
|
||||
|
||||
|
||||
# static fields
|
||||
.field public static final synthetic $VALUES:[Lenums/TestEnumWithFields;
|
||||
|
||||
.field public static final DEFAULT:Lenums/TestEnumWithFields;
|
||||
|
||||
.field public static final enum DISABLED:Lenums/TestEnumWithFields;
|
||||
|
||||
.field public static final enum FIVE_SECONDS:Lenums/TestEnumWithFields;
|
||||
|
||||
.field public static final MAX:Lenums/TestEnumWithFields;
|
||||
|
||||
.field public static final enum TWO_AND_A_HALF_SECONDS:Lenums/TestEnumWithFields;
|
||||
|
||||
.field public static final sValues:[Lenums/TestEnumWithFields;
|
||||
|
||||
|
||||
# instance fields
|
||||
.field public final mRawValue:I
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public static constructor <clinit>()V
|
||||
.locals 6
|
||||
|
||||
.line 1
|
||||
new-instance v0, Lenums/TestEnumWithFields;
|
||||
|
||||
const/4 v1, 0x0
|
||||
|
||||
const-string v2, "DISABLED"
|
||||
|
||||
invoke-direct {v0, v2, v1, v1}, Lenums/TestEnumWithFields;-><init>(Ljava/lang/String;II)V
|
||||
|
||||
sput-object v0, Lenums/TestEnumWithFields;->DISABLED:Lenums/TestEnumWithFields;
|
||||
|
||||
.line 2
|
||||
new-instance v0, Lenums/TestEnumWithFields;
|
||||
|
||||
const/4 v2, 0x1
|
||||
|
||||
const-string v3, "TWO_AND_A_HALF_SECONDS"
|
||||
|
||||
invoke-direct {v0, v3, v2, v2}, Lenums/TestEnumWithFields;-><init>(Ljava/lang/String;II)V
|
||||
|
||||
sput-object v0, Lenums/TestEnumWithFields;->TWO_AND_A_HALF_SECONDS:Lenums/TestEnumWithFields;
|
||||
|
||||
.line 3
|
||||
new-instance v0, Lenums/TestEnumWithFields;
|
||||
|
||||
const/4 v3, 0x2
|
||||
|
||||
const-string v4, "FIVE_SECONDS"
|
||||
|
||||
invoke-direct {v0, v4, v3, v3}, Lenums/TestEnumWithFields;-><init>(Ljava/lang/String;II)V
|
||||
|
||||
sput-object v0, Lenums/TestEnumWithFields;->FIVE_SECONDS:Lenums/TestEnumWithFields;
|
||||
|
||||
const/4 v4, 0x3
|
||||
|
||||
new-array v4, v4, [Lenums/TestEnumWithFields;
|
||||
|
||||
.line 4
|
||||
sget-object v5, Lenums/TestEnumWithFields;->DISABLED:Lenums/TestEnumWithFields;
|
||||
|
||||
aput-object v5, v4, v1
|
||||
|
||||
sget-object v1, Lenums/TestEnumWithFields;->TWO_AND_A_HALF_SECONDS:Lenums/TestEnumWithFields;
|
||||
|
||||
aput-object v1, v4, v2
|
||||
|
||||
aput-object v0, v4, v3
|
||||
|
||||
sput-object v4, Lenums/TestEnumWithFields;->$VALUES:[Lenums/TestEnumWithFields;
|
||||
|
||||
.line 5
|
||||
sput-object v5, Lenums/TestEnumWithFields;->DEFAULT:Lenums/TestEnumWithFields;
|
||||
|
||||
.line 6
|
||||
sput-object v0, Lenums/TestEnumWithFields;->MAX:Lenums/TestEnumWithFields;
|
||||
|
||||
.line 7
|
||||
invoke-static {}, Lenums/TestEnumWithFields;->values()[Lenums/TestEnumWithFields;
|
||||
|
||||
move-result-object v0
|
||||
|
||||
sput-object v0, Lenums/TestEnumWithFields;->sValues:[Lenums/TestEnumWithFields;
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public constructor <init>(Ljava/lang/String;II)V
|
||||
.locals 0
|
||||
.annotation system Ldalvik/annotation/Signature;
|
||||
value = {
|
||||
"(I)V"
|
||||
}
|
||||
.end annotation
|
||||
|
||||
.line 1
|
||||
invoke-direct {p0, p1, p2}, Ljava/lang/Enum;-><init>(Ljava/lang/String;I)V
|
||||
|
||||
iput p3, p0, Lenums/TestEnumWithFields;->mRawValue:I
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public static valueOf(Ljava/lang/String;)Lenums/TestEnumWithFields;
|
||||
.locals 1
|
||||
|
||||
.line 1
|
||||
const-class v0, Lenums/TestEnumWithFields;
|
||||
|
||||
invoke-static {v0, p0}, Ljava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
|
||||
|
||||
move-result-object p0
|
||||
|
||||
check-cast p0, Lenums/TestEnumWithFields;
|
||||
|
||||
return-object p0
|
||||
.end method
|
||||
|
||||
.method public static values()[Lenums/TestEnumWithFields;
|
||||
.locals 1
|
||||
|
||||
.line 1
|
||||
sget-object v0, Lenums/TestEnumWithFields;->$VALUES:[Lenums/TestEnumWithFields;
|
||||
|
||||
invoke-virtual {v0}, [Lenums/TestEnumWithFields;->clone()Ljava/lang/Object;
|
||||
|
||||
move-result-object v0
|
||||
|
||||
check-cast v0, [Lenums/TestEnumWithFields;
|
||||
|
||||
return-object v0
|
||||
.end method
|
||||
Reference in New Issue
Block a user