From ebf06fde650e4af015689897008f35c19a31f6c7 Mon Sep 17 00:00:00 2001 From: Skylot Date: Fri, 27 Dec 2013 23:17:27 +0400 Subject: [PATCH] gui: remove not generated elements from class node tree --- .../src/main/java/jadx/api/JavaClass.java | 38 ++++++++++--------- .../src/main/java/jadx/api/JavaMethod.java | 17 ++++----- .../main/java/jadx/core/codegen/ClassGen.java | 11 ++---- .../main/java/jadx/core/codegen/InsnGen.java | 1 + .../java/jadx/core/dex/nodes/MethodNode.java | 5 +-- .../src/main/java/jadx/gui/MainWindow.java | 21 ++++++++++ .../main/java/jadx/gui/treemodel/JClass.java | 38 +++++++++++++------ .../main/java/jadx/gui/treemodel/JMethod.java | 18 ++++++--- .../java/jadx/gui/treemodel/TextNode.java | 35 +++++++++++++++++ .../resources/i18n/Messages_en_US.properties | 1 + 10 files changed, 132 insertions(+), 53 deletions(-) create mode 100644 jadx-gui/src/main/java/jadx/gui/treemodel/TextNode.java diff --git a/jadx-core/src/main/java/jadx/api/JavaClass.java b/jadx-core/src/main/java/jadx/api/JavaClass.java index 0d95fcb7..c6526e64 100644 --- a/jadx-core/src/main/java/jadx/api/JavaClass.java +++ b/jadx-core/src/main/java/jadx/api/JavaClass.java @@ -1,6 +1,7 @@ package jadx.api; import jadx.core.codegen.CodeWriter; +import jadx.core.dex.attributes.AttributeFlag; import jadx.core.dex.info.AccessInfo; import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.FieldNode; @@ -15,44 +16,47 @@ public final class JavaClass { private final Decompiler decompiler; private final ClassNode cls; - private final List innerClasses; - private final List fields; - private final List methods; + + private List innerClasses = Collections.emptyList(); + private List fields = Collections.emptyList(); + private List methods = Collections.emptyList(); JavaClass(Decompiler decompiler, ClassNode classNode) { this.decompiler = decompiler; this.cls = classNode; + } + + public void decompile() { + decompiler.processClass(cls); int inClsCount = cls.getInnerClasses().size(); - if (inClsCount == 0) { - this.innerClasses = Collections.emptyList(); - } else { + if (inClsCount != 0) { List list = new ArrayList(inClsCount); for (ClassNode inner : cls.getInnerClasses()) { - list.add(new JavaClass(decompiler, inner)); + if (!inner.getAttributes().contains(AttributeFlag.DONT_GENERATE)) { + list.add(new JavaClass(decompiler, inner)); + } } this.innerClasses = Collections.unmodifiableList(list); } int fieldsCount = cls.getFields().size(); - if (fieldsCount == 0) { - this.fields = Collections.emptyList(); - } else { + if (fieldsCount != 0) { List flds = new ArrayList(fieldsCount); for (FieldNode f : cls.getFields()) { - flds.add(new JavaField(f)); + if (!f.getAttributes().contains(AttributeFlag.DONT_GENERATE)) { + flds.add(new JavaField(f)); + } } this.fields = Collections.unmodifiableList(flds); } int methodsCount = cls.getMethods().size(); - if (methodsCount == 0) { - this.methods = Collections.emptyList(); - } else { + if (methodsCount != 0) { List mths = new ArrayList(methodsCount); for (MethodNode m : cls.getMethods()) { - if (!m.getAccessFlags().isSynthetic()) { - mths.add(new JavaMethod(m)); + if (!m.getAttributes().contains(AttributeFlag.DONT_GENERATE)) { + mths.add(new JavaMethod(this, m)); } } Collections.sort(mths, new Comparator() { @@ -68,7 +72,7 @@ public final class JavaClass { public String getCode() { CodeWriter code = cls.getCode(); if (code == null) { - decompiler.processClass(cls); + decompile(); code = cls.getCode(); } return code != null ? code.toString() : "error processing class"; diff --git a/jadx-core/src/main/java/jadx/api/JavaMethod.java b/jadx-core/src/main/java/jadx/api/JavaMethod.java index 46eae637..45da1afe 100644 --- a/jadx-core/src/main/java/jadx/api/JavaMethod.java +++ b/jadx-core/src/main/java/jadx/api/JavaMethod.java @@ -1,7 +1,6 @@ package jadx.api; import jadx.core.dex.info.AccessInfo; -import jadx.core.dex.info.MethodInfo; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.nodes.MethodNode; @@ -9,19 +8,19 @@ import java.util.List; public final class JavaMethod { private final MethodNode mth; + private final JavaClass parent; - public JavaMethod(MethodNode m) { + public JavaMethod(JavaClass cls, MethodNode m) { + this.parent = cls; this.mth = m; } public String getName() { - MethodInfo mi = mth.getMethodInfo(); - if (mi.isConstructor()) { - return mth.getParentClass().getShortName(); - } else if (mi.isClassInit()) { - return "static"; - } - return mi.getName(); + return mth.getMethodInfo().getName(); + } + + public JavaClass getDeclaringClass() { + return parent; } public AccessInfo getAccessFlags() { diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index ae900d28..8fb30f85 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -216,9 +216,9 @@ public class ClassGen { CodeWriter code = new CodeWriter(clsCode.getIndent() + 1); for (Iterator it = mthList.iterator(); it.hasNext(); ) { MethodNode mth = it.next(); - if (mth.getAttributes().contains(AttributeFlag.DONT_GENERATE)) + if (mth.getAttributes().contains(AttributeFlag.DONT_GENERATE)) { continue; - + } try { if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) { MethodGen mthGen = new MethodGen(this, mth); @@ -232,9 +232,6 @@ public class ClassGen { } code.add(';'); } else { - if (mth.isNoCode()) - continue; - MethodGen mthGen = new MethodGen(this, mth); if (mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) { code.startLine("/* JADX WARNING: inconsistent code */"); @@ -253,9 +250,9 @@ public class ClassGen { String msg = ErrorsCounter.methodError(mth, "Method generation error", e); code.startLine("/* " + msg + CodeWriter.NL + Utils.getStackTrace(e) + " */"); } - - if (it.hasNext()) + if (it.hasNext()) { code.newLine(); + } } return code; } diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index 5fcec3d1..5d0d7270 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -533,6 +533,7 @@ public class InsnGen { } else { parent = cls.getSuperClass(); } + cls.getAttributes().add(AttributeFlag.DONT_GENERATE); MethodNode defCtr = cls.getDefaultConstructor(); if (RegionUtils.notEmpty(defCtr.getRegion())) { defCtr.getAttributes().add(AttributeFlag.ANONYMOUS_CONSTRUCTOR); diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java index ddcc080c..9443e861 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java @@ -124,14 +124,13 @@ public class MethodNode extends LineAttrNode implements ILoadable { @Override public void unload() { - if (noCode) + if (noCode) { return; - + } if (instructions != null) instructions.clear(); blocks = null; exitBlocks = null; if (exceptionHandlers != null) exceptionHandlers.clear(); - getAttributes().clear(); noCode = true; } diff --git a/jadx-gui/src/main/java/jadx/gui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/MainWindow.java index eb7e3a5e..17a7c2df 100644 --- a/jadx-gui/src/main/java/jadx/gui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/MainWindow.java @@ -26,14 +26,18 @@ import javax.swing.JToolBar; import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.ProgressMonitor; +import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.plaf.basic.BasicButtonUI; import javax.swing.text.BadLocationException; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.ExpandVetoException; +import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import java.awt.BorderLayout; import java.awt.Color; @@ -192,6 +196,7 @@ public class MainWindow extends JFrame { } private void showCode(JClass cls, int line) { + cls.load(); JPanel panel = (JPanel) openTabs.get(cls); if (panel != null) { panel = (JPanel) openTabs.get(cls); @@ -379,6 +384,22 @@ public class MainWindow extends JFrame { return c; } }); + tree.addTreeWillExpandListener(new TreeWillExpandListener() { + + @Override + public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { + TreePath path = event.getPath(); + Object node = path.getLastPathComponent(); + if (node instanceof JClass) { + JClass cls = (JClass) node; + cls.load(); + } + } + + @Override + public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { + } + }); JScrollPane treeScrollPane = new JScrollPane(tree); splitPane.setLeftComponent(treeScrollPane); diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java index 9038c4b5..6a10e1a8 100644 --- a/jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java @@ -4,6 +4,7 @@ import jadx.api.JavaClass; import jadx.api.JavaField; import jadx.api.JavaMethod; import jadx.core.dex.info.AccessInfo; +import jadx.gui.utils.NLS; import jadx.gui.utils.Utils; import javax.swing.Icon; @@ -22,6 +23,7 @@ public class JClass extends JNode { private final JavaClass cls; private JClass jParrent; + private boolean loaded; public JClass(JavaClass cls) { this.cls = cls; @@ -31,21 +33,33 @@ public class JClass extends JNode { return cls; } + public synchronized void load() { + if (!loaded) { + cls.decompile(); + loaded = true; + updateChilds(); + } + } + @Override public void updateChilds() { removeAllChildren(); - JClass currentParent = jParrent == null ? this : jParrent; - for (JavaClass javaClass : cls.getInnerClasses()) { - JClass child = new JClass(javaClass); - child.setJParent(currentParent); - child.updateChilds(); - add(child); - } - for (JavaField f : cls.getFields()) { - add(new JField(f, currentParent)); - } - for (JavaMethod m : cls.getMethods()) { - add(new JMethod(m, currentParent)); + if (!loaded) { + add(new TextNode(NLS.str("tree.loading"))); + } else { + JClass currentParent = jParrent == null ? this : jParrent; + for (JavaClass javaClass : cls.getInnerClasses()) { + JClass child = new JClass(javaClass); + child.setJParent(currentParent); + child.updateChilds(); + add(child); + } + for (JavaField f : cls.getFields()) { + add(new JField(f, currentParent)); + } + for (JavaMethod m : cls.getMethods()) { + add(new JMethod(m, currentParent)); + } } } diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java b/jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java index 12766774..2d97416b 100644 --- a/jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java @@ -47,8 +47,12 @@ public class JMethod extends JNode { public Icon getIcon() { AccessInfo accessFlags = mth.getAccessFlags(); OverlayIcon icon = Utils.makeIcon(accessFlags, ICON_MTH_PUB, ICON_MTH_PRI, ICON_MTH_PRO, ICON_MTH_DEF); - if (accessFlags.isConstructor()) icon.add(ICON_CONSTRUCTOR); - if (accessFlags.isSynchronized()) icon.add(ICON_SYNC); + if (accessFlags.isConstructor()) { + icon.add(ICON_CONSTRUCTOR); + } + if (accessFlags.isSynchronized()) { + icon.add(ICON_SYNC); + } return icon; } @@ -57,14 +61,18 @@ public class JMethod extends JNode { if (mth.isClassInit()) { return "{...}"; } - StringBuilder base = new StringBuilder(); - base.append(mth.getName()); + if (mth.isConstructor()) { + base.append(mth.getDeclaringClass().getShortName()); + } else { + base.append(mth.getName()); + } base.append('('); for (Iterator it = mth.getArguments().iterator(); it.hasNext(); ) { base.append(Utils.typeStr(it.next())); - if (it.hasNext()) + if (it.hasNext()) { base.append(", "); + } } base.append(')'); return Utils.typeFormat(base.toString(), mth.getReturnType()); diff --git a/jadx-gui/src/main/java/jadx/gui/treemodel/TextNode.java b/jadx-gui/src/main/java/jadx/gui/treemodel/TextNode.java new file mode 100644 index 00000000..c2586502 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/treemodel/TextNode.java @@ -0,0 +1,35 @@ +package jadx.gui.treemodel; + +import javax.swing.Icon; + +public class TextNode extends JNode { + private final String label; + + public TextNode(String str) { + this.label = str; + } + + @Override + public JClass getJParent() { + return null; + } + + @Override + public int getLine() { + return 0; + } + + @Override + public void updateChilds() { + } + + @Override + public Icon getIcon() { + return null; + } + + @Override + public String toString() { + return label; + } +} diff --git a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties index 4290f501..068746b4 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -6,6 +6,7 @@ file.select=Select file.exit=Exit tree.flatten=Flatten packages +tree.loading=Loading... search=Search search.previous=Previous -- GitLab