diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java index d781e0b66..561ddb8f3 100644 --- a/jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java @@ -84,11 +84,13 @@ public class JPackage extends JNode implements Comparable { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - JPackage jPackage = (JPackage) o; - if (!name.equals(jPackage.name)) return false; - return true; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return name.equals(((JPackage) o).name); } @Override diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java index aa7e59b70..1e2647cd0 100644 --- a/jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JRoot.java @@ -10,7 +10,7 @@ import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -47,6 +47,12 @@ public class JRoot extends JNode { } } + /** + * Convert packages list to hierarchical packages representation + * + * @param packages input packages list + * @return root packages + */ List getHierarchyPackages(List packages) { Map pkgMap = new HashMap(); for (JavaPackage pkg : packages) { @@ -63,11 +69,11 @@ public class JRoot extends JNode { pkg.getInnerPackages().addAll(innerPkg.getInnerPackages()); pkg.getClasses().addAll(innerPkg.getClasses()); pkg.setName(pkg.getName() + "." + innerPkg.getName()); + innerPkg.getInnerPackages().clear(); innerPkg.getClasses().clear(); repeat = true; - pkgMap.remove(innerPkg.getName()); break; } } @@ -80,14 +86,16 @@ public class JRoot extends JNode { it.remove(); } } - // find root packages - Set inners = new HashSet(); + + // use identity set for collect inner packages + Set innerPackages = Collections.newSetFromMap(new IdentityHashMap()); for (JPackage pkg : pkgMap.values()) { - inners.addAll(pkg.getInnerPackages()); + innerPackages.addAll(pkg.getInnerPackages()); } + // find root packages List rootPkgs = new ArrayList(); for (JPackage pkg : pkgMap.values()) { - if (!inners.contains(pkg)) { + if (!innerPackages.contains(pkg)) { rootPkgs.add(pkg); } } diff --git a/jadx-gui/src/test/java/jadx/gui/treemodel/JRootTest.java b/jadx-gui/src/test/java/jadx/gui/treemodel/JRootTest.java index 15b4bb365..4e5cd77a8 100644 --- a/jadx-gui/src/test/java/jadx/gui/treemodel/JRootTest.java +++ b/jadx-gui/src/test/java/jadx/gui/treemodel/JRootTest.java @@ -8,10 +8,10 @@ import jadx.api.JavaPackage; import jadx.core.dex.nodes.ClassNode; import jadx.gui.JadxWrapper; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -19,19 +19,20 @@ import static org.mockito.Mockito.mock; public class JRootTest { + private JRoot root; + private Decompiler decompiler; + + @Before + public void init() { + root = new JRoot(mock(JadxWrapper.class)); + decompiler = new Decompiler(mock(IJadxArgs.class)); + } + @Test public void testHierarchyPackages() { String pkgName = "a.b.c.d.e"; - JadxWrapper wrapper = mock(JadxWrapper.class); - JRoot root = new JRoot(wrapper); - - JavaClass cls = Factory.newClass(new Decompiler(mock(IJadxArgs.class)), mock(ClassNode.class)); - JavaPackage pkg = Factory.newPackage(pkgName, Arrays.asList(cls)); - - List packages = new ArrayList(); - packages.add(pkg); - + List packages = Arrays.asList(newPkg(pkgName)); List out = root.getHierarchyPackages(packages); assertEquals(out.size(), 1); @@ -40,4 +41,62 @@ public class JRootTest { assertEquals(jpkg.getClasses().size(), 1); } + @Test + public void testHierarchyPackages2() { + List packages = Arrays.asList( + newPkg("a.b"), + newPkg("a.c"), + newPkg("a.d") + ); + List out = root.getHierarchyPackages(packages); + + assertEquals(out.size(), 1); + JPackage jpkg = out.get(0); + assertEquals(jpkg.getName(), "a"); + assertEquals(jpkg.getClasses().size(), 0); + assertEquals(jpkg.getInnerPackages().size(), 3); + } + + @Test + public void testHierarchyPackages3() { + List packages = Arrays.asList( + newPkg("a.b.p1"), + newPkg("a.b.p2"), + newPkg("a.b.p3") + ); + List out = root.getHierarchyPackages(packages); + + assertEquals(out.size(), 1); + JPackage jpkg = out.get(0); + assertEquals(jpkg.getName(), "a.b"); + assertEquals(jpkg.getClasses().size(), 0); + assertEquals(jpkg.getInnerPackages().size(), 3); + } + + @Test + public void testHierarchyPackages4() { + List packages = Arrays.asList( + newPkg("a.p1"), + newPkg("a.b.c.p2"), + newPkg("a.b.c.p3"), + newPkg("d.e"), + newPkg("d.f.a") + ); + List out = root.getHierarchyPackages(packages); + + assertEquals(out.size(), 2); + assertEquals(out.get(0).getName(), "a"); + assertEquals(out.get(0).getInnerPackages().size(), 2); + assertEquals(out.get(1).getName(), "d"); + assertEquals(out.get(1).getInnerPackages().size(), 2); + } + + private JavaPackage newPkg(String name) { + return Factory.newPackage(name, Arrays.asList(newClass())); + } + + private JavaClass newClass() { + return Factory.newClass(decompiler, mock(ClassNode.class)); + } + }