fix: convert inner enums and fix inner classes reference (#719)
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
package jadx.core.codegen;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import com.android.dx.rop.code.AccessFlags;
|
||||
@@ -148,7 +150,7 @@ public class ClassGen {
|
||||
ArgType sup = cls.getSuperClass();
|
||||
if (sup != null
|
||||
&& !sup.equals(ArgType.OBJECT)
|
||||
&& !sup.getObject().equals(ArgType.ENUM.getObject())) {
|
||||
&& !cls.isEnum()) {
|
||||
clsCode.add("extends ");
|
||||
useClass(clsCode, sup);
|
||||
clsCode.add(' ');
|
||||
@@ -513,6 +515,9 @@ public class ClassGen {
|
||||
if (isClassInnerFor(useCls, extClsInfo)) {
|
||||
return shortName;
|
||||
}
|
||||
if (extClsInfo.isInner()) {
|
||||
return expandInnerClassName(useCls, extClsInfo);
|
||||
}
|
||||
if (isBothClassesInOneTopClass(useCls, extClsInfo)) {
|
||||
return shortName;
|
||||
}
|
||||
@@ -550,6 +555,26 @@ public class ClassGen {
|
||||
return shortName;
|
||||
}
|
||||
|
||||
private String expandInnerClassName(ClassInfo useCls, ClassInfo extClsInfo) {
|
||||
List<ClassInfo> clsList = new ArrayList<>();
|
||||
clsList.add(extClsInfo);
|
||||
ClassInfo parentCls = extClsInfo.getParentClass();
|
||||
boolean addImport = true;
|
||||
while (parentCls != null) {
|
||||
if (parentCls == useCls || isClassInnerFor(useCls, parentCls)) {
|
||||
addImport = false;
|
||||
break;
|
||||
}
|
||||
clsList.add(parentCls);
|
||||
parentCls = parentCls.getParentClass();
|
||||
}
|
||||
Collections.reverse(clsList);
|
||||
if (addImport) {
|
||||
addImport(clsList.get(0));
|
||||
}
|
||||
return Utils.listToString(clsList, ".", ClassInfo::getAliasShortName);
|
||||
}
|
||||
|
||||
private void addImport(ClassInfo classInfo) {
|
||||
if (parentGen != null) {
|
||||
parentGen.addImport(classInfo);
|
||||
@@ -579,7 +604,7 @@ public class ClassGen {
|
||||
private static boolean isClassInnerFor(ClassInfo inner, ClassInfo parent) {
|
||||
if (inner.isInner()) {
|
||||
ClassInfo p = inner.getParentClass();
|
||||
return p.equals(parent) || isClassInnerFor(p, parent);
|
||||
return Objects.equals(p, parent) || isClassInnerFor(p, parent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -44,13 +44,19 @@ public class EnumVisitor extends AbstractVisitor {
|
||||
|
||||
@Override
|
||||
public boolean visit(ClassNode cls) throws JadxException {
|
||||
if (!cls.isEnum()) {
|
||||
if (!convertToEnum(cls)) {
|
||||
AccessInfo accessFlags = cls.getAccessFlags();
|
||||
if (accessFlags.isEnum()) {
|
||||
cls.setAccessFlags(accessFlags.remove(AccessFlags.ACC_ENUM));
|
||||
cls.addAttr(AType.COMMENTS, "'enum' access flag removed");
|
||||
cls.addAttr(AType.COMMENTS, "'enum' modifier removed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean convertToEnum(ClassNode cls) {
|
||||
if (!cls.isEnum()) {
|
||||
return false;
|
||||
}
|
||||
// search class init method
|
||||
MethodNode staticMethod = null;
|
||||
@@ -63,7 +69,7 @@ public class EnumVisitor extends AbstractVisitor {
|
||||
}
|
||||
if (staticMethod == null) {
|
||||
ErrorsCounter.classWarn(cls, "Enum class init method not found");
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
ArgType clsType = cls.getClassInfo().getType();
|
||||
@@ -167,7 +173,7 @@ public class EnumVisitor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void processEnumInnerCls(ConstructorInsn co, EnumField field, ClassNode innerCls) {
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package jadx.tests.integration.enums;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
import static jadx.tests.api.utils.JadxMatchers.containsOne;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class TestInnerEnums extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
public enum Numbers {
|
||||
ONE(1, NumString.ONE), TWO(2, NumString.TWO);
|
||||
|
||||
private final int num;
|
||||
private final NumString str;
|
||||
|
||||
public enum NumString {
|
||||
ONE("one"), TWO("two");
|
||||
|
||||
private final String name;
|
||||
|
||||
NumString(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
Numbers(int n, NumString str) {
|
||||
this.num = n;
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
public int getNum() {
|
||||
return num;
|
||||
}
|
||||
|
||||
public NumString getNumStr() {
|
||||
return str;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return str.getName();
|
||||
}
|
||||
}
|
||||
|
||||
public void check() {
|
||||
assertEquals(1, Numbers.ONE.getNum());
|
||||
assertEquals(Numbers.NumString.ONE, Numbers.ONE.getNumStr());
|
||||
assertEquals("one", Numbers.ONE.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("ONE(1, NumString.ONE)"));
|
||||
assertThat(code, containsOne("ONE(\"one\")"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user