mirror of
https://github.com/skylot/jadx.git
synced 2025-02-17 03:30:06 +00:00
core: fix incorrect package for R class (#99)
This commit is contained in:
parent
2b1f815c58
commit
4e982722a5
@ -501,6 +501,10 @@ public class ClassGen {
|
||||
if (searchCollision(cls.dex(), useCls, extClsInfo)) {
|
||||
return fullName;
|
||||
}
|
||||
// ignore classes from default package
|
||||
if (extClsInfo.isDefaultPackage()) {
|
||||
return shortName;
|
||||
}
|
||||
if (extClsInfo.getPackage().equals(useCls.getPackage())) {
|
||||
fullName = extClsInfo.getNameWithoutPackage();
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static jadx.core.utils.android.AndroidResourcesUtils.handleAppResField;
|
||||
|
||||
public class InsnGen {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(InsnGen.class);
|
||||
|
||||
@ -169,12 +171,7 @@ public class InsnGen {
|
||||
boolean fieldFromThisClass = clsGen.getClassNode().getClassInfo().equals(declClass);
|
||||
if (!fieldFromThisClass) {
|
||||
// Android specific resources class handler
|
||||
ClassInfo parentClass = declClass.getParentClass();
|
||||
if (parentClass != null && parentClass.getShortName().equals("R")) {
|
||||
clsGen.useClass(code, parentClass);
|
||||
code.add('.');
|
||||
code.add(declClass.getAlias().getShortName());
|
||||
} else {
|
||||
if (!handleAppResField(code, clsGen, declClass)) {
|
||||
clsGen.useClass(code, declClass);
|
||||
}
|
||||
code.add('.');
|
||||
|
@ -125,6 +125,10 @@ public final class ClassInfo {
|
||||
return pkg;
|
||||
}
|
||||
|
||||
public boolean isDefaultPackage() {
|
||||
return pkg.isEmpty();
|
||||
}
|
||||
|
||||
public String getRawName() {
|
||||
return type.getObject();
|
||||
}
|
||||
|
@ -17,10 +17,8 @@ public class FieldNode extends LineAttrNode {
|
||||
private ArgType type; // store signature
|
||||
|
||||
public FieldNode(ClassNode cls, Field field) {
|
||||
this.parent = cls;
|
||||
this.fieldInfo = FieldInfo.fromDex(cls.dex(), field.getFieldIndex());
|
||||
this.type = fieldInfo.getType();
|
||||
this.accFlags = new AccessInfo(field.getAccessFlags(), AFType.FIELD);
|
||||
this(cls, FieldInfo.fromDex(cls.dex(), field.getFieldIndex()),
|
||||
field.getAccessFlags());
|
||||
}
|
||||
|
||||
public FieldNode(ClassNode cls, FieldInfo fieldInfo, int accessFlags) {
|
||||
|
@ -9,6 +9,7 @@ import jadx.core.dex.info.ClassInfo;
|
||||
import jadx.core.dex.info.ConstStorage;
|
||||
import jadx.core.utils.ErrorsCounter;
|
||||
import jadx.core.utils.StringUtils;
|
||||
import jadx.core.utils.android.AndroidResourcesUtils;
|
||||
import jadx.core.utils.exceptions.DecodeException;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
import jadx.core.utils.files.DexFile;
|
||||
@ -97,24 +98,7 @@ public class RootNode {
|
||||
}
|
||||
|
||||
public void initAppResClass() {
|
||||
ClassNode resCls;
|
||||
if (appPackage == null) {
|
||||
appResClass = makeClass("R");
|
||||
return;
|
||||
}
|
||||
String fullName = appPackage + ".R";
|
||||
resCls = searchClassByName(fullName);
|
||||
if (resCls != null) {
|
||||
appResClass = resCls;
|
||||
} else {
|
||||
appResClass = makeClass(fullName);
|
||||
}
|
||||
}
|
||||
|
||||
private ClassNode makeClass(String clsName) {
|
||||
DexNode firstDex = dexNodes.get(0);
|
||||
ClassInfo r = ClassInfo.fromName(firstDex, clsName);
|
||||
return new ClassNode(firstDex, r);
|
||||
appResClass = AndroidResourcesUtils.searchAppResClass(this);
|
||||
}
|
||||
|
||||
public void initClassPath() throws DecodeException {
|
||||
@ -169,6 +153,18 @@ public class RootNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<ClassNode> searchClassByShortName(String shortName) {
|
||||
List<ClassNode> list = new ArrayList<ClassNode>();
|
||||
for (DexNode dexNode : dexNodes) {
|
||||
for (ClassNode cls : dexNode.getClasses()) {
|
||||
if (cls.getClassInfo().getShortName().equals(shortName)) {
|
||||
list.add(cls);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<DexNode> getDexNodes() {
|
||||
return dexNodes;
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
package jadx.core.utils.android;
|
||||
|
||||
import jadx.core.codegen.ClassGen;
|
||||
import jadx.core.codegen.CodeWriter;
|
||||
import jadx.core.dex.info.ClassInfo;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.DexNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Android resources specific handlers
|
||||
*/
|
||||
public class AndroidResourcesUtils {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AndroidResourcesUtils.class);
|
||||
|
||||
public static ClassNode searchAppResClass(RootNode root) {
|
||||
String appPackage = root.getAppPackage();
|
||||
String fullName = appPackage != null ? appPackage + ".R" : "R";
|
||||
ClassNode resCls = root.searchClassByName(fullName);
|
||||
if (resCls != null) {
|
||||
return resCls;
|
||||
}
|
||||
List<ClassNode> candidates = root.searchClassByShortName("R");
|
||||
if (candidates.size() == 1) {
|
||||
return candidates.get(0);
|
||||
}
|
||||
if (!candidates.isEmpty()) {
|
||||
LOG.info("Found several 'R' class candidates: {}", candidates);
|
||||
}
|
||||
LOG.warn("Unknown 'R' class, create references to '{}'", fullName);
|
||||
return makeClass(root, fullName);
|
||||
}
|
||||
|
||||
public static boolean handleAppResField(CodeWriter code, ClassGen clsGen, ClassInfo declClass) {
|
||||
ClassInfo parentClass = declClass.getParentClass();
|
||||
if (parentClass != null && parentClass.getShortName().equals("R")) {
|
||||
clsGen.useClass(code, parentClass);
|
||||
code.add('.');
|
||||
code.add(declClass.getAlias().getShortName());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static ClassNode makeClass(RootNode root, String clsName) {
|
||||
DexNode firstDex = root.getDexNodes().get(0);
|
||||
ClassInfo r = ClassInfo.fromName(firstDex, clsName);
|
||||
return new ClassNode(firstDex, r);
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ import java.util.Map;
|
||||
import org.junit.Test;
|
||||
|
||||
import static jadx.tests.api.utils.JadxMatchers.containsOne;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class TestRFieldRestore extends IntegrationTest {
|
||||
@ -31,5 +33,6 @@ public class TestRFieldRestore extends IntegrationTest {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
assertThat(code, containsOne("return R.id.Button;"));
|
||||
assertThat(code, not(containsString("import R;")));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user