Projects STRLCPY jadx Commits 890c0a99
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java
    skipped 150 lines
    151 151   code.add(InsnGen.makeStaticFieldAccess(field, classGen));
    152 152   } else if (val instanceof List) {
    153 153   code.add('{');
    154  - List list = (List) val;
    155  - Iterator it = list.iterator();
     154 + Iterator<?> it = ((List) val).iterator();
    156 155   while (it.hasNext()) {
    157 156   Object obj = it.next();
    158 157   encodeValue(code, obj);
    skipped 14 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
    skipped 42 lines
    43 43   private final boolean fallback;
    44 44   
    45 45   private final Set<ClassInfo> imports = new HashSet<ClassInfo>();
     46 + private int clsDeclLine = 0;
    46 47   
    47 48   public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean fallback) {
    48 49   this.cls = cls;
    skipped 46 lines
    95 96   if (cls.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) {
    96 97   code.startLine("// jadx: inconsistent code");
    97 98   }
    98  - makeClassDeclaration(code);
    99  - makeClassBody(code);
    100  - code.newLine();
     99 + addClassDeclaration(code);
     100 + addClassBody(code);
    101 101   }
    102 102   
    103  - public void makeClassDeclaration(CodeWriter clsCode) {
     103 + public void addClassDeclaration(CodeWriter clsCode) {
    104 104   AccessInfo af = cls.getAccessFlags();
    105 105   if (af.isInterface()) {
    106 106   af = af.remove(AccessFlags.ACC_ABSTRACT);
    skipped 16 lines
    123 123   }
    124 124   clsCode.add(cls.getShortName());
    125 125   
    126  - makeGenericMap(clsCode, cls.getGenericMap());
     126 + addGenericMap(clsCode, cls.getGenericMap());
    127 127   clsCode.add(' ');
    128 128   
    129 129   ClassInfo sup = cls.getSuperClass();
    skipped 20 lines
    150 150   clsCode.add(' ');
    151 151   }
    152 152   }
    153  - 
    154 153   clsCode.attachDefinition(cls);
    155 154   }
    156 155   
    157  - public boolean makeGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
     156 + public boolean addGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
    158 157   if (gmap == null || gmap.isEmpty()) {
    159 158   return false;
    160 159   }
    skipped 22 lines
    183 182   return true;
    184 183   }
    185 184   
    186  - public void makeClassBody(CodeWriter clsCode) throws CodegenException {
     185 + public void addClassBody(CodeWriter clsCode) throws CodegenException {
    187 186   clsCode.add('{');
    188  - CodeWriter mthsCode = makeMethods(clsCode, cls.getMethods());
    189  - CodeWriter fieldsCode = makeFields(clsCode, cls, cls.getFields());
    190  - clsCode.add(fieldsCode);
    191  - if (fieldsCode.notEmpty() && mthsCode.notEmpty()) {
    192  - clsCode.newLine();
    193  - }
    194  - // insert inner classes code
    195  - if (cls.getInnerClasses().size() != 0) {
    196  - clsCode.add(makeInnerClasses(cls, clsCode.getIndent()));
    197  - if (mthsCode.notEmpty()) {
    198  - clsCode.newLine();
    199  - }
    200  - }
    201  - clsCode.add(mthsCode);
     187 + clsDeclLine = clsCode.getLine();
     188 + clsCode.incIndent();
     189 + addFields(clsCode);
     190 + addInnerClasses(clsCode, cls);
     191 + addMethods(clsCode);
     192 + clsCode.decIndent();
    202 193   clsCode.startLine('}');
    203 194   }
    204 195   
    205  - private CodeWriter makeInnerClasses(ClassNode cls, int indent) throws CodegenException {
    206  - CodeWriter innerClsCode = new CodeWriter(indent + 1);
    207  - for (ClassNode inCls : cls.getInnerClasses()) {
    208  - if (!inCls.isAnonymous()) {
    209  - ClassGen inClGen = new ClassGen(inCls, parentGen == null ? this : parentGen, fallback);
    210  - inClGen.addClassCode(innerClsCode);
     196 + private void addInnerClasses(CodeWriter code, ClassNode cls) throws CodegenException {
     197 + for (ClassNode innerCls : cls.getInnerClasses()) {
     198 + if (!innerCls.isAnonymous()) {
     199 + ClassGen inClGen = new ClassGen(innerCls, getParentGen(), fallback);
     200 + code.newLine();
     201 + inClGen.addClassCode(code);
    211 202   imports.addAll(inClGen.getImports());
    212 203   }
    213 204   }
    214  - return innerClsCode;
    215 205   }
    216 206   
    217  - private CodeWriter makeMethods(CodeWriter clsCode, List<MethodNode> mthList) {
    218  - CodeWriter code = new CodeWriter(clsCode.getIndent() + 1);
    219  - for (Iterator<MethodNode> it = mthList.iterator(); it.hasNext(); ) {
    220  - MethodNode mth = it.next();
    221  - if (mth.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
    222  - continue;
     207 + private void addMethods(CodeWriter code) {
     208 + for (MethodNode mth : cls.getMethods()) {
     209 + if (!mth.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
     210 + try {
     211 + if (code.getLine() != clsDeclLine) {
     212 + code.newLine();
     213 + }
     214 + addMethod(code, mth);
     215 + } catch (Exception e) {
     216 + String msg = ErrorsCounter.methodError(mth, "Method generation error", e);
     217 + code.startLine("/* " + msg + CodeWriter.NL + Utils.getStackTrace(e) + " */");
     218 + }
    223 219   }
    224  - try {
    225  - if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) {
    226  - MethodGen mthGen = new MethodGen(this, mth);
    227  - mthGen.addDefinition(code);
    228  - if (cls.getAccessFlags().isAnnotation()) {
    229  - Object def = annotationGen.getAnnotationDefaultValue(mth.getName());
    230  - if (def != null) {
    231  - code.add(" default ");
    232  - annotationGen.encodeValue(code, def);
    233  - }
    234  - }
    235  - code.add(';');
    236  - } else {
    237  - MethodGen mthGen = new MethodGen(this, mth);
    238  - boolean badCode = mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE);
    239  - if (badCode) {
    240  - code.startLine("/* JADX WARNING: inconsistent code. */");
    241  - code.startLine("/* Code decompiled incorrectly, please refer to instructions dump. */");
    242  - LOG.error(ErrorsCounter.formatErrorMsg(mth, " Inconsistent code"));
    243  - }
    244  - if (mthGen.addDefinition(code)) {
    245  - code.add(' ');
    246  - }
    247  - code.add('{');
    248  - code.incIndent();
    249  - insertSourceFileInfo(code, mth);
    250  - mthGen.addInstructions(code);
    251  - code.decIndent();
    252  - code.startLine('}');
     220 + }
     221 + }
     222 + 
     223 + private void addMethod(CodeWriter code, MethodNode mth) throws CodegenException {
     224 + MethodGen mthGen = new MethodGen(this, mth);
     225 + if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) {
     226 + mthGen.addDefinition(code);
     227 + if (cls.getAccessFlags().isAnnotation()) {
     228 + Object def = annotationGen.getAnnotationDefaultValue(mth.getName());
     229 + if (def != null) {
     230 + code.add(" default ");
     231 + annotationGen.encodeValue(code, def);
    253 232   }
    254  - } catch (Throwable e) {
    255  - String msg = ErrorsCounter.methodError(mth, "Method generation error", e);
    256  - code.startLine("/* " + msg + CodeWriter.NL + Utils.getStackTrace(e) + " */");
    257 233   }
    258  - if (it.hasNext()) {
    259  - code.newLine();
     234 + code.add(';');
     235 + } else {
     236 + boolean badCode = mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE);
     237 + if (badCode) {
     238 + code.startLine("/* JADX WARNING: inconsistent code. */");
     239 + code.startLine("/* Code decompiled incorrectly, please refer to instructions dump. */");
     240 + LOG.error(ErrorsCounter.formatErrorMsg(mth, " Inconsistent code"));
    260 241   }
     242 + if (mthGen.addDefinition(code)) {
     243 + code.add(' ');
     244 + }
     245 + code.add('{');
     246 + code.incIndent();
     247 + insertSourceFileInfo(code, mth);
     248 + mthGen.addInstructions(code);
     249 + code.decIndent();
     250 + code.startLine('}');
    261 251   }
    262  - return code;
    263 252   }
    264 253   
    265  - private CodeWriter makeFields(CodeWriter clsCode, ClassNode cls, List<FieldNode> fields) throws CodegenException {
    266  - CodeWriter code = new CodeWriter(clsCode.getIndent() + 1);
    267  - 
    268  - addEnumFields(cls, code);
    269  - 
    270  - for (FieldNode f : fields) {
     254 + private void addFields(CodeWriter code) throws CodegenException {
     255 + addEnumFields(code);
     256 + for (FieldNode f : cls.getFields()) {
    271 257   if (f.getAttributes().contains(AttributeFlag.DONT_GENERATE)) {
    272 258   continue;
    273 259   }
    skipped 14 lines
    288 274   code.add(';');
    289 275   code.attachDefinition(f);
    290 276   }
    291  - return code;
    292 277   }
    293 278   
    294  - private void addEnumFields(ClassNode cls, CodeWriter code) throws CodegenException {
     279 + private void addEnumFields(CodeWriter code) throws CodegenException {
    295 280   EnumClassAttr enumFields = (EnumClassAttr) cls.getAttributes().get(AttributeType.ENUM_CLASS);
    296 281   if (enumFields != null) {
    297 282   InsnGen igen = null;
    skipped 7 lines
    305 290   if (igen == null) {
    306 291   // don't init mth gen if this is simple enum
    307 292   MethodGen mthGen = new MethodGen(this, enumFields.getStaticMethod());
    308  - igen = new InsnGen(mthGen, enumFields.getStaticMethod(), false);
     293 + igen = new InsnGen(mthGen, false);
    309 294   }
    310 295   igen.addArg(code, arg);
    311 296   if (aIt.hasNext()) {
    skipped 3 lines
    315 300   code.add(')');
    316 301   }
    317 302   if (f.getCls() != null) {
    318  - new ClassGen(f.getCls(), this, fallback).makeClassBody(code);
     303 + new ClassGen(f.getCls(), this, fallback).addClassBody(code);
    319 304   }
    320 305   if (it.hasNext()) {
    321 306   code.add(',');
    skipped 156 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
    skipped 94 lines
    95 95   return this;
    96 96   }
    97 97   
    98  - @Deprecated
    99  - public CodeWriter add(CodeWriter code) {
     98 + CodeWriter add(CodeWriter code) {
    100 99   line--;
    101 100   for (Map.Entry<CodePosition, Object> entry : code.annotations.entrySet()) {
    102 101   CodePosition pos = entry.getKey();
    103 102   attachAnnotation(entry.getValue(), new CodePosition(line + pos.getLine(), pos.getOffset()));
    104 103   }
    105 104   line += code.line;
    106  - String str = code.toString();
    107  - buf.append(str);
    108  - if (str.contains(NL)) {
    109  - offset = code.offset;
    110  - } else {
    111  - offset += code.offset;
    112  - }
     105 + offset = code.offset;
     106 + buf.append(code);
    113 107   return this;
    114 108   }
    115 109   
    skipped 25 lines
    141 135   }
    142 136   this.indentStr = s.toString();
    143 137   }
     138 + }
     139 + 
     140 + public int getLine() {
     141 + return line;
    144 142   }
    145 143   
    146 144   public int getIndent() {
    skipped 150 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java
    skipped 11 lines
    12 12  import jadx.core.dex.regions.IfCondition;
    13 13  import jadx.core.utils.ErrorsCounter;
    14 14  import jadx.core.utils.exceptions.CodegenException;
     15 +import jadx.core.utils.exceptions.JadxRuntimeException;
     16 + 
     17 +import java.util.Iterator;
    15 18   
    16 19  import org.slf4j.Logger;
    17 20  import org.slf4j.LoggerFactory;
    18 21   
    19  -public class ConditionGen {
     22 +public class ConditionGen extends InsnGen {
    20 23   private static final Logger LOG = LoggerFactory.getLogger(ConditionGen.class);
    21 24   
    22  - static String make(InsnGen insnGen, IfCondition condition) throws CodegenException {
     25 + public ConditionGen(InsnGen insnGen) {
     26 + super(insnGen.mgen, insnGen.fallback);
     27 + }
     28 + 
     29 + void add(CodeWriter code, IfCondition condition) throws CodegenException {
    23 30   switch (condition.getMode()) {
    24 31   case COMPARE:
    25  - return makeCompare(insnGen, condition.getCompare());
     32 + addCompare(code, condition.getCompare());
     33 + break;
     34 + 
    26 35   case NOT:
    27  - return "!(" + make(insnGen, condition.getArgs().get(0)) + ")";
     36 + addNot(code, condition);
     37 + break;
     38 + 
    28 39   case AND:
    29 40   case OR:
    30  - String mode = condition.getMode() == IfCondition.Mode.AND ? " && " : " || ";
    31  - StringBuilder sb = new StringBuilder();
    32  - for (IfCondition arg : condition.getArgs()) {
    33  - if (sb.length() != 0) {
    34  - sb.append(mode);
    35  - }
    36  - String s = make(insnGen, arg);
    37  - if (arg.isCompare()) {
    38  - sb.append(s);
    39  - } else {
    40  - sb.append('(').append(s).append(')');
    41  - }
    42  - }
    43  - return sb.toString();
     41 + addAndOr(code, condition);
     42 + break;
     43 + 
    44 44   default:
    45  - return "??" + condition;
     45 + throw new JadxRuntimeException("Unknown condition mode: " + condition);
    46 46   }
    47 47   }
    48 48   
    49  - private static String makeCompare(InsnGen insnGen, Compare compare) throws CodegenException {
     49 + void wrap(CodeWriter code, IfCondition cond) throws CodegenException {
     50 + boolean wrap = isWrapNeeded(cond);
     51 + if (wrap) {
     52 + code.add('(');
     53 + }
     54 + add(code, cond);
     55 + if (wrap) {
     56 + code.add(')');
     57 + }
     58 + }
     59 + 
     60 + private void addCompare(CodeWriter code, Compare compare) throws CodegenException {
    50 61   IfOp op = compare.getOp();
    51 62   InsnArg firstArg = compare.getA();
    52 63   InsnArg secondArg = compare.getB();
    skipped 6 lines
    59 70   }
    60 71   if (op == IfOp.EQ) {
    61 72   // == true
    62  - return insnGen.arg(firstArg, false).toString();
     73 + addArg(code, firstArg, false);
     74 + return;
    63 75   } else if (op == IfOp.NE) {
    64 76   // != true
    65  - if (isWrapNeeded(firstArg)) {
    66  - return "!(" + insnGen.arg(firstArg) + ")";
    67  - } else {
    68  - return "!" + insnGen.arg(firstArg);
     77 + code.add('!');
     78 + boolean wrap = isWrapNeeded(firstArg);
     79 + if (wrap) {
     80 + code.add('(');
     81 + }
     82 + addArg(code, firstArg, false);
     83 + if (wrap) {
     84 + code.add(')');
    69 85   }
     86 + return;
    70 87   }
    71  - LOG.warn(ErrorsCounter.formatErrorMsg(insnGen.mth, "Unsupported boolean condition " + op.getSymbol()));
     88 + LOG.warn(ErrorsCounter.formatErrorMsg(mth, "Unsupported boolean condition " + op.getSymbol()));
    72 89   }
    73  - return insnGen.arg(firstArg, isWrapNeeded(firstArg))
    74  - + " " + op.getSymbol() + " "
    75  - + insnGen.arg(secondArg, isWrapNeeded(secondArg));
     90 + 
     91 + addArg(code, firstArg, isWrapNeeded(firstArg));
     92 + code.add(' ').add(op.getSymbol()).add(' ');
     93 + addArg(code, secondArg, isWrapNeeded(secondArg));
     94 + }
     95 + 
     96 + private void addNot(CodeWriter code, IfCondition condition) throws CodegenException {
     97 + code.add('!');
     98 + wrap(code, condition.getArgs().get(0));
     99 + }
     100 + 
     101 + private void addAndOr(CodeWriter code, IfCondition condition) throws CodegenException {
     102 + String mode = condition.getMode() == IfCondition.Mode.AND ? " && " : " || ";
     103 + Iterator<IfCondition> it = condition.getArgs().iterator();
     104 + while (it.hasNext()) {
     105 + wrap(code, it.next());
     106 + if (it.hasNext()) {
     107 + code.add(mode);
     108 + }
     109 + }
     110 + }
     111 + 
     112 + private boolean isWrapNeeded(IfCondition condition) {
     113 + return !condition.isCompare();
    76 114   }
    77 115   
    78 116   private static boolean isWrapNeeded(InsnArg arg) {
    skipped 20 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
    skipped 56 lines
    57 57   protected final MethodGen mgen;
    58 58   protected final MethodNode mth;
    59 59   protected final RootNode root;
    60  - private final boolean fallback;
     60 + protected final boolean fallback;
    61 61   
    62 62   private static enum Flags {
    63 63   BODY_ONLY,
    64 64   BODY_ONLY_NOWRAP,
    65 65   }
    66 66   
    67  - public InsnGen(MethodGen mgen, MethodNode mth, boolean fallback) {
     67 + public InsnGen(MethodGen mgen, boolean fallback) {
    68 68   this.mgen = mgen;
    69  - this.mth = mth;
     69 + this.mth = mgen.getMethodNode();
    70 70   this.root = mth.dex().root();
    71 71   this.fallback = fallback;
    72 72   }
    skipped 2 lines
    75 75   return fallback;
    76 76   }
    77 77   
    78  - @Deprecated
    79  - public CodeWriter arg(InsnNode insn, int arg) throws CodegenException {
    80  - return arg(insn.getArg(arg));
    81  - }
    82  - 
    83  - @Deprecated
    84  - public CodeWriter arg(InsnArg arg) throws CodegenException {
    85  - return arg(arg, true);
    86  - }
    87  - 
    88  - @Deprecated
    89  - public CodeWriter arg(InsnArg arg, boolean wrap) throws CodegenException {
    90  - CodeWriter code = new CodeWriter();
    91  - addArg(code, arg, wrap);
    92  - return code;
    93  - }
    94  - 
    95 78   public void addArgDot(CodeWriter code, InsnArg arg) throws CodegenException {
    96 79   int len = code.length();
    97 80   addArg(code, arg, true);
    skipped 30 lines
    128 111   }
    129 112   }
    130 113   
    131  - public String assignVar(InsnNode insn) throws CodegenException {
     114 + public void assignVar(CodeWriter code, InsnNode insn) throws CodegenException {
    132 115   RegisterArg arg = insn.getResult();
    133 116   if (insn.getAttributes().contains(AttributeFlag.DECLARE_VAR)) {
    134  - return declareVar(arg);
     117 + declareVar(code, arg);
    135 118   } else {
    136  - return arg(arg).toString();
     119 + addArg(code, arg, false);
    137 120   }
    138 121   }
    139 122   
    140  - public String declareVar(RegisterArg arg) {
    141  - return useType(arg.getType()) + " " + mgen.assignArg(arg);
     123 + public void declareVar(CodeWriter code, RegisterArg arg) {
     124 + code.add(useType(arg.getType()));
     125 + code.add(' ');
     126 + code.add(mgen.assignArg(arg));
    142 127   }
    143 128   
    144 129   private static String lit(LiteralArg arg) {
    skipped 29 lines
    174 159   return clsGen.useClass(declClass) + '.' + field.getName();
    175 160   }
    176 161   
    177  - private void fieldPut(IndexInsnNode insn) {
    178  - FieldInfo field = (FieldInfo) insn.getIndex();
    179  - String thisClass = mth.getParentClass().getFullName();
    180  - if (field.getDeclClass().getFullName().equals(thisClass)) {
    181  - // if we generate this field - don't init if its final and used
    182  - FieldNode fn = mth.getParentClass().searchField(field);
    183  - if (fn != null && fn.getAccessFlags().isFinal()) {
    184  - fn.getAttributes().remove(AttributeType.FIELD_VALUE);
    185  - }
    186  - }
    187  - }
    188  - 
    189 162   protected String staticField(FieldInfo field) {
    190 163   return makeStaticFieldAccess(field, mgen.getClassGen());
    191 164   }
    skipped 25 lines
    217 190   code.attachAnnotation(insn.getSourceLine());
    218 191   }
    219 192   if (insn.getResult() != null && insn.getType() != InsnType.ARITH_ONEARG) {
    220  - code.add(assignVar(insn)).add(" = ");
     193 + assignVar(code, insn);
     194 + code.add(" = ");
    221 195   }
    222 196   makeInsnBody(code, insn, state);
    223 197   code.add(';');
    skipped 49 lines
    273 247   makeArithOneArg((ArithNode) insn, code, state);
    274 248   break;
    275 249   
    276  - case NEG:
    277  - String base = "-" + arg(insn.getArg(0));
    278  - if (state.contains(Flags.BODY_ONLY)) {
    279  - code.add('(').add(base).add(')');
    280  - } else {
    281  - code.add(base);
     250 + case NEG: {
     251 + boolean wrap = state.contains(Flags.BODY_ONLY);
     252 + if (wrap) {
     253 + code.add('(');
     254 + }
     255 + code.add('-');
     256 + addArg(code, insn.getArg(0));
     257 + if (wrap) {
     258 + code.add(')');
    282 259   }
    283 260   break;
     261 + }
    284 262   
    285 263   case RETURN:
    286 264   if (insn.getArgsCount() != 0) {
    skipped 19 lines
    306 284   
    307 285   case CMP_L:
    308 286   case CMP_G:
    309  - code.add(String.format("(%1$s > %2$s ? 1 : (%1$s == %2$s ? 0 : -1))", arg(insn, 0), arg(insn, 1)));
     287 + code.add('(');
     288 + addArg(code, insn.getArg(0));
     289 + code.add(" > ");
     290 + addArg(code, insn.getArg(1));
     291 + code.add(" ? 1 : (");
     292 + addArg(code, insn.getArg(0));
     293 + code.add(" == ");
     294 + addArg(code, insn.getArg(1));
     295 + code.add("? 0 : -1))");
    310 296   break;
    311 297   
    312 298   case INSTANCE_OF: {
    skipped 1 lines
    314 300   if (wrap) {
    315 301   code.add('(');
    316 302   }
    317  - code.add(arg(insn, 0));
     303 + addArg(code, insn.getArg(0));
    318 304   code.add(" instanceof ");
    319 305   code.add(useType((ArgType) ((IndexInsnNode) insn).getIndex()));
    320 306   if (wrap) {
    skipped 11 lines
    332 318   
    333 319   case NEW_ARRAY: {
    334 320   ArgType arrayType = insn.getResult().getType();
     321 + code.add("new ").add(useType(arrayType.getArrayRootElement()));
     322 + code.add('[');
     323 + addArg(code, insn.getArg(0));
     324 + code.add(']');
    335 325   int dim = arrayType.getArrayDimension();
    336  - code.add("new ").add(useType(arrayType.getArrayRootElement())).add('[').add(arg(insn, 0)).add(']');
    337 326   for (int i = 0; i < dim - 1; i++) {
    338 327   code.add("[]");
    339 328   }
    skipped 1 lines
    341 330   }
    342 331   
    343 332   case ARRAY_LENGTH:
    344  - code.add(arg(insn, 0)).add(".length");
     333 + addArg(code, insn.getArg(0));
     334 + code.add(".length");
    345 335   break;
    346 336   
    347 337   case FILL_ARRAY:
    skipped 36 lines
    384 374   code.add(staticField((FieldInfo) ((IndexInsnNode) insn).getIndex()));
    385 375   break;
    386 376   case SPUT:
    387  - IndexInsnNode node = (IndexInsnNode) insn;
    388  - fieldPut(node);
    389  - code.add(staticField((FieldInfo) node.getIndex())).add(" = ");
    390  - addArg(code, node.getArg(0), false);
     377 + FieldInfo field = (FieldInfo) ((IndexInsnNode) insn).getIndex();
     378 + code.add(staticField(field)).add(" = ");
     379 + addArg(code, insn.getArg(0), false);
    391 380   break;
    392 381   
    393 382   case STR_CONCAT:
    394  - StringBuilder sb = new StringBuilder();
     383 + boolean wrap = state.contains(Flags.BODY_ONLY);
     384 + if (wrap) {
     385 + code.add('(');
     386 + }
    395 387   for (Iterator<InsnArg> it = insn.getArguments().iterator(); it.hasNext(); ) {
    396  - sb.append(arg(it.next()));
     388 + addArg(code, it.next());
    397 389   if (it.hasNext()) {
    398  - sb.append(" + ");
     390 + code.add(" + ");
    399 391   }
    400 392   }
    401  - // TODO: wrap in braces only if necessary
    402  - if (state.contains(Flags.BODY_ONLY)) {
    403  - code.add('(').add(sb.toString()).add(')');
    404  - } else {
    405  - code.add(sb.toString());
     393 + if (wrap) {
     394 + code.add(')');
    406 395   }
    407 396   break;
    408 397   
    409 398   case MONITOR_ENTER:
    410 399   if (isFallback()) {
    411  - code.add("monitor-enter(").add(arg(insn.getArg(0))).add(')');
     400 + code.add("monitor-enter(");
     401 + addArg(code, insn.getArg(0));
     402 + code.add(')');
    412 403   }
    413 404   break;
    414 405   
    415 406   case MONITOR_EXIT:
    416 407   if (isFallback()) {
    417  - code.add("monitor-exit(").add(arg(insn, 0)).add(')');
     408 + code.add("monitor-exit(");
     409 + addArg(code, insn.getArg(0));
     410 + code.add(')');
    418 411   }
    419 412   break;
    420 413   
    skipped 1 lines
    422 415   if (isFallback()) {
    423 416   code.add("move-exception");
    424 417   } else {
    425  - code.add(arg(insn, 0));
     418 + addArg(code, insn.getArg(0));
    426 419   }
    427 420   break;
    428 421   
    skipped 2 lines
    431 424   break;
    432 425   
    433 426   case ARGS:
    434  - code.add(arg(insn, 0));
     427 + addArg(code, insn.getArg(0));
    435 428   break;
    436 429   
    437 430   /* fallback mode instructions */
    skipped 1 lines
    439 432   assert isFallback() : "if insn in not fallback mode";
    440 433   IfNode ifInsn = (IfNode) insn;
    441 434   code.add("if (");
    442  - code.add(arg(insn.getArg(0))).add(' ');
     435 + addArg(code, insn.getArg(0));
     436 + code.add(' ');
    443 437   code.add(ifInsn.getOp().getSymbol()).add(' ');
    444  - code.add(arg(insn.getArg(1)));
     438 + addArg(code, insn.getArg(1));
    445 439   code.add(") goto ").add(MethodGen.getLabelName(ifInsn.getTarget()));
    446 440   break;
    447 441   
    skipped 5 lines
    453 447   case SWITCH:
    454 448   assert isFallback();
    455 449   SwitchNode sw = (SwitchNode) insn;
    456  - code.add("switch(").add(arg(insn, 0)).add(") {");
     450 + code.add("switch(");
     451 + addArg(code, insn.getArg(0));
     452 + code.add(") {");
    457 453   code.incIndent();
    458 454   for (int i = 0; i < sw.getCasesCount(); i++) {
    459 455   code.startLine("case ").add(sw.getKeys()[i]).add(": goto ");
    skipped 21 lines
    481 477   code.add("new ").add(useType(insn.getResult().getType()));
    482 478   code.add('{');
    483 479   for (int i = 0; i < c; i++) {
    484  - code.add(arg(insn, i));
     480 + addArg(code, insn.getArg(i));
    485 481   if (i + 1 < c) {
    486 482   code.add(", ");
    487 483   }
    skipped 77 lines
    565 561   defCtr.getAttributes().add(AttributeFlag.DONT_GENERATE);
    566 562   }
    567 563   code.add("new ").add(parent == null ? "Object" : useClass(parent)).add("() ");
    568  - new ClassGen(cls, mgen.getClassGen().getParentGen(), fallback).makeClassBody(code);
     564 + new ClassGen(cls, mgen.getClassGen().getParentGen(), fallback).addClassBody(code);
    569 565   return;
    570 566   }
    571 567   if (insn.isSelf()) {
    skipped 133 lines
    705 701   }
    706 702   
    707 703   private void makeTernary(TernaryInsn insn, CodeWriter code, EnumSet<Flags> state) throws CodegenException {
    708  - String cond = ConditionGen.make(this, insn.getCondition());
    709  - CodeWriter th = arg(insn.getArg(0), false);
    710  - CodeWriter els = arg(insn.getArg(1), false);
    711  - if (th.toString().equals("true") && els.toString().equals("false")) {
    712  - code.add(cond);
     704 + boolean wrap = state.contains(Flags.BODY_ONLY);
     705 + if (wrap) {
     706 + code.add('(');
     707 + }
     708 + InsnArg first = insn.getArg(0);
     709 + InsnArg second = insn.getArg(1);
     710 + ConditionGen condGen = new ConditionGen(this);
     711 + if (first.equals(LiteralArg.TRUE) && second.equals(LiteralArg.FALSE)) {
     712 + condGen.add(code, insn.getCondition());
    713 713   } else {
    714  - if (state.contains(Flags.BODY_ONLY)) {
    715  - code.add("((").add(cond).add(')').add(" ? ").add(th).add(" : ").add(els).add(')');
    716  - } else {
    717  - code.add('(').add(cond).add(')').add(" ? ").add(th).add(" : ").add(els);
    718  - }
     714 + condGen.wrap(code, insn.getCondition());
     715 + code.add(" ? ");
     716 + addArg(code, first, false);
     717 + code.add(" : ");
     718 + addArg(code, second, false);
     719 + }
     720 + if (wrap) {
     721 + code.add(')');
    719 722   }
    720 723   }
    721 724   
    skipped 21 lines
    743 746   if (arg.isLiteral() && (op == ArithOp.ADD || op == ArithOp.SUB)) {
    744 747   LiteralArg lit = (LiteralArg) arg;
    745 748   if (lit.isInteger() && lit.getLiteral() == 1) {
     749 + assignVar(code, insn);
    746 750   String opSymbol = op.getSymbol();
    747  - code.add(assignVar(insn)).add(opSymbol).add(opSymbol);
     751 + code.add(opSymbol).add(opSymbol);
    748 752   return;
    749 753   }
    750 754   }
    751 755   // +=, -= ...
    752  - code.add(assignVar(insn)).add(' ').add(op.getSymbol()).add("= ");
     756 + assignVar(code, insn);
     757 + code.add(' ').add(op.getSymbol()).add("= ");
    753 758   addArg(code, arg, false);
    754 759   }
    755 760  }
    skipped 1 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
    skipped 57 lines
    58 58   return classGen;
    59 59   }
    60 60   
     61 + public MethodNode getMethodNode() {
     62 + return mth;
     63 + }
     64 + 
    61 65   public boolean addDefinition(CodeWriter code) {
    62 66   if (mth.getMethodInfo().isClassInit()) {
    63 67   code.startLine("static");
    skipped 20 lines
    84 88   }
    85 89   code.startLine(ai.makeString());
    86 90   
    87  - if (classGen.makeGenericMap(code, mth.getGenericMap())) {
     91 + if (classGen.addGenericMap(code, mth.getGenericMap())) {
    88 92   code.add(' ');
    89 93   }
    90 94   if (mth.getAccessFlags().isConstructor()) {
    skipped 154 lines
    245 249   } else {
    246 250   Region startRegion = mth.getRegion();
    247 251   if (startRegion != null) {
    248  - (new RegionGen(this, mth)).makeRegion(code, startRegion);
     252 + (new RegionGen(this)).makeRegion(code, startRegion);
    249 253   } else {
    250 254   addFallbackMethodCode(code);
    251 255   }
    skipped 37 lines
    289 293   }
    290 294   
    291 295   public static void addFallbackInsns(CodeWriter code, MethodNode mth, List<InsnNode> insns, boolean addLabels) {
    292  - InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), mth, true);
     296 + InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), true);
    293 297   for (InsnNode insn : insns) {
    294 298   AttributesList attrs = insn.getAttributes();
    295 299   if (addLabels) {
    skipped 34 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
    skipped 14 lines
    15 15  import jadx.core.dex.nodes.IContainer;
    16 16  import jadx.core.dex.nodes.IRegion;
    17 17  import jadx.core.dex.nodes.InsnNode;
    18  -import jadx.core.dex.nodes.MethodNode;
    19 18  import jadx.core.dex.regions.IfCondition;
    20 19  import jadx.core.dex.regions.IfRegion;
    21 20  import jadx.core.dex.regions.LoopRegion;
    skipped 14 lines
    36 35  public class RegionGen extends InsnGen {
    37 36   private static final Logger LOG = LoggerFactory.getLogger(RegionGen.class);
    38 37   
    39  - public RegionGen(MethodGen mgen, MethodNode mth) {
    40  - super(mgen, mth, false);
     38 + public RegionGen(MethodGen mgen) {
     39 + super(mgen, false);
    41 40   }
    42 41   
    43 42   public void makeRegion(CodeWriter code, IContainer cont) throws CodegenException {
    skipped 22 lines
    66 65   (DeclareVariablesAttr) cont.getAttributes().get(AttributeType.DECLARE_VARIABLES);
    67 66   if (declVars != null) {
    68 67   for (RegisterArg v : declVars.getVars()) {
    69  - code.startLine(declareVar(v)).add(';');
     68 + code.startLine();
     69 + declareVar(code, v);
     70 + code.add(';');
    70 71   }
    71 72   }
    72 73   }
    skipped 38 lines
    111 112   if (newLine) {
    112 113   code.startLine();
    113 114   }
    114  - code.add("if (").add(ConditionGen.make(this, region.getCondition())).add(") {");
     115 + code.add("if (");
     116 + new ConditionGen(this).add(code, region.getCondition());
     117 + code.add(") {");
    115 118   makeRegionIndent(code, region.getThenRegion());
    116 119   code.startLine('}');
    117 120   
    skipped 51 lines
    169 172   return code;
    170 173   }
    171 174   
    172  - String condStr = ConditionGen.make(this, condition);
     175 + ConditionGen conditionGen = new ConditionGen(this);
    173 176   if (region.isConditionAtEnd()) {
    174 177   code.startLine("do {");
    175 178   makeRegionIndent(code, region.getBody());
    176  - code.startLine("} while (").add(condStr).add(");");
     179 + code.startLine("} while (");
     180 + conditionGen.add(code, condition);
     181 + code.add(");");
    177 182   } else {
    178  - code.startLine("while (").add(condStr).add(") {");
     183 + code.startLine("while (");
     184 + conditionGen.add(code, condition);
     185 + code.add(") {");
    179 186   makeRegionIndent(code, region.getBody());
    180 187   code.startLine('}');
    181 188   }
    skipped 92 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java
    1 1  package jadx.core.dex.visitors;
    2 2   
    3 3  import jadx.core.dex.attributes.AttributeFlag;
     4 +import jadx.core.dex.attributes.AttributeType;
    4 5  import jadx.core.dex.attributes.AttributesList;
    5 6  import jadx.core.dex.attributes.FieldReplaceAttr;
    6 7  import jadx.core.dex.info.AccessInfo;
    skipped 32 lines
    39 40   removeSyntheticFields(cls);
    40 41   removeSyntheticMethods(cls);
    41 42   removeEmptyMethods(cls);
     43 + 
     44 + checkFieldsInit(cls);
    42 45   return false;
    43 46   }
    44 47   
    skipped 129 lines
    174 177   }
    175 178   return true;
    176 179   }
     180 + 
     181 + private static void checkFieldsInit(ClassNode cls) {
     182 + MethodNode clinit = cls.searchMethodByName("<clinit>()V");
     183 + if (clinit == null
     184 + || !clinit.getAccessFlags().isStatic()
     185 + || clinit.isNoCode()) {
     186 + return;
     187 + }
     188 + 
     189 + for (BlockNode block : clinit.getBasicBlocks()) {
     190 + for (InsnNode insn : block.getInstructions()) {
     191 + if (insn.getType() == InsnType.SPUT) {
     192 + processStaticFieldAssign(cls, (IndexInsnNode) insn);
     193 + }
     194 + }
     195 + }
     196 + }
     197 + 
     198 + /**
     199 + * Remove field initialization if it assign in "<clinit>" method
     200 + */
     201 + private static void processStaticFieldAssign(ClassNode cls, IndexInsnNode insn) {
     202 + FieldInfo field = (FieldInfo) insn.getIndex();
     203 + String thisClass = cls.getFullName();
     204 + if (field.getDeclClass().getFullName().equals(thisClass)) {
     205 + FieldNode fn = cls.searchField(field);
     206 + if (fn != null && fn.getAccessFlags().isFinal()) {
     207 + fn.getAttributes().remove(AttributeType.FIELD_VALUE);
     208 + }
     209 + }
     210 + }
     211 + 
    177 212  }
    178 213   
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/internal/TestRedundantBrackets.java
    skipped 5 lines
    6 6  import org.junit.Test;
    7 7   
    8 8  import static org.hamcrest.CoreMatchers.containsString;
    9  -import static org.hamcrest.CoreMatchers.either;
    10 9  import static org.hamcrest.CoreMatchers.not;
    11 10  import static org.junit.Assert.assertThat;
    12 11   
    skipped 5 lines
    18 17   }
    19 18   
    20 19   public int method2(Object obj) {
    21  - if (obj instanceof String) {
    22  - return ((String) obj).length();
    23  - }
    24  - return 0;
     20 + return obj instanceof String ? ((String) obj).length() : 0;
    25 21   }
    26 22   
    27 23   public int method3(int a, int b) {
    skipped 22 lines
    50 46   public void test() {
    51 47   ClassNode cls = getClassNode(TestCls.class);
    52 48   String code = cls.getCode().toString();
     49 + System.out.println(code);
    53 50   
    54 51   assertThat(code, not(containsString("(-1)")));
    55 52   assertThat(code, not(containsString("return;")));
    56  - assertThat(code, either(containsString("if (obj instanceof String) {"))
    57  - .or(containsString("return (obj instanceof String) ? ")));
     53 + 
     54 + assertThat(code, containsString("return obj instanceof String ? ((String) obj).length() : 0;"));
    58 55   assertThat(code, containsString("if (a + b < 10)"));
    59 56   assertThat(code, containsString("if ((a & b) != 0)"));
    60 57   assertThat(code, containsString("if (num == 4 || num == 6 || num == 8 || num == 10)"));
    skipped 11 lines
  • ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/internal/TestReturnWrapping.java
    skipped 56 lines
    57 57   assertThat(code, containsString("return 255;"));
    58 58   assertThat(code, containsString("return arg0 + 1;"));
    59 59   //assertThat(code, containsString("return Integer.toHexString(i);"));
    60  - assertThat(code, containsString("return (i > 128) ? arg0.toString() + ret.toString() : Integer.valueOf(i);"));
     60 + assertThat(code, containsString("return i > 128 ? arg0.toString() + ret.toString() : Integer.valueOf(i);"));
    61 61   assertThat(code, containsString("return arg0 + 2;"));
    62 62   assertThat(code, containsString("arg0 -= 951;"));
    63 63   }
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/internal/TestStaticFieldsInit.java
     1 +package jadx.tests.internal;
     2 + 
     3 +import jadx.api.InternalJadxTest;
     4 +import jadx.core.dex.nodes.ClassNode;
     5 + 
     6 +import org.junit.Test;
     7 + 
     8 +import static org.hamcrest.CoreMatchers.containsString;
     9 +import static org.hamcrest.CoreMatchers.not;
     10 +import static org.junit.Assert.assertThat;
     11 + 
     12 +public class TestStaticFieldsInit extends InternalJadxTest {
     13 + 
     14 + public static class TestCls {
     15 + public static final String s1 = "1";
     16 + public static final String s2 = "12".substring(1);
     17 + public static final String s3 = null;
     18 + public static final String s4;
     19 + public static final String s5 = "5";
     20 + public static String s6 = "6";
     21 + 
     22 + static {
     23 + if (s5.equals("?")) {
     24 + s4 = "?";
     25 + } else {
     26 + s4 = "4";
     27 + }
     28 + }
     29 + }
     30 + 
     31 + @Test
     32 + public void test() {
     33 + ClassNode cls = getClassNode(TestCls.class);
     34 + String code = cls.getCode().toString();
     35 + System.out.println(code);
     36 + 
     37 + assertThat(code, not(containsString("public static final String s2 = null;")));
     38 + // TODO:
     39 + // assertThat(code, containsString("public static final String s3 = null;"));
     40 + }
     41 +}
     42 + 
  • ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/internal/generics/TestGenerics2.java
    skipped 42 lines
    43 43   assertThat(code, containsString("public ItemReference(V item, Object id, ReferenceQueue<? super V> queue) {"));
    44 44   assertThat(code, containsString("public V get(Object id) {"));
    45 45   assertThat(code, containsString("WeakReference<V> ref = "));
    46  - assertThat(code, containsString("return (ref != null) ? ref.get() : null;"));
     46 + assertThat(code, containsString("return ref != null ? ref.get() : null;"));
    47 47   }
    48 48  }
    49 49   
  • ■ ■ ■ ■ ■ ■
    jadx-gui/src/main/java/jadx/gui/JadxTextArea.java
    skipped 20 lines
    21 21  public class JadxTextArea extends RSyntaxTextArea {
    22 22   private static final Logger LOG = LoggerFactory.getLogger(JadxTextArea.class);
    23 23   
     24 + private static final long serialVersionUID = 6312736869579635796L;
     25 + 
    24 26   private static final Color BACKGROUND = new Color(0xf7f7f7);
    25 27   private static final Color JUMP_FOREGROUND = new Color(0x785523);
    26 28   private static final Color JUMP_BACKGROUND = new Color(0xE6E6FF);
    skipped 105 lines
Please wait...
Page is in error, reload to recover