Commit ebf06fde authored by Skylot's avatar Skylot

gui: remove not generated elements from class node tree

parent 438b3b50
package jadx.api; package jadx.api;
import jadx.core.codegen.CodeWriter; import jadx.core.codegen.CodeWriter;
import jadx.core.dex.attributes.AttributeFlag;
import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.FieldNode;
...@@ -15,44 +16,47 @@ public final class JavaClass { ...@@ -15,44 +16,47 @@ public final class JavaClass {
private final Decompiler decompiler; private final Decompiler decompiler;
private final ClassNode cls; private final ClassNode cls;
private final List<JavaClass> innerClasses;
private final List<JavaField> fields; private List<JavaClass> innerClasses = Collections.emptyList();
private final List<JavaMethod> methods; private List<JavaField> fields = Collections.emptyList();
private List<JavaMethod> methods = Collections.emptyList();
JavaClass(Decompiler decompiler, ClassNode classNode) { JavaClass(Decompiler decompiler, ClassNode classNode) {
this.decompiler = decompiler; this.decompiler = decompiler;
this.cls = classNode; this.cls = classNode;
}
public void decompile() {
decompiler.processClass(cls);
int inClsCount = cls.getInnerClasses().size(); int inClsCount = cls.getInnerClasses().size();
if (inClsCount == 0) { if (inClsCount != 0) {
this.innerClasses = Collections.emptyList();
} else {
List<JavaClass> list = new ArrayList<JavaClass>(inClsCount); List<JavaClass> list = new ArrayList<JavaClass>(inClsCount);
for (ClassNode inner : cls.getInnerClasses()) { for (ClassNode inner : cls.getInnerClasses()) {
if (!inner.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
list.add(new JavaClass(decompiler, inner)); list.add(new JavaClass(decompiler, inner));
} }
}
this.innerClasses = Collections.unmodifiableList(list); this.innerClasses = Collections.unmodifiableList(list);
} }
int fieldsCount = cls.getFields().size(); int fieldsCount = cls.getFields().size();
if (fieldsCount == 0) { if (fieldsCount != 0) {
this.fields = Collections.emptyList();
} else {
List<JavaField> flds = new ArrayList<JavaField>(fieldsCount); List<JavaField> flds = new ArrayList<JavaField>(fieldsCount);
for (FieldNode f : cls.getFields()) { for (FieldNode f : cls.getFields()) {
if (!f.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
flds.add(new JavaField(f)); flds.add(new JavaField(f));
} }
}
this.fields = Collections.unmodifiableList(flds); this.fields = Collections.unmodifiableList(flds);
} }
int methodsCount = cls.getMethods().size(); int methodsCount = cls.getMethods().size();
if (methodsCount == 0) { if (methodsCount != 0) {
this.methods = Collections.emptyList();
} else {
List<JavaMethod> mths = new ArrayList<JavaMethod>(methodsCount); List<JavaMethod> mths = new ArrayList<JavaMethod>(methodsCount);
for (MethodNode m : cls.getMethods()) { for (MethodNode m : cls.getMethods()) {
if (!m.getAccessFlags().isSynthetic()) { if (!m.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
mths.add(new JavaMethod(m)); mths.add(new JavaMethod(this, m));
} }
} }
Collections.sort(mths, new Comparator<JavaMethod>() { Collections.sort(mths, new Comparator<JavaMethod>() {
...@@ -68,7 +72,7 @@ public final class JavaClass { ...@@ -68,7 +72,7 @@ public final class JavaClass {
public String getCode() { public String getCode() {
CodeWriter code = cls.getCode(); CodeWriter code = cls.getCode();
if (code == null) { if (code == null) {
decompiler.processClass(cls); decompile();
code = cls.getCode(); code = cls.getCode();
} }
return code != null ? code.toString() : "error processing class"; return code != null ? code.toString() : "error processing class";
......
package jadx.api; package jadx.api;
import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
...@@ -9,19 +8,19 @@ import java.util.List; ...@@ -9,19 +8,19 @@ import java.util.List;
public final class JavaMethod { public final class JavaMethod {
private final MethodNode mth; private final MethodNode mth;
private final JavaClass parent;
public JavaMethod(MethodNode m) { public JavaMethod(JavaClass cls, MethodNode m) {
this.parent = cls;
this.mth = m; this.mth = m;
} }
public String getName() { public String getName() {
MethodInfo mi = mth.getMethodInfo(); return mth.getMethodInfo().getName();
if (mi.isConstructor()) {
return mth.getParentClass().getShortName();
} else if (mi.isClassInit()) {
return "static";
} }
return mi.getName();
public JavaClass getDeclaringClass() {
return parent;
} }
public AccessInfo getAccessFlags() { public AccessInfo getAccessFlags() {
......
...@@ -216,9 +216,9 @@ public class ClassGen { ...@@ -216,9 +216,9 @@ public class ClassGen {
CodeWriter code = new CodeWriter(clsCode.getIndent() + 1); CodeWriter code = new CodeWriter(clsCode.getIndent() + 1);
for (Iterator<MethodNode> it = mthList.iterator(); it.hasNext(); ) { for (Iterator<MethodNode> it = mthList.iterator(); it.hasNext(); ) {
MethodNode mth = it.next(); MethodNode mth = it.next();
if (mth.getAttributes().contains(AttributeFlag.DONT_GENERATE)) if (mth.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
continue; continue;
}
try { try {
if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) { if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) {
MethodGen mthGen = new MethodGen(this, mth); MethodGen mthGen = new MethodGen(this, mth);
...@@ -232,9 +232,6 @@ public class ClassGen { ...@@ -232,9 +232,6 @@ public class ClassGen {
} }
code.add(';'); code.add(';');
} else { } else {
if (mth.isNoCode())
continue;
MethodGen mthGen = new MethodGen(this, mth); MethodGen mthGen = new MethodGen(this, mth);
if (mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) { if (mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) {
code.startLine("/* JADX WARNING: inconsistent code */"); code.startLine("/* JADX WARNING: inconsistent code */");
...@@ -253,10 +250,10 @@ public class ClassGen { ...@@ -253,10 +250,10 @@ public class ClassGen {
String msg = ErrorsCounter.methodError(mth, "Method generation error", e); String msg = ErrorsCounter.methodError(mth, "Method generation error", e);
code.startLine("/* " + msg + CodeWriter.NL + Utils.getStackTrace(e) + " */"); code.startLine("/* " + msg + CodeWriter.NL + Utils.getStackTrace(e) + " */");
} }
if (it.hasNext()) {
if (it.hasNext())
code.newLine(); code.newLine();
} }
}
return code; return code;
} }
......
...@@ -533,6 +533,7 @@ public class InsnGen { ...@@ -533,6 +533,7 @@ public class InsnGen {
} else { } else {
parent = cls.getSuperClass(); parent = cls.getSuperClass();
} }
cls.getAttributes().add(AttributeFlag.DONT_GENERATE);
MethodNode defCtr = cls.getDefaultConstructor(); MethodNode defCtr = cls.getDefaultConstructor();
if (RegionUtils.notEmpty(defCtr.getRegion())) { if (RegionUtils.notEmpty(defCtr.getRegion())) {
defCtr.getAttributes().add(AttributeFlag.ANONYMOUS_CONSTRUCTOR); defCtr.getAttributes().add(AttributeFlag.ANONYMOUS_CONSTRUCTOR);
......
...@@ -124,14 +124,13 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -124,14 +124,13 @@ public class MethodNode extends LineAttrNode implements ILoadable {
@Override @Override
public void unload() { public void unload() {
if (noCode) if (noCode) {
return; return;
}
if (instructions != null) instructions.clear(); if (instructions != null) instructions.clear();
blocks = null; blocks = null;
exitBlocks = null; exitBlocks = null;
if (exceptionHandlers != null) exceptionHandlers.clear(); if (exceptionHandlers != null) exceptionHandlers.clear();
getAttributes().clear();
noCode = true; noCode = true;
} }
......
...@@ -26,14 +26,18 @@ import javax.swing.JToolBar; ...@@ -26,14 +26,18 @@ import javax.swing.JToolBar;
import javax.swing.JTree; import javax.swing.JTree;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
import javax.swing.ProgressMonitor; import javax.swing.ProgressMonitor;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.plaf.basic.BasicButtonUI; import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.text.BadLocationException; import javax.swing.text.BadLocationException;
import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel; import javax.swing.tree.TreeSelectionModel;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
...@@ -192,6 +196,7 @@ public class MainWindow extends JFrame { ...@@ -192,6 +196,7 @@ public class MainWindow extends JFrame {
} }
private void showCode(JClass cls, int line) { private void showCode(JClass cls, int line) {
cls.load();
JPanel panel = (JPanel) openTabs.get(cls); JPanel panel = (JPanel) openTabs.get(cls);
if (panel != null) { if (panel != null) {
panel = (JPanel) openTabs.get(cls); panel = (JPanel) openTabs.get(cls);
...@@ -379,6 +384,22 @@ public class MainWindow extends JFrame { ...@@ -379,6 +384,22 @@ public class MainWindow extends JFrame {
return c; 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); JScrollPane treeScrollPane = new JScrollPane(tree);
splitPane.setLeftComponent(treeScrollPane); splitPane.setLeftComponent(treeScrollPane);
......
...@@ -4,6 +4,7 @@ import jadx.api.JavaClass; ...@@ -4,6 +4,7 @@ import jadx.api.JavaClass;
import jadx.api.JavaField; import jadx.api.JavaField;
import jadx.api.JavaMethod; import jadx.api.JavaMethod;
import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo;
import jadx.gui.utils.NLS;
import jadx.gui.utils.Utils; import jadx.gui.utils.Utils;
import javax.swing.Icon; import javax.swing.Icon;
...@@ -22,6 +23,7 @@ public class JClass extends JNode { ...@@ -22,6 +23,7 @@ public class JClass extends JNode {
private final JavaClass cls; private final JavaClass cls;
private JClass jParrent; private JClass jParrent;
private boolean loaded;
public JClass(JavaClass cls) { public JClass(JavaClass cls) {
this.cls = cls; this.cls = cls;
...@@ -31,9 +33,20 @@ public class JClass extends JNode { ...@@ -31,9 +33,20 @@ public class JClass extends JNode {
return cls; return cls;
} }
public synchronized void load() {
if (!loaded) {
cls.decompile();
loaded = true;
updateChilds();
}
}
@Override @Override
public void updateChilds() { public void updateChilds() {
removeAllChildren(); removeAllChildren();
if (!loaded) {
add(new TextNode(NLS.str("tree.loading")));
} else {
JClass currentParent = jParrent == null ? this : jParrent; JClass currentParent = jParrent == null ? this : jParrent;
for (JavaClass javaClass : cls.getInnerClasses()) { for (JavaClass javaClass : cls.getInnerClasses()) {
JClass child = new JClass(javaClass); JClass child = new JClass(javaClass);
...@@ -48,6 +61,7 @@ public class JClass extends JNode { ...@@ -48,6 +61,7 @@ public class JClass extends JNode {
add(new JMethod(m, currentParent)); add(new JMethod(m, currentParent));
} }
} }
}
public String getCode() { public String getCode() {
return cls.getCode(); return cls.getCode();
......
...@@ -47,8 +47,12 @@ public class JMethod extends JNode { ...@@ -47,8 +47,12 @@ public class JMethod extends JNode {
public Icon getIcon() { public Icon getIcon() {
AccessInfo accessFlags = mth.getAccessFlags(); AccessInfo accessFlags = mth.getAccessFlags();
OverlayIcon icon = Utils.makeIcon(accessFlags, ICON_MTH_PUB, ICON_MTH_PRI, ICON_MTH_PRO, ICON_MTH_DEF); 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.isConstructor()) {
if (accessFlags.isSynchronized()) icon.add(ICON_SYNC); icon.add(ICON_CONSTRUCTOR);
}
if (accessFlags.isSynchronized()) {
icon.add(ICON_SYNC);
}
return icon; return icon;
} }
...@@ -57,15 +61,19 @@ public class JMethod extends JNode { ...@@ -57,15 +61,19 @@ public class JMethod extends JNode {
if (mth.isClassInit()) { if (mth.isClassInit()) {
return "{...}"; return "{...}";
} }
StringBuilder base = new StringBuilder(); StringBuilder base = new StringBuilder();
if (mth.isConstructor()) {
base.append(mth.getDeclaringClass().getShortName());
} else {
base.append(mth.getName()); base.append(mth.getName());
}
base.append('('); base.append('(');
for (Iterator<ArgType> it = mth.getArguments().iterator(); it.hasNext(); ) { for (Iterator<ArgType> it = mth.getArguments().iterator(); it.hasNext(); ) {
base.append(Utils.typeStr(it.next())); base.append(Utils.typeStr(it.next()));
if (it.hasNext()) if (it.hasNext()) {
base.append(", "); base.append(", ");
} }
}
base.append(')'); base.append(')');
return Utils.typeFormat(base.toString(), mth.getReturnType()); return Utils.typeFormat(base.toString(), mth.getReturnType());
} }
......
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;
}
}
...@@ -6,6 +6,7 @@ file.select=Select ...@@ -6,6 +6,7 @@ file.select=Select
file.exit=Exit file.exit=Exit
tree.flatten=Flatten packages tree.flatten=Flatten packages
tree.loading=Loading...
search=Search search=Search
search.previous=Previous search.previous=Previous
......
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