ClassGen.java 17.9 KB
Newer Older
S
Skylot 已提交
1 2
package jadx.core.codegen;

S
Skylot 已提交
3 4 5 6 7 8 9 10 11 12 13 14
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.android.dx.rop.code.AccessFlags;

15
import jadx.api.JadxArgs;
S
Skylot 已提交
16 17
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
S
Skylot 已提交
18
import jadx.core.dex.attributes.AttrNode;
S
Skylot 已提交
19 20
import jadx.core.dex.attributes.nodes.EnumClassAttr;
import jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField;
21 22
import jadx.core.dex.attributes.nodes.JadxError;
import jadx.core.dex.attributes.nodes.JadxWarn;
S
Skylot 已提交
23
import jadx.core.dex.attributes.nodes.LineAttrNode;
S
Skylot 已提交
24
import jadx.core.dex.attributes.nodes.SourceFileAttr;
S
Skylot 已提交
25 26 27
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.instructions.args.ArgType;
28
import jadx.core.dex.instructions.args.PrimitiveType;
29
import jadx.core.dex.instructions.mods.ConstructorInsn;
S
Skylot 已提交
30
import jadx.core.dex.nodes.ClassNode;
S
Skylot 已提交
31
import jadx.core.dex.nodes.DexNode;
S
Skylot 已提交
32
import jadx.core.dex.nodes.FieldNode;
33
import jadx.core.dex.nodes.InsnNode;
S
Skylot 已提交
34
import jadx.core.dex.nodes.MethodNode;
35 36
import jadx.core.dex.nodes.parser.FieldInitAttr;
import jadx.core.dex.nodes.parser.FieldInitAttr.InitType;
37
import jadx.core.utils.CodegenUtils;
S
Skylot 已提交
38 39 40
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.CodegenException;
S
Skylot 已提交
41 42

public class ClassGen {
S
Skylot 已提交
43

S
Skylot 已提交
44 45 46 47
	private final ClassNode cls;
	private final ClassGen parentGen;
	private final AnnotationGen annotationGen;
	private final boolean fallback;
S
Sergey Toshin 已提交
48
	private final boolean useImports;
S
Skylot 已提交
49
	private final boolean showInconsistentCode;
50

S
Skylot 已提交
51
	private final Set<ClassInfo> imports = new HashSet<>();
S
Skylot 已提交
52
	private int clsDeclLine;
S
Skylot 已提交
53

54 55
	public ClassGen(ClassNode cls, JadxArgs jadxArgs) {
		this(cls, null, jadxArgs.isUseImports(), jadxArgs.isFallbackMode(), jadxArgs.isShowInconsistentCode());
S
Skylot 已提交
56 57 58
	}

	public ClassGen(ClassNode cls, ClassGen parentClsGen) {
S
Sergey Toshin 已提交
59
		this(cls, parentClsGen, parentClsGen.useImports, parentClsGen.fallback, parentClsGen.showInconsistentCode);
60 61
	}

S
Sergey Toshin 已提交
62
	public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean useImports, boolean fallback, boolean showBadCode) {
S
Skylot 已提交
63 64 65
		this.cls = cls;
		this.parentGen = parentClsGen;
		this.fallback = fallback;
S
Sergey Toshin 已提交
66
		this.useImports = useImports;
S
Skylot 已提交
67
		this.showInconsistentCode = showBadCode;
S
Skylot 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81

		this.annotationGen = new AnnotationGen(cls, this);
	}

	public ClassNode getClassNode() {
		return cls;
	}

	public CodeWriter makeClass() throws CodegenException {
		CodeWriter clsBody = new CodeWriter();
		addClassCode(clsBody);

		CodeWriter clsCode = new CodeWriter();
		if (!"".equals(cls.getPackage())) {
S
Skylot 已提交
82
			clsCode.add("package ").add(cls.getPackage()).add(';');
83
			clsCode.newLine();
S
Skylot 已提交
84
		}
S
Skylot 已提交
85 86
		int importsCount = imports.size();
		if (importsCount != 0) {
S
Skylot 已提交
87
			List<String> sortImports = new ArrayList<>(importsCount);
S
Skylot 已提交
88
			for (ClassInfo ic : imports) {
S
Skylot 已提交
89
				sortImports.add(ic.getAlias().getFullName());
S
Skylot 已提交
90
			}
S
Skylot 已提交
91 92 93
			Collections.sort(sortImports);

			for (String imp : sortImports) {
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
				ClassInfo importClassInfo = ClassInfo.fromName(cls.dex().root(), imp);
				ClassNode classNode = cls.dex().resolveClass(importClassInfo);
				// Clickable element seems to be limited by the next dot, therefore
				// we can't just use the complete class name including packagename
				int clsDotIdx = imp.lastIndexOf('.');
				String pkg = "";
				if (clsDotIdx >= 0) {
					pkg = imp.substring(0, clsDotIdx + 1);
					imp = imp.substring(clsDotIdx + 1);
				}
				clsCode.startLine("import ");
				clsCode.add(pkg);
				if (classNode != null) {
					// attach the clickable link info to the class name
					clsCode.attachAnnotation(classNode);
				}
				clsCode.add(imp);
				clsCode.add(';');
S
Skylot 已提交
112
			}
113
			clsCode.newLine();
S
Skylot 已提交
114 115 116 117 118 119 120 121 122

			sortImports.clear();
			imports.clear();
		}
		clsCode.add(clsBody);
		return clsCode;
	}

	public void addClassCode(CodeWriter code) throws CodegenException {
S
Skylot 已提交
123
		if (cls.contains(AFlag.DONT_GENERATE)) {
S
Skylot 已提交
124
			return;
S
Skylot 已提交
125
		}
126 127
		CodegenUtils.addComments(code, cls);
		insertDecompilationProblems(code, cls);
S
Skylot 已提交
128 129
		addClassDeclaration(code);
		addClassBody(code);
S
Skylot 已提交
130 131
	}

S
Skylot 已提交
132
	public void addClassDeclaration(CodeWriter clsCode) {
S
Skylot 已提交
133 134
		AccessInfo af = cls.getAccessFlags();
		if (af.isInterface()) {
135 136
			af = af.remove(AccessFlags.ACC_ABSTRACT)
					.remove(AccessFlags.ACC_STATIC);
S
Skylot 已提交
137
		} else if (af.isEnum()) {
S
Skylot 已提交
138 139 140
			af = af.remove(AccessFlags.ACC_FINAL)
					.remove(AccessFlags.ACC_ABSTRACT)
					.remove(AccessFlags.ACC_STATIC);
S
Skylot 已提交
141 142
		}

143
		// 'static' and 'private' modifier not allowed for top classes (not inner)
S
Skylot 已提交
144
		if (!cls.getAlias().isInner()) {
145
			af = af.remove(AccessFlags.ACC_STATIC).remove(AccessFlags.ACC_PRIVATE);
S
Skylot 已提交
146 147
		}

S
Skylot 已提交
148
		annotationGen.addForClass(clsCode);
S
Skylot 已提交
149
		insertSourceFileInfo(clsCode, cls);
150
		insertRenameInfo(clsCode, cls);
S
Skylot 已提交
151 152
		clsCode.startLine(af.makeString());
		if (af.isInterface()) {
S
Skylot 已提交
153
			if (af.isAnnotation()) {
S
Skylot 已提交
154
				clsCode.add('@');
S
Skylot 已提交
155
			}
S
Skylot 已提交
156 157 158 159 160 161
			clsCode.add("interface ");
		} else if (af.isEnum()) {
			clsCode.add("enum ");
		} else {
			clsCode.add("class ");
		}
162
		clsCode.attachDefinition(cls);
S
Skylot 已提交
163
		clsCode.add(cls.getShortName());
S
Skylot 已提交
164

S
Skylot 已提交
165
		addGenericMap(clsCode, cls.getGenericMap());
166 167
		clsCode.add(' ');

S
Skylot 已提交
168
		ArgType sup = cls.getSuperClass();
S
Skylot 已提交
169
		if (sup != null
S
Skylot 已提交
170 171
				&& !sup.equals(ArgType.OBJECT)
				&& !sup.getObject().equals(ArgType.ENUM.getObject())) {
172 173 174
			clsCode.add("extends ");
			useClass(clsCode, sup);
			clsCode.add(' ');
S
Skylot 已提交
175 176
		}

S
Skylot 已提交
177
		if (!cls.getInterfaces().isEmpty() && !af.isAnnotation()) {
S
Skylot 已提交
178
			if (cls.getAccessFlags().isInterface()) {
179
				clsCode.add("extends ");
S
Skylot 已提交
180
			} else {
181
				clsCode.add("implements ");
S
Skylot 已提交
182
			}
S
Skylot 已提交
183 184
			for (Iterator<ArgType> it = cls.getInterfaces().iterator(); it.hasNext(); ) {
				ArgType interf = it.next();
185
				useClass(clsCode, interf);
S
Skylot 已提交
186
				if (it.hasNext()) {
S
Skylot 已提交
187
					clsCode.add(", ");
S
Skylot 已提交
188
				}
S
Skylot 已提交
189
			}
S
Skylot 已提交
190
			if (!cls.getInterfaces().isEmpty()) {
191
				clsCode.add(' ');
S
Skylot 已提交
192
			}
193 194 195
		}
	}

S
Skylot 已提交
196
	public boolean addGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
S
Skylot 已提交
197
		if (gmap == null || gmap.isEmpty()) {
S
Skylot 已提交
198
			return false;
S
Skylot 已提交
199
		}
200 201 202 203 204 205 206 207
		code.add('<');
		int i = 0;
		for (Entry<ArgType, List<ArgType>> e : gmap.entrySet()) {
			ArgType type = e.getKey();
			List<ArgType> list = e.getValue();
			if (i != 0) {
				code.add(", ");
			}
208 209 210
			if (type.isGenericType()) {
				code.add(type.getObject());
			} else {
S
Skylot 已提交
211
				useClass(code, type);
212
			}
213 214
			if (list != null && !list.isEmpty()) {
				code.add(" extends ");
S
Skylot 已提交
215
				for (Iterator<ArgType> it = list.iterator(); it.hasNext(); ) {
216
					ArgType g = it.next();
217 218 219
					if (g.isGenericType()) {
						code.add(g.getObject());
					} else {
S
Skylot 已提交
220
						useClass(code, g);
221
					}
222 223 224 225 226 227
					if (it.hasNext()) {
						code.add(" & ");
					}
				}
			}
			i++;
S
Skylot 已提交
228
		}
229
		code.add('>');
S
Skylot 已提交
230
		return true;
S
Skylot 已提交
231 232
	}

S
Skylot 已提交
233
	public void addClassBody(CodeWriter clsCode) throws CodegenException {
234
		clsCode.add('{');
S
Skylot 已提交
235 236 237 238 239 240
		clsDeclLine = clsCode.getLine();
		clsCode.incIndent();
		addFields(clsCode);
		addInnerClasses(clsCode, cls);
		addMethods(clsCode);
		clsCode.decIndent();
241
		clsCode.startLine('}');
S
Skylot 已提交
242 243
	}

S
Skylot 已提交
244
	private void addInnerClasses(CodeWriter code, ClassNode cls) throws CodegenException {
S
Skylot 已提交
245 246
		for (ClassNode innerCls : cls.getInnerClasses()) {
			if (innerCls.contains(AFlag.DONT_GENERATE)
S
Skylot 已提交
247
					|| innerCls.contains(AFlag.ANONYMOUS_CLASS)) {
S
Skylot 已提交
248 249
				continue;
			}
S
Skylot 已提交
250
			ClassGen inClGen = new ClassGen(innerCls, getParentGen());
S
Skylot 已提交
251 252 253 254 255 256 257
			code.newLine();
			inClGen.addClassCode(code);
			imports.addAll(inClGen.getImports());
		}
	}

	private boolean isInnerClassesPresents() {
S
Skylot 已提交
258
		for (ClassNode innerCls : cls.getInnerClasses()) {
S
Skylot 已提交
259
			if (!innerCls.contains(AFlag.ANONYMOUS_CLASS)) {
S
Skylot 已提交
260
				return true;
S
Skylot 已提交
261
			}
S
Skylot 已提交
262
		}
S
Skylot 已提交
263
		return false;
S
Skylot 已提交
264 265
	}

S
Skylot 已提交
266
	private void addMethods(CodeWriter code) {
S
Skylot 已提交
267 268
		List<MethodNode> methods = sortMethodsByLine(cls.getMethods());
		for (MethodNode mth : methods) {
S
Skylot 已提交
269 270 271 272 273 274
			if (mth.contains(AFlag.DONT_GENERATE)) {
				continue;
			}
			if (code.getLine() != clsDeclLine) {
				code.newLine();
			}
275
			int savedIndent = code.getIndent();
S
Skylot 已提交
276 277 278
			try {
				addMethod(code, mth);
			} catch (Exception e) {
279 280 281 282
				code.newLine().add("/*");
				code.newLine().add(ErrorsCounter.methodError(mth, "Method generation error", e));
				code.newLine().add(Utils.getStackTrace(e));
				code.newLine().add("*/");
283
				code.setIndent(savedIndent);
S
Skylot 已提交
284 285 286 287
			}
		}
	}

S
Skylot 已提交
288
	private static List<MethodNode> sortMethodsByLine(List<MethodNode> methods) {
S
Skylot 已提交
289
		List<MethodNode> out = new ArrayList<>(methods);
S
Skylot 已提交
290
		out.sort(Comparator.comparingInt(LineAttrNode::getSourceLine));
S
Skylot 已提交
291 292 293
		return out;
	}

S
Skylot 已提交
294
	private boolean isMethodsPresents() {
S
Skylot 已提交
295
		for (MethodNode mth : cls.getMethods()) {
S
Skylot 已提交
296
			if (!mth.contains(AFlag.DONT_GENERATE)) {
S
Skylot 已提交
297
				return true;
298
			}
S
Skylot 已提交
299
		}
S
Skylot 已提交
300
		return false;
S
Skylot 已提交
301 302
	}

S
Skylot 已提交
303 304
	private void addMethod(CodeWriter code, MethodNode mth) throws CodegenException {
		if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) {
S
Skylot 已提交
305
			MethodGen mthGen = new MethodGen(this, mth);
S
Skylot 已提交
306 307 308 309 310 311 312 313 314 315
			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 {
316
			CodegenUtils.addComments(code, mth);
317
			insertDecompilationProblems(code, mth);
S
Skylot 已提交
318
			boolean badCode = mth.contains(AFlag.INCONSISTENT_CODE);
S
Skylot 已提交
319 320 321 322
			if (badCode && showInconsistentCode) {
				code.startLine("/* Code decompiled incorrectly, please refer to instructions dump. */");
				mth.remove(AFlag.INCONSISTENT_CODE);
				badCode = false;
S
Skylot 已提交
323
			}
S
Skylot 已提交
324
			MethodGen mthGen;
325
			if (badCode || mth.contains(AType.JADX_ERROR) || fallback) {
S
Skylot 已提交
326 327 328 329
				mthGen = MethodGen.getFallbackMethodGen(mth);
			} else {
				mthGen = new MethodGen(this, mth);
			}
S
Skylot 已提交
330 331 332 333 334 335
			if (mthGen.addDefinition(code)) {
				code.add(' ');
			}
			code.add('{');
			code.incIndent();
			insertSourceFileInfo(code, mth);
336 337 338 339 340
			if (fallback) {
				mthGen.addFallbackMethodCode(code);
			} else {
				mthGen.addInstructions(code);
			}
S
Skylot 已提交
341 342 343 344
			code.decIndent();
			code.startLine('}');
		}
	}
345

346 347 348
	private void insertDecompilationProblems(CodeWriter code, AttrNode node) {
		List<JadxError> errors = node.getAll(AType.JADX_ERROR);
		List<JadxWarn> warns = node.getAll(AType.JADX_WARN);
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
		if (!errors.isEmpty()) {
			errors.forEach(err -> {
				code.startLine("/*  JADX ERROR: ").add(err.getError());
				Throwable cause = err.getCause();
				if (cause != null) {
					code.incIndent();
					Utils.appendStackTrace(code, cause);
					code.decIndent();
				}
				code.add("*/");
			});
		}
		if (!warns.isEmpty()) {
			warns.forEach(warn -> code.startLine("/* JADX WARNING: ").add(warn.getWarn()).add(" */"));
		}
	}

S
Skylot 已提交
366 367 368
	private void addFields(CodeWriter code) throws CodegenException {
		addEnumFields(code);
		for (FieldNode f : cls.getFields()) {
S
Skylot 已提交
369
			if (f.contains(AFlag.DONT_GENERATE)) {
370 371
				continue;
			}
372
			CodegenUtils.addComments(code, f);
373
			annotationGen.addForField(code, f);
374

S
Skylot 已提交
375
			if (f.getFieldInfo().isRenamed()) {
376 377
				code.startLine("/* renamed from: ").add(f.getName()).add(" */");
			}
378
			code.startLine(f.getAccessFlags().makeString());
379
			useType(code, f.getType());
380
			code.add(' ');
381
			code.attachDefinition(f);
382
			code.add(f.getAlias());
383
			FieldInitAttr fv = f.get(AType.FIELD_INIT);
384 385 386
			if (fv != null) {
				code.add(" = ");
				if (fv.getValue() == null) {
387
					code.add(TypeGen.literalToString(0, f.getType(), cls));
388
				} else {
389 390 391 392 393 394
					if (fv.getValueType() == InitType.CONST) {
						annotationGen.encodeValue(code, fv.getValue());
					} else if (fv.getValueType() == InitType.INSN) {
						InsnGen insnGen = makeInsnGen(fv.getInsnMth());
						addInsnBody(insnGen, code, fv.getInsn());
					}
395 396 397 398 399 400
				}
			}
			code.add(';');
		}
	}

S
Skylot 已提交
401 402 403 404 405 406 407 408 409
	private boolean isFieldsPresents() {
		for (FieldNode field : cls.getFields()) {
			if (!field.contains(AFlag.DONT_GENERATE)) {
				return true;
			}
		}
		return false;
	}

S
Skylot 已提交
410
	private void addEnumFields(CodeWriter code) throws CodegenException {
S
Skylot 已提交
411
		EnumClassAttr enumFields = cls.get(AType.ENUM_CLASS);
412 413 414 415 416 417
		if (enumFields == null) {
			return;
		}
		InsnGen igen = null;
		for (Iterator<EnumField> it = enumFields.getFields().iterator(); it.hasNext(); ) {
			EnumField f = it.next();
418
			code.startLine(f.getField().getAlias());
419 420 421
			ConstructorInsn constrInsn = f.getConstrInsn();
			if (constrInsn.getArgsCount() > f.getStartArg()) {
				if (igen == null) {
422
					igen = makeInsnGen(enumFields.getStaticMethod());
S
Skylot 已提交
423
				}
424 425
				MethodNode callMth = cls.dex().resolveMethod(constrInsn.getCallMth());
				igen.generateMethodArguments(code, constrInsn, f.getStartArg(), callMth);
S
Skylot 已提交
426
			}
427
			if (f.getCls() != null) {
S
Skylot 已提交
428
				code.add(' ');
S
Skylot 已提交
429
				new ClassGen(f.getCls(), this).addClassBody(code);
S
Skylot 已提交
430
			}
431 432 433 434
			if (it.hasNext()) {
				code.add(',');
			}
		}
S
Skylot 已提交
435 436 437 438 439
		if (isMethodsPresents() || isFieldsPresents() || isInnerClassesPresents()) {
			if (enumFields.getFields().isEmpty()) {
				code.startLine();
			}
			code.add(';');
440 441 442
			if (isFieldsPresents()) {
				code.startLine();
			}
S
Skylot 已提交
443 444 445
		}
	}

446 447 448 449 450 451 452 453 454 455 456 457 458
	private InsnGen makeInsnGen(MethodNode mth) {
		MethodGen mthGen = new MethodGen(this, mth);
		return new InsnGen(mthGen, false);
	}

	private void addInsnBody(InsnGen insnGen, CodeWriter code, InsnNode insn) {
		try {
			insnGen.makeInsn(insn, code, InsnGen.Flags.BODY_ONLY_NOWRAP);
		} catch (Exception e) {
			ErrorsCounter.classError(cls, "Failed to generate init code", e);
		}
	}

459
	public void useType(CodeWriter code, ArgType type) {
S
Skylot 已提交
460
		PrimitiveType stype = type.getPrimitiveType();
461 462 463 464 465 466
		if (stype == null) {
			code.add(type.toString());
		} else if (stype == PrimitiveType.OBJECT) {
			if (type.isGenericType()) {
				code.add(type.getObject());
			} else {
S
Skylot 已提交
467
				useClass(code, type);
468 469 470 471 472 473
			}
		} else if (stype == PrimitiveType.ARRAY) {
			useType(code, type.getArrayElement());
			code.add("[]");
		} else {
			code.add(stype.getLongName());
474 475
		}
	}
476

S
Skylot 已提交
477
	public void useClass(CodeWriter code, ArgType type) {
S
Skylot 已提交
478
		useClass(code, ClassInfo.extCls(cls.root(), type));
S
Skylot 已提交
479
		ArgType[] generics = type.getGenericTypes();
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
		if (generics != null) {
			code.add('<');
			int len = generics.length;
			for (int i = 0; i < len; i++) {
				if (i != 0) {
					code.add(", ");
				}
				ArgType gt = generics[i];
				ArgType wt = gt.getWildcardType();
				if (wt != null) {
					code.add('?');
					int bounds = gt.getWildcardBounds();
					if (bounds != 0) {
						code.add(bounds == -1 ? " super " : " extends ");
						useType(code, wt);
					}
				} else {
					useType(code, gt);
S
Skylot 已提交
498
				}
499
			}
500
			code.add('>');
501
		}
S
Skylot 已提交
502 503
	}

S
Skylot 已提交
504 505 506 507 508 509 510 511 512 513 514
	public void useClass(CodeWriter code, ClassInfo classInfo) {
		ClassNode classNode = cls.dex().resolveClass(classInfo);
		if (classNode != null) {
			code.attachAnnotation(classNode);
		}
		String baseClass = useClassInternal(cls.getAlias(), classInfo.getAlias());
		code.add(baseClass);
	}

	private String useClassInternal(ClassInfo useCls, ClassInfo extClsInfo) {
		String fullName = extClsInfo.getFullName();
S
Sergey Toshin 已提交
515
		if (fallback || !useImports) {
516
			return fullName;
S
Skylot 已提交
517
		}
S
Skylot 已提交
518 519
		String shortName = extClsInfo.getShortName();
		if (extClsInfo.getPackage().equals("java.lang") && extClsInfo.getParentClass() == null) {
S
Skylot 已提交
520
			return shortName;
S
Skylot 已提交
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
		}
		if (isClassInnerFor(useCls, extClsInfo)) {
			return shortName;
		}
		if (isBothClassesInOneTopClass(useCls, extClsInfo)) {
			return shortName;
		}
		// don't add import if this class from same package
		if (extClsInfo.getPackage().equals(useCls.getPackage()) && !extClsInfo.isInner()) {
			return shortName;
		}
		// don't add import if class not public (must be accessed using inheritance)
		ClassNode classNode = cls.dex().resolveClass(extClsInfo);
		if (classNode != null && !classNode.getAccessFlags().isPublic()) {
			return shortName;
		}
		if (searchCollision(cls.dex(), useCls, extClsInfo)) {
			return fullName;
		}
540 541 542 543
		// ignore classes from default package
		if (extClsInfo.isDefaultPackage()) {
			return shortName;
		}
S
Skylot 已提交
544 545 546 547 548 549 550 551 552 553 554
		if (extClsInfo.getPackage().equals(useCls.getPackage())) {
			fullName = extClsInfo.getNameWithoutPackage();
		}
		for (ClassInfo importCls : getImports()) {
			if (!importCls.equals(extClsInfo)
					&& importCls.getShortName().equals(shortName)) {
				if (extClsInfo.isInner()) {
					String parent = useClassInternal(useCls, extClsInfo.getParentClass().getAlias());
					return parent + "." + shortName;
				} else {
					return fullName;
S
Skylot 已提交
555 556 557
				}
			}
		}
S
Skylot 已提交
558 559
		addImport(extClsInfo);
		return shortName;
S
Skylot 已提交
560 561
	}

562 563
	private void addImport(ClassInfo classInfo) {
		if (parentGen != null) {
S
Skylot 已提交
564
			parentGen.addImport(classInfo.getAlias());
565 566 567 568 569
		} else {
			imports.add(classInfo);
		}
	}

570 571 572 573 574 575 576 577
	private Set<ClassInfo> getImports() {
		if (parentGen != null) {
			return parentGen.getImports();
		} else {
			return imports;
		}
	}

S
Skylot 已提交
578 579 580 581 582 583 584 585 586 587
	private static boolean isBothClassesInOneTopClass(ClassInfo useCls, ClassInfo extClsInfo) {
		ClassInfo a = useCls.getTopParentClass();
		ClassInfo b = extClsInfo.getTopParentClass();
		if (a != null) {
			return a.equals(b);
		}
		// useCls - is a top class
		return useCls.equals(b);
	}

S
Skylot 已提交
588
	private static boolean isClassInnerFor(ClassInfo inner, ClassInfo parent) {
S
Skylot 已提交
589 590
		if (inner.isInner()) {
			ClassInfo p = inner.getParentClass();
S
Skylot 已提交
591
			return p.equals(parent) || isClassInnerFor(p, parent);
S
Skylot 已提交
592 593 594 595
		}
		return false;
	}

S
Skylot 已提交
596
	private static boolean searchCollision(DexNode dex, ClassInfo useCls, ClassInfo searchCls) {
S
Skylot 已提交
597 598 599
		if (useCls == null) {
			return false;
		}
S
Skylot 已提交
600
		String shortName = searchCls.getShortName();
S
Skylot 已提交
601 602 603 604
		if (useCls.getShortName().equals(shortName)) {
			return true;
		}
		ClassNode classNode = dex.resolveClass(useCls);
605 606
		if (classNode != null) {
			for (ClassNode inner : classNode.getInnerClasses()) {
S
Skylot 已提交
607
				if (inner.getShortName().equals(shortName)
S
Skylot 已提交
608
						&& !inner.getAlias().equals(searchCls)) {
609 610
					return true;
				}
S
Skylot 已提交
611 612
			}
		}
S
Skylot 已提交
613
		return searchCollision(dex, useCls.getParentClass(), searchCls);
S
Skylot 已提交
614 615
	}

616
	private void insertSourceFileInfo(CodeWriter code, AttrNode node) {
S
Skylot 已提交
617
		SourceFileAttr sourceFileAttr = node.get(AType.SOURCE_FILE);
618
		if (sourceFileAttr != null) {
619
			code.startLine("/* compiled from: ").add(sourceFileAttr.getFileName()).add(" */");
620 621 622
		}
	}

623 624
	private void insertRenameInfo(CodeWriter code, ClassNode cls) {
		ClassInfo classInfo = cls.getClassInfo();
625 626
		if (classInfo.isRenamed()) {
			code.startLine("/* renamed from: ").add(classInfo.getType().getObject()).add(" */");
627 628 629
		}
	}

S
Skylot 已提交
630
	public ClassGen getParentGen() {
631
		return parentGen == null ? this : parentGen;
S
Skylot 已提交
632 633 634 635 636 637 638 639 640 641
	}

	public AnnotationGen getAnnotationGen() {
		return annotationGen;
	}

	public boolean isFallbackMode() {
		return fallback;
	}
}