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