ClassGen.java 10.9 KB
Newer Older
S
Skylot 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
package jadx.core.codegen;

import jadx.core.Consts;
import jadx.core.dex.attributes.AttrNode;
import jadx.core.dex.attributes.AttributeFlag;
import jadx.core.dex.attributes.AttributeType;
import jadx.core.dex.attributes.EnumClassAttr;
import jadx.core.dex.attributes.EnumClassAttr.EnumField;
import jadx.core.dex.attributes.IAttribute;
import jadx.core.dex.attributes.SourceFileAttr;
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;
import jadx.core.dex.nodes.ClassNode;
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 已提交
22 23 24 25 26 27

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
28 29
import java.util.Map;
import java.util.Map.Entry;
S
Skylot 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
import java.util.Set;

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

public class ClassGen {
	private final ClassNode cls;
	private final ClassGen parentGen;
	private final AnnotationGen annotationGen;
	private final boolean fallback;

	private final Set<ClassInfo> imports = new HashSet<ClassInfo>();

	public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean fallback) {
		this.cls = cls;
		this.parentGen = parentClsGen;
		this.fallback = fallback;

		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())) {
61
			clsCode.add("package ").add(cls.getPackage()).add(';');
62
			clsCode.newLine();
S
Skylot 已提交
63 64
		}

S
Skylot 已提交
65 66 67 68
		int importsCount = imports.size();
		if (importsCount != 0) {
			List<String> sortImports = new ArrayList<String>(importsCount);
			for (ClassInfo ic : imports) {
S
Skylot 已提交
69
				sortImports.add(ic.getFullName());
S
Skylot 已提交
70
			}
S
Skylot 已提交
71 72 73
			Collections.sort(sortImports);

			for (String imp : sortImports) {
74
				clsCode.startLine("import ").add(imp).add(';');
S
Skylot 已提交
75
			}
76
			clsCode.newLine();
S
Skylot 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89

			sortImports.clear();
			imports.clear();
		}

		clsCode.add(clsBody);
		return clsCode;
	}

	public void addClassCode(CodeWriter code) throws CodegenException {
		if (cls.getAttributes().contains(AttributeFlag.DONT_GENERATE))
			return;

S
Skylot 已提交
90 91 92
		if (cls.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE))
			code.startLine("// jadx: inconsistent code");

S
Skylot 已提交
93 94
		makeClassDeclaration(code);
		makeClassBody(code);
95
		code.newLine();
S
Skylot 已提交
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
	}

	public void makeClassDeclaration(CodeWriter clsCode) {
		AccessInfo af = cls.getAccessFlags();
		if (af.isInterface()) {
			af = af.remove(AccessFlags.ACC_ABSTRACT);
		} else if (af.isEnum()) {
			af = af.remove(AccessFlags.ACC_FINAL).remove(AccessFlags.ACC_ABSTRACT);
		}

		annotationGen.addForClass(clsCode);
		clsCode.startLine(af.makeString());
		if (af.isInterface()) {
			if (af.isAnnotation())
				clsCode.add('@');
			clsCode.add("interface ");
		} else if (af.isEnum()) {
			clsCode.add("enum ");
		} else {
			clsCode.add("class ");
		}
		clsCode.add(cls.getShortName());

119 120 121 122
		makeGenericMap(clsCode, cls.getGenericMap());
		clsCode.add(' ');

		ClassInfo sup = cls.getSuperClass();
S
Skylot 已提交
123 124 125
		if (sup != null
				&& !sup.getFullName().equals(Consts.CLASS_OBJECT)
				&& !sup.getFullName().equals(Consts.CLASS_ENUM)) {
126
			clsCode.add("extends ").add(useClass(sup)).add(' ');
S
Skylot 已提交
127 128 129 130
		}

		if (cls.getInterfaces().size() > 0 && !af.isAnnotation()) {
			if (cls.getAccessFlags().isInterface())
131
				clsCode.add("extends ");
S
Skylot 已提交
132
			else
133
				clsCode.add("implements ");
S
Skylot 已提交
134

S
Skylot 已提交
135
			for (Iterator<ClassInfo> it = cls.getInterfaces().iterator(); it.hasNext(); ) {
S
Skylot 已提交
136 137 138 139 140
				ClassInfo interf = it.next();
				clsCode.add(useClass(interf));
				if (it.hasNext())
					clsCode.add(", ");
			}
141 142 143
			if (!cls.getInterfaces().isEmpty())
				clsCode.add(' ');
		}
144 145

		clsCode.attachAnnotation(cls);
146 147
	}

S
Skylot 已提交
148
	public boolean makeGenericMap(CodeWriter code, Map<ArgType, List<ArgType>> gmap) {
149
		if (gmap == null || gmap.isEmpty())
S
Skylot 已提交
150
			return false;
151 152 153 154 155 156 157 158 159 160 161 162

		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(", ");
			}
			code.add(useClass(type));
			if (list != null && !list.isEmpty()) {
				code.add(" extends ");
S
Skylot 已提交
163
				for (Iterator<ArgType> it = list.iterator(); it.hasNext(); ) {
164 165 166 167 168 169 170 171
					ArgType g = it.next();
					code.add(useClass(g));
					if (it.hasNext()) {
						code.add(" & ");
					}
				}
			}
			i++;
S
Skylot 已提交
172
		}
173
		code.add('>');
S
Skylot 已提交
174
		return true;
S
Skylot 已提交
175 176 177
	}

	public void makeClassBody(CodeWriter clsCode) throws CodegenException {
178
		clsCode.add('{');
179 180
		insertSourceFileInfo(clsCode, cls);

S
Skylot 已提交
181
		CodeWriter mthsCode = makeMethods(clsCode, cls.getMethods());
S
Skylot 已提交
182 183 184
		CodeWriter fieldsCode = makeFields(clsCode, cls, cls.getFields());
		clsCode.add(fieldsCode);
		if (fieldsCode.notEmpty() && mthsCode.notEmpty())
185
			clsCode.newLine();
S
Skylot 已提交
186 187 188 189

		// insert inner classes code
		if (cls.getInnerClasses().size() != 0) {
			clsCode.add(makeInnerClasses(cls, clsCode.getIndent()));
S
Skylot 已提交
190
			if (mthsCode.notEmpty())
191
				clsCode.newLine();
S
Skylot 已提交
192 193
		}
		clsCode.add(mthsCode);
194
		clsCode.startLine('}');
S
Skylot 已提交
195 196
	}

S
Skylot 已提交
197
	private CodeWriter makeInnerClasses(ClassNode cls, int indent) throws CodegenException {
S
Skylot 已提交
198 199 200 201 202 203 204 205 206 207 208 209
		CodeWriter innerClsCode = new CodeWriter(indent + 1);
		for (ClassNode inCls : cls.getInnerClasses()) {
			if (inCls.isAnonymous())
				continue;

			ClassGen inClGen = new ClassGen(inCls, parentGen == null ? this : parentGen, fallback);
			inClGen.addClassCode(innerClsCode);
			imports.addAll(inClGen.getImports());
		}
		return innerClsCode;
	}

210
	private CodeWriter makeMethods(CodeWriter clsCode, List<MethodNode> mthList) {
S
Skylot 已提交
211
		CodeWriter code = new CodeWriter(clsCode.getIndent() + 1);
S
Skylot 已提交
212
		for (Iterator<MethodNode> it = mthList.iterator(); it.hasNext(); ) {
S
Skylot 已提交
213
			MethodNode mth = it.next();
S
Skylot 已提交
214 215 216
			if (mth.getAttributes().contains(AttributeFlag.DONT_GENERATE))
				continue;

S
Skylot 已提交
217 218 219 220 221 222 223 224 225 226 227
			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) {
							String v = annotationGen.encValueToString(def);
							code.add(" default ").add(v);
						}
					}
228
					code.add(';');
S
Skylot 已提交
229 230 231 232 233 234 235
				} else {
					if (mth.isNoCode())
						continue;

					MethodGen mthGen = new MethodGen(this, mth);
					mthGen.addDefinition(code);
					code.add(" {");
236
					insertSourceFileInfo(code, mth);
S
Skylot 已提交
237
					code.add(mthGen.makeInstructions(code.getIndent()));
238
					code.startLine('}');
S
Skylot 已提交
239 240 241 242 243 244 245
				}
			} catch (Throwable e) {
				String msg = ErrorsCounter.methodError(mth, "Method generation error", e);
				code.startLine("/* " + msg + CodeWriter.NL + Utils.getStackTrace(e) + "*/");
			}

			if (it.hasNext())
246
				code.newLine();
S
Skylot 已提交
247 248 249 250 251 252 253 254 255
		}
		return code;
	}

	private CodeWriter makeFields(CodeWriter clsCode, ClassNode cls, List<FieldNode> fields) throws CodegenException {
		CodeWriter code = new CodeWriter(clsCode.getIndent() + 1);

		EnumClassAttr enumFields = (EnumClassAttr) cls.getAttributes().get(AttributeType.ENUM_CLASS);
		if (enumFields != null) {
S
Skylot 已提交
256 257
			InsnGen igen = null;
			for (Iterator<EnumField> it = enumFields.getFields().iterator(); it.hasNext(); ) {
S
Skylot 已提交
258 259 260 261
				EnumField f = it.next();
				code.startLine(f.getName());
				if (f.getArgs().size() != 0) {
					code.add('(');
S
Skylot 已提交
262
					for (Iterator<InsnArg> aIt = f.getArgs().iterator(); aIt.hasNext(); ) {
S
Skylot 已提交
263
						InsnArg arg = aIt.next();
S
Skylot 已提交
264 265 266 267 268
						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);
						}
S
Skylot 已提交
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
						code.add(igen.arg(arg));
						if (aIt.hasNext())
							code.add(", ");
					}
					code.add(')');
				}
				if (f.getCls() != null) {
					new ClassGen(f.getCls(), this, fallback).makeClassBody(code);
				}
				if (it.hasNext())
					code.add(',');
			}
			if (enumFields.getFields().isEmpty())
				code.startLine();

			code.add(';');
285
			code.newLine();
S
Skylot 已提交
286 287 288 289 290 291
		}

		for (FieldNode f : fields) {
			annotationGen.addForField(code, f);
			code.startLine(f.getAccessFlags().makeString());
			code.add(TypeGen.translate(this, f.getType()));
292
			code.add(' ');
S
Skylot 已提交
293 294 295 296 297 298 299 300 301 302
			code.add(f.getName());
			FieldValueAttr fv = (FieldValueAttr) f.getAttributes().get(AttributeType.FIELD_VALUE);
			if (fv != null) {
				code.add(" = ");
				if (fv.getValue() == null) {
					code.add(TypeGen.literalToString(0, f.getType()));
				} else {
					code.add(annotationGen.encValueToString(fv.getValue()));
				}
			}
303
			code.add(';');
304
			code.attachAnnotation(f);
S
Skylot 已提交
305 306 307 308 309
		}
		return code;
	}

	public String useClass(ArgType clsType) {
310 311 312
		if (clsType.isGenericType()) {
			return clsType.getObject();
		}
S
Skylot 已提交
313
		return useClass(ClassInfo.fromType(clsType));
314
	}
315

316
	public String useClass(ClassInfo classInfo) {
S
Skylot 已提交
317
		String baseClass = useClassInternal(classInfo);
318
		ArgType[] generics = classInfo.getType().getGenericTypes();
319 320 321
		if (generics != null) {
			StringBuilder sb = new StringBuilder();
			sb.append(baseClass);
322
			sb.append('<');
323 324 325 326 327 328 329
			int len = generics.length;
			for (int i = 0; i < len; i++) {
				if (i != 0) {
					sb.append(", ");
				}
				ArgType gt = generics[i];
				if (gt.isTypeKnown())
330
					sb.append(TypeGen.translate(this, gt));
331 332 333
				else
					sb.append('?');
			}
334
			sb.append('>');
335 336 337 338
			return sb.toString();
		} else {
			return baseClass;
		}
S
Skylot 已提交
339 340
	}

S
Skylot 已提交
341
	private String useClassInternal(ClassInfo classInfo) {
S
Skylot 已提交
342
		if (parentGen != null)
S
Skylot 已提交
343
			return parentGen.useClassInternal(classInfo);
S
Skylot 已提交
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376

		String clsStr = classInfo.getFullName();
		if (fallback)
			return clsStr;

		String shortName = classInfo.getShortName();

		if (classInfo.getPackage().equals("java.lang") && classInfo.getParentClass() == null) {
			return shortName;
		} else {
			// don't add import if this class inner for current class
			if (isInner(classInfo, cls.getClassInfo()))
				return shortName;

			for (ClassInfo cls : imports) {
				if (!cls.equals(classInfo)) {
					if (cls.getShortName().equals(shortName))
						return clsStr;
				}
			}
			imports.add(classInfo);
			return shortName;
		}
	}

	private boolean isInner(ClassInfo inner, ClassInfo parent) {
		if (inner.isInner()) {
			ClassInfo p = inner.getParentClass();
			return p.equals(parent) || isInner(p, parent);
		}
		return false;
	}

377 378 379 380 381 382 383 384
	private void insertSourceFileInfo(CodeWriter code, AttrNode node) {
		IAttribute sourceFileAttr = node.getAttributes().get(AttributeType.SOURCE_FILE);
		if(sourceFileAttr != null) {
			code.startLine(1, "// compiled from: ");
			code.add(((SourceFileAttr)sourceFileAttr).getFileName());
		}
	}

S
Skylot 已提交
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
	public Set<ClassInfo> getImports() {
		return imports;
	}

	public ClassGen getParentGen() {
		return parentGen;
	}

	public AnnotationGen getAnnotationGen() {
		return annotationGen;
	}

	public boolean isFallbackMode() {
		return fallback;
	}
}