-
Notifications
You must be signed in to change notification settings - Fork 0
/
BridgeScanner.java
132 lines (121 loc) · 6.41 KB
/
BridgeScanner.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package bridge.mvn;
import bridge.asm.HierarchyScanner;
import bridge.asm.TypeMap;
import org.objectweb.asm.*;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import static org.objectweb.asm.Opcodes.*;
final class BridgeScanner extends HierarchyScanner {
private static final int ACC_VALID = ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC | ACC_TRANSIENT | ACC_VARARGS;
private static final String[] EMPTY = new String[0];
private final BridgeData data;
BridgeScanner(TypeMap types) {
super(types);
super.data = data = new BridgeData();
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (!visible) {
if (desc.equals("Lbridge/Adopt;")) {
return new AnnotationVisitor(ASM9) {
LinkedList<String> implemented;
String extended;
String signature;
boolean clean;
@Override
public void visit(String name, Object value) {
if (name.equals("clean")) {
clean = (boolean) value;
} else if (name.equals("parent")) {
extended = ((Type) value).getInternalName();
} else {
signature = value.toString();
}
}
@Override
public AnnotationVisitor visitArray(String name) {
if (implemented == null) implemented = new LinkedList<>();
return new AnnotationVisitor(ASM9) {
public void visit(String name, Object value) {
implemented.add(((Type) value).getInternalName());
}
};
}
@Override
public void visitEnd() {
int i;
if (implemented != null && implemented.size() != 0) {
if (!clean && BridgeScanner.super.implemented != null && (i = BridgeScanner.super.implemented.length) != 0) {
String[] array = BridgeScanner.super.implemented = Arrays.copyOf(BridgeScanner.super.implemented, i + implemented.size(), String[].class);
for (Iterator<String> it = implemented.iterator(); it.hasNext();) array[i++] = it.next();
} else {
BridgeScanner.super.implemented = implemented.toArray(new String[0]);
}
} else if (clean) {
BridgeScanner.super.implemented = EMPTY;
}
if (extended != null) {
BridgeScanner.super.extended = extended;
} else if (clean) {
BridgeScanner.super.extended = "java/lang/Object";
}
data.signature = signature;
data.adopted = true;
}
};
} else if (desc.equals("Lbridge/Synthetic;")) {
access |= ACC_SYNTHETIC;
return null;
}
}
return super.visitAnnotation(desc, visible);
}
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
String identifier;
data.members.put(identifier = descriptor + name, access);
return new FieldVisitor(ASM9, super.visitField(access, name, descriptor, signature, value)) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (!visible) {
if (desc.equals("Lbridge/Bridges;") || desc.equals("Lbridge/Bridge;")) {
final int ACC_VALID = ((access & ACC_STATIC) == 0)? BridgeScanner.ACC_VALID : BridgeScanner.ACC_VALID | ACC_STATIC;
return new BridgeAnnotation(ACC_TRANSIENT | ACC_SYNTHETIC | access, name, descriptor, null, Type.getType(descriptor), data -> {
BridgeScanner.this.data.bridges.computeIfAbsent(identifier, k -> new LinkedList<>()).add(data);
BridgeScanner.this.data.members.put(data.desc + data.name, data.access &= ACC_VALID);
});
} else if (desc.equals("Lbridge/Synthetic;")) {
data.members.put(identifier, access | ACC_SYNTHETIC);
return null;
}
}
return super.visitAnnotation(desc, visible);
}
};
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
String identifier;
data.members.put(identifier = name + descriptor, access);
return new MethodVisitor(ASM9, super.visitMethod(access, name, descriptor, signature, exceptions)) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if (!visible) {
if (desc.equals("Lbridge/Bridges;") || desc.equals("Lbridge/Bridge;")) {
final int ACC_VALID = ((access & ACC_STATIC) == 0)? BridgeScanner.ACC_VALID : BridgeScanner.ACC_VALID | ACC_STATIC;
final int ACC_COMPATIBLE = (name.equals("<init>"))? (access & ACC_SYNCHRONIZED) : (access & ACC_SYNCHRONIZED) | ACC_BRIDGE;
return new BridgeAnnotation(ACC_SYNTHETIC | access, name, descriptor, exceptions, Type.getReturnType(descriptor), data -> {
BridgeScanner.this.data.bridges.computeIfAbsent(identifier, k -> new LinkedList<>()).add(data);
BridgeScanner.this.data.members.put(data.name + data.desc, data.access = (data.access & ACC_VALID) | ACC_COMPATIBLE);
});
} else if (desc.equals("Lbridge/Synthetic;")) {
data.members.put(identifier, access | ACC_SYNTHETIC);
return null;
}
}
return super.visitAnnotation(desc, visible);
}
};
}
}