gui: remove not generated elements from class node tree
This commit is contained in:
@@ -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<JavaClass> innerClasses;
|
||||
private final List<JavaField> fields;
|
||||
private final List<JavaMethod> methods;
|
||||
|
||||
private List<JavaClass> innerClasses = Collections.emptyList();
|
||||
private List<JavaField> fields = Collections.emptyList();
|
||||
private List<JavaMethod> 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<JavaClass> list = new ArrayList<JavaClass>(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<JavaField> flds = new ArrayList<JavaField>(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<JavaMethod> mths = new ArrayList<JavaMethod>(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<JavaMethod>() {
|
||||
@@ -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";
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -216,9 +216,9 @@ public class ClassGen {
|
||||
CodeWriter code = new CodeWriter(clsCode.getIndent() + 1);
|
||||
for (Iterator<MethodNode> 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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ArgType> 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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ file.select=Select
|
||||
file.exit=Exit
|
||||
|
||||
tree.flatten=Flatten packages
|
||||
tree.loading=Loading...
|
||||
|
||||
search=Search
|
||||
search.previous=Previous
|
||||
|
||||
Reference in New Issue
Block a user