15
15
*/
16
16
package com .google .auto .common ;
17
17
18
+ import java .util .HashSet ;
18
19
import java .util .List ;
19
20
import java .util .Map ;
21
+ import java .util .Set ;
22
+ import java .util .stream .Collectors ;
20
23
import javax .lang .model .element .AnnotationMirror ;
21
24
import javax .lang .model .element .AnnotationValue ;
22
25
import javax .lang .model .element .AnnotationValueVisitor ;
46
49
* @author Gregory Kick
47
50
*/
48
51
public final class SuperficialValidation {
52
+
53
+ private final Set <Element > visited = new HashSet <>();
54
+
55
+ private SuperficialValidation () {}
56
+
49
57
public static boolean validateElements (Iterable <? extends Element > elements ) {
58
+ return new SuperficialValidation ().validateElementsInternal (elements );
59
+ }
60
+
61
+ public static boolean validateElement (Element element ) {
62
+ return new SuperficialValidation ().validateElementInternal (element );
63
+ }
64
+
65
+ private boolean validateElementsInternal (Iterable <? extends Element > elements ) {
50
66
for (Element element : elements ) {
51
- if (!validateElement (element )) {
67
+ if (!validateElementInternal (element )) {
52
68
return false ;
53
69
}
54
70
}
55
71
return true ;
56
72
}
57
73
58
- private static final ElementVisitor <Boolean , Void > ELEMENT_VALIDATING_VISITOR =
74
+ private final ElementVisitor <Boolean , Void > ELEMENT_VALIDATING_VISITOR =
59
75
new AbstractElementVisitor6 <Boolean , Void >() {
60
76
@ Override public Boolean visitPackage (PackageElement e , Void p ) {
61
77
// don't validate enclosed elements because it will return types in the package
62
78
return validateAnnotations (e .getAnnotationMirrors ());
63
79
}
64
80
65
81
@ Override public Boolean visitType (TypeElement e , Void p ) {
82
+ TypeMirror superclass = e .getSuperclass ();
66
83
return isValidBaseElement (e )
67
- && validateElements (e .getTypeParameters ())
84
+ && validateElementsInternal (e .getTypeParameters ())
68
85
&& validateTypes (e .getInterfaces ())
69
- && validateType (e .getSuperclass ());
86
+ && validateType (superclass )
87
+ && e .getInterfaces ().stream ().map (MoreTypes ::asElement ).allMatch (i -> validateElementInternal (i ))
88
+ && (superclass .getKind () == TypeKind .NONE || validateElementInternal (MoreTypes .asElement (superclass )));
70
89
}
71
90
72
91
@ Override public Boolean visitVariable (VariableElement e , Void p ) {
@@ -79,8 +98,8 @@ && validateTypes(e.getInterfaces())
79
98
&& (defaultValue == null || validateAnnotationValue (defaultValue , e .getReturnType ()))
80
99
&& validateType (e .getReturnType ())
81
100
&& validateTypes (e .getThrownTypes ())
82
- && validateElements (e .getTypeParameters ())
83
- && validateElements (e .getParameters ());
101
+ && validateElementsInternal (e .getTypeParameters ())
102
+ && validateElementsInternal (e .getParameters ());
84
103
}
85
104
86
105
@ Override public Boolean visitTypeParameter (TypeParameterElement e , Void p ) {
@@ -94,17 +113,21 @@ && validateElements(e.getTypeParameters())
94
113
}
95
114
};
96
115
97
- public static boolean validateElement (Element element ) {
98
- return element .accept (ELEMENT_VALIDATING_VISITOR , null );
116
+ private boolean validateElementInternal (Element element ) {
117
+ if (visited .add (element )) {
118
+ return element .accept (ELEMENT_VALIDATING_VISITOR , null );
119
+ } else {
120
+ return true ;
121
+ }
99
122
}
100
123
101
- private static boolean isValidBaseElement (Element e ) {
124
+ private boolean isValidBaseElement (Element e ) {
102
125
return validateType (e .asType ())
103
126
&& validateAnnotations (e .getAnnotationMirrors ())
104
- && validateElements (e .getEnclosedElements ());
127
+ && validateElementsInternal (e .getEnclosedElements ());
105
128
}
106
129
107
- private static boolean validateTypes (Iterable <? extends TypeMirror > types ) {
130
+ private boolean validateTypes (Iterable <? extends TypeMirror > types ) {
108
131
for (TypeMirror type : types ) {
109
132
if (!validateType (type )) {
110
133
return false ;
@@ -118,7 +141,7 @@ private static boolean validateTypes(Iterable<? extends TypeMirror> types) {
118
141
* an issue. Javac turns the whole type parameter into an error type if it can't figure out the
119
142
* bounds.
120
143
*/
121
- private static final TypeVisitor <Boolean , Void > TYPE_VALIDATING_VISITOR =
144
+ private final TypeVisitor <Boolean , Void > TYPE_VALIDATING_VISITOR =
122
145
new SimpleTypeVisitor6 <Boolean , Void >() {
123
146
@ Override
124
147
protected Boolean defaultAction (TypeMirror t , Void p ) {
@@ -163,11 +186,11 @@ && validateTypes(t.getThrownTypes())
163
186
}
164
187
};
165
188
166
- private static boolean validateType (TypeMirror type ) {
189
+ private boolean validateType (TypeMirror type ) {
167
190
return type .accept (TYPE_VALIDATING_VISITOR , null );
168
191
}
169
192
170
- private static boolean validateAnnotations (
193
+ private boolean validateAnnotations (
171
194
Iterable <? extends AnnotationMirror > annotationMirrors ) {
172
195
for (AnnotationMirror annotationMirror : annotationMirrors ) {
173
196
if (!validateAnnotation (annotationMirror )) {
@@ -177,13 +200,13 @@ private static boolean validateAnnotations(
177
200
return true ;
178
201
}
179
202
180
- private static boolean validateAnnotation (AnnotationMirror annotationMirror ) {
203
+ private boolean validateAnnotation (AnnotationMirror annotationMirror ) {
181
204
return validateType (annotationMirror .getAnnotationType ())
182
205
&& validateAnnotationValues (annotationMirror .getElementValues ());
183
206
}
184
207
185
208
@ SuppressWarnings ("unused" )
186
- private static boolean validateAnnotationValues (
209
+ private boolean validateAnnotationValues (
187
210
Map <? extends ExecutableElement , ? extends AnnotationValue > valueMap ) {
188
211
for (Map .Entry <? extends ExecutableElement , ? extends AnnotationValue > valueEntry :
189
212
valueMap .entrySet ()) {
@@ -195,7 +218,7 @@ private static boolean validateAnnotationValues(
195
218
return true ;
196
219
}
197
220
198
- private static final AnnotationValueVisitor <Boolean , TypeMirror > VALUE_VALIDATING_VISITOR =
221
+ private final AnnotationValueVisitor <Boolean , TypeMirror > VALUE_VALIDATING_VISITOR =
199
222
new SimpleAnnotationValueVisitor6 <Boolean , TypeMirror >() {
200
223
@ Override protected Boolean defaultAction (Object o , TypeMirror expectedType ) {
201
224
return MoreTypes .isTypeOf (o .getClass (), expectedType );
@@ -232,7 +255,7 @@ public Boolean visitArray(List<? extends AnnotationValue> values, TypeMirror exp
232
255
@ Override
233
256
public Boolean visitEnumConstant (VariableElement enumConstant , TypeMirror expectedType ) {
234
257
return MoreTypes .equivalence ().equivalent (enumConstant .asType (), expectedType )
235
- && validateElement (enumConstant );
258
+ && validateElementInternal (enumConstant );
236
259
}
237
260
238
261
@ Override public Boolean visitType (TypeMirror type , TypeMirror ignored ) {
@@ -276,7 +299,7 @@ public Boolean visitEnumConstant(VariableElement enumConstant, TypeMirror expect
276
299
}
277
300
};
278
301
279
- private static boolean validateAnnotationValue (
302
+ private boolean validateAnnotationValue (
280
303
AnnotationValue annotationValue , TypeMirror expectedType ) {
281
304
return annotationValue .accept (VALUE_VALIDATING_VISITOR , expectedType );
282
305
}
0 commit comments