1
1
package org .terasology .gestalt .annotation .processing ;
2
2
3
+ import com .google .common .collect .HashMultimap ;
4
+ import com .google .common .collect .Multimap ;
3
5
import com .google .common .collect .Queues ;
6
+ import org .terasology .context .annotation .BindAnnotationFor ;
4
7
import org .terasology .context .annotation .Index ;
5
8
import org .terasology .context .annotation .IndexInherited ;
6
9
7
10
import javax .annotation .processing .AbstractProcessor ;
8
11
import javax .annotation .processing .Filer ;
9
12
import javax .annotation .processing .ProcessingEnvironment ;
10
13
import javax .annotation .processing .RoundEnvironment ;
14
+ import javax .lang .model .element .AnnotationValue ;
11
15
import javax .lang .model .element .Element ;
12
16
import javax .lang .model .element .ElementKind ;
13
17
import javax .lang .model .element .PackageElement ;
19
23
import javax .tools .StandardLocation ;
20
24
import java .io .IOException ;
21
25
import java .io .Writer ;
26
+ import java .lang .annotation .Annotation ;
22
27
import java .util .Arrays ;
23
28
import java .util .Collections ;
29
+ import java .util .Map ;
30
+ import java .util .Optional ;
24
31
import java .util .Queue ;
25
32
import java .util .Set ;
26
33
@@ -31,17 +38,34 @@ public class ClassIndexProcessor extends AbstractProcessor {
31
38
private SubtypesTypeWriter subtypesTypeWriter ;
32
39
private ElementUtility elementUtility ;
33
40
41
+ private Multimap <TypeMirror , Class <? extends Annotation >> boundAnnotations ;
42
+
34
43
@ Override
35
44
public synchronized void init (ProcessingEnvironment processingEnv ) {
36
45
super .init (processingEnv );
37
46
filer = processingEnv .getFiler ();
38
47
annotationTypeWriter = new AnnotationTypeWriter (filer );
39
48
subtypesTypeWriter = new SubtypesTypeWriter (filer );
40
49
elementUtility = new ElementUtility (processingEnv .getElementUtils (), processingEnv .getTypeUtils ());
50
+ boundAnnotations = HashMultimap .create ();
41
51
}
42
52
43
53
@ Override
44
54
public boolean process (Set <? extends TypeElement > annotations , RoundEnvironment roundEnv ) {
55
+ for (TypeElement annotation : annotations ) {
56
+ if (annotation .asType ().toString ().equals (BindAnnotationFor .class .getName ())) {
57
+ for (Element type : roundEnv .getElementsAnnotatedWith (annotation )) {
58
+ TypeMirror foreighElement = getBindAnnotationFor (type );
59
+ if (elementUtility .hasStereotype (type , Collections .singletonList (IndexInherited .class .getName ()))) {
60
+ boundAnnotations .put (foreighElement , IndexInherited .class );
61
+ }
62
+ if (elementUtility .hasStereotype (type , Collections .singletonList (Index .class .getName ()))) {
63
+ boundAnnotations .put (foreighElement , Index .class );
64
+ }
65
+ }
66
+ }
67
+ }
68
+
45
69
for (TypeElement annotation : annotations ) {
46
70
// Annotation Index
47
71
processAnnotationIndex (roundEnv , annotation );
@@ -71,7 +95,7 @@ private void processSubtypeIndexInReverseWay(Element type) {
71
95
TypeMirror candidate = supers .poll ();
72
96
if (candidate .getKind () != TypeKind .NONE ) {
73
97
if (elementUtility .hasStereotype (elementUtility .getTypes ().asElement (candidate ),
74
- Collections .singletonList (IndexInherited .class .getName ()))) {
98
+ Collections .singletonList (IndexInherited .class .getName ())) || boundAnnotations . containsEntry ( candidate , IndexInherited . class )) {
75
99
TypeElement candidateElement = (TypeElement ) elementUtility .getTypes ().asElement (elementUtility .getTypes ().erasure (candidate ));
76
100
TypeElement erasedType = (TypeElement ) elementUtility .getTypes ().asElement (elementUtility .getTypes ().erasure (type .asType ()));
77
101
subtypesTypeWriter .writeSubType (elementUtility .getElements ().getBinaryName (candidateElement ).toString (),
@@ -94,7 +118,7 @@ private void processSubtypeIndexByDirectMarked(RoundEnvironment roundEnv, TypeEl
94
118
TypeMirror candidate = supers .poll ();
95
119
if (candidate .getKind () != TypeKind .NONE ) {
96
120
if (elementUtility .hasStereotype (elementUtility .getTypes ().asElement (candidate ),
97
- Collections .singletonList (IndexInherited .class .getName ())))
121
+ Collections .singletonList (IndexInherited .class .getName ())) || boundAnnotations . containsEntry ( candidate , IndexInherited . class ) )
98
122
subtypesTypeWriter .writeSubType (elementUtility .getTypes ().erasure (candidate ).toString (), elementUtility .getTypes ().erasure (type .asType ()).toString ());
99
123
supers .addAll (elementUtility .getTypes ().directSupertypes (candidate ));
100
124
}
@@ -117,6 +141,27 @@ private void processAnnotationIndex(RoundEnvironment roundEnv, TypeElement annot
117
141
}
118
142
}
119
143
144
+ private TypeMirror getBindAnnotationFor (Element element ) {
145
+ return (TypeMirror ) getAnnotationValue (element , BindAnnotationFor .class , "value" ).orElse (null );
146
+ }
147
+
148
+ private Optional <Object > getAnnotationValue (Element element , Class <?> annotation , String fieldName ) {
149
+ return element
150
+ .getAnnotationMirrors ()
151
+ .stream ()
152
+ .filter (am -> am .getAnnotationType ().toString ().equals (annotation .getName ()))
153
+ .map (am -> am .getElementValues ()
154
+ .entrySet ()
155
+ .stream ()
156
+ .filter (kv -> kv .getKey ().getSimpleName ().toString ().equals (fieldName ))
157
+ .map (Map .Entry ::getValue )
158
+ .findFirst ())
159
+ .filter (Optional ::isPresent )
160
+ .map (Optional ::get )
161
+ .map (AnnotationValue ::getValue )
162
+ .findFirst ();
163
+ }
164
+
120
165
private void writeIndexes () {
121
166
try {
122
167
annotationTypeWriter .finish ();
0 commit comments