gui: add type and access info to classes tree
This commit is contained in:
@@ -12,7 +12,6 @@ public class JadxCLI {
|
||||
JadxArgs jadxArgs = new JadxArgs(args, true);
|
||||
Decompiler jadx = new Decompiler(jadxArgs);
|
||||
jadx.processAndSaveAll();
|
||||
LOG.info("done");
|
||||
System.exit(jadx.getErrorsCount());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public final class Decompiler {
|
||||
return Collections.unmodifiableList(packages);
|
||||
}
|
||||
|
||||
public ThreadPoolExecutor saveAll(File dir) throws InterruptedException {
|
||||
public ThreadPoolExecutor saveAll(File dir) {
|
||||
int threadsCount = args.getThreadsCount();
|
||||
LOG.debug("processing threads count: {}", threadsCount);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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;
|
||||
@@ -51,7 +50,7 @@ public final class JavaClass {
|
||||
} else {
|
||||
List<JavaMethod> mths = new ArrayList<JavaMethod>(methodsCount);
|
||||
for (MethodNode m : cls.getMethods()) {
|
||||
if (!m.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
|
||||
if (!m.getAccessFlags().isSynthetic()) {
|
||||
mths.add(new JavaMethod(m));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package jadx.api;
|
||||
|
||||
import jadx.core.dex.info.AccessInfo;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.nodes.FieldNode;
|
||||
|
||||
public class JavaField {
|
||||
@@ -19,6 +20,10 @@ public class JavaField {
|
||||
return field.getAccessFlags();
|
||||
}
|
||||
|
||||
public ArgType getType() {
|
||||
return field.getType();
|
||||
}
|
||||
|
||||
public int getDecompiledLine() {
|
||||
return field.getDecompiledLine();
|
||||
}
|
||||
|
||||
@@ -2,8 +2,11 @@ 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class JavaMethod {
|
||||
private final MethodNode mth;
|
||||
|
||||
@@ -25,6 +28,22 @@ public class JavaMethod {
|
||||
return mth.getAccessFlags();
|
||||
}
|
||||
|
||||
public List<ArgType> getArguments() {
|
||||
return mth.getMethodInfo().getArgumentsTypes();
|
||||
}
|
||||
|
||||
public ArgType getReturnType() {
|
||||
return mth.getReturnType();
|
||||
}
|
||||
|
||||
public boolean isConstructor() {
|
||||
return mth.getMethodInfo().isConstructor();
|
||||
}
|
||||
|
||||
public boolean isClassInit() {
|
||||
return mth.getMethodInfo().isClassInit();
|
||||
}
|
||||
|
||||
public int getDecompiledLine() {
|
||||
return mth.getDecompiledLine();
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ public class InsnGen {
|
||||
private void makeInvoke(InvokeNode insn, CodeWriter code) throws CodegenException {
|
||||
MethodInfo callMth = insn.getCallMth();
|
||||
|
||||
// inline method if METHOD_INLINE attribute is attached
|
||||
// inline method
|
||||
MethodNode callMthNode = mth.dex().resolveMethod(callMth);
|
||||
if (callMthNode != null
|
||||
&& callMthNode.getAttributes().contains(AttributeType.METHOD_INLINE)) {
|
||||
@@ -507,8 +507,10 @@ public class InsnGen {
|
||||
|
||||
case STATIC:
|
||||
ClassInfo insnCls = mth.getParentClass().getClassInfo();
|
||||
if (!insnCls.equals(callMth.getDeclClass()))
|
||||
code.add(useClass(callMth.getDeclClass())).add('.');
|
||||
ClassInfo declClass = callMth.getDeclClass();
|
||||
if (!insnCls.equals(declClass)) {
|
||||
code.add(useClass(declClass)).add('.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
code.add(callMth.getName());
|
||||
|
||||
@@ -93,6 +93,18 @@ public class AccessInfo {
|
||||
return (accFlags & AccessFlags.ACC_VARARGS) != 0;
|
||||
}
|
||||
|
||||
public boolean isSynchronized() {
|
||||
return (accFlags & (AccessFlags.ACC_SYNCHRONIZED | AccessFlags.ACC_DECLARED_SYNCHRONIZED)) != 0;
|
||||
}
|
||||
|
||||
public boolean isTransient() {
|
||||
return (accFlags & AccessFlags.ACC_TRANSIENT) != 0;
|
||||
}
|
||||
|
||||
public boolean isVolatile() {
|
||||
return (accFlags & AccessFlags.ACC_VOLATILE) != 0;
|
||||
}
|
||||
|
||||
public int getFlags() {
|
||||
return accFlags;
|
||||
}
|
||||
@@ -126,10 +138,7 @@ public class AccessInfo {
|
||||
|
||||
switch (type) {
|
||||
case METHOD:
|
||||
if ((accFlags & AccessFlags.ACC_SYNCHRONIZED) != 0)
|
||||
code.append("synchronized ");
|
||||
|
||||
if ((accFlags & AccessFlags.ACC_DECLARED_SYNCHRONIZED) != 0)
|
||||
if (isSynchronized())
|
||||
code.append("synchronized ");
|
||||
|
||||
if (isBridge())
|
||||
@@ -142,10 +151,10 @@ public class AccessInfo {
|
||||
break;
|
||||
|
||||
case FIELD:
|
||||
if ((accFlags & AccessFlags.ACC_VOLATILE) != 0)
|
||||
if (isVolatile())
|
||||
code.append("volatile ");
|
||||
|
||||
if ((accFlags & AccessFlags.ACC_TRANSIENT) != 0)
|
||||
if (isTransient())
|
||||
code.append("transient ");
|
||||
break;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package jadx.core.dex.visitors;
|
||||
|
||||
import jadx.core.dex.attributes.AttributeFlag;
|
||||
import jadx.core.dex.attributes.IAttribute;
|
||||
import jadx.core.dex.attributes.AttributesList;
|
||||
import jadx.core.dex.attributes.MethodInlineAttr;
|
||||
import jadx.core.dex.info.AccessInfo;
|
||||
import jadx.core.dex.instructions.InsnType;
|
||||
@@ -43,8 +43,8 @@ public class MethodInlinerVisitor extends AbstractVisitor {
|
||||
}
|
||||
|
||||
private static void addInlineAttr(MethodNode mth, InsnNode insn) {
|
||||
IAttribute attr = new MethodInlineAttr(insn);
|
||||
mth.getAttributes().add(attr);
|
||||
mth.getAttributes().add(AttributeFlag.DONT_GENERATE);
|
||||
AttributesList attributes = mth.getAttributes();
|
||||
attributes.add(new MethodInlineAttr(insn));
|
||||
attributes.add(AttributeFlag.DONT_GENERATE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import jadx.core.utils.exceptions.CodegenException;
|
||||
import java.io.File;
|
||||
|
||||
public class SaveCode extends AbstractVisitor {
|
||||
|
||||
private final File dir;
|
||||
private final IJadxArgs args;
|
||||
|
||||
@@ -22,13 +21,10 @@ public class SaveCode extends AbstractVisitor {
|
||||
CodeWriter clsCode = cls.getCode();
|
||||
|
||||
String fileName = cls.getClassInfo().getFullPath() + ".java";
|
||||
if (isFallbackMode())
|
||||
if (args.isFallbackMode()) {
|
||||
fileName += ".jadx";
|
||||
}
|
||||
clsCode.save(dir, fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFallbackMode() {
|
||||
return args.isFallbackMode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ public class JClass extends DefaultMutableTreeNode implements JNode {
|
||||
|
||||
@Override
|
||||
public void updateChilds() {
|
||||
removeAllChildren();
|
||||
JClass currentParent = jParrent == null ? this : jParrent;
|
||||
for (JavaClass javaClass : cls.getInnerClasses()) {
|
||||
JClass child = new JClass(javaClass);
|
||||
|
||||
@@ -2,18 +2,22 @@ package jadx.gui.treemodel;
|
||||
|
||||
import jadx.api.JavaField;
|
||||
import jadx.core.dex.info.AccessInfo;
|
||||
import jadx.gui.utils.OverlayIcon;
|
||||
import jadx.gui.utils.Utils;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
public class JField extends DefaultMutableTreeNode implements JNode {
|
||||
public class JField extends DefaultMutableTreeNode implements JNode {
|
||||
private static final ImageIcon ICON_FLD_DEF = Utils.openIcon("field_default_obj");
|
||||
private static final ImageIcon ICON_FLD_PRI = Utils.openIcon("field_private_obj");
|
||||
private static final ImageIcon ICON_FLD_PRO = Utils.openIcon("field_protected_obj");
|
||||
private static final ImageIcon ICON_FLD_PUB = Utils.openIcon("field_public_obj");
|
||||
|
||||
private static final ImageIcon ICON_TRANSIENT = Utils.openIcon("transient_co");
|
||||
private static final ImageIcon ICON_VOLATILE = Utils.openIcon("volatile_co");
|
||||
|
||||
private final JavaField field;
|
||||
private final JClass jParent;
|
||||
|
||||
@@ -39,19 +43,14 @@ public class JField extends DefaultMutableTreeNode implements JNode {
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
AccessInfo af = field.getAccessFlags();
|
||||
if(af.isPublic()){
|
||||
return ICON_FLD_PUB;
|
||||
} else if(af.isPrivate()) {
|
||||
return ICON_FLD_PRI;
|
||||
} else if(af.isProtected()) {
|
||||
return ICON_FLD_PRO;
|
||||
} else {
|
||||
return ICON_FLD_DEF;
|
||||
}
|
||||
OverlayIcon icon = Utils.makeIcon(af, ICON_FLD_PUB, ICON_FLD_PRI, ICON_FLD_PRO, ICON_FLD_DEF);
|
||||
if (af.isTransient()) icon.add(ICON_TRANSIENT);
|
||||
if (af.isVolatile()) icon.add(ICON_VOLATILE);
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return field.getName();
|
||||
return Utils.typeFormat(field.getName(), field.getType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,14 @@ package jadx.gui.treemodel;
|
||||
|
||||
import jadx.api.JavaMethod;
|
||||
import jadx.core.dex.info.AccessInfo;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.gui.utils.OverlayIcon;
|
||||
import jadx.gui.utils.Utils;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class JMethod extends DefaultMutableTreeNode implements JNode {
|
||||
private static final ImageIcon ICON_MTH_DEF = Utils.openIcon("methdef_obj");
|
||||
@@ -14,6 +17,9 @@ public class JMethod extends DefaultMutableTreeNode implements JNode {
|
||||
private static final ImageIcon ICON_MTH_PRO = Utils.openIcon("methpro_obj");
|
||||
private static final ImageIcon ICON_MTH_PUB = Utils.openIcon("methpub_obj");
|
||||
|
||||
private static final ImageIcon ICON_CONSTRUCTOR = Utils.openIcon("constr_ovr");
|
||||
private static final ImageIcon ICON_SYNC = Utils.openIcon("synch_co");
|
||||
|
||||
private final JavaMethod mth;
|
||||
private final JClass jparent;
|
||||
|
||||
@@ -38,20 +44,28 @@ public class JMethod extends DefaultMutableTreeNode implements JNode {
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
AccessInfo af = mth.getAccessFlags();
|
||||
if (af.isPublic()) {
|
||||
return ICON_MTH_PUB;
|
||||
} else if (af.isPrivate()) {
|
||||
return ICON_MTH_PRI;
|
||||
} else if (af.isProtected()) {
|
||||
return ICON_MTH_PRO;
|
||||
} else {
|
||||
return ICON_MTH_DEF;
|
||||
}
|
||||
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);
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mth.getName();
|
||||
if (mth.isClassInit()) {
|
||||
return "{...}";
|
||||
}
|
||||
|
||||
StringBuilder base = new StringBuilder();
|
||||
base.append(mth.getName());
|
||||
base.append('(');
|
||||
for (Iterator<ArgType> it = mth.getArguments().iterator(); it.hasNext(); ) {
|
||||
base.append(Utils.typeStr(it.next()));
|
||||
if(it.hasNext())
|
||||
base.append(", ");
|
||||
}
|
||||
base.append(')');
|
||||
return Utils.typeFormat(base.toString(), mth.getReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package jadx.gui.utils;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class OverlayIcon implements Icon {
|
||||
|
||||
private final Icon icon;
|
||||
private final List<Icon> icons = new ArrayList<Icon>(4);
|
||||
|
||||
private static final double A = 0.8;
|
||||
private static final double B = 0.2;
|
||||
private static final double[] pos = new double[]{A, B, B, B, A, A, B, A};
|
||||
|
||||
public OverlayIcon(Icon icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight() {
|
||||
return icon.getIconHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
return icon.getIconWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
int w = getIconWidth();
|
||||
int h = getIconHeight();
|
||||
|
||||
icon.paintIcon(c, g, x, y);
|
||||
int k = 0;
|
||||
for (Icon icon : icons) {
|
||||
int dx = (int) (pos[k++] * (w - icon.getIconWidth()));
|
||||
int dy = (int) (pos[k++] * (h - icon.getIconHeight()));
|
||||
icon.paintIcon(c, g, x + dx, y + dy);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(Icon icon) {
|
||||
icons.add(icon);
|
||||
}
|
||||
|
||||
public void addAll(Collection<Icon> icons) {
|
||||
icons.addAll(icons);
|
||||
}
|
||||
|
||||
public List<Icon> getIcons() {
|
||||
return icons;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package jadx.gui.utils;
|
||||
|
||||
import jadx.core.dex.info.AccessInfo;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.KeyStroke;
|
||||
@@ -10,6 +13,11 @@ import java.net.URL;
|
||||
|
||||
public class Utils {
|
||||
|
||||
private static final ImageIcon ICON_STATIC = Utils.openIcon("static_co");
|
||||
private static final ImageIcon ICON_FINAL = Utils.openIcon("final_co");
|
||||
private static final ImageIcon ICON_ABSTRACT = Utils.openIcon("abstract_co");
|
||||
private static final ImageIcon ICON_NATIVE = Utils.openIcon("native_co");
|
||||
|
||||
public static ImageIcon openIcon(String name) {
|
||||
String iconPath = "/icons-16/" + name + ".png";
|
||||
URL resource = Utils.class.getResource(iconPath);
|
||||
@@ -23,4 +31,43 @@ public class Utils {
|
||||
comp.getInputMap().put(key, id);
|
||||
comp.getActionMap().put(id, action);
|
||||
}
|
||||
|
||||
public static String typeFormat(String name, ArgType type) {
|
||||
return "<html>" + name + "<span style='color:#888888;'> : " + typeStr(type) + "</span></html>";
|
||||
}
|
||||
|
||||
public static String typeStr(ArgType type) {
|
||||
if (type.isObject()) {
|
||||
String cls = type.getObject();
|
||||
int dot = cls.lastIndexOf('.');
|
||||
if (dot != -1) {
|
||||
return cls.substring(dot + 1);
|
||||
} else {
|
||||
return cls;
|
||||
}
|
||||
}
|
||||
if (type.isArray()) {
|
||||
return typeStr(type.getArrayElement()) + "[]";
|
||||
}
|
||||
return type.toString();
|
||||
}
|
||||
|
||||
public static OverlayIcon makeIcon(AccessInfo af, Icon pub, Icon pri, Icon pro, Icon def) {
|
||||
Icon icon;
|
||||
if (af.isPublic()) {
|
||||
icon = pub;
|
||||
} else if (af.isPrivate()) {
|
||||
icon = pri;
|
||||
} else if (af.isProtected()) {
|
||||
icon = pro;
|
||||
} else {
|
||||
icon = def;
|
||||
}
|
||||
OverlayIcon overIcon = new OverlayIcon(icon);
|
||||
if (af.isFinal()) overIcon.add(ICON_FINAL);
|
||||
if (af.isStatic()) overIcon.add(ICON_STATIC);
|
||||
if (af.isAbstract()) overIcon.add(ICON_ABSTRACT);
|
||||
if (af.isNative()) overIcon.add(ICON_NATIVE);
|
||||
return overIcon;
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 760 B |
Binary file not shown.
|
Before Width: | Height: | Size: 180 B |
Reference in New Issue
Block a user