提交 cf1d9e83 编写于 作者: S Skylot

fix: allow to reuse enum fields in static fields (#1019)

上级 b096d886
......@@ -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 {
......
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();
}
}
.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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册