fix: improve generated code on errors
This commit is contained in:
@@ -370,7 +370,7 @@ public class ClassGen {
|
||||
if (fv != null) {
|
||||
code.add(" = ");
|
||||
if (fv.getValue() == null) {
|
||||
code.add(TypeGen.literalToString(0, f.getType(), cls));
|
||||
code.add(TypeGen.literalToString(0, f.getType(), cls, fallback));
|
||||
} else {
|
||||
if (fv.getValueType() == InitType.CONST) {
|
||||
annotationGen.encodeValue(code, fv.getValue());
|
||||
|
||||
@@ -138,7 +138,7 @@ public class InsnGen {
|
||||
}
|
||||
|
||||
private String lit(LiteralArg arg) {
|
||||
return TypeGen.literalToString(arg.getLiteral(), arg.getType(), mth);
|
||||
return TypeGen.literalToString(arg.getLiteral(), arg.getType(), mth, fallback);
|
||||
}
|
||||
|
||||
private void instanceField(CodeWriter code, FieldInfo field, InsnArg arg) throws CodegenException {
|
||||
|
||||
@@ -148,7 +148,13 @@ public class MethodGen {
|
||||
if (var.isFinal()) {
|
||||
code.add("final ");
|
||||
}
|
||||
ArgType argType = var.getType();
|
||||
ArgType argType;
|
||||
if (var.getType() == ArgType.UNKNOWN) {
|
||||
// occur on decompilation errors
|
||||
argType = mthArg.getInitType();
|
||||
} else {
|
||||
argType = var.getType();
|
||||
}
|
||||
if (!it.hasNext() && mth.getAccessFlags().isVarArgs()) {
|
||||
// change last array argument to varargs
|
||||
if (argType.isArray()) {
|
||||
|
||||
@@ -266,7 +266,7 @@ public class RegionGen extends InsnGen {
|
||||
}
|
||||
}
|
||||
} else if (k instanceof Integer) {
|
||||
code.add(TypeGen.literalToString((Integer) k, arg.getType(), mth));
|
||||
code.add(TypeGen.literalToString((Integer) k, arg.getType(), mth, fallback));
|
||||
} else {
|
||||
throw new JadxRuntimeException("Unexpected key in switch: " + (k != null ? k.getClass() : null));
|
||||
}
|
||||
|
||||
@@ -33,14 +33,14 @@ public class TypeGen {
|
||||
*
|
||||
* @throws JadxRuntimeException for incorrect type or literal value
|
||||
*/
|
||||
public static String literalToString(long lit, ArgType type, IDexNode dexNode) {
|
||||
return literalToString(lit, type, dexNode.root().getStringUtils());
|
||||
public static String literalToString(long lit, ArgType type, IDexNode dexNode, boolean fallback) {
|
||||
return literalToString(lit, type, dexNode.root().getStringUtils(), fallback);
|
||||
}
|
||||
|
||||
public static String literalToString(long lit, ArgType type, StringUtils stringUtils) {
|
||||
public static String literalToString(long lit, ArgType type, StringUtils stringUtils, boolean fallback) {
|
||||
if (type == null || !type.isTypeKnown()) {
|
||||
String n = Long.toString(lit);
|
||||
if (Math.abs(lit) > 100) {
|
||||
if (fallback && Math.abs(lit) > 100) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(n).append("(0x").append(Long.toHexString(lit));
|
||||
if (type == null || type.contains(PrimitiveType.FLOAT)) {
|
||||
|
||||
@@ -70,7 +70,7 @@ public final class LiteralArg extends InsnArg {
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
String value = TypeGen.literalToString(literal, getType(), DEF_STRING_UTILS);
|
||||
String value = TypeGen.literalToString(literal, getType(), DEF_STRING_UTILS, true);
|
||||
if (getType().equals(ArgType.BOOLEAN) && (value.equals("true") || value.equals("false"))) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -5,11 +5,15 @@ import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.android.dx.rop.code.AccessFlags;
|
||||
|
||||
import jadx.core.codegen.TypeGen;
|
||||
import jadx.core.deobf.NameMapper;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.EnumClassAttr;
|
||||
import jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField;
|
||||
import jadx.core.dex.info.AccessInfo;
|
||||
import jadx.core.dex.info.ClassInfo;
|
||||
import jadx.core.dex.info.FieldInfo;
|
||||
import jadx.core.dex.info.MethodInfo;
|
||||
@@ -41,6 +45,11 @@ public class EnumVisitor extends AbstractVisitor {
|
||||
@Override
|
||||
public boolean visit(ClassNode cls) throws JadxException {
|
||||
if (!cls.isEnum()) {
|
||||
AccessInfo accessFlags = cls.getAccessFlags();
|
||||
if (accessFlags.isEnum()) {
|
||||
cls.setAccessFlags(accessFlags.remove(AccessFlags.ACC_ENUM));
|
||||
cls.addAttr(AType.COMMENTS, "'enum' access flag removed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// search class init method
|
||||
|
||||
@@ -28,7 +28,7 @@ public class FixAccessModifiers extends AbstractVisitor {
|
||||
return;
|
||||
}
|
||||
int newVisFlag = fixVisibility(mth);
|
||||
if (newVisFlag != 0) {
|
||||
if (newVisFlag != -1) {
|
||||
changeVisibility(mth, newVisFlag);
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public class FixAccessModifiers extends AbstractVisitor {
|
||||
AccessInfo newAccFlags = accessFlags.changeVisibility(newVisFlag);
|
||||
if (newAccFlags != accessFlags) {
|
||||
node.setAccessFlags(newAccFlags);
|
||||
node.addAttr(AType.COMMENTS, "access modifiers changed from: " + accessFlags.rawString());
|
||||
node.addAttr(AType.COMMENTS, "access modifiers changed from: " + accessFlags.getVisibility().rawString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +52,15 @@ public class FixAccessModifiers extends AbstractVisitor {
|
||||
// make abstract methods public
|
||||
return AccessFlags.ACC_PUBLIC;
|
||||
}
|
||||
// enum constructor can't be public
|
||||
if (accessFlags.isConstructor()
|
||||
&& accessFlags.isPublic()
|
||||
&& mth.getParentClass().isEnum()) {
|
||||
return 0;
|
||||
}
|
||||
if (accessFlags.isConstructor() || accessFlags.isStatic()) {
|
||||
// TODO: make public if used outside
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
// make other direct methods private
|
||||
return AccessFlags.ACC_PRIVATE;
|
||||
|
||||
@@ -103,7 +103,9 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor
|
||||
}
|
||||
RegisterArg initArg = phiInsn.getArg(0);
|
||||
InsnNode initInsn = initArg.getAssignInsn();
|
||||
if (initInsn == null || initArg.getSVar().getUseCount() != 1) {
|
||||
if (initInsn == null
|
||||
|| initInsn.contains(AFlag.DONT_GENERATE)
|
||||
|| initArg.getSVar().getUseCount() != 1) {
|
||||
return false;
|
||||
}
|
||||
if (!usedOnlyInLoop(mth, loopRegion, arg)) {
|
||||
|
||||
@@ -44,6 +44,6 @@ public class TestEnums3 extends IntegrationTest {
|
||||
assertThat(code, containsOne("ONE(1)"));
|
||||
// assertThat(code, containsOne("THREE(three)"));
|
||||
// assertThat(code, containsOne("assertTrue(Numbers.ONE.getNum() == 1);"));
|
||||
assertThat(code, containsOne("private Numbers(int n) {"));
|
||||
assertThat(code, containsOne("Numbers(int n) {"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user