Commit 5de4d079 authored by sergey-wowwow's avatar sergey-wowwow Committed by skylot

fix: generates code of missing R class (#353)

parent 8c43e7f7
...@@ -91,7 +91,6 @@ public final class JadxDecompiler { ...@@ -91,7 +91,6 @@ public final class JadxDecompiler {
root.initClassPath(); root.initClassPath();
root.loadResources(getResources()); root.loadResources(getResources());
root.initAppResClass();
initVisitors(); initVisitors();
} }
......
...@@ -94,10 +94,7 @@ public class RootNode { ...@@ -94,10 +94,7 @@ public class RootNode {
ResourceStorage resStorage = parser.getResStorage(); ResourceStorage resStorage = parser.getResStorage();
constValues.setResourcesNames(resStorage.getResourcesNames()); constValues.setResourcesNames(resStorage.getResourcesNames());
appPackage = resStorage.getAppPackage(); appPackage = resStorage.getAppPackage();
} appResClass = AndroidResourcesUtils.searchAppResClass(this, resStorage);
public void initAppResClass() {
appResClass = AndroidResourcesUtils.searchAppResClass(this);
} }
public void initClassPath() { public void initClassPath() {
......
package jadx.core.utils.android; package jadx.core.utils.android;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -11,6 +16,8 @@ import jadx.core.dex.info.ClassInfo; ...@@ -11,6 +16,8 @@ import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.DexNode;
import jadx.core.dex.nodes.RootNode; import jadx.core.dex.nodes.RootNode;
import jadx.core.xmlgen.ResourceStorage;
import jadx.core.xmlgen.entry.ResourceEntry;
/** /**
* Android resources specific handlers * Android resources specific handlers
...@@ -21,7 +28,7 @@ public class AndroidResourcesUtils { ...@@ -21,7 +28,7 @@ public class AndroidResourcesUtils {
private AndroidResourcesUtils() { private AndroidResourcesUtils() {
} }
public static ClassNode searchAppResClass(RootNode root) { public static ClassNode searchAppResClass(RootNode root, ResourceStorage resStorage) {
String appPackage = root.getAppPackage(); String appPackage = root.getAppPackage();
String fullName = appPackage != null ? appPackage + ".R" : "R"; String fullName = appPackage != null ? appPackage + ".R" : "R";
ClassNode resCls = root.searchClassByName(fullName); ClassNode resCls = root.searchClassByName(fullName);
...@@ -36,7 +43,7 @@ public class AndroidResourcesUtils { ...@@ -36,7 +43,7 @@ public class AndroidResourcesUtils {
LOG.info("Found several 'R' class candidates: {}", candidates); LOG.info("Found several 'R' class candidates: {}", candidates);
} }
LOG.warn("Unknown 'R' class, create references to '{}'", fullName); LOG.warn("Unknown 'R' class, create references to '{}'", fullName);
return makeClass(root, fullName); return makeClass(root, fullName, resStorage);
} }
public static boolean handleAppResField(CodeWriter code, ClassGen clsGen, ClassInfo declClass) { public static boolean handleAppResField(CodeWriter code, ClassGen clsGen, ClassInfo declClass) {
...@@ -50,12 +57,48 @@ public class AndroidResourcesUtils { ...@@ -50,12 +57,48 @@ public class AndroidResourcesUtils {
return false; return false;
} }
private static ClassNode makeClass(RootNode root, String clsName) { private static ClassNode makeClass(RootNode root, String clsName, ResourceStorage resStorage) {
List<DexNode> dexNodes = root.getDexNodes(); List<DexNode> dexNodes = root.getDexNodes();
if (dexNodes.isEmpty()) { if (dexNodes.isEmpty()) {
return null; return null;
} }
ClassInfo r = ClassInfo.fromName(root, clsName); ClassInfo r = ClassInfo.fromName(root, clsName);
return new ClassNode(dexNodes.get(0), r); ClassNode classNode = new ClassNode(dexNodes.get(0), r);
generateMissingRCode(classNode, resStorage);
return classNode;
}
private static void generateMissingRCode(ClassNode cls, ResourceStorage resStorage) {
Map<String, List<ResourceEntry>> sortedMap = new HashMap<>();
for(ResourceEntry ri : resStorage.getResources()) {
List<ResourceEntry> entries = sortedMap.get(ri.getTypeName());
if(entries == null) {
entries = new LinkedList<>();
sortedMap.put(ri.getTypeName(), entries);
}
entries.add(ri);
}
Set<String> addedValues = new HashSet<>();
CodeWriter clsCode = new CodeWriter();
if (!"".equals(cls.getPackage())) {
clsCode.add("package ").add(cls.getPackage()).add(';').newLine();
}
clsCode.startLine("public final class ").add(cls.getShortName()).add(" {").incIndent();
for(String typeName : sortedMap.keySet()) {
clsCode.startLine("public static final class ").add(typeName).add(" {").incIndent();
for(ResourceEntry ri : sortedMap.get(typeName)) {
if(addedValues.add(ri.getTypeName() + "." + ri.getKeyName())) {
clsCode.startLine("public static final int ").add(ri.getKeyName()).add(" = ")
.add("" + ri.getId()).add(";");
}
}
clsCode.decIndent();
clsCode.add("}");
}
clsCode.decIndent();
clsCode.add("}");
cls.setCode(clsCode);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment