ClassNode.java 17.9 KB
Newer Older
S
Skylot 已提交
1 2
package jadx.core.dex.nodes;

3
import java.io.StringWriter;
4
import java.nio.file.Path;
5 6 7
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
8
import java.util.LinkedHashSet;
9 10
import java.util.List;
import java.util.Map;
11
import java.util.Objects;
12
import java.util.Set;
13
import java.util.function.Consumer;
14
import java.util.stream.Collectors;
15

16
import org.jetbrains.annotations.NotNull;
17 18 19 20
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

21
import jadx.api.ICodeCache;
S
Skylot 已提交
22
import jadx.api.ICodeInfo;
23 24 25
import jadx.api.plugins.input.data.IClassData;
import jadx.api.plugins.input.data.annotations.EncodedValue;
import jadx.api.plugins.input.data.annotations.IAnnotation;
S
Skylot 已提交
26
import jadx.core.Consts;
S
Skylot 已提交
27
import jadx.core.ProcessClass;
28
import jadx.core.dex.attributes.AFlag;
29 30
import jadx.core.dex.attributes.FieldInitAttr;
import jadx.core.dex.attributes.annotations.AnnotationsList;
31
import jadx.core.dex.attributes.nodes.NotificationAttrNode;
S
Skylot 已提交
32
import jadx.core.dex.attributes.nodes.SourceFileAttr;
S
Skylot 已提交
33 34 35 36 37 38
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.AccessInfo.AFType;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType;
1
13.beta2 已提交
39
import jadx.core.dex.instructions.args.LiteralArg;
S
Skylot 已提交
40
import jadx.core.dex.nodes.parser.SignatureParser;
41
import jadx.core.dex.visitors.ProcessAnonymous;
42
import jadx.core.utils.SmaliUtils;
43
import jadx.core.utils.Utils;
S
Skylot 已提交
44
import jadx.core.utils.exceptions.JadxRuntimeException;
S
Skylot 已提交
45

S
Skylot 已提交
46
import static jadx.core.dex.nodes.ProcessState.LOADED;
47
import static jadx.core.dex.nodes.ProcessState.NOT_LOADED;
48

49
public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeNode, Comparable<ClassNode> {
S
Skylot 已提交
50
	private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class);
S
Skylot 已提交
51

52
	private final RootNode root;
S
Skylot 已提交
53
	private final IClassData cls;
54
	private final int clsDefOffset;
55
	@Nullable
56 57
	private final Path inputPath;

S
Skylot 已提交
58
	private final ClassInfo clsInfo;
59
	private AccessInfo accessFlags;
S
Skylot 已提交
60 61
	private ArgType superClass;
	private List<ArgType> interfaces;
62
	private List<ArgType> generics = Collections.emptyList();
S
Skylot 已提交
63

64 65
	private List<MethodNode> methods;
	private List<FieldNode> fields;
66
	private List<ClassNode> innerClasses = Collections.emptyList();
S
Skylot 已提交
67

68 69
	private List<ClassNode> inlinedClasses = Collections.emptyList();

70 71
	// store smali
	private String smali;
72 73
	// store parent for inner classes or 'this' otherwise
	private ClassNode parentClass;
S
Skylot 已提交
74

S
Skylot 已提交
75
	private volatile ProcessState state = ProcessState.NOT_LOADED;
76 77

	/** Top level classes used in this class (only for top level classes, empty for inners) */
S
Skylot 已提交
78
	private List<ClassNode> dependencies = Collections.emptyList();
79 80 81 82
	/** Classes which uses this class */
	private List<ClassNode> useIn = Collections.emptyList();
	/** Methods which uses this class (by instructions only, definition is excluded) */
	private List<MethodNode> useInMth = Collections.emptyList();
83

S
Skylot 已提交
84 85 86
	// cache maps
	private Map<MethodInfo, MethodNode> mthInfoMap = Collections.emptyMap();

87 88 89 90 91
	public ClassNode(RootNode root, IClassData cls) {
		this.root = root;
		this.inputPath = cls.getInputPath();
		this.clsDefOffset = cls.getClassDefOffset();
		this.clsInfo = ClassInfo.fromType(root, ArgType.object(cls.getType()));
S
Skylot 已提交
92 93
		initialLoad(cls);
		this.cls = cls.copy(); // TODO: need only for rename feature
94 95
	}

S
Skylot 已提交
96
	private void initialLoad(IClassData cls) {
S
Skylot 已提交
97
		try {
98 99
			String superType = cls.getSuperType();
			if (superType == null) {
100 101 102 103
				// only java.lang.Object don't have super class
				if (!clsInfo.getType().getObject().equals(Consts.CLASS_OBJECT)) {
					throw new JadxRuntimeException("No super class in " + clsInfo.getType());
				}
104
				this.superClass = null;
S
Skylot 已提交
105
			} else {
106
				this.superClass = ArgType.object(superType);
S
Skylot 已提交
107
			}
108
			this.interfaces = Utils.collectionMap(cls.getInterfacesTypes(), ArgType::object);
S
Skylot 已提交
109

110 111 112 113 114
			methods = new ArrayList<>();
			fields = new ArrayList<>();
			cls.visitFieldsAndMethods(
					fld -> fields.add(FieldNode.build(this, fld)),
					mth -> methods.add(MethodNode.build(this, mth)));
S
Skylot 已提交
115

116 117
			AnnotationsList.attach(this, cls.getAnnotations());
			loadStaticValues(cls, fields);
118
			initAccessFlags(cls);
119 120
			parseClassSignature();
			setFieldsTypesFromSignature();
121
			methods.forEach(MethodNode::initMethodTypes);
S
Skylot 已提交
122

123
			addSourceFilenameAttr(cls.getSourceFile());
S
Skylot 已提交
124
			buildCache();
S
Skylot 已提交
125
		} catch (Exception e) {
126
			throw new JadxRuntimeException("Error decode class: " + clsInfo, e);
S
Skylot 已提交
127 128 129
		}
	}

130 131 132
	/**
	 * Restore original access flags from Dalvik annotation if present
	 */
133
	private void initAccessFlags(IClassData cls) {
134
		int accFlagsValue;
135
		IAnnotation a = getAnnotation(Consts.DALVIK_INNER_CLASS);
136
		if (a != null) {
137
			accFlagsValue = (Integer) a.getValues().get("accessFlags").getValue();
138 139 140 141 142 143
		} else {
			accFlagsValue = cls.getAccessFlags();
		}
		this.accessFlags = new AccessInfo(accFlagsValue, AFType.CLASS);
	}

144 145 146 147 148 149 150 151 152 153
	public static ClassNode addSyntheticClass(RootNode root, String name, int accessFlags) {
		ClassNode cls = new ClassNode(root, name, accessFlags);
		cls.add(AFlag.SYNTHETIC);
		cls.setState(ProcessState.PROCESS_COMPLETE);
		root.addClassNode(cls);
		return cls;
	}

	// Create empty class
	private ClassNode(RootNode root, String name, int accessFlags) {
154
		this.root = root;
S
Skylot 已提交
155
		this.cls = null;
156
		this.inputPath = null;
157
		this.clsDefOffset = 0;
158
		this.clsInfo = ClassInfo.fromName(root, name);
159 160 161 162
		this.interfaces = new ArrayList<>();
		this.methods = new ArrayList<>();
		this.fields = new ArrayList<>();
		this.accessFlags = new AccessInfo(accessFlags, AFType.CLASS);
163 164 165
		this.parentClass = this;
	}

166 167 168
	private void loadStaticValues(IClassData cls, List<FieldNode> fields) {
		if (fields.isEmpty()) {
			return;
S
Skylot 已提交
169
		}
170
		List<FieldNode> staticFields = fields.stream().filter(FieldNode::isStatic).collect(Collectors.toList());
S
Skylot 已提交
171 172
		for (FieldNode f : staticFields) {
			if (f.getAccessFlags().isFinal()) {
173
				// incorrect initialization will be removed if assign found in constructor
174
				f.addAttr(FieldInitAttr.NULL_VALUE);
S
Skylot 已提交
175 176
			}
		}
177 178 179
		List<EncodedValue> values = cls.getStaticFieldInitValues();
		int count = values.size();
		if (count == 0 || count > staticFields.size()) {
180 181
			return;
		}
182 183 184
		for (int i = 0; i < count; i++) {
			staticFields.get(i).addAttr(FieldInitAttr.constValue(values.get(i)));
		}
185 186
		// process const fields
		root().getConstValues().processConstFields(this, staticFields);
S
Skylot 已提交
187 188
	}

189 190 191 192
	/**
	 * Class signature format:
	 * https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.9.1
	 */
193
	private void parseClassSignature() {
S
Skylot 已提交
194 195
		SignatureParser sp = SignatureParser.fromNode(this);
		if (sp == null) {
196
			return;
S
Skylot 已提交
197
		}
S
Skylot 已提交
198 199
		try {
			// parse class generic map
200
			generics = sp.consumeGenericTypeParameters();
S
Skylot 已提交
201
			// parse super class signature
202
			superClass = validateSuperCls(sp.consumeType(), superClass);
S
Skylot 已提交
203 204 205 206
			// parse interfaces signatures
			for (int i = 0; i < interfaces.size(); i++) {
				ArgType type = sp.consumeType();
				if (type != null) {
S
Skylot 已提交
207
					interfaces.set(i, type);
S
Skylot 已提交
208 209
				} else {
					break;
210 211
				}
			}
212
		} catch (Exception e) {
S
Skylot 已提交
213
			LOG.error("Class signature parse error: {}", this, e);
214 215 216
		}
	}

217 218 219 220 221 222 223 224 225 226 227 228
	private ArgType validateSuperCls(ArgType candidateType, ArgType currentType) {
		if (!candidateType.isObject()) {
			this.addComment("Incorrect class signature, super class is not object: " + SignatureParser.getSignature(this));
			return currentType;
		}
		if (Objects.equals(candidateType.getObject(), this.getClassInfo().getType().getObject())) {
			this.addComment("Incorrect class signature, super class is equals to this class: " + SignatureParser.getSignature(this));
			return currentType;
		}
		return candidateType;
	}

229 230
	private void setFieldsTypesFromSignature() {
		for (FieldNode field : fields) {
231 232 233
			try {
				SignatureParser sp = SignatureParser.fromNode(field);
				if (sp != null) {
S
Skylot 已提交
234 235
					ArgType gType = sp.consumeType();
					if (gType != null) {
236
						field.setType(root.getTypeUtils().expandTypeVariables(this, gType));
S
Skylot 已提交
237
					}
S
Skylot 已提交
238
				}
239 240
			} catch (Exception e) {
				LOG.error("Field signature parse error: {}.{}", this.getFullName(), field.getName(), e);
S
Skylot 已提交
241
			}
242 243 244
		}
	}

245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
	private void addSourceFilenameAttr(String fileName) {
		if (fileName == null) {
			return;
		}
		if (fileName.endsWith(".java")) {
			fileName = fileName.substring(0, fileName.length() - 5);
		}
		if (fileName.isEmpty()
				|| fileName.equals("SourceFile")
				|| fileName.equals("\"")) {
			return;
		}
		if (clsInfo != null) {
			String name = clsInfo.getShortName();
			if (fileName.equals(name)) {
				return;
			}
			if (fileName.contains("$")
263
					&& fileName.endsWith('$' + name)) {
264 265
				return;
			}
S
Skylot 已提交
266 267
			ClassInfo parentCls = clsInfo.getTopParentClass();
			if (parentCls != null && fileName.equals(parentCls.getShortName())) {
S
Skylot 已提交
268 269
				return;
			}
270 271 272 273
		}
		this.addAttr(new SourceFileAttr(fileName));
	}

274 275 276 277 278 279 280
	public void ensureProcessed() {
		ClassNode topClass = getTopParentClass();
		ProcessState topState = topClass.getState();
		if (!topState.isProcessed()) {
			throw new JadxRuntimeException("Expected class to be processed at this point,"
					+ " class: " + topClass + ", state: " + topState);
		}
S
Skylot 已提交
281 282
	}

283 284 285 286 287 288 289 290
	public ICodeInfo decompile() {
		return decompile(true);
	}

	public ICodeInfo getCode() {
		return decompile(true);
	}

S
Skylot 已提交
291 292 293 294
	public synchronized ICodeInfo reRunDecompile() {
		return decompile(false);
	}

295 296
	public synchronized ICodeInfo reloadCode() {
		unload();
297
		deepUnload();
298 299 300
		return decompile(false);
	}

S
Skylot 已提交
301 302 303 304 305
	public void deepUnload() {
		if (cls == null) {
			// manually added class
			return;
		}
306
		clearAttributes();
307
		root().getConstValues().removeForClass(this);
S
Skylot 已提交
308
		initialLoad(cls);
309 310 311 312 313
		ProcessAnonymous.runForClass(this);

		for (ClassNode innerClass : innerClasses) {
			innerClass.deepUnload();
		}
314 315 316
	}

	private synchronized ICodeInfo decompile(boolean searchInCache) {
317 318 319
		ICodeCache codeCache = root().getCodeCache();
		ClassNode topParentClass = getTopParentClass();
		String clsRawName = topParentClass.getRawName();
320 321
		if (searchInCache) {
			ICodeInfo code = codeCache.get(clsRawName);
322
			if (code != null && code != ICodeInfo.EMPTY) {
323 324
				return code;
			}
S
Skylot 已提交
325
		}
326 327
		ICodeInfo codeInfo = ProcessClass.generateCode(topParentClass);
		codeCache.add(clsRawName, codeInfo);
S
Skylot 已提交
328 329 330
		return codeInfo;
	}

S
Skylot 已提交
331
	@Override
S
Skylot 已提交
332
	public void load() {
S
Skylot 已提交
333
		for (MethodNode mth : getMethods()) {
S
Skylot 已提交
334 335
			try {
				mth.load();
336
			} catch (Exception e) {
337
				mth.addError("Method load error", e);
S
Skylot 已提交
338
			}
S
Skylot 已提交
339 340 341 342
		}
		for (ClassNode innerCls : getInnerClasses()) {
			innerCls.load();
		}
S
Skylot 已提交
343
		setState(LOADED);
S
Skylot 已提交
344 345 346 347
	}

	@Override
	public void unload() {
348 349 350 351
		methods.forEach(MethodNode::unload);
		innerClasses.forEach(ClassNode::unload);
		fields.forEach(FieldNode::unloadAttributes);
		unloadAttributes();
352
		setState(NOT_LOADED);
353
		this.smali = null;
S
Skylot 已提交
354 355
	}

S
Skylot 已提交
356
	private void buildCache() {
S
Skylot 已提交
357
		mthInfoMap = new HashMap<>(methods.size());
S
Skylot 已提交
358 359 360 361 362
		for (MethodNode mth : methods) {
			mthInfoMap.put(mth.getMethodInfo(), mth);
		}
	}

S
Skylot 已提交
363 364
	@Nullable
	public ArgType getSuperClass() {
S
Skylot 已提交
365 366 367
		return superClass;
	}

S
Skylot 已提交
368
	public List<ArgType> getInterfaces() {
S
Skylot 已提交
369 370 371
		return interfaces;
	}

372
	public List<ArgType> getGenericTypeParameters() {
373
		return generics;
374 375
	}

376 377 378 379 380 381 382 383
	public ArgType getType() {
		ArgType clsType = clsInfo.getType();
		if (Utils.notEmpty(generics)) {
			return ArgType.generic(clsType, generics);
		}
		return clsType;
	}

S
Skylot 已提交
384 385 386 387 388 389 390 391
	public List<MethodNode> getMethods() {
		return methods;
	}

	public List<FieldNode> getFields() {
		return fields;
	}

392 393 394 395
	public FieldNode getConstField(Object obj) {
		return getConstField(obj, true);
	}

396
	@Nullable
397
	public FieldNode getConstField(Object obj, boolean searchGlobal) {
398
		return root().getConstValues().getConstField(this, obj, searchGlobal);
399 400
	}

401
	@Nullable
1
13.beta2 已提交
402
	public FieldNode getConstFieldByLiteralArg(LiteralArg arg) {
403
		return root().getConstValues().getConstFieldByLiteralArg(this, arg);
1
13.beta2 已提交
404 405
	}

406
	public FieldNode searchField(FieldInfo field) {
S
Skylot 已提交
407
		for (FieldNode f : fields) {
408
			if (f.getFieldInfo().equals(field)) {
S
Skylot 已提交
409
				return f;
S
Skylot 已提交
410
			}
S
Skylot 已提交
411 412 413 414
		}
		return null;
	}

415 416 417 418 419 420 421 422 423
	public FieldNode searchFieldByNameAndType(FieldInfo field) {
		for (FieldNode f : fields) {
			if (f.getFieldInfo().equalsNameAndType(field)) {
				return f;
			}
		}
		return null;
	}

S
Skylot 已提交
424
	public FieldNode searchFieldByName(String name) {
S
Skylot 已提交
425
		for (FieldNode f : fields) {
S
Skylot 已提交
426
			if (f.getName().equals(name)) {
S
Skylot 已提交
427
				return f;
S
Skylot 已提交
428
			}
S
Skylot 已提交
429 430 431 432
		}
		return null;
	}

S
Skylot 已提交
433
	public MethodNode searchMethod(MethodInfo mth) {
S
Skylot 已提交
434
		return mthInfoMap.get(mth);
S
Skylot 已提交
435 436
	}

437
	public MethodNode searchMethodByShortId(String shortId) {
S
Skylot 已提交
438
		for (MethodNode m : methods) {
S
Skylot 已提交
439
			if (m.getMethodInfo().getShortId().equals(shortId)) {
S
Skylot 已提交
440
				return m;
S
Skylot 已提交
441
			}
S
Skylot 已提交
442 443 444 445
		}
		return null;
	}

446 447
	/**
	 * Return first method by original short name
448 449
	 * Note: methods are not unique by name (class can have several methods with same name but different
	 * signature)
450 451 452 453 454 455 456 457 458 459 460
	 */
	@Nullable
	public MethodNode searchMethodByShortName(String name) {
		for (MethodNode m : methods) {
			if (m.getMethodInfo().getName().equals(name)) {
				return m;
			}
		}
		return null;
	}

461 462 463
	public ClassNode getParentClass() {
		if (parentClass == null) {
			if (clsInfo.isInner()) {
464
				ClassNode parent = root.resolveClass(clsInfo.getParentClass());
465
				parentClass = parent == null ? this : parent;
466 467 468 469 470 471 472
			} else {
				parentClass = this;
			}
		}
		return parentClass;
	}

473 474
	public ClassNode getTopParentClass() {
		ClassNode parent = getParentClass();
475
		return parent == this ? this : parent.getTopParentClass();
476 477
	}

478 479 480 481 482 483 484 485 486 487
	public void visitParentClasses(Consumer<ClassNode> consumer) {
		ClassNode currentCls = this;
		ClassNode parentCls = currentCls.getParentClass();
		while (parentCls != currentCls) {
			consumer.accept(parentCls);
			currentCls = parentCls;
			parentCls = currentCls.getParentClass();
		}
	}

488 489 490 491 492 493 494 495 496 497 498
	public boolean hasNotGeneratedParent() {
		if (contains(AFlag.DONT_GENERATE)) {
			return true;
		}
		ClassNode parent = getParentClass();
		if (parent == this) {
			return false;
		}
		return parent.hasNotGeneratedParent();
	}

S
Skylot 已提交
499 500 501 502
	public List<ClassNode> getInnerClasses() {
		return innerClasses;
	}

503
	/**
504
	 * Get all inner and inlined classes recursively
505
	 *
506
	 * @param resultClassesSet all identified inner and inlined classes are added to this set
507
	 */
508 509 510 511 512 513 514 515 516 517
	public void getInnerAndInlinedClassesRecursive(Set<ClassNode> resultClassesSet) {
		for (ClassNode innerCls : innerClasses) {
			if (resultClassesSet.add(innerCls)) {
				innerCls.getInnerAndInlinedClassesRecursive(resultClassesSet);
			}
		}
		for (ClassNode inlinedCls : inlinedClasses) {
			if (resultClassesSet.add(inlinedCls)) {
				inlinedCls.getInnerAndInlinedClassesRecursive(resultClassesSet);
			}
518 519 520
		}
	}

S
Skylot 已提交
521
	public void addInnerClass(ClassNode cls) {
522 523 524
		if (innerClasses.isEmpty()) {
			innerClasses = new ArrayList<>(5);
		}
S
Skylot 已提交
525
		innerClasses.add(cls);
526
		cls.parentClass = this;
S
Skylot 已提交
527 528
	}

529 530 531 532 533 534 535
	public void addInlinedClass(ClassNode cls) {
		if (inlinedClasses.isEmpty()) {
			inlinedClasses = new ArrayList<>(5);
		}
		inlinedClasses.add(cls);
	}

536
	public boolean isEnum() {
S
Skylot 已提交
537 538 539
		return getAccessFlags().isEnum()
				&& getSuperClass() != null
				&& getSuperClass().getObject().equals(ArgType.ENUM.getObject());
540 541
	}

S
Skylot 已提交
542
	public boolean isAnonymous() {
543
		return contains(AFlag.ANONYMOUS_CLASS);
544 545
	}

546 547 548 549
	public boolean isInner() {
		return parentClass != null;
	}

550 551
	@Nullable
	public MethodNode getClassInitMth() {
552
		return searchMethodByShortId("<clinit>()V");
553 554 555
	}

	@Nullable
S
Skylot 已提交
556 557
	public MethodNode getDefaultConstructor() {
		for (MethodNode mth : methods) {
558
			if (mth.isDefaultConstructor()) {
S
Skylot 已提交
559
				return mth;
S
Skylot 已提交
560 561
			}
		}
S
Skylot 已提交
562
		return null;
S
Skylot 已提交
563 564
	}

565
	@Override
S
Skylot 已提交
566 567 568 569
	public AccessInfo getAccessFlags() {
		return accessFlags;
	}

570 571 572 573 574
	@Override
	public void setAccessFlags(AccessInfo accessFlags) {
		this.accessFlags = accessFlags;
	}

575 576
	@Override
	public RootNode root() {
577
		return root;
578 579
	}

580 581 582 583 584
	@Override
	public String typeName() {
		return "class";
	}

S
Skylot 已提交
585 586 587 588 589 590 591
	public String getRawName() {
		return clsInfo.getRawName();
	}

	/**
	 * Internal class info (don't use in code generation and external api).
	 */
S
Skylot 已提交
592 593 594 595 596
	public ClassInfo getClassInfo() {
		return clsInfo;
	}

	public String getShortName() {
597
		return clsInfo.getAliasShortName();
S
Skylot 已提交
598 599 600
	}

	public String getFullName() {
601
		return clsInfo.getAliasFullName();
S
Skylot 已提交
602 603 604
	}

	public String getPackage() {
605
		return clsInfo.getAliasPkg();
606 607
	}

608
	public String getSmali() {
609
		if (smali == null) {
610 611 612
			StringWriter stringWriter = new StringWriter(4096);
			getSmali(this, stringWriter);
			stringWriter.append(System.lineSeparator());
613 614 615
			Set<ClassNode> allInlinedClasses = new LinkedHashSet<>();
			getInnerAndInlinedClassesRecursive(allInlinedClasses);
			for (ClassNode innerClass : allInlinedClasses) {
616 617 618 619
				getSmali(innerClass, stringWriter);
				stringWriter.append(System.lineSeparator());
			}
			smali = stringWriter.toString();
620
		}
621 622 623
		return smali;
	}

624
	protected static boolean getSmali(ClassNode classNode, StringWriter stringWriter) {
625 626 627 628 629
		Path inputPath = classNode.inputPath;
		if (inputPath == null) {
			stringWriter.append(String.format("###### Class %s is created by jadx", classNode.getFullName()));
			return false;
		}
630 631
		stringWriter.append(String.format("###### Class %s (%s)", classNode.getFullName(), classNode.getRawName()));
		stringWriter.append(System.lineSeparator());
632
		return SmaliUtils.getSmaliCode(inputPath, classNode.clsDefOffset, stringWriter);
633 634
	}

635 636 637 638 639 640 641 642
	public ProcessState getState() {
		return state;
	}

	public void setState(ProcessState state) {
		this.state = state;
	}

S
Skylot 已提交
643
	public List<ClassNode> getDependencies() {
644 645 646
		return dependencies;
	}

S
Skylot 已提交
647 648 649 650
	public void setDependencies(List<ClassNode> dependencies) {
		this.dependencies = dependencies;
	}

651 652 653 654 655 656 657 658 659 660
	public List<ClassNode> getUseIn() {
		return useIn;
	}

	public void setUseIn(List<ClassNode> useIn) {
		this.useIn = useIn;
	}

	public List<MethodNode> getUseInMth() {
		return useInMth;
661 662
	}

663 664
	public void setUseInMth(List<MethodNode> useInMth) {
		this.useInMth = useInMth;
665 666
	}

667 668 669 670 671
	@Override
	public Path getInputPath() {
		return inputPath;
	}

672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
	@Override
	public int hashCode() {
		return clsInfo.hashCode();
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) {
			return true;
		}
		if (o instanceof ClassNode) {
			ClassNode other = (ClassNode) o;
			return clsInfo.equals(other.clsInfo);
		}
		return false;
	}

689 690 691 692 693
	@Override
	public int compareTo(@NotNull ClassNode o) {
		return this.getFullName().compareTo(o.getFullName());
	}

S
Skylot 已提交
694 695
	@Override
	public String toString() {
S
Skylot 已提交
696
		return clsInfo.getFullName();
S
Skylot 已提交
697 698
	}
}