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 );
@@ -66,7 +90,7 @@ private void processSubtypeIndexInReverseWay(RoundEnvironment roundEnv) {
66
90
TypeMirror candidate = supers .poll ();
67
91
if (candidate .getKind () != TypeKind .NONE ) {
68
92
if (elementUtility .hasStereotype (elementUtility .getTypes ().asElement (candidate ),
69
- Collections .singletonList (IndexInherited .class .getName ())))
93
+ Collections .singletonList (IndexInherited .class .getName ())) || boundAnnotations . containsEntry ( candidate , IndexInherited . class ) )
70
94
subtypesTypeWriter .writeSubType (elementUtility .getTypes ().erasure (candidate ).toString (), elementUtility .getTypes ().erasure (type .asType ()).toString ());
71
95
supers .addAll (elementUtility .getTypes ().directSupertypes (candidate ));
72
96
}
@@ -86,7 +110,7 @@ private void processSubtypeIndexByDirectMarked(RoundEnvironment roundEnv, TypeEl
86
110
TypeMirror candidate = supers .poll ();
87
111
if (candidate .getKind () != TypeKind .NONE ) {
88
112
if (elementUtility .hasStereotype (elementUtility .getTypes ().asElement (candidate ),
89
- Collections .singletonList (IndexInherited .class .getName ())))
113
+ Collections .singletonList (IndexInherited .class .getName ())) || boundAnnotations . containsEntry ( candidate , IndexInherited . class ) )
90
114
subtypesTypeWriter .writeSubType (elementUtility .getTypes ().erasure (candidate ).toString (), elementUtility .getTypes ().erasure (type .asType ()).toString ());
91
115
supers .addAll (elementUtility .getTypes ().directSupertypes (candidate ));
92
116
}
@@ -109,6 +133,27 @@ private void processAnnotationIndex(RoundEnvironment roundEnv, TypeElement annot
109
133
}
110
134
}
111
135
136
+ private TypeMirror getBindAnnotationFor (Element element ) {
137
+ return (TypeMirror ) getAnnotationValue (element , BindAnnotationFor .class , "value" ).orElse (null );
138
+ }
139
+
140
+ private Optional <Object > getAnnotationValue (Element element , Class <?> annotation , String fieldName ) {
141
+ return element
142
+ .getAnnotationMirrors ()
143
+ .stream ()
144
+ .filter (am -> am .getAnnotationType ().toString ().equals (annotation .getName ()))
145
+ .map (am -> am .getElementValues ()
146
+ .entrySet ()
147
+ .stream ()
148
+ .filter (kv -> kv .getKey ().getSimpleName ().toString ().equals (fieldName ))
149
+ .map (Map .Entry ::getValue )
150
+ .findFirst ())
151
+ .filter (Optional ::isPresent )
152
+ .map (Optional ::get )
153
+ .map (AnnotationValue ::getValue )
154
+ .findFirst ();
155
+ }
156
+
112
157
private void writeIndexes () {
113
158
try {
114
159
annotationTypeWriter .finish ();
0 commit comments