1515 */
1616package com .google .auto .common ;
1717
18+ import java .util .HashSet ;
1819import java .util .List ;
1920import java .util .Map ;
21+ import java .util .Set ;
22+ import java .util .stream .Collectors ;
2023import javax .lang .model .element .AnnotationMirror ;
2124import javax .lang .model .element .AnnotationValue ;
2225import javax .lang .model .element .AnnotationValueVisitor ;
4649 * @author Gregory Kick
4750 */
4851public final class SuperficialValidation {
52+
53+ private final Set <Element > visited = new HashSet <>();
54+
55+ private SuperficialValidation () {}
56+
4957 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 ) {
5066 for (Element element : elements ) {
51- if (!validateElement (element )) {
67+ if (!validateElementInternal (element )) {
5268 return false ;
5369 }
5470 }
5571 return true ;
5672 }
5773
58- private static final ElementVisitor <Boolean , Void > ELEMENT_VALIDATING_VISITOR =
74+ private final ElementVisitor <Boolean , Void > ELEMENT_VALIDATING_VISITOR =
5975 new AbstractElementVisitor6 <Boolean , Void >() {
6076 @ Override public Boolean visitPackage (PackageElement e , Void p ) {
6177 // don't validate enclosed elements because it will return types in the package
6278 return validateAnnotations (e .getAnnotationMirrors ());
6379 }
6480
6581 @ Override public Boolean visitType (TypeElement e , Void p ) {
82+ TypeMirror superclass = e .getSuperclass ();
6683 return isValidBaseElement (e )
67- && validateElements (e .getTypeParameters ())
84+ && validateElementsInternal (e .getTypeParameters ())
6885 && 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 )));
7089 }
7190
7291 @ Override public Boolean visitVariable (VariableElement e , Void p ) {
@@ -79,8 +98,8 @@ && validateTypes(e.getInterfaces())
7998 && (defaultValue == null || validateAnnotationValue (defaultValue , e .getReturnType ()))
8099 && validateType (e .getReturnType ())
81100 && validateTypes (e .getThrownTypes ())
82- && validateElements (e .getTypeParameters ())
83- && validateElements (e .getParameters ());
101+ && validateElementsInternal (e .getTypeParameters ())
102+ && validateElementsInternal (e .getParameters ());
84103 }
85104
86105 @ Override public Boolean visitTypeParameter (TypeParameterElement e , Void p ) {
@@ -94,17 +113,21 @@ && validateElements(e.getTypeParameters())
94113 }
95114 };
96115
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+ }
99122 }
100123
101- private static boolean isValidBaseElement (Element e ) {
124+ private boolean isValidBaseElement (Element e ) {
102125 return validateType (e .asType ())
103126 && validateAnnotations (e .getAnnotationMirrors ())
104- && validateElements (e .getEnclosedElements ());
127+ && validateElementsInternal (e .getEnclosedElements ());
105128 }
106129
107- private static boolean validateTypes (Iterable <? extends TypeMirror > types ) {
130+ private boolean validateTypes (Iterable <? extends TypeMirror > types ) {
108131 for (TypeMirror type : types ) {
109132 if (!validateType (type )) {
110133 return false ;
@@ -118,7 +141,7 @@ private static boolean validateTypes(Iterable<? extends TypeMirror> types) {
118141 * an issue. Javac turns the whole type parameter into an error type if it can't figure out the
119142 * bounds.
120143 */
121- private static final TypeVisitor <Boolean , Void > TYPE_VALIDATING_VISITOR =
144+ private final TypeVisitor <Boolean , Void > TYPE_VALIDATING_VISITOR =
122145 new SimpleTypeVisitor6 <Boolean , Void >() {
123146 @ Override
124147 protected Boolean defaultAction (TypeMirror t , Void p ) {
@@ -163,11 +186,11 @@ && validateTypes(t.getThrownTypes())
163186 }
164187 };
165188
166- private static boolean validateType (TypeMirror type ) {
189+ private boolean validateType (TypeMirror type ) {
167190 return type .accept (TYPE_VALIDATING_VISITOR , null );
168191 }
169192
170- private static boolean validateAnnotations (
193+ private boolean validateAnnotations (
171194 Iterable <? extends AnnotationMirror > annotationMirrors ) {
172195 for (AnnotationMirror annotationMirror : annotationMirrors ) {
173196 if (!validateAnnotation (annotationMirror )) {
@@ -177,13 +200,13 @@ private static boolean validateAnnotations(
177200 return true ;
178201 }
179202
180- private static boolean validateAnnotation (AnnotationMirror annotationMirror ) {
203+ private boolean validateAnnotation (AnnotationMirror annotationMirror ) {
181204 return validateType (annotationMirror .getAnnotationType ())
182205 && validateAnnotationValues (annotationMirror .getElementValues ());
183206 }
184207
185208 @ SuppressWarnings ("unused" )
186- private static boolean validateAnnotationValues (
209+ private boolean validateAnnotationValues (
187210 Map <? extends ExecutableElement , ? extends AnnotationValue > valueMap ) {
188211 for (Map .Entry <? extends ExecutableElement , ? extends AnnotationValue > valueEntry :
189212 valueMap .entrySet ()) {
@@ -195,7 +218,7 @@ private static boolean validateAnnotationValues(
195218 return true ;
196219 }
197220
198- private static final AnnotationValueVisitor <Boolean , TypeMirror > VALUE_VALIDATING_VISITOR =
221+ private final AnnotationValueVisitor <Boolean , TypeMirror > VALUE_VALIDATING_VISITOR =
199222 new SimpleAnnotationValueVisitor6 <Boolean , TypeMirror >() {
200223 @ Override protected Boolean defaultAction (Object o , TypeMirror expectedType ) {
201224 return MoreTypes .isTypeOf (o .getClass (), expectedType );
@@ -232,7 +255,7 @@ public Boolean visitArray(List<? extends AnnotationValue> values, TypeMirror exp
232255 @ Override
233256 public Boolean visitEnumConstant (VariableElement enumConstant , TypeMirror expectedType ) {
234257 return MoreTypes .equivalence ().equivalent (enumConstant .asType (), expectedType )
235- && validateElement (enumConstant );
258+ && validateElementInternal (enumConstant );
236259 }
237260
238261 @ Override public Boolean visitType (TypeMirror type , TypeMirror ignored ) {
@@ -276,7 +299,7 @@ public Boolean visitEnumConstant(VariableElement enumConstant, TypeMirror expect
276299 }
277300 };
278301
279- private static boolean validateAnnotationValue (
302+ private boolean validateAnnotationValue (
280303 AnnotationValue annotationValue , TypeMirror expectedType ) {
281304 return annotationValue .accept (VALUE_VALIDATING_VISITOR , expectedType );
282305 }
0 commit comments