1
2
3
4
5 package mockit.internal.faking;
6
7 import static mockit.asm.jvmConstants.Access.ABSTRACT;
8 import static mockit.asm.jvmConstants.Access.BRIDGE;
9 import static mockit.asm.jvmConstants.Access.NATIVE;
10 import static mockit.asm.jvmConstants.Access.SYNTHETIC;
11
12 import edu.umd.cs.findbugs.annotations.NonNull;
13
14 import java.util.EnumSet;
15 import java.util.List;
16
17 import mockit.Mock;
18 import mockit.MockUp;
19 import mockit.asm.metadata.ClassMetadataReader;
20 import mockit.asm.metadata.ClassMetadataReader.Attribute;
21 import mockit.asm.metadata.ClassMetadataReader.MethodInfo;
22 import mockit.asm.types.JavaType;
23 import mockit.internal.ClassFile;
24 import mockit.internal.faking.FakeMethods.FakeMethod;
25 import mockit.internal.util.ClassLoad;
26
27
28
29
30
31 final class FakeMethodCollector {
32 private static final int INVALID_METHOD_ACCESSES = BRIDGE + SYNTHETIC + ABSTRACT + NATIVE;
33 private static final EnumSet<Attribute> ANNOTATIONS = EnumSet.of(Attribute.Annotations);
34
35 @NonNull
36 private final FakeMethods fakeMethods;
37 private boolean collectingFromSuperClass;
38
39 FakeMethodCollector(@NonNull FakeMethods fakeMethods) {
40 this.fakeMethods = fakeMethods;
41 }
42
43 void collectFakeMethods(@NonNull Class<?> fakeClass) {
44 ClassLoad.registerLoadedClass(fakeClass);
45 fakeMethods.setFakeClassInternalName(JavaType.getInternalName(fakeClass));
46
47 Class<?> classToCollectFakesFrom = fakeClass;
48
49 do {
50 byte[] classfileBytes = ClassFile.readBytesFromClassFile(classToCollectFakesFrom);
51 ClassMetadataReader cmr = new ClassMetadataReader(classfileBytes, ANNOTATIONS);
52 List<MethodInfo> methods = cmr.getMethods();
53 addFakeMethods(methods);
54
55 classToCollectFakesFrom = classToCollectFakesFrom.getSuperclass();
56 collectingFromSuperClass = true;
57 } while (classToCollectFakesFrom != MockUp.class);
58 }
59
60 private void addFakeMethods(@NonNull List<MethodInfo> methods) {
61 for (MethodInfo method : methods) {
62 int access = method.accessFlags;
63
64 if ((access & INVALID_METHOD_ACCESSES) == 0 && method.isMethod() && method.hasAnnotation("Lmockit/Mock;")) {
65 FakeMethod fakeMethod = fakeMethods.addMethod(collectingFromSuperClass, access, method.name,
66 method.desc);
67
68 if (fakeMethod != null && fakeMethod.requiresFakeState()) {
69 FakeState fakeState = new FakeState(fakeMethod);
70 fakeMethods.addFakeState(fakeState);
71 }
72 }
73 }
74 }
75 }