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 static com.google.common.base.Preconditions.checkNotNull; 19 import static com.google.common.collect.ImmutableList.toImmutableList; 20 21 import com.google.common.base.Equivalence; 22 import com.google.common.collect.ImmutableList; 23 import java.util.List; 24 import java.util.function.Function; 25 import javax.lang.model.element.AnnotationMirror; 26 import javax.lang.model.element.AnnotationValue; 27 import javax.lang.model.element.VariableElement; 28 import javax.lang.model.type.DeclaredType; 29 import javax.lang.model.type.TypeMirror; 30 import javax.lang.model.util.SimpleAnnotationValueVisitor8; 31 32 /** 33 * A utility class for working with {@link AnnotationValue} instances. 34 * 35 * @author Christian Gruber 36 */ 37 public final class AnnotationValues { 38 private static final Equivalence<AnnotationValue> ANNOTATION_VALUE_EQUIVALENCE = 39 new Equivalence<AnnotationValue>() { 40 @Override protected boolean doEquivalent(AnnotationValue left, AnnotationValue right) { 41 return left.accept(new SimpleAnnotationValueVisitor8<Boolean, AnnotationValue>() { 42 // LHS is not an annotation or array of annotation values, so just test equality. 43 @Override protected Boolean defaultAction(Object left, AnnotationValue right) { 44 return left.equals(right.accept( 45 new SimpleAnnotationValueVisitor8<Object, Void>() { 46 @Override protected Object defaultAction(Object object, Void unused) { 47 return object; 48 } 49 }, null)); 50 } 51 52 // LHS is an annotation mirror so test equivalence for RHS annotation mirrors 53 // and false for other types. 54 @Override public Boolean visitAnnotation(AnnotationMirror left, AnnotationValue right) { 55 return right.accept( 56 new SimpleAnnotationValueVisitor8<Boolean, AnnotationMirror>() { 57 @Override protected Boolean defaultAction(Object right, AnnotationMirror left) { 58 return false; // Not an annotation mirror, so can't be equal to such. 59 } 60 @Override 61 public Boolean visitAnnotation(AnnotationMirror right, AnnotationMirror left) { 62 return AnnotationMirrors.equivalence().equivalent(left, right); 63 } 64 }, left); 65 } 66 67 // LHS is a list of annotation values have to collect-test equivalences, or false 68 // for any other types. 69 @Override 70 public Boolean visitArray(List<? extends AnnotationValue> left, AnnotationValue right) { 71 return right.accept( 72 new SimpleAnnotationValueVisitor8<Boolean, List<? extends AnnotationValue>>() { 73 @Override protected Boolean defaultAction( 74 Object ignored, List<? extends AnnotationValue> alsoIgnored) { 75 return false; // Not an array, so can't be equal to such. 76 } 77 78 @SuppressWarnings("unchecked") // safe covariant cast 79 @Override public Boolean visitArray( 80 List<? extends AnnotationValue> right , 81 List<? extends AnnotationValue> left) { 82 return AnnotationValues.equivalence().pairwise().equivalent( 83 (List<AnnotationValue>) left, (List<AnnotationValue>) right); 84 } 85 }, left); 86 } 87 88 @Override 89 public Boolean visitType(TypeMirror left, AnnotationValue right) { 90 return right.accept( 91 new SimpleAnnotationValueVisitor8<Boolean, TypeMirror>() { 92 @Override protected Boolean defaultAction( 93 Object ignored, TypeMirror alsoIgnored) { 94 return false; // Not an annotation mirror, so can't be equal to such. 95 } 96 97 @Override public Boolean visitType(TypeMirror right, TypeMirror left) { 98 return MoreTypes.equivalence().equivalent(left, right); 99 } 100 }, left); 101 } 102 }, right); 103 } 104 105 @Override protected int doHash(AnnotationValue value) { 106 return value.accept(new SimpleAnnotationValueVisitor8<Integer, Void>() { 107 @Override public Integer visitAnnotation(AnnotationMirror value, Void ignore) { 108 return AnnotationMirrors.equivalence().hash(value); 109 } 110 111 @SuppressWarnings("unchecked") // safe covariant cast 112 @Override public Integer visitArray( 113 List<? extends AnnotationValue> values, Void ignore) { 114 return AnnotationValues.equivalence().pairwise().hash((List<AnnotationValue>) values); 115 } 116 117 @Override public Integer visitType(TypeMirror value, Void ignore) { 118 return MoreTypes.equivalence().hash(value); 119 } 120 121 @Override protected Integer defaultAction(Object value, Void ignored) { 122 return value.hashCode(); 123 } 124 }, null); 125 } 126 }; 127 128 /** 129 * Returns an {@link Equivalence} for {@link AnnotationValue} as annotation values may 130 * contain {@link AnnotationMirror} instances some of whose implementations delegate 131 * equality tests to {@link Object#equals} whereas the documentation explicitly states 132 * that instance/reference equality is not the proper test. 133 * 134 * @see AnnotationMirrors#equivalence() 135 */ equivalence()136 public static Equivalence<AnnotationValue> equivalence() { 137 return ANNOTATION_VALUE_EQUIVALENCE; 138 } 139 140 private static class DefaultVisitor<T> extends SimpleAnnotationValueVisitor8<T, Void> { 141 final Class<T> clazz; 142 DefaultVisitor(Class<T> clazz)143 DefaultVisitor(Class<T> clazz) { 144 this.clazz = checkNotNull(clazz); 145 } 146 147 @Override defaultAction(Object o, Void unused)148 public T defaultAction(Object o, Void unused) { 149 throw new IllegalArgumentException( 150 "Expected a " + clazz.getSimpleName() + ", got instead: " + o); 151 } 152 } 153 154 private static final class TypeMirrorVisitor extends DefaultVisitor<DeclaredType> { 155 static final TypeMirrorVisitor INSTANCE = new TypeMirrorVisitor(); 156 TypeMirrorVisitor()157 TypeMirrorVisitor() { 158 super(DeclaredType.class); 159 } 160 161 @Override visitType(TypeMirror value, Void unused)162 public DeclaredType visitType(TypeMirror value, Void unused) { 163 return MoreTypes.asDeclared(value); 164 } 165 } 166 ; 167 168 /** 169 * Returns the value as a class. 170 * 171 * @throws IllegalArgumentException if the value is not a class. 172 */ getTypeMirror(AnnotationValue value)173 public static DeclaredType getTypeMirror(AnnotationValue value) { 174 return TypeMirrorVisitor.INSTANCE.visit(value); 175 } 176 177 private static final class AnnotationMirrorVisitor extends DefaultVisitor<AnnotationMirror> { 178 static final AnnotationMirrorVisitor INSTANCE = new AnnotationMirrorVisitor(); 179 AnnotationMirrorVisitor()180 AnnotationMirrorVisitor() { 181 super(AnnotationMirror.class); 182 } 183 184 @Override visitAnnotation(AnnotationMirror value, Void unused)185 public AnnotationMirror visitAnnotation(AnnotationMirror value, Void unused) { 186 return value; 187 } 188 } 189 ; 190 191 /** 192 * Returns the value as an AnnotationMirror. 193 * 194 * @throws IllegalArgumentException if the value is not an annotation. 195 */ getAnnotationMirror(AnnotationValue value)196 public static AnnotationMirror getAnnotationMirror(AnnotationValue value) { 197 return AnnotationMirrorVisitor.INSTANCE.visit(value); 198 } 199 200 private static final class EnumVisitor extends DefaultVisitor<VariableElement> { 201 static final EnumVisitor INSTANCE = new EnumVisitor(); 202 EnumVisitor()203 EnumVisitor() { 204 super(VariableElement.class); 205 } 206 207 @Override visitEnumConstant(VariableElement value, Void unused)208 public VariableElement visitEnumConstant(VariableElement value, Void unused) { 209 return value; 210 } 211 } 212 ; 213 214 /** 215 * Returns the value as a VariableElement. 216 * 217 * @throws IllegalArgumentException if the value is not an enum. 218 */ getEnum(AnnotationValue value)219 public static VariableElement getEnum(AnnotationValue value) { 220 return EnumVisitor.INSTANCE.visit(value); 221 } 222 valueOfType(AnnotationValue annotationValue, Class<T> type)223 private static <T> T valueOfType(AnnotationValue annotationValue, Class<T> type) { 224 Object value = annotationValue.getValue(); 225 if (!type.isInstance(value)) { 226 throw new IllegalArgumentException( 227 "Expected " + type.getSimpleName() + ", got instead: " + value); 228 } 229 return type.cast(value); 230 } 231 232 /** 233 * Returns the value as a string. 234 * 235 * @throws IllegalArgumentException if the value is not a string. 236 */ getString(AnnotationValue value)237 public static String getString(AnnotationValue value) { 238 return valueOfType(value, String.class); 239 } 240 241 /** 242 * Returns the value as an int. 243 * 244 * @throws IllegalArgumentException if the value is not an int. 245 */ getInt(AnnotationValue value)246 public static int getInt(AnnotationValue value) { 247 return valueOfType(value, Integer.class); 248 } 249 250 /** 251 * Returns the value as a long. 252 * 253 * @throws IllegalArgumentException if the value is not a long. 254 */ getLong(AnnotationValue value)255 public static long getLong(AnnotationValue value) { 256 return valueOfType(value, Long.class); 257 } 258 259 /** 260 * Returns the value as a byte. 261 * 262 * @throws IllegalArgumentException if the value is not a byte. 263 */ getByte(AnnotationValue value)264 public static byte getByte(AnnotationValue value) { 265 return valueOfType(value, Byte.class); 266 } 267 268 /** 269 * Returns the value as a short. 270 * 271 * @throws IllegalArgumentException if the value is not a short. 272 */ getShort(AnnotationValue value)273 public static short getShort(AnnotationValue value) { 274 return valueOfType(value, Short.class); 275 } 276 277 /** 278 * Returns the value as a float. 279 * 280 * @throws IllegalArgumentException if the value is not a float. 281 */ getFloat(AnnotationValue value)282 public static float getFloat(AnnotationValue value) { 283 return valueOfType(value, Float.class); 284 } 285 286 /** 287 * Returns the value as a double. 288 * 289 * @throws IllegalArgumentException if the value is not a double. 290 */ getDouble(AnnotationValue value)291 public static double getDouble(AnnotationValue value) { 292 return valueOfType(value, Double.class); 293 } 294 295 /** 296 * Returns the value as a boolean. 297 * 298 * @throws IllegalArgumentException if the value is not a boolean. 299 */ getBoolean(AnnotationValue value)300 public static boolean getBoolean(AnnotationValue value) { 301 return valueOfType(value, Boolean.class); 302 } 303 304 /** 305 * Returns the value as a char. 306 * 307 * @throws IllegalArgumentException if the value is not a char. 308 */ getChar(AnnotationValue value)309 public static char getChar(AnnotationValue value) { 310 return valueOfType(value, Character.class); 311 } 312 313 private static final class ArrayVisitor<T> 314 extends SimpleAnnotationValueVisitor8<ImmutableList<T>, Void> { 315 final Function<AnnotationValue, T> visitT; 316 ArrayVisitor(Function<AnnotationValue, T> visitT)317 ArrayVisitor(Function<AnnotationValue, T> visitT) { 318 this.visitT = checkNotNull(visitT); 319 } 320 321 @Override defaultAction(Object o, Void unused)322 public ImmutableList<T> defaultAction(Object o, Void unused) { 323 throw new IllegalStateException("Expected an array, got instead: " + o); 324 } 325 326 @Override visitArray(List<? extends AnnotationValue> values, Void unused)327 public ImmutableList<T> visitArray(List<? extends AnnotationValue> values, Void unused) { 328 return values.stream().map(visitT).collect(toImmutableList()); 329 } 330 } 331 332 private static final ArrayVisitor<DeclaredType> TYPE_MIRRORS_VISITOR = 333 new ArrayVisitor<>(AnnotationValues::getTypeMirror); 334 335 /** 336 * Returns the value as a list of classes. 337 * 338 * @throws IllegalArgumentException if the value is not an array of classes. 339 */ getTypeMirrors(AnnotationValue value)340 public static ImmutableList<DeclaredType> getTypeMirrors(AnnotationValue value) { 341 return TYPE_MIRRORS_VISITOR.visit(value); 342 } 343 344 private static final ArrayVisitor<AnnotationMirror> ANNOTATION_MIRRORS_VISITOR = 345 new ArrayVisitor<>(AnnotationValues::getAnnotationMirror); 346 347 /** 348 * Returns the value as a list of annotations. 349 * 350 * @throws IllegalArgumentException if the value if not an array of annotations. 351 */ getAnnotationMirrors(AnnotationValue value)352 public static ImmutableList<AnnotationMirror> getAnnotationMirrors(AnnotationValue value) { 353 return ANNOTATION_MIRRORS_VISITOR.visit(value); 354 } 355 356 private static final ArrayVisitor<VariableElement> ENUMS_VISITOR = 357 new ArrayVisitor<>(AnnotationValues::getEnum); 358 359 /** 360 * Returns the value as a list of enums. 361 * 362 * @throws IllegalArgumentException if the value is not an array of enums. 363 */ getEnums(AnnotationValue value)364 public static ImmutableList<VariableElement> getEnums(AnnotationValue value) { 365 return ENUMS_VISITOR.visit(value); 366 } 367 368 private static final ArrayVisitor<String> STRINGS_VISITOR = 369 new ArrayVisitor<>(AnnotationValues::getString); 370 371 /** 372 * Returns the value as a list of strings. 373 * 374 * @throws IllegalArgumentException if the value is not an array of strings. 375 */ getStrings(AnnotationValue value)376 public static ImmutableList<String> getStrings(AnnotationValue value) { 377 return STRINGS_VISITOR.visit(value); 378 } 379 380 private static final ArrayVisitor<Integer> INTS_VISITOR = 381 new ArrayVisitor<>(AnnotationValues::getInt); 382 383 /** 384 * Returns the value as a list of integers. 385 * 386 * @throws IllegalArgumentException if the value is not an array of ints. 387 */ getInts(AnnotationValue value)388 public static ImmutableList<Integer> getInts(AnnotationValue value) { 389 return INTS_VISITOR.visit(value); 390 } 391 392 private static final ArrayVisitor<Long> LONGS_VISITOR = 393 new ArrayVisitor<>(AnnotationValues::getLong); 394 395 /** 396 * Returns the value as a list of longs. 397 * 398 * @throws IllegalArgumentException if the value is not an array of longs. 399 */ getLongs(AnnotationValue value)400 public static ImmutableList<Long> getLongs(AnnotationValue value) { 401 return LONGS_VISITOR.visit(value); 402 } 403 404 private static final ArrayVisitor<Byte> BYTES_VISITOR = 405 new ArrayVisitor<>(AnnotationValues::getByte); 406 407 /** 408 * Returns the value as a list of bytes. 409 * 410 * @throws IllegalArgumentException if the value is not an array of bytes. 411 */ getBytes(AnnotationValue value)412 public static ImmutableList<Byte> getBytes(AnnotationValue value) { 413 return BYTES_VISITOR.visit(value); 414 } 415 416 private static final ArrayVisitor<Short> SHORTS_VISITOR = 417 new ArrayVisitor<>(AnnotationValues::getShort); 418 /** 419 * Returns the value as a list of shorts. 420 * 421 * @throws IllegalArgumentException if the value is not an array of shorts. 422 */ getShorts(AnnotationValue value)423 public static ImmutableList<Short> getShorts(AnnotationValue value) { 424 return SHORTS_VISITOR.visit(value); 425 } 426 427 private static final ArrayVisitor<Float> FLOATS_VISITOR = 428 new ArrayVisitor<>(AnnotationValues::getFloat); 429 430 /** 431 * Returns the value as a list of floats. 432 * 433 * @throws IllegalArgumentException if the value is not an array of floats. 434 */ getFloats(AnnotationValue value)435 public static ImmutableList<Float> getFloats(AnnotationValue value) { 436 return FLOATS_VISITOR.visit(value); 437 } 438 439 private static final ArrayVisitor<Double> DOUBLES_VISITOR = 440 new ArrayVisitor<>(AnnotationValues::getDouble); 441 442 /** 443 * Returns the value as a list of doubles. 444 * 445 * @throws IllegalArgumentException if the value is not an array of doubles. 446 */ getDoubles(AnnotationValue value)447 public static ImmutableList<Double> getDoubles(AnnotationValue value) { 448 return DOUBLES_VISITOR.visit(value); 449 } 450 451 private static final ArrayVisitor<Boolean> BOOLEANS_VISITOR = 452 new ArrayVisitor<>(AnnotationValues::getBoolean); 453 454 /** 455 * Returns the value as a list of booleans. 456 * 457 * @throws IllegalArgumentException if the value is not an array of booleans. 458 */ getBooleans(AnnotationValue value)459 public static ImmutableList<Boolean> getBooleans(AnnotationValue value) { 460 return BOOLEANS_VISITOR.visit(value); 461 } 462 463 private static final ArrayVisitor<Character> CHARS_VISITOR = 464 new ArrayVisitor<>(AnnotationValues::getChar); 465 466 /** 467 * Returns the value as a list of characters. 468 * 469 * @throws IllegalArgumentException if the value is not an array of chars. 470 */ getChars(AnnotationValue value)471 public static ImmutableList<Character> getChars(AnnotationValue value) { 472 return CHARS_VISITOR.visit(value); 473 } 474 475 private static final ArrayVisitor<AnnotationValue> ANNOTATION_VALUES_VISITOR = 476 new ArrayVisitor<>(x -> x); 477 478 /** 479 * Returns the value as a list of {@link AnnotationValue}s. 480 * 481 * @throws IllegalArgumentException if the value is not an array. 482 */ getAnnotationValues(AnnotationValue value)483 public static ImmutableList<AnnotationValue> getAnnotationValues(AnnotationValue value) { 484 return ANNOTATION_VALUES_VISITOR.visit(value); 485 } 486 AnnotationValues()487 private AnnotationValues() {} 488 } 489 490