feat: select better class from duplicates (#2701)(PR #2702)

* select the right class in in case of duplicate

* select correct class in gui in case of duplication

* fix code format

---------

Co-authored-by: Jean-Marie 'Histausse' Mineau <histausse@protonmail.com>
This commit is contained in:
Histausse
2025-11-29 20:50:49 +01:00
committed by GitHub
parent 4c760f1029
commit 1d831d82d4
5 changed files with 59 additions and 4 deletions
@@ -543,9 +543,10 @@ public final class JadxDecompiler implements Closeable {
return foundPkg;
}
List<JavaClass> clsList = Utils.collectionMap(pkg.getClasses(), this::convertClassNode);
List<JavaClass> clsListNoDup = Utils.collectionMap(pkg.getClassesNoDup(), this::convertClassNode);
int subPkgsCount = pkg.getSubPackages().size();
List<JavaPackage> subPkgs = subPkgsCount == 0 ? Collections.emptyList() : new ArrayList<>(subPkgsCount);
JavaPackage javaPkg = new JavaPackage(pkg, clsList, subPkgs);
JavaPackage javaPkg = new JavaPackage(pkg, clsList, clsListNoDup, subPkgs);
if (subPkgsCount != 0) {
// add subpackages after parent to avoid endless recursion
for (PackageNode subPackage : pkg.getSubPackages()) {
@@ -15,11 +15,17 @@ import jadx.core.dex.nodes.PackageNode;
public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
private final PackageNode pkgNode;
private final List<JavaClass> classes;
private final List<JavaClass> clsListNoDup;
private final List<JavaPackage> subPkgs;
JavaPackage(PackageNode pkgNode, List<JavaClass> classes, List<JavaPackage> subPkgs) {
this(pkgNode, classes, classes, subPkgs);
}
JavaPackage(PackageNode pkgNode, List<JavaClass> classes, List<JavaClass> clsListNoDup, List<JavaPackage> subPkgs) {
this.pkgNode = pkgNode;
this.classes = classes;
this.clsListNoDup = clsListNoDup;
this.subPkgs = subPkgs;
}
@@ -49,6 +55,10 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
return classes;
}
public List<JavaClass> getClassesNoDup() {
return clsListNoDup;
}
public boolean isRoot() {
return pkgNode.isRoot();
}
@@ -3,6 +3,7 @@ package jadx.core.dex.nodes;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -188,6 +189,14 @@ public class PackageNode extends LineAttrNode
return classes;
}
public List<ClassNode> getClassesNoDup() {
return classes.stream()
.map(ClassNode::getClassInfo)
.collect(Collectors.toSet())
.stream()
.map(e -> root.resolveClass(e)).collect(Collectors.toList());
}
public JavaPackage getJavaNode() {
return javaNode;
}
@@ -217,8 +217,43 @@ public class RootNode {
public void addClassNode(ClassNode clsNode) {
classes.add(clsNode);
clsMap.put(clsNode.getClassInfo(), clsNode);
rawClsMap.put(clsNode.getRawName(), clsNode);
ClassNode prevClsNode = clsMap.get(clsNode.getClassInfo());
if (prevClsNode == null) {
clsMap.put(clsNode.getClassInfo(), clsNode);
rawClsMap.put(clsNode.getRawName(), clsNode);
} else {
String prevFileName = prevClsNode.getInputFileName();
String fileName = clsNode.getInputFileName();
boolean prevFileNameIsValid = prevFileName.matches("classes[1-9]\\d*.dex") && !prevFileName.equals("classes1.dex");
boolean fileNameIsValid = fileName.matches("classes[1-9]\\d*.dex") && !fileName.equals("classes1.dex");
ClassNode newClsNode = clsNode;
// classes.dex has precedence
if (fileName.equals("classes.dex")) {
newClsNode = clsNode;
} else if (prevFileName.equals("classes.dex")) {
newClsNode = prevClsNode;
} else if (prevFileNameIsValid && !fileNameIsValid) {
// valid dex names have precedence
newClsNode = prevClsNode;
} else if (!prevFileNameIsValid && fileNameIsValid) {
newClsNode = clsNode;
} else if (prevFileNameIsValid && fileNameIsValid) {
// if both are valid, the lower index has precedence
long index = Long.parseLong(fileName.substring(7, fileName.length() - 4));
long prevIndex = Long.parseLong(prevFileName.substring(7, prevFileName.length() - 4));
if (index < prevIndex) {
newClsNode = clsNode;
} else {
newClsNode = prevClsNode;
}
}
clsMap.put(newClsNode.getClassInfo(), newClsNode);
rawClsMap.put(newClsNode.getRawName(), newClsNode);
}
}
public void loadResources(ResourcesLoader resLoader, List<ResourceFile> resources) {
@@ -174,7 +174,7 @@ public class PackageHelper {
if (synthetic) {
classes = Collections.emptyList();
} else {
classes = Utils.collectionMap(javaPkg.getClasses(), nodeCache::makeFrom);
classes = Utils.collectionMap(javaPkg.getClassesNoDup(), nodeCache::makeFrom);
classes.sort(CLASS_COMPARATOR);
}
return nodeCache.newJPackage(javaPkg, synthetic, pkgEnabled, classes);