1 /* 2 * Copyright 2014 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.auto.common; 17 18 import java.util.List; 19 import java.util.Map; 20 import java.util.stream.StreamSupport; 21 import javax.lang.model.element.AnnotationMirror; 22 import javax.lang.model.element.AnnotationValue; 23 import javax.lang.model.element.AnnotationValueVisitor; 24 import javax.lang.model.element.Element; 25 import javax.lang.model.element.ElementVisitor; 26 import javax.lang.model.element.ExecutableElement; 27 import javax.lang.model.element.PackageElement; 28 import javax.lang.model.element.TypeElement; 29 import javax.lang.model.element.TypeParameterElement; 30 import javax.lang.model.element.VariableElement; 31 import javax.lang.model.type.ArrayType; 32 import javax.lang.model.type.DeclaredType; 33 import javax.lang.model.type.ErrorType; 34 import javax.lang.model.type.ExecutableType; 35 import javax.lang.model.type.TypeKind; 36 import javax.lang.model.type.TypeMirror; 37 import javax.lang.model.type.TypeVisitor; 38 import javax.lang.model.type.WildcardType; 39 import javax.lang.model.util.AbstractElementVisitor8; 40 import javax.lang.model.util.SimpleAnnotationValueVisitor8; 41 import javax.lang.model.util.SimpleTypeVisitor8; 42 43 /** 44 * A utility class that traverses {@link Element} instances and ensures that all type information 45 * is present and resolvable. 46 * 47 * @author Gregory Kick 48 */ 49 public final class SuperficialValidation { 50 /** 51 * Returns true if all of the given elements return true from {@link #validateElement(Element)}. 52 */ validateElements(Iterable<? extends Element> elements)53 public static boolean validateElements(Iterable<? extends Element> elements) { 54 return StreamSupport.stream(elements.spliterator(), false) 55 .allMatch(SuperficialValidation::validateElement); 56 } 57 58 private static final ElementVisitor<Boolean, Void> ELEMENT_VALIDATING_VISITOR = 59 new AbstractElementVisitor8<Boolean, Void>() { 60 @Override 61 public Boolean visitPackage(PackageElement e, Void p) { 62 // don't validate enclosed elements because it will return types in the package 63 return validateAnnotations(e.getAnnotationMirrors()); 64 } 65 66 @Override 67 public Boolean visitType(TypeElement e, Void p) { 68 return isValidBaseElement(e) 69 && validateElements(e.getTypeParameters()) 70 && validateTypes(e.getInterfaces()) 71 && validateType(e.getSuperclass()); 72 } 73 74 @Override 75 public Boolean visitVariable(VariableElement e, Void p) { 76 return isValidBaseElement(e); 77 } 78 79 @Override 80 public Boolean visitExecutable(ExecutableElement e, Void p) { 81 AnnotationValue defaultValue = e.getDefaultValue(); 82 return isValidBaseElement(e) 83 && (defaultValue == null || validateAnnotationValue(defaultValue, e.getReturnType())) 84 && validateType(e.getReturnType()) 85 && validateTypes(e.getThrownTypes()) 86 && validateElements(e.getTypeParameters()) 87 && validateElements(e.getParameters()); 88 } 89 90 @Override 91 public Boolean visitTypeParameter(TypeParameterElement e, Void p) { 92 return isValidBaseElement(e) && validateTypes(e.getBounds()); 93 } 94 95 @Override 96 public Boolean visitUnknown(Element e, Void p) { 97 // just assume that unknown elements are OK 98 return true; 99 } 100 }; 101 102 /** 103 * Returns true if all types referenced by the given element are defined. The exact meaning of 104 * this depends on the kind of element. For packages, it means that all annotations on the package 105 * are fully defined. For other element kinds, it means that types referenced by the element, 106 * anything it contains, and any of its annotations element are all defined. 107 */ validateElement(Element element)108 public static boolean validateElement(Element element) { 109 return element.accept(ELEMENT_VALIDATING_VISITOR, null); 110 } 111 isValidBaseElement(Element e)112 private static boolean isValidBaseElement(Element e) { 113 return validateType(e.asType()) 114 && validateAnnotations(e.getAnnotationMirrors()) 115 && validateElements(e.getEnclosedElements()); 116 } 117 validateTypes(Iterable<? extends TypeMirror> types)118 private static boolean validateTypes(Iterable<? extends TypeMirror> types) { 119 for (TypeMirror type : types) { 120 if (!validateType(type)) { 121 return false; 122 } 123 } 124 return true; 125 } 126 127 /* 128 * This visitor does not test type variables specifically, but it seems that that is not actually 129 * an issue. Javac turns the whole type parameter into an error type if it can't figure out the 130 * bounds. 131 */ 132 private static final TypeVisitor<Boolean, Void> TYPE_VALIDATING_VISITOR = 133 new SimpleTypeVisitor8<Boolean, Void>() { 134 @Override 135 protected Boolean defaultAction(TypeMirror t, Void p) { 136 return true; 137 } 138 139 @Override 140 public Boolean visitArray(ArrayType t, Void p) { 141 return validateType(t.getComponentType()); 142 } 143 144 @Override 145 public Boolean visitDeclared(DeclaredType t, Void p) { 146 return validateTypes(t.getTypeArguments()); 147 } 148 149 @Override 150 public Boolean visitError(ErrorType t, Void p) { 151 return false; 152 } 153 154 @Override 155 public Boolean visitUnknown(TypeMirror t, Void p) { 156 // just make the default choice for unknown types 157 return defaultAction(t, p); 158 } 159 160 @Override 161 public Boolean visitWildcard(WildcardType t, Void p) { 162 TypeMirror extendsBound = t.getExtendsBound(); 163 TypeMirror superBound = t.getSuperBound(); 164 return (extendsBound == null || validateType(extendsBound)) 165 && (superBound == null || validateType(superBound)); 166 } 167 168 @Override 169 public Boolean visitExecutable(ExecutableType t, Void p) { 170 return validateTypes(t.getParameterTypes()) 171 && validateType(t.getReturnType()) 172 && validateTypes(t.getThrownTypes()) 173 && validateTypes(t.getTypeVariables()); 174 } 175 }; 176 177 /** 178 * Returns true if the given type is fully defined. This means that the type itself is defined, as 179 * are any types it references, such as any type arguments or type bounds. For an {@link 180 * ExecutableType}, the parameter and return types must be fully defined, as must types declared 181 * in a {@code throws} clause or in the bounds of any type parameters. 182 */ validateType(TypeMirror type)183 public static boolean validateType(TypeMirror type) { 184 return type.accept(TYPE_VALIDATING_VISITOR, null); 185 } 186 validateAnnotations( Iterable<? extends AnnotationMirror> annotationMirrors)187 private static boolean validateAnnotations( 188 Iterable<? extends AnnotationMirror> annotationMirrors) { 189 for (AnnotationMirror annotationMirror : annotationMirrors) { 190 if (!validateAnnotation(annotationMirror)) { 191 return false; 192 } 193 } 194 return true; 195 } 196 validateAnnotation(AnnotationMirror annotationMirror)197 private static boolean validateAnnotation(AnnotationMirror annotationMirror) { 198 return validateType(annotationMirror.getAnnotationType()) 199 && validateAnnotationValues(annotationMirror.getElementValues()); 200 } 201 validateAnnotationValues( Map<? extends ExecutableElement, ? extends AnnotationValue> valueMap)202 private static boolean validateAnnotationValues( 203 Map<? extends ExecutableElement, ? extends AnnotationValue> valueMap) { 204 return valueMap.entrySet().stream() 205 .allMatch( 206 valueEntry -> { 207 TypeMirror expectedType = valueEntry.getKey().getReturnType(); 208 return validateAnnotationValue(valueEntry.getValue(), expectedType); 209 }); 210 } 211 212 private static final AnnotationValueVisitor<Boolean, TypeMirror> VALUE_VALIDATING_VISITOR = 213 new SimpleAnnotationValueVisitor8<Boolean, TypeMirror>() { 214 @Override 215 protected Boolean defaultAction(Object o, TypeMirror expectedType) { 216 return MoreTypes.isTypeOf(o.getClass(), expectedType); 217 } 218 219 @Override 220 public Boolean visitUnknown(AnnotationValue av, TypeMirror expectedType) { 221 // just take the default action for the unknown 222 return defaultAction(av, expectedType); 223 } 224 225 @Override 226 public Boolean visitAnnotation(AnnotationMirror a, TypeMirror expectedType) { 227 return MoreTypes.equivalence().equivalent(a.getAnnotationType(), expectedType) 228 && validateAnnotation(a); 229 } 230 231 @Override 232 public Boolean visitArray(List<? extends AnnotationValue> values, TypeMirror expectedType) { 233 if (!expectedType.getKind().equals(TypeKind.ARRAY)) { 234 return false; 235 } 236 TypeMirror componentType = MoreTypes.asArray(expectedType).getComponentType(); 237 return values.stream().allMatch(value -> value.accept(this, componentType)); 238 } 239 240 @Override 241 public Boolean visitEnumConstant(VariableElement enumConstant, TypeMirror expectedType) { 242 return MoreTypes.equivalence().equivalent(enumConstant.asType(), expectedType) 243 && validateElement(enumConstant); 244 } 245 246 @Override 247 public Boolean visitType(TypeMirror type, TypeMirror ignored) { 248 // We could check assignability here, but would require a Types instance. Since this 249 // isn't really the sort of thing that shows up in a bad AST from upstream compilation 250 // we ignore the expected type and just validate the type. It might be wrong, but 251 // it's valid. 252 return validateType(type); 253 } 254 255 @Override 256 public Boolean visitBoolean(boolean b, TypeMirror expectedType) { 257 return MoreTypes.isTypeOf(Boolean.TYPE, expectedType); 258 } 259 260 @Override 261 public Boolean visitByte(byte b, TypeMirror expectedType) { 262 return MoreTypes.isTypeOf(Byte.TYPE, expectedType); 263 } 264 265 @Override 266 public Boolean visitChar(char c, TypeMirror expectedType) { 267 return MoreTypes.isTypeOf(Character.TYPE, expectedType); 268 } 269 270 @Override 271 public Boolean visitDouble(double d, TypeMirror expectedType) { 272 return MoreTypes.isTypeOf(Double.TYPE, expectedType); 273 } 274 275 @Override 276 public Boolean visitFloat(float f, TypeMirror expectedType) { 277 return MoreTypes.isTypeOf(Float.TYPE, expectedType); 278 } 279 280 @Override 281 public Boolean visitInt(int i, TypeMirror expectedType) { 282 return MoreTypes.isTypeOf(Integer.TYPE, expectedType); 283 } 284 285 @Override 286 public Boolean visitLong(long l, TypeMirror expectedType) { 287 return MoreTypes.isTypeOf(Long.TYPE, expectedType); 288 } 289 290 @Override 291 public Boolean visitShort(short s, TypeMirror expectedType) { 292 return MoreTypes.isTypeOf(Short.TYPE, expectedType); 293 } 294 }; 295 validateAnnotationValue( AnnotationValue annotationValue, TypeMirror expectedType)296 private static boolean validateAnnotationValue( 297 AnnotationValue annotationValue, TypeMirror expectedType) { 298 return annotationValue.accept(VALUE_VALIDATING_VISITOR, expectedType); 299 } 300 SuperficialValidation()301 private SuperficialValidation() {} 302 } 303