diff --git a/jadx-core/src/main/java/jadx/core/Consts.java b/jadx-core/src/main/java/jadx/core/Consts.java index e8dd88093..c1afd7337 100644 --- a/jadx-core/src/main/java/jadx/core/Consts.java +++ b/jadx-core/src/main/java/jadx/core/Consts.java @@ -21,4 +21,6 @@ public class Consts { public static final String DEFAULT_PACKAGE_NAME = "defpackage"; public static final String ANONYMOUS_CLASS_PREFIX = "AnonymousClass_"; + + public static final String MTH_TOSTRING_SIGNATURE = "toString()Ljava/lang/String;"; } diff --git a/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java b/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java index 5fc4d0d75..22065c41d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java +++ b/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java @@ -31,14 +31,16 @@ public final class MethodInfo { retType = dex.getType(proto.getReturnTypeIndex()); args = dex.readParamList(proto.getParametersOffset()); - StringBuilder strArg = new StringBuilder(); - strArg.append('('); - for (ArgType arg : args) - strArg.append(TypeGen.signature(arg)); - strArg.append(')'); - // strArg.append(TypeGen.signature(retType)); + StringBuilder signature = new StringBuilder(); + signature.append(name); + signature.append('('); + for (ArgType arg : args) { + signature.append(TypeGen.signature(arg)); + } + signature.append(')'); + signature.append(TypeGen.signature(retType)); - shortId = name + strArg; + shortId = signature.toString(); } public String getName() { @@ -108,8 +110,8 @@ public final class MethodInfo { @Override public String toString() { - return retType + " " + declClass.getFullName() + "." + name - + "(" + Utils.listToString(args) + ")"; + return declClass.getFullName() + "." + name + + "(" + Utils.listToString(args) + "):" + retType; } } 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 9443e861d..c5f020f5c 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 @@ -516,8 +516,8 @@ public class MethodNode extends LineAttrNode implements ILoadable { @Override public String toString() { - return retType - + " " + parentClass.getFullName() + "." + mthInfo.getName() - + "(" + Utils.listToString(mthInfo.getArgumentsTypes()) + ")"; + return parentClass.getFullName() + "." + mthInfo.getName() + + "(" + Utils.listToString(mthInfo.getArgumentsTypes()) + "):" + + retType; } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java index 6f36e3a80..bda56f144 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java @@ -1,5 +1,6 @@ package jadx.core.dex.visitors; +import jadx.core.codegen.TypeGen; import jadx.core.dex.attributes.AttributeFlag; import jadx.core.dex.attributes.EnumClassAttr; import jadx.core.dex.attributes.EnumClassAttr.EnumField; @@ -8,6 +9,7 @@ import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.MethodInfo; import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; +import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.mods.ConstructorInsn; @@ -30,8 +32,9 @@ public class EnumVisitor extends AbstractVisitor { @Override public boolean visit(ClassNode cls) throws JadxException { - if (!cls.isEnum()) + if (!cls.isEnum()) { return true; + } // collect enum fields, remove synthetic List enumFields = new ArrayList(); @@ -47,19 +50,29 @@ public class EnumVisitor extends AbstractVisitor { MethodNode staticMethod = null; + ArgType clsType = cls.getClassInfo().getType(); + String enumConstructor = "(Ljava/lang/String;I)V"; + String valuesOfMethod = "valueOf(Ljava/lang/String;)" + TypeGen.signature(clsType); + String valuesMethod = "values()" + TypeGen.signature(ArgType.array(clsType)); + // remove synthetic methods for (Iterator it = cls.getMethods().iterator(); it.hasNext(); ) { MethodNode mth = it.next(); MethodInfo mi = mth.getMethodInfo(); if (mi.isClassInit()) { staticMethod = mth; - } else if (mi.isConstructor() && !mth.getAccessFlags().isSynthetic()) { - if (mi.getShortId().equals("(Ljava/lang/String;I)")) + } else { + String shortId = mi.getShortId(); + boolean isSynthetic = mth.getAccessFlags().isSynthetic(); + if (mi.isConstructor() && !isSynthetic) { + if (shortId.equals(enumConstructor)) { + it.remove(); + } + } else if (isSynthetic + || shortId.equals(valuesMethod) + || shortId.equals(valuesOfMethod)) { it.remove(); - } else if (mth.getAccessFlags().isSynthetic() - || mi.getShortId().equals("values()") - || mi.getShortId().equals("valueOf(Ljava/lang/String;)")) { - it.remove(); + } } } @@ -89,10 +102,11 @@ public class EnumVisitor extends AbstractVisitor { IndexInsnNode fp = (IndexInsnNode) insn; FieldInfo f = (FieldInfo) fp.getIndex(); if (f.getName().equals("$VALUES")) { - if (i == size - 1) + if (i == size - 1) { cls.getMethods().remove(staticMethod); - else + } else { list.subList(0, i + 1).clear(); + } break; } } @@ -102,16 +116,19 @@ public class EnumVisitor extends AbstractVisitor { if (insn.getType() == InsnType.CONSTRUCTOR) { ConstructorInsn co = (ConstructorInsn) insn; - if (insn.getArgsCount() < 2) + if (insn.getArgsCount() < 2) { continue; + } ClassInfo clsInfo = co.getClassType(); ClassNode constrCls = cls.dex().resolveClass(clsInfo); - if (constrCls == null) + if (constrCls == null) { continue; + } - if (!clsInfo.equals(cls.getClassInfo()) && !constrCls.getAccessFlags().isEnum()) + if (!clsInfo.equals(cls.getClassInfo()) && !constrCls.getAccessFlags().isEnum()) { continue; + } RegisterArg nameArg = (RegisterArg) insn.getArg(0); // InsnArg pos = insn.getArg(1); @@ -130,8 +147,9 @@ public class EnumVisitor extends AbstractVisitor { constrArg = iArg; } else { constrArg = CodeShrinker.inlineArgument(staticMethod, (RegisterArg) iArg); - if (constrArg == null) + if (constrArg == null) { throw new JadxException("Can't inline constructor arg in enum: " + cls); + } } field.getArgs().add(constrArg); } @@ -143,8 +161,9 @@ public class EnumVisitor extends AbstractVisitor { // remove constructor, because it is anonymous class for (Iterator mit = innerCls.getMethods().iterator(); mit.hasNext(); ) { MethodNode innerMth = (MethodNode) mit.next(); - if (innerMth.getAccessFlags().isConstructor()) + if (innerMth.getAccessFlags().isConstructor()) { mit.remove(); + } } field.setCls(innerCls); innerCls.getAttributes().add(AttributeFlag.DONT_GENERATE); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java index 4c1d664f2..7c9fd3212 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java @@ -109,7 +109,7 @@ public class SimplifyVisitor extends AbstractVisitor { case INVOKE: MethodInfo callMth = ((InvokeNode) insn).getCallMth(); if (callMth.getDeclClass().getFullName().equals(Consts.CLASS_STRING_BUILDER) - && callMth.getShortId().equals("toString()") + && callMth.getShortId().equals(Consts.MTH_TOSTRING_SIGNATURE) && insn.getArg(0).isInsnWrap()) { try { List chain = flattenInsnChain(insn);