提交 890c0a99 编写于 作者: S Skylot

refactor: remove deprecated methods

上级 b73cb406
......@@ -151,8 +151,7 @@ public class AnnotationGen {
code.add(InsnGen.makeStaticFieldAccess(field, classGen));
} else if (val instanceof List) {
code.add('{');
List list = (List) val;
Iterator it = list.iterator();
Iterator<?> it = ((List) val).iterator();
while (it.hasNext()) {
Object obj = it.next();
encodeValue(code, obj);
......
......@@ -43,6 +43,7 @@ public class ClassGen {
private final boolean fallback;
private final Set<ClassInfo> imports = new HashSet<ClassInfo>();
private int clsDeclLine = 0;
public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean fallback) {
this.cls = cls;
......@@ -95,12 +96,11 @@ public class ClassGen {
if (cls.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) {
code.startLine("// jadx: inconsistent code");
}
makeClassDeclaration(code);
makeClassBody(code);
code.newLine();
addClassDeclaration(code);
addClassBody(code);
}
public void makeClassDeclaration(CodeWriter clsCode) {
public void addClassDeclaration(CodeWriter clsCode) {
AccessInfo af = cls.getAccessFlags();
if (af.isInterface()) {
af = af.remove(AccessFlags.ACC_ABSTRACT);
......@@ -123,7 +123,7 @@ public class ClassGen {
}
clsCode.add(cls.getShortName());
makeGenericMap(clsCode, cls.getGenericMap());
addGenericMap(clsCode, cls.getGenericMap());
clsCode.add(' ');
ClassInfo sup = cls.getSuperClass();
......@@ -150,11 +150,10 @@ public class ClassGen {
clsCode.add(' ');
}
}
clsCode.attachDefinition(cls);
}
public boolean makeGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
public boolean addGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
if (gmap == null || gmap.isEmpty()) {
return false;
}
......@@ -183,91 +182,78 @@ public class ClassGen {
return true;
}
public void makeClassBody(CodeWriter clsCode) throws CodegenException {
public void addClassBody(CodeWriter clsCode) throws CodegenException {
clsCode.add('{');
CodeWriter mthsCode = makeMethods(clsCode, cls.getMethods());
CodeWriter fieldsCode = makeFields(clsCode, cls, cls.getFields());
clsCode.add(fieldsCode);
if (fieldsCode.notEmpty() && mthsCode.notEmpty()) {
clsCode.newLine();
}
// insert inner classes code
if (cls.getInnerClasses().size() != 0) {
clsCode.add(makeInnerClasses(cls, clsCode.getIndent()));
if (mthsCode.notEmpty()) {
clsCode.newLine();
}
}
clsCode.add(mthsCode);
clsDeclLine = clsCode.getLine();
clsCode.incIndent();
addFields(clsCode);
addInnerClasses(clsCode, cls);
addMethods(clsCode);
clsCode.decIndent();
clsCode.startLine('}');
}
private CodeWriter makeInnerClasses(ClassNode cls, int indent) throws CodegenException {
CodeWriter innerClsCode = new CodeWriter(indent + 1);
for (ClassNode inCls : cls.getInnerClasses()) {
if (!inCls.isAnonymous()) {
ClassGen inClGen = new ClassGen(inCls, parentGen == null ? this : parentGen, fallback);
inClGen.addClassCode(innerClsCode);
private void addInnerClasses(CodeWriter code, ClassNode cls) throws CodegenException {
for (ClassNode innerCls : cls.getInnerClasses()) {
if (!innerCls.isAnonymous()) {
ClassGen inClGen = new ClassGen(innerCls, getParentGen(), fallback);
code.newLine();
inClGen.addClassCode(code);
imports.addAll(inClGen.getImports());
}
}
return innerClsCode;
}
private CodeWriter makeMethods(CodeWriter clsCode, List<MethodNode> mthList) {
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)) {
continue;
}
try {
if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) {
MethodGen mthGen = new MethodGen(this, mth);
mthGen.addDefinition(code);
if (cls.getAccessFlags().isAnnotation()) {
Object def = annotationGen.getAnnotationDefaultValue(mth.getName());
if (def != null) {
code.add(" default ");
annotationGen.encodeValue(code, def);
}
}
code.add(';');
} else {
MethodGen mthGen = new MethodGen(this, mth);
boolean badCode = mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE);
if (badCode) {
code.startLine("/* JADX WARNING: inconsistent code. */");
code.startLine("/* Code decompiled incorrectly, please refer to instructions dump. */");
LOG.error(ErrorsCounter.formatErrorMsg(mth, " Inconsistent code"));
}
if (mthGen.addDefinition(code)) {
code.add(' ');
private void addMethods(CodeWriter code) {
for (MethodNode mth : cls.getMethods()) {
if (!mth.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
try {
if (code.getLine() != clsDeclLine) {
code.newLine();
}
code.add('{');
code.incIndent();
insertSourceFileInfo(code, mth);
mthGen.addInstructions(code);
code.decIndent();
code.startLine('}');
addMethod(code, mth);
} catch (Exception e) {
String msg = ErrorsCounter.methodError(mth, "Method generation error", e);
code.startLine("/* " + msg + CodeWriter.NL + Utils.getStackTrace(e) + " */");
}
} catch (Throwable e) {
String msg = ErrorsCounter.methodError(mth, "Method generation error", e);
code.startLine("/* " + msg + CodeWriter.NL + Utils.getStackTrace(e) + " */");
}
if (it.hasNext()) {
code.newLine();
}
}
return code;
}
private CodeWriter makeFields(CodeWriter clsCode, ClassNode cls, List<FieldNode> fields) throws CodegenException {
CodeWriter code = new CodeWriter(clsCode.getIndent() + 1);
addEnumFields(cls, code);
private void addMethod(CodeWriter code, MethodNode mth) throws CodegenException {
MethodGen mthGen = new MethodGen(this, mth);
if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) {
mthGen.addDefinition(code);
if (cls.getAccessFlags().isAnnotation()) {
Object def = annotationGen.getAnnotationDefaultValue(mth.getName());
if (def != null) {
code.add(" default ");
annotationGen.encodeValue(code, def);
}
}
code.add(';');
} else {
boolean badCode = mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE);
if (badCode) {
code.startLine("/* JADX WARNING: inconsistent code. */");
code.startLine("/* Code decompiled incorrectly, please refer to instructions dump. */");
LOG.error(ErrorsCounter.formatErrorMsg(mth, " Inconsistent code"));
}
if (mthGen.addDefinition(code)) {
code.add(' ');
}
code.add('{');
code.incIndent();
insertSourceFileInfo(code, mth);
mthGen.addInstructions(code);
code.decIndent();
code.startLine('}');
}
}
for (FieldNode f : fields) {
private void addFields(CodeWriter code) throws CodegenException {
addEnumFields(code);
for (FieldNode f : cls.getFields()) {
if (f.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
continue;
}
......@@ -288,10 +274,9 @@ public class ClassGen {
code.add(';');
code.attachDefinition(f);
}
return code;
}
private void addEnumFields(ClassNode cls, CodeWriter code) throws CodegenException {
private void addEnumFields(CodeWriter code) throws CodegenException {
EnumClassAttr enumFields = (EnumClassAttr) cls.getAttributes().get(AttributeType.ENUM_CLASS);
if (enumFields != null) {
InsnGen igen = null;
......@@ -305,7 +290,7 @@ public class ClassGen {
if (igen == null) {
// don't init mth gen if this is simple enum
MethodGen mthGen = new MethodGen(this, enumFields.getStaticMethod());
igen = new InsnGen(mthGen, enumFields.getStaticMethod(), false);
igen = new InsnGen(mthGen, false);
}
igen.addArg(code, arg);
if (aIt.hasNext()) {
......@@ -315,7 +300,7 @@ public class ClassGen {
code.add(')');
}
if (f.getCls() != null) {
new ClassGen(f.getCls(), this, fallback).makeClassBody(code);
new ClassGen(f.getCls(), this, fallback).addClassBody(code);
}
if (it.hasNext()) {
code.add(',');
......
......@@ -95,21 +95,15 @@ public class CodeWriter {
return this;
}
@Deprecated
public CodeWriter add(CodeWriter code) {
CodeWriter add(CodeWriter code) {
line--;
for (Map.Entry<CodePosition, Object> entry : code.annotations.entrySet()) {
CodePosition pos = entry.getKey();
attachAnnotation(entry.getValue(), new CodePosition(line + pos.getLine(), pos.getOffset()));
}
line += code.line;
String str = code.toString();
buf.append(str);
if (str.contains(NL)) {
offset = code.offset;
} else {
offset += code.offset;
}
offset = code.offset;
buf.append(code);
return this;
}
......@@ -143,6 +137,10 @@ public class CodeWriter {
}
}
public int getLine() {
return line;
}
public int getIndent() {
return indent;
}
......
......@@ -12,41 +12,52 @@ import jadx.core.dex.regions.Compare;
import jadx.core.dex.regions.IfCondition;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.JadxRuntimeException;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConditionGen {
public class ConditionGen extends InsnGen {
private static final Logger LOG = LoggerFactory.getLogger(ConditionGen.class);
static String make(InsnGen insnGen, IfCondition condition) throws CodegenException {
public ConditionGen(InsnGen insnGen) {
super(insnGen.mgen, insnGen.fallback);
}
void add(CodeWriter code, IfCondition condition) throws CodegenException {
switch (condition.getMode()) {
case COMPARE:
return makeCompare(insnGen, condition.getCompare());
addCompare(code, condition.getCompare());
break;
case NOT:
return "!(" + make(insnGen, condition.getArgs().get(0)) + ")";
addNot(code, condition);
break;
case AND:
case OR:
String mode = condition.getMode() == IfCondition.Mode.AND ? " && " : " || ";
StringBuilder sb = new StringBuilder();
for (IfCondition arg : condition.getArgs()) {
if (sb.length() != 0) {
sb.append(mode);
}
String s = make(insnGen, arg);
if (arg.isCompare()) {
sb.append(s);
} else {
sb.append('(').append(s).append(')');
}
}
return sb.toString();
addAndOr(code, condition);
break;
default:
return "??" + condition;
throw new JadxRuntimeException("Unknown condition mode: " + condition);
}
}
void wrap(CodeWriter code, IfCondition cond) throws CodegenException {
boolean wrap = isWrapNeeded(cond);
if (wrap) {
code.add('(');
}
add(code, cond);
if (wrap) {
code.add(')');
}
}
private static String makeCompare(InsnGen insnGen, Compare compare) throws CodegenException {
private void addCompare(CodeWriter code, Compare compare) throws CodegenException {
IfOp op = compare.getOp();
InsnArg firstArg = compare.getA();
InsnArg secondArg = compare.getB();
......@@ -59,20 +70,47 @@ public class ConditionGen {
}
if (op == IfOp.EQ) {
// == true
return insnGen.arg(firstArg, false).toString();
addArg(code, firstArg, false);
return;
} else if (op == IfOp.NE) {
// != true
if (isWrapNeeded(firstArg)) {
return "!(" + insnGen.arg(firstArg) + ")";
} else {
return "!" + insnGen.arg(firstArg);
code.add('!');
boolean wrap = isWrapNeeded(firstArg);
if (wrap) {
code.add('(');
}
addArg(code, firstArg, false);
if (wrap) {
code.add(')');
}
return;
}
LOG.warn(ErrorsCounter.formatErrorMsg(mth, "Unsupported boolean condition " + op.getSymbol()));
}
addArg(code, firstArg, isWrapNeeded(firstArg));
code.add(' ').add(op.getSymbol()).add(' ');
addArg(code, secondArg, isWrapNeeded(secondArg));
}
private void addNot(CodeWriter code, IfCondition condition) throws CodegenException {
code.add('!');
wrap(code, condition.getArgs().get(0));
}
private void addAndOr(CodeWriter code, IfCondition condition) throws CodegenException {
String mode = condition.getMode() == IfCondition.Mode.AND ? " && " : " || ";
Iterator<IfCondition> it = condition.getArgs().iterator();
while (it.hasNext()) {
wrap(code, it.next());
if (it.hasNext()) {
code.add(mode);
}
LOG.warn(ErrorsCounter.formatErrorMsg(insnGen.mth, "Unsupported boolean condition " + op.getSymbol()));
}
return insnGen.arg(firstArg, isWrapNeeded(firstArg))
+ " " + op.getSymbol() + " "
+ insnGen.arg(secondArg, isWrapNeeded(secondArg));
}
private boolean isWrapNeeded(IfCondition condition) {
return !condition.isCompare();
}
private static boolean isWrapNeeded(InsnArg arg) {
......
......@@ -57,16 +57,16 @@ public class InsnGen {
protected final MethodGen mgen;
protected final MethodNode mth;
protected final RootNode root;
private final boolean fallback;
protected final boolean fallback;
private static enum Flags {
BODY_ONLY,
BODY_ONLY_NOWRAP,
}
public InsnGen(MethodGen mgen, MethodNode mth, boolean fallback) {
public InsnGen(MethodGen mgen, boolean fallback) {
this.mgen = mgen;
this.mth = mth;
this.mth = mgen.getMethodNode();
this.root = mth.dex().root();
this.fallback = fallback;
}
......@@ -75,23 +75,6 @@ public class InsnGen {
return fallback;
}
@Deprecated
public CodeWriter arg(InsnNode insn, int arg) throws CodegenException {
return arg(insn.getArg(arg));
}
@Deprecated
public CodeWriter arg(InsnArg arg) throws CodegenException {
return arg(arg, true);
}
@Deprecated
public CodeWriter arg(InsnArg arg, boolean wrap) throws CodegenException {
CodeWriter code = new CodeWriter();
addArg(code, arg, wrap);
return code;
}
public void addArgDot(CodeWriter code, InsnArg arg) throws CodegenException {
int len = code.length();
addArg(code, arg, true);
......@@ -128,17 +111,19 @@ public class InsnGen {
}
}
public String assignVar(InsnNode insn) throws CodegenException {
public void assignVar(CodeWriter code, InsnNode insn) throws CodegenException {
RegisterArg arg = insn.getResult();
if (insn.getAttributes().contains(AttributeFlag.DECLARE_VAR)) {
return declareVar(arg);
declareVar(code, arg);
} else {
return arg(arg).toString();
addArg(code, arg, false);
}
}
public String declareVar(RegisterArg arg) {
return useType(arg.getType()) + " " + mgen.assignArg(arg);
public void declareVar(CodeWriter code, RegisterArg arg) {
code.add(useType(arg.getType()));
code.add(' ');
code.add(mgen.assignArg(arg));
}
private static String lit(LiteralArg arg) {
......@@ -174,18 +159,6 @@ public class InsnGen {
return clsGen.useClass(declClass) + '.' + field.getName();
}
private void fieldPut(IndexInsnNode insn) {
FieldInfo field = (FieldInfo) insn.getIndex();
String thisClass = mth.getParentClass().getFullName();
if (field.getDeclClass().getFullName().equals(thisClass)) {
// if we generate this field - don't init if its final and used
FieldNode fn = mth.getParentClass().searchField(field);
if (fn != null && fn.getAccessFlags().isFinal()) {
fn.getAttributes().remove(AttributeType.FIELD_VALUE);
}
}
}
protected String staticField(FieldInfo field) {
return makeStaticFieldAccess(field, mgen.getClassGen());
}
......@@ -217,7 +190,8 @@ public class InsnGen {
code.attachAnnotation(insn.getSourceLine());
}
if (insn.getResult() != null && insn.getType() != InsnType.ARITH_ONEARG) {
code.add(assignVar(insn)).add(" = ");
assignVar(code, insn);
code.add(" = ");
}
makeInsnBody(code, insn, state);
code.add(';');
......@@ -273,14 +247,18 @@ public class InsnGen {
makeArithOneArg((ArithNode) insn, code, state);
break;
case NEG:
String base = "-" + arg(insn.getArg(0));
if (state.contains(Flags.BODY_ONLY)) {
code.add('(').add(base).add(')');
} else {
code.add(base);
case NEG: {
boolean wrap = state.contains(Flags.BODY_ONLY);
if (wrap) {
code.add('(');
}
code.add('-');
addArg(code, insn.getArg(0));
if (wrap) {
code.add(')');
}
break;
}
case RETURN:
if (insn.getArgsCount() != 0) {
......@@ -306,7 +284,15 @@ public class InsnGen {
case CMP_L:
case CMP_G:
code.add(String.format("(%1$s > %2$s ? 1 : (%1$s == %2$s ? 0 : -1))", arg(insn, 0), arg(insn, 1)));
code.add('(');
addArg(code, insn.getArg(0));
code.add(" > ");
addArg(code, insn.getArg(1));
code.add(" ? 1 : (");
addArg(code, insn.getArg(0));
code.add(" == ");
addArg(code, insn.getArg(1));
code.add("? 0 : -1))");
break;
case INSTANCE_OF: {
......@@ -314,7 +300,7 @@ public class InsnGen {
if (wrap) {
code.add('(');
}
code.add(arg(insn, 0));
addArg(code, insn.getArg(0));
code.add(" instanceof ");
code.add(useType((ArgType) ((IndexInsnNode) insn).getIndex()));
if (wrap) {
......@@ -332,8 +318,11 @@ public class InsnGen {
case NEW_ARRAY: {
ArgType arrayType = insn.getResult().getType();
code.add("new ").add(useType(arrayType.getArrayRootElement()));
code.add('[');
addArg(code, insn.getArg(0));
code.add(']');
int dim = arrayType.getArrayDimension();
code.add("new ").add(useType(arrayType.getArrayRootElement())).add('[').add(arg(insn, 0)).add(']');
for (int i = 0; i < dim - 1; i++) {
code.add("[]");
}
......@@ -341,7 +330,8 @@ public class InsnGen {
}
case ARRAY_LENGTH:
code.add(arg(insn, 0)).add(".length");
addArg(code, insn.getArg(0));
code.add(".length");
break;
case FILL_ARRAY:
......@@ -384,37 +374,40 @@ public class InsnGen {
code.add(staticField((FieldInfo) ((IndexInsnNode) insn).getIndex()));
break;
case SPUT:
IndexInsnNode node = (IndexInsnNode) insn;
fieldPut(node);
code.add(staticField((FieldInfo) node.getIndex())).add(" = ");
addArg(code, node.getArg(0), false);
FieldInfo field = (FieldInfo) ((IndexInsnNode) insn).getIndex();
code.add(staticField(field)).add(" = ");
addArg(code, insn.getArg(0), false);
break;
case STR_CONCAT:
StringBuilder sb = new StringBuilder();
boolean wrap = state.contains(Flags.BODY_ONLY);
if (wrap) {
code.add('(');
}
for (Iterator<InsnArg> it = insn.getArguments().iterator(); it.hasNext(); ) {
sb.append(arg(it.next()));
addArg(code, it.next());
if (it.hasNext()) {
sb.append(" + ");
code.add(" + ");
}
}
// TODO: wrap in braces only if necessary
if (state.contains(Flags.BODY_ONLY)) {
code.add('(').add(sb.toString()).add(')');
} else {
code.add(sb.toString());
if (wrap) {
code.add(')');
}
break;
case MONITOR_ENTER:
if (isFallback()) {
code.add("monitor-enter(").add(arg(insn.getArg(0))).add(')');
code.add("monitor-enter(");
addArg(code, insn.getArg(0));
code.add(')');
}
break;
case MONITOR_EXIT:
if (isFallback()) {
code.add("monitor-exit(").add(arg(insn, 0)).add(')');
code.add("monitor-exit(");
addArg(code, insn.getArg(0));
code.add(')');
}
break;
......@@ -422,7 +415,7 @@ public class InsnGen {
if (isFallback()) {
code.add("move-exception");
} else {
code.add(arg(insn, 0));
addArg(code, insn.getArg(0));
}
break;
......@@ -431,7 +424,7 @@ public class InsnGen {
break;
case ARGS:
code.add(arg(insn, 0));
addArg(code, insn.getArg(0));
break;
/* fallback mode instructions */
......@@ -439,9 +432,10 @@ public class InsnGen {
assert isFallback() : "if insn in not fallback mode";
IfNode ifInsn = (IfNode) insn;
code.add("if (");
code.add(arg(insn.getArg(0))).add(' ');
addArg(code, insn.getArg(0));
code.add(' ');
code.add(ifInsn.getOp().getSymbol()).add(' ');
code.add(arg(insn.getArg(1)));
addArg(code, insn.getArg(1));
code.add(") goto ").add(MethodGen.getLabelName(ifInsn.getTarget()));
break;
......@@ -453,7 +447,9 @@ public class InsnGen {
case SWITCH:
assert isFallback();
SwitchNode sw = (SwitchNode) insn;
code.add("switch(").add(arg(insn, 0)).add(") {");
code.add("switch(");
addArg(code, insn.getArg(0));
code.add(") {");
code.incIndent();
for (int i = 0; i < sw.getCasesCount(); i++) {
code.startLine("case ").add(sw.getKeys()[i]).add(": goto ");
......@@ -481,7 +477,7 @@ public class InsnGen {
code.add("new ").add(useType(insn.getResult().getType()));
code.add('{');
for (int i = 0; i < c; i++) {
code.add(arg(insn, i));
addArg(code, insn.getArg(i));
if (i + 1 < c) {
code.add(", ");
}
......@@ -565,7 +561,7 @@ public class InsnGen {
defCtr.getAttributes().add(AttributeFlag.DONT_GENERATE);
}
code.add("new ").add(parent == null ? "Object" : useClass(parent)).add("() ");
new ClassGen(cls, mgen.getClassGen().getParentGen(), fallback).makeClassBody(code);
new ClassGen(cls, mgen.getClassGen().getParentGen(), fallback).addClassBody(code);
return;
}
if (insn.isSelf()) {
......@@ -705,17 +701,24 @@ public class InsnGen {
}
private void makeTernary(TernaryInsn insn, CodeWriter code, EnumSet<Flags> state) throws CodegenException {
String cond = ConditionGen.make(this, insn.getCondition());
CodeWriter th = arg(insn.getArg(0), false);
CodeWriter els = arg(insn.getArg(1), false);
if (th.toString().equals("true") && els.toString().equals("false")) {
code.add(cond);
boolean wrap = state.contains(Flags.BODY_ONLY);
if (wrap) {
code.add('(');
}
InsnArg first = insn.getArg(0);
InsnArg second = insn.getArg(1);
ConditionGen condGen = new ConditionGen(this);
if (first.equals(LiteralArg.TRUE) && second.equals(LiteralArg.FALSE)) {
condGen.add(code, insn.getCondition());
} else {
if (state.contains(Flags.BODY_ONLY)) {
code.add("((").add(cond).add(')').add(" ? ").add(th).add(" : ").add(els).add(')');
} else {
code.add('(').add(cond).add(')').add(" ? ").add(th).add(" : ").add(els);
}
condGen.wrap(code, insn.getCondition());
code.add(" ? ");
addArg(code, first, false);
code.add(" : ");
addArg(code, second, false);
}
if (wrap) {
code.add(')');
}
}
......@@ -743,13 +746,15 @@ public class InsnGen {
if (arg.isLiteral() && (op == ArithOp.ADD || op == ArithOp.SUB)) {
LiteralArg lit = (LiteralArg) arg;
if (lit.isInteger() && lit.getLiteral() == 1) {
assignVar(code, insn);
String opSymbol = op.getSymbol();
code.add(assignVar(insn)).add(opSymbol).add(opSymbol);
code.add(opSymbol).add(opSymbol);
return;
}
}
// +=, -= ...
code.add(assignVar(insn)).add(' ').add(op.getSymbol()).add("= ");
assignVar(code, insn);
code.add(' ').add(op.getSymbol()).add("= ");
addArg(code, arg, false);
}
}
......@@ -58,6 +58,10 @@ public class MethodGen {
return classGen;
}
public MethodNode getMethodNode() {
return mth;
}
public boolean addDefinition(CodeWriter code) {
if (mth.getMethodInfo().isClassInit()) {
code.startLine("static");
......@@ -84,7 +88,7 @@ public class MethodGen {
}
code.startLine(ai.makeString());
if (classGen.makeGenericMap(code, mth.getGenericMap())) {
if (classGen.addGenericMap(code, mth.getGenericMap())) {
code.add(' ');
}
if (mth.getAccessFlags().isConstructor()) {
......@@ -245,7 +249,7 @@ public class MethodGen {
} else {
Region startRegion = mth.getRegion();
if (startRegion != null) {
(new RegionGen(this, mth)).makeRegion(code, startRegion);
(new RegionGen(this)).makeRegion(code, startRegion);
} else {
addFallbackMethodCode(code);
}
......@@ -289,7 +293,7 @@ public class MethodGen {
}
public static void addFallbackInsns(CodeWriter code, MethodNode mth, List<InsnNode> insns, boolean addLabels) {
InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), mth, true);
InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), true);
for (InsnNode insn : insns) {
AttributesList attrs = insn.getAttributes();
if (addLabels) {
......
......@@ -15,7 +15,6 @@ import jadx.core.dex.nodes.IBlock;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.IfCondition;
import jadx.core.dex.regions.IfRegion;
import jadx.core.dex.regions.LoopRegion;
......@@ -36,8 +35,8 @@ import org.slf4j.LoggerFactory;
public class RegionGen extends InsnGen {
private static final Logger LOG = LoggerFactory.getLogger(RegionGen.class);
public RegionGen(MethodGen mgen, MethodNode mth) {
super(mgen, mth, false);
public RegionGen(MethodGen mgen) {
super(mgen, false);
}
public void makeRegion(CodeWriter code, IContainer cont) throws CodegenException {
......@@ -66,7 +65,9 @@ public class RegionGen extends InsnGen {
(DeclareVariablesAttr) cont.getAttributes().get(AttributeType.DECLARE_VARIABLES);
if (declVars != null) {
for (RegisterArg v : declVars.getVars()) {
code.startLine(declareVar(v)).add(';');
code.startLine();
declareVar(code, v);
code.add(';');
}
}
}
......@@ -111,7 +112,9 @@ public class RegionGen extends InsnGen {
if (newLine) {
code.startLine();
}
code.add("if (").add(ConditionGen.make(this, region.getCondition())).add(") {");
code.add("if (");
new ConditionGen(this).add(code, region.getCondition());
code.add(") {");
makeRegionIndent(code, region.getThenRegion());
code.startLine('}');
......@@ -169,13 +172,17 @@ public class RegionGen extends InsnGen {
return code;
}
String condStr = ConditionGen.make(this, condition);
ConditionGen conditionGen = new ConditionGen(this);
if (region.isConditionAtEnd()) {
code.startLine("do {");
makeRegionIndent(code, region.getBody());
code.startLine("} while (").add(condStr).add(");");
code.startLine("} while (");
conditionGen.add(code, condition);
code.add(");");
} else {
code.startLine("while (").add(condStr).add(") {");
code.startLine("while (");
conditionGen.add(code, condition);
code.add(") {");
makeRegionIndent(code, region.getBody());
code.startLine('}');
}
......
package jadx.core.dex.visitors;
import jadx.core.dex.attributes.AttributeFlag;
import jadx.core.dex.attributes.AttributeType;
import jadx.core.dex.attributes.AttributesList;
import jadx.core.dex.attributes.FieldReplaceAttr;
import jadx.core.dex.info.AccessInfo;
......@@ -39,6 +40,8 @@ public class ClassModifier extends AbstractVisitor {
removeSyntheticFields(cls);
removeSyntheticMethods(cls);
removeEmptyMethods(cls);
checkFieldsInit(cls);
return false;
}
......@@ -174,4 +177,36 @@ public class ClassModifier extends AbstractVisitor {
}
return true;
}
private static void checkFieldsInit(ClassNode cls) {
MethodNode clinit = cls.searchMethodByName("<clinit>()V");
if (clinit == null
|| !clinit.getAccessFlags().isStatic()
|| clinit.isNoCode()) {
return;
}
for (BlockNode block : clinit.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) {
if (insn.getType() == InsnType.SPUT) {
processStaticFieldAssign(cls, (IndexInsnNode) insn);
}
}
}
}
/**
* Remove field initialization if it assign in "<clinit>" method
*/
private static void processStaticFieldAssign(ClassNode cls, IndexInsnNode insn) {
FieldInfo field = (FieldInfo) insn.getIndex();
String thisClass = cls.getFullName();
if (field.getDeclClass().getFullName().equals(thisClass)) {
FieldNode fn = cls.searchField(field);
if (fn != null && fn.getAccessFlags().isFinal()) {
fn.getAttributes().remove(AttributeType.FIELD_VALUE);
}
}
}
}
......@@ -6,7 +6,6 @@ import jadx.core.dex.nodes.ClassNode;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.either;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
......@@ -18,10 +17,7 @@ public class TestRedundantBrackets extends InternalJadxTest {
}
public int method2(Object obj) {
if (obj instanceof String) {
return ((String) obj).length();
}
return 0;
return obj instanceof String ? ((String) obj).length() : 0;
}
public int method3(int a, int b) {
......@@ -50,11 +46,12 @@ public class TestRedundantBrackets extends InternalJadxTest {
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
System.out.println(code);
assertThat(code, not(containsString("(-1)")));
assertThat(code, not(containsString("return;")));
assertThat(code, either(containsString("if (obj instanceof String) {"))
.or(containsString("return (obj instanceof String) ? ")));
assertThat(code, containsString("return obj instanceof String ? ((String) obj).length() : 0;"));
assertThat(code, containsString("if (a + b < 10)"));
assertThat(code, containsString("if ((a & b) != 0)"));
assertThat(code, containsString("if (num == 4 || num == 6 || num == 8 || num == 10)"));
......
......@@ -57,7 +57,7 @@ public class TestReturnWrapping extends InternalJadxTest {
assertThat(code, containsString("return 255;"));
assertThat(code, containsString("return arg0 + 1;"));
//assertThat(code, containsString("return Integer.toHexString(i);"));
assertThat(code, containsString("return (i > 128) ? arg0.toString() + ret.toString() : Integer.valueOf(i);"));
assertThat(code, containsString("return i > 128 ? arg0.toString() + ret.toString() : Integer.valueOf(i);"));
assertThat(code, containsString("return arg0 + 2;"));
assertThat(code, containsString("arg0 -= 951;"));
}
......
package jadx.tests.internal;
import jadx.api.InternalJadxTest;
import jadx.core.dex.nodes.ClassNode;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
public class TestStaticFieldsInit extends InternalJadxTest {
public static class TestCls {
public static final String s1 = "1";
public static final String s2 = "12".substring(1);
public static final String s3 = null;
public static final String s4;
public static final String s5 = "5";
public static String s6 = "6";
static {
if (s5.equals("?")) {
s4 = "?";
} else {
s4 = "4";
}
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
System.out.println(code);
assertThat(code, not(containsString("public static final String s2 = null;")));
// TODO:
// assertThat(code, containsString("public static final String s3 = null;"));
}
}
......@@ -43,6 +43,6 @@ public class TestGenerics2 extends InternalJadxTest {
assertThat(code, containsString("public ItemReference(V item, Object id, ReferenceQueue<? super V> queue) {"));
assertThat(code, containsString("public V get(Object id) {"));
assertThat(code, containsString("WeakReference<V> ref = "));
assertThat(code, containsString("return (ref != null) ? ref.get() : null;"));
assertThat(code, containsString("return ref != null ? ref.get() : null;"));
}
}
......@@ -21,6 +21,8 @@ import org.slf4j.LoggerFactory;
public class JadxTextArea extends RSyntaxTextArea {
private static final Logger LOG = LoggerFactory.getLogger(JadxTextArea.class);
private static final long serialVersionUID = 6312736869579635796L;
private static final Color BACKGROUND = new Color(0xf7f7f7);
private static final Color JUMP_FOREGROUND = new Color(0x785523);
private static final Color JUMP_BACKGROUND = new Color(0xE6E6FF);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册