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

3
import jadx.api.IJadxArgs;
S
Skylot 已提交
4 5
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
S
Skylot 已提交
6
import jadx.core.dex.attributes.AttrNode;
S
Skylot 已提交
7 8 9
import jadx.core.dex.attributes.nodes.EnumClassAttr;
import jadx.core.dex.attributes.nodes.EnumClassAttr.EnumField;
import jadx.core.dex.attributes.nodes.SourceFileAttr;
S
Skylot 已提交
10 11 12 13
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
14
import jadx.core.dex.instructions.args.PrimitiveType;
S
Skylot 已提交
15
import jadx.core.dex.nodes.ClassNode;
S
Skylot 已提交
16
import jadx.core.dex.nodes.DexNode;
S
Skylot 已提交
17 18 19 20 21 22
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.parser.FieldValueAttr;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.CodegenException;
S
Skylot 已提交
23 24 25

import java.util.ArrayList;
import java.util.Collections;
S
Skylot 已提交
26
import java.util.Comparator;
S
Skylot 已提交
27 28 29
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
30 31
import java.util.Map;
import java.util.Map.Entry;
S
Skylot 已提交
32 33
import java.util.Set;

34 35 36
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

S
Skylot 已提交
37 38 39
import com.android.dx.rop.code.AccessFlags;

public class ClassGen {
40 41
	private static final Logger LOG = LoggerFactory.getLogger(ClassGen.class);

S
Skylot 已提交
42 43 44 45 46 47 48
	public static final Comparator<MethodNode> METHOD_LINE_COMPARATOR = new Comparator<MethodNode>() {
		@Override
		public int compare(MethodNode a, MethodNode b) {
			return Utils.compare(a.getSourceLine(), b.getSourceLine());
		}
	};

S
Skylot 已提交
49 50 51 52
	private final ClassNode cls;
	private final ClassGen parentGen;
	private final AnnotationGen annotationGen;
	private final boolean fallback;
S
Skylot 已提交
53
	private final boolean showInconsistentCode;
54

S
Skylot 已提交
55
	private final Set<ClassInfo> imports = new HashSet<ClassInfo>();
S
Skylot 已提交
56
	private int clsDeclLine;
S
Skylot 已提交
57

S
Skylot 已提交
58 59 60 61 62 63
	public ClassGen(ClassNode cls, IJadxArgs jadxArgs) {
		this(cls, null, jadxArgs.isFallbackMode(), jadxArgs.isShowInconsistentCode());
	}

	public ClassGen(ClassNode cls, ClassGen parentClsGen) {
		this(cls, parentClsGen, parentClsGen.fallback, parentClsGen.showInconsistentCode);
64 65
	}

S
Skylot 已提交
66
	public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean fallback, boolean showBadCode) {
S
Skylot 已提交
67 68 69
		this.cls = cls;
		this.parentGen = parentClsGen;
		this.fallback = fallback;
S
Skylot 已提交
70
		this.showInconsistentCode = showBadCode;
S
Skylot 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84

		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 已提交
85
			clsCode.add("package ").add(cls.getPackage()).add(';');
86
			clsCode.newLine();
S
Skylot 已提交
87
		}
S
Skylot 已提交
88 89 90 91
		int importsCount = imports.size();
		if (importsCount != 0) {
			List<String> sortImports = new ArrayList<String>(importsCount);
			for (ClassInfo ic : imports) {
S
Skylot 已提交
92
				sortImports.add(ic.getAlias().getFullName());
S
Skylot 已提交
93
			}
S
Skylot 已提交
94 95 96
			Collections.sort(sortImports);

			for (String imp : sortImports) {
97
				clsCode.startLine("import ").add(imp).add(';');
S
Skylot 已提交
98
			}
99
			clsCode.newLine();
S
Skylot 已提交
100 101 102 103 104 105 106 107 108

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

	public void addClassCode(CodeWriter code) throws CodegenException {
S
Skylot 已提交
109
		if (cls.contains(AFlag.DONT_GENERATE)) {
S
Skylot 已提交
110
			return;
S
Skylot 已提交
111
		}
S
Skylot 已提交
112
		if (cls.contains(AFlag.INCONSISTENT_CODE)) {
S
Skylot 已提交
113
			code.startLine("// jadx: inconsistent code");
S
Skylot 已提交
114
		}
S
Skylot 已提交
115 116
		addClassDeclaration(code);
		addClassBody(code);
S
Skylot 已提交
117 118
	}

S
Skylot 已提交
119
	public void addClassDeclaration(CodeWriter clsCode) {
S
Skylot 已提交
120 121 122 123
		AccessInfo af = cls.getAccessFlags();
		if (af.isInterface()) {
			af = af.remove(AccessFlags.ACC_ABSTRACT);
		} else if (af.isEnum()) {
S
Skylot 已提交
124 125 126
			af = af.remove(AccessFlags.ACC_FINAL)
					.remove(AccessFlags.ACC_ABSTRACT)
					.remove(AccessFlags.ACC_STATIC);
S
Skylot 已提交
127 128
		}

S
Skylot 已提交
129
		// 'static' modifier not allowed for top classes (not inner)
S
Skylot 已提交
130
		if (!cls.getAlias().isInner()) {
S
Skylot 已提交
131 132 133
			af = af.remove(AccessFlags.ACC_STATIC);
		}

S
Skylot 已提交
134
		annotationGen.addForClass(clsCode);
S
Skylot 已提交
135
		insertSourceFileInfo(clsCode, cls);
136
		insertRenameInfo(clsCode, cls);
S
Skylot 已提交
137 138
		clsCode.startLine(af.makeString());
		if (af.isInterface()) {
S
Skylot 已提交
139
			if (af.isAnnotation()) {
S
Skylot 已提交
140
				clsCode.add('@');
S
Skylot 已提交
141
			}
S
Skylot 已提交
142 143 144 145 146 147
			clsCode.add("interface ");
		} else if (af.isEnum()) {
			clsCode.add("enum ");
		} else {
			clsCode.add("class ");
		}
S
Skylot 已提交
148
		clsCode.add(cls.getShortName());
S
Skylot 已提交
149

S
Skylot 已提交
150
		addGenericMap(clsCode, cls.getGenericMap());
151 152
		clsCode.add(' ');

S
Skylot 已提交
153
		ArgType sup = cls.getSuperClass();
S
Skylot 已提交
154
		if (sup != null
S
Skylot 已提交
155 156
				&& !sup.equals(ArgType.OBJECT)
				&& !sup.getObject().equals(ArgType.ENUM.getObject())) {
157 158 159
			clsCode.add("extends ");
			useClass(clsCode, sup);
			clsCode.add(' ');
S
Skylot 已提交
160 161
		}

S
Skylot 已提交
162
		if (!cls.getInterfaces().isEmpty() && !af.isAnnotation()) {
S
Skylot 已提交
163
			if (cls.getAccessFlags().isInterface()) {
164
				clsCode.add("extends ");
S
Skylot 已提交
165
			} else {
166
				clsCode.add("implements ");
S
Skylot 已提交
167
			}
S
Skylot 已提交
168 169
			for (Iterator<ArgType> it = cls.getInterfaces().iterator(); it.hasNext(); ) {
				ArgType interf = it.next();
170
				useClass(clsCode, interf);
S
Skylot 已提交
171
				if (it.hasNext()) {
S
Skylot 已提交
172
					clsCode.add(", ");
S
Skylot 已提交
173
				}
S
Skylot 已提交
174
			}
S
Skylot 已提交
175
			if (!cls.getInterfaces().isEmpty()) {
176
				clsCode.add(' ');
S
Skylot 已提交
177
			}
178
		}
179
		clsCode.attachDefinition(cls);
180 181
	}

S
Skylot 已提交
182
	public boolean addGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
S
Skylot 已提交
183
		if (gmap == null || gmap.isEmpty()) {
S
Skylot 已提交
184
			return false;
S
Skylot 已提交
185
		}
186 187 188 189 190 191 192 193
		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(", ");
			}
194 195 196
			if (type.isGenericType()) {
				code.add(type.getObject());
			} else {
S
Skylot 已提交
197
				useClass(code, type);
198
			}
199 200
			if (list != null && !list.isEmpty()) {
				code.add(" extends ");
S
Skylot 已提交
201
				for (Iterator<ArgType> it = list.iterator(); it.hasNext(); ) {
202
					ArgType g = it.next();
203 204 205
					if (g.isGenericType()) {
						code.add(g.getObject());
					} else {
S
Skylot 已提交
206
						useClass(code, g);
207
					}
208 209 210 211 212 213
					if (it.hasNext()) {
						code.add(" & ");
					}
				}
			}
			i++;
S
Skylot 已提交
214
		}
215
		code.add('>');
S
Skylot 已提交
216
		return true;
S
Skylot 已提交
217 218
	}

S
Skylot 已提交
219
	public void addClassBody(CodeWriter clsCode) throws CodegenException {
220
		clsCode.add('{');
S
Skylot 已提交
221 222 223 224 225 226
		clsDeclLine = clsCode.getLine();
		clsCode.incIndent();
		addFields(clsCode);
		addInnerClasses(clsCode, cls);
		addMethods(clsCode);
		clsCode.decIndent();
227
		clsCode.startLine('}');
S
Skylot 已提交
228 229
	}

S
Skylot 已提交
230
	private void addInnerClasses(CodeWriter code, ClassNode cls) throws CodegenException {
S
Skylot 已提交
231 232 233 234 235
		for (ClassNode innerCls : cls.getInnerClasses()) {
			if (innerCls.contains(AFlag.DONT_GENERATE)
					|| innerCls.isAnonymous()) {
				continue;
			}
S
Skylot 已提交
236
			ClassGen inClGen = new ClassGen(innerCls, getParentGen());
S
Skylot 已提交
237 238 239 240 241 242 243
			code.newLine();
			inClGen.addClassCode(code);
			imports.addAll(inClGen.getImports());
		}
	}

	private boolean isInnerClassesPresents() {
S
Skylot 已提交
244 245
		for (ClassNode innerCls : cls.getInnerClasses()) {
			if (!innerCls.isAnonymous()) {
S
Skylot 已提交
246
				return true;
S
Skylot 已提交
247
			}
S
Skylot 已提交
248
		}
S
Skylot 已提交
249
		return false;
S
Skylot 已提交
250 251
	}

S
Skylot 已提交
252
	private void addMethods(CodeWriter code) {
S
Skylot 已提交
253 254
		List<MethodNode> methods = sortMethodsByLine(cls.getMethods());
		for (MethodNode mth : methods) {
S
Skylot 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
			if (mth.contains(AFlag.DONT_GENERATE)) {
				continue;
			}
			if (code.getLine() != clsDeclLine) {
				code.newLine();
			}
			try {
				addMethod(code, mth);
			} catch (Exception e) {
				String msg = ErrorsCounter.methodError(mth, "Method generation error", e);
				code.startLine("/* " + msg + CodeWriter.NL + Utils.getStackTrace(e) + " */");
			}
		}
	}

S
Skylot 已提交
270 271 272 273 274 275
	private static List<MethodNode> sortMethodsByLine(List<MethodNode> methods) {
		List<MethodNode> out = new ArrayList<MethodNode>(methods);
		Collections.sort(out, METHOD_LINE_COMPARATOR);
		return out;
	}

S
Skylot 已提交
276
	private boolean isMethodsPresents() {
S
Skylot 已提交
277
		for (MethodNode mth : cls.getMethods()) {
S
Skylot 已提交
278
			if (!mth.contains(AFlag.DONT_GENERATE)) {
S
Skylot 已提交
279
				return true;
280
			}
S
Skylot 已提交
281
		}
S
Skylot 已提交
282
		return false;
S
Skylot 已提交
283 284
	}

S
Skylot 已提交
285 286
	private void addMethod(CodeWriter code, MethodNode mth) throws CodegenException {
		if (mth.getAccessFlags().isAbstract() || mth.getAccessFlags().isNative()) {
S
Skylot 已提交
287
			MethodGen mthGen = new MethodGen(this, mth);
S
Skylot 已提交
288 289 290 291 292 293 294 295 296 297
			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 {
S
Skylot 已提交
298
			boolean badCode = mth.contains(AFlag.INCONSISTENT_CODE);
S
Skylot 已提交
299 300 301
			if (badCode) {
				code.startLine("/* JADX WARNING: inconsistent code. */");
				code.startLine("/* Code decompiled incorrectly, please refer to instructions dump. */");
S
Skylot 已提交
302
				ErrorsCounter.methodError(mth, "Inconsistent code");
303 304
				if (showInconsistentCode) {
					mth.remove(AFlag.INCONSISTENT_CODE);
S
Skylot 已提交
305
					badCode = false;
306
				}
S
Skylot 已提交
307
			}
S
Skylot 已提交
308
			MethodGen mthGen;
309
			if (badCode || mth.contains(AType.JADX_ERROR) || fallback) {
S
Skylot 已提交
310 311 312 313
				mthGen = MethodGen.getFallbackMethodGen(mth);
			} else {
				mthGen = new MethodGen(this, mth);
			}
S
Skylot 已提交
314 315 316 317 318 319
			if (mthGen.addDefinition(code)) {
				code.add(' ');
			}
			code.add('{');
			code.incIndent();
			insertSourceFileInfo(code, mth);
320 321 322 323 324
			if (fallback) {
				mthGen.addFallbackMethodCode(code);
			} else {
				mthGen.addInstructions(code);
			}
S
Skylot 已提交
325 326 327 328
			code.decIndent();
			code.startLine('}');
		}
	}
329

S
Skylot 已提交
330 331 332
	private void addFields(CodeWriter code) throws CodegenException {
		addEnumFields(code);
		for (FieldNode f : cls.getFields()) {
S
Skylot 已提交
333
			if (f.contains(AFlag.DONT_GENERATE)) {
334 335 336 337
				continue;
			}
			annotationGen.addForField(code, f);
			code.startLine(f.getAccessFlags().makeString());
338
			useType(code, f.getType());
339
			code.add(' ');
340
			code.add(f.getAlias());
S
Skylot 已提交
341
			FieldValueAttr fv = f.get(AType.FIELD_VALUE);
342 343 344 345 346
			if (fv != null) {
				code.add(" = ");
				if (fv.getValue() == null) {
					code.add(TypeGen.literalToString(0, f.getType()));
				} else {
347
					annotationGen.encodeValue(code, fv.getValue());
348 349 350
				}
			}
			code.add(';');
351
			code.attachDefinition(f);
352 353 354
		}
	}

S
Skylot 已提交
355 356 357 358 359 360 361 362 363
	private boolean isFieldsPresents() {
		for (FieldNode field : cls.getFields()) {
			if (!field.contains(AFlag.DONT_GENERATE)) {
				return true;
			}
		}
		return false;
	}

S
Skylot 已提交
364
	private void addEnumFields(CodeWriter code) throws CodegenException {
S
Skylot 已提交
365
		EnumClassAttr enumFields = cls.get(AType.ENUM_CLASS);
366 367 368 369 370 371 372
		if (enumFields == null) {
			return;
		}
		InsnGen igen = null;
		for (Iterator<EnumField> it = enumFields.getFields().iterator(); it.hasNext(); ) {
			EnumField f = it.next();
			code.startLine(f.getName());
S
Skylot 已提交
373
			if (!f.getArgs().isEmpty()) {
374 375 376 377 378 379 380 381 382 383 384
				code.add('(');
				for (Iterator<InsnArg> aIt = f.getArgs().iterator(); aIt.hasNext(); ) {
					InsnArg arg = aIt.next();
					if (igen == null) {
						// don't init mth gen if this is simple enum
						MethodGen mthGen = new MethodGen(this, enumFields.getStaticMethod());
						igen = new InsnGen(mthGen, false);
					}
					igen.addArg(code, arg);
					if (aIt.hasNext()) {
						code.add(", ");
S
Skylot 已提交
385
					}
S
Skylot 已提交
386
				}
387
				code.add(')');
S
Skylot 已提交
388
			}
389
			if (f.getCls() != null) {
S
Skylot 已提交
390
				code.add(' ');
S
Skylot 已提交
391
				new ClassGen(f.getCls(), this).addClassBody(code);
S
Skylot 已提交
392
			}
393 394 395 396
			if (it.hasNext()) {
				code.add(',');
			}
		}
S
Skylot 已提交
397 398 399 400 401
		if (isMethodsPresents() || isFieldsPresents() || isInnerClassesPresents()) {
			if (enumFields.getFields().isEmpty()) {
				code.startLine();
			}
			code.add(';');
S
Skylot 已提交
402 403 404
		}
	}

405
	public void useType(CodeWriter code, ArgType type) {
S
Skylot 已提交
406
		PrimitiveType stype = type.getPrimitiveType();
407 408 409 410 411 412
		if (stype == null) {
			code.add(type.toString());
		} else if (stype == PrimitiveType.OBJECT) {
			if (type.isGenericType()) {
				code.add(type.getObject());
			} else {
S
Skylot 已提交
413
				useClass(code, type);
414 415 416 417 418 419
			}
		} else if (stype == PrimitiveType.ARRAY) {
			useType(code, type.getArrayElement());
			code.add("[]");
		} else {
			code.add(stype.getLongName());
420 421
		}
	}
422

S
Skylot 已提交
423 424 425
	public void useClass(CodeWriter code, ArgType type) {
		useClass(code, ClassInfo.extCls(cls.dex(), type));
		ArgType[] generics = type.getGenericTypes();
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
		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 已提交
444
				}
445
			}
446
			code.add('>');
447
		}
S
Skylot 已提交
448 449
	}

S
Skylot 已提交
450 451 452 453 454 455 456 457 458 459 460
	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
Skylot 已提交
461
		if (fallback) {
462
			return fullName;
S
Skylot 已提交
463
		}
S
Skylot 已提交
464 465 466
		fullName = extClsInfo.getFullName();
		String shortName = extClsInfo.getShortName();
		if (extClsInfo.getPackage().equals("java.lang") && extClsInfo.getParentClass() == null) {
S
Skylot 已提交
467 468 469
			return shortName;
		} else {
			// don't add import if this class inner for current class
S
Skylot 已提交
470
			if (isClassInnerFor(extClsInfo, useCls)) {
S
Skylot 已提交
471
				return shortName;
S
Skylot 已提交
472
			}
473
			// don't add import if this class from same package
S
Skylot 已提交
474
			if (extClsInfo.getPackage().equals(useCls.getPackage()) && !extClsInfo.isInner()) {
475
				return shortName;
S
Skylot 已提交
476
			}
S
Skylot 已提交
477
			// don't add import if class not public (must be accessed using inheritance)
S
Skylot 已提交
478
			ClassNode classNode = cls.dex().resolveClass(extClsInfo);
S
Skylot 已提交
479 480
			if (classNode != null && !classNode.getAccessFlags().isPublic()) {
				return shortName;
S
Skylot 已提交
481
			}
S
Skylot 已提交
482
			if (searchCollision(cls.dex(), useCls, extClsInfo)) {
483
				return fullName;
S
Skylot 已提交
484
			}
S
Skylot 已提交
485 486
			if (extClsInfo.getPackage().equals(useCls.getPackage())) {
				fullName = extClsInfo.getNameWithoutPackage();
S
Skylot 已提交
487
			}
488
			for (ClassInfo importCls : getImports()) {
S
Skylot 已提交
489
				if (!importCls.equals(extClsInfo)
S
Skylot 已提交
490
						&& importCls.getShortName().equals(shortName)) {
S
Skylot 已提交
491 492
					if (extClsInfo.isInner()) {
						String parent = useClassInternal(useCls, extClsInfo.getParentClass().getAlias());
493 494 495 496
						return parent + "." + shortName;
					} else {
						return fullName;
					}
S
Skylot 已提交
497 498
				}
			}
S
Skylot 已提交
499
			addImport(extClsInfo);
S
Skylot 已提交
500 501 502 503
			return shortName;
		}
	}

504 505
	private void addImport(ClassInfo classInfo) {
		if (parentGen != null) {
S
Skylot 已提交
506
			parentGen.addImport(classInfo.getAlias());
507 508 509 510 511
		} else {
			imports.add(classInfo);
		}
	}

512 513 514 515 516 517 518 519
	private Set<ClassInfo> getImports() {
		if (parentGen != null) {
			return parentGen.getImports();
		} else {
			return imports;
		}
	}

S
Skylot 已提交
520
	private static boolean isClassInnerFor(ClassInfo inner, ClassInfo parent) {
S
Skylot 已提交
521 522
		if (inner.isInner()) {
			ClassInfo p = inner.getParentClass();
S
Skylot 已提交
523
			return p.equals(parent) || isClassInnerFor(p, parent);
S
Skylot 已提交
524 525 526 527
		}
		return false;
	}

S
Skylot 已提交
528
	private static boolean searchCollision(DexNode dex, ClassInfo useCls, ClassInfo searchCls) {
S
Skylot 已提交
529 530 531
		if (useCls == null) {
			return false;
		}
S
Skylot 已提交
532
		String shortName = searchCls.getShortName();
S
Skylot 已提交
533 534 535 536
		if (useCls.getShortName().equals(shortName)) {
			return true;
		}
		ClassNode classNode = dex.resolveClass(useCls);
537 538
		if (classNode != null) {
			for (ClassNode inner : classNode.getInnerClasses()) {
S
Skylot 已提交
539
				if (inner.getShortName().equals(shortName)
S
Skylot 已提交
540
						&& !inner.getAlias().equals(searchCls)) {
541 542
					return true;
				}
S
Skylot 已提交
543 544
			}
		}
S
Skylot 已提交
545
		return searchCollision(dex, useCls.getParentClass(), searchCls);
S
Skylot 已提交
546 547
	}

548
	private void insertSourceFileInfo(CodeWriter code, AttrNode node) {
S
Skylot 已提交
549
		SourceFileAttr sourceFileAttr = node.get(AType.SOURCE_FILE);
550
		if (sourceFileAttr != null) {
551
			code.startLine("/* compiled from: ").add(sourceFileAttr.getFileName()).add(" */");
552 553 554
		}
	}

555 556 557 558 559 560 561
	private void insertRenameInfo(CodeWriter code, ClassNode cls) {
		ClassInfo classInfo = cls.getClassInfo();
		if (classInfo.isRenamed()) {
			code.startLine("/* renamed from: ").add(classInfo.getFullName()).add(" */");
		}
	}

S
Skylot 已提交
562
	public ClassGen getParentGen() {
563
		return parentGen == null ? this : parentGen;
S
Skylot 已提交
564 565 566 567 568 569 570 571 572 573
	}

	public AnnotationGen getAnnotationGen() {
		return annotationGen;
	}

	public boolean isFallbackMode() {
		return fallback;
	}
}