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.base.Preconditions.checkState; 20 import static javax.lang.model.type.TypeKind.ARRAY; 21 import static javax.lang.model.type.TypeKind.DECLARED; 22 import static javax.lang.model.type.TypeKind.EXECUTABLE; 23 import static javax.lang.model.type.TypeKind.INTERSECTION; 24 import static javax.lang.model.type.TypeKind.TYPEVAR; 25 import static javax.lang.model.type.TypeKind.WILDCARD; 26 27 import com.google.common.base.Equivalence; 28 import com.google.common.base.Optional; 29 import com.google.common.collect.ImmutableList; 30 import com.google.common.collect.ImmutableSet; 31 import java.util.HashSet; 32 import java.util.Iterator; 33 import java.util.List; 34 import java.util.Set; 35 import javax.lang.model.element.Element; 36 import javax.lang.model.element.ElementKind; 37 import javax.lang.model.element.ExecutableElement; 38 import javax.lang.model.element.Modifier; 39 import javax.lang.model.element.TypeElement; 40 import javax.lang.model.element.TypeParameterElement; 41 import javax.lang.model.element.VariableElement; 42 import javax.lang.model.type.ArrayType; 43 import javax.lang.model.type.DeclaredType; 44 import javax.lang.model.type.ErrorType; 45 import javax.lang.model.type.ExecutableType; 46 import javax.lang.model.type.IntersectionType; 47 import javax.lang.model.type.NoType; 48 import javax.lang.model.type.NullType; 49 import javax.lang.model.type.PrimitiveType; 50 import javax.lang.model.type.TypeKind; 51 import javax.lang.model.type.TypeMirror; 52 import javax.lang.model.type.TypeVariable; 53 import javax.lang.model.type.WildcardType; 54 import javax.lang.model.util.Elements; 55 import javax.lang.model.util.SimpleTypeVisitor8; 56 import javax.lang.model.util.Types; 57 import org.checkerframework.checker.nullness.qual.Nullable; 58 59 /** 60 * Utilities related to {@link TypeMirror} instances. 61 * 62 * @author Gregory Kick 63 * @since 2.0 64 */ 65 public final class MoreTypes { 66 private static final class TypeEquivalence extends Equivalence<TypeMirror> { 67 private static final TypeEquivalence INSTANCE = new TypeEquivalence(); 68 69 @Override doEquivalent(TypeMirror a, TypeMirror b)70 protected boolean doEquivalent(TypeMirror a, TypeMirror b) { 71 return MoreTypes.equal(a, b, ImmutableSet.<ComparedElements>of()); 72 } 73 74 @Override doHash(TypeMirror t)75 protected int doHash(TypeMirror t) { 76 return MoreTypes.hash(t, ImmutableSet.<Element>of()); 77 } 78 79 @Override toString()80 public String toString() { 81 return "MoreTypes.equivalence()"; 82 } 83 } 84 85 /** 86 * Returns an {@link Equivalence} that can be used to compare types. The standard way to compare 87 * types is {@link javax.lang.model.util.Types#isSameType Types.isSameType}, but this alternative 88 * may be preferred in a number of cases: 89 * 90 * <ul> 91 * <li>If you don't have an instance of {@code Types}. 92 * <li>If you want a reliable {@code hashCode()} for the types, for example to construct a set 93 * of types using {@link java.util.HashSet} with {@link Equivalence#wrap(Object)}. 94 * <li>If you want distinct type variables to be considered equal if they have the same names 95 * and bounds. 96 * <li>If you want wildcard types to compare equal if they have the same bounds. {@code 97 * Types.isSameType} never considers wildcards equal, even when comparing a type to itself. 98 * </ul> 99 */ equivalence()100 public static Equivalence<TypeMirror> equivalence() { 101 return TypeEquivalence.INSTANCE; 102 } 103 104 // So EQUAL_VISITOR can be a singleton, we maintain visiting state, in particular which types 105 // have been seen already, in this object. 106 // The logic for handling recursive types like Comparable<T extends Comparable<T>> is very tricky. 107 // If we're not careful we'll end up with an infinite recursion. So we record the types that 108 // we've already seen during the recursion, and if we see the same pair of types again we just 109 // return true provisionally. But "the same pair of types" is itself poorly-defined. We can't 110 // just say that it is an equal pair of TypeMirrors, because of course if we knew how to 111 // determine that then we wouldn't need the complicated type visitor at all. On the other hand, 112 // we can't say that it is an identical pair of TypeMirrors either, because there's no 113 // guarantee that the TypeMirrors for the two Ts in Comparable<T extends Comparable<T>> will be 114 // represented by the same object, and indeed with the Eclipse compiler they aren't. We could 115 // compare the corresponding Elements, since equality is well-defined there, but that's not enough 116 // either, because the Element for Set<Object> is the same as the one for Set<String>. So we 117 // approximate by comparing the Elements and, if there are any type arguments, requiring them to 118 // be identical. This may not be foolproof either but it is sufficient for all the cases we've 119 // encountered so far. 120 private static final class EqualVisitorParam { 121 TypeMirror type; 122 Set<ComparedElements> visiting; 123 } 124 125 private static class ComparedElements { 126 final Element a; 127 final ImmutableList<TypeMirror> aArguments; 128 final Element b; 129 final ImmutableList<TypeMirror> bArguments; 130 ComparedElements( Element a, ImmutableList<TypeMirror> aArguments, Element b, ImmutableList<TypeMirror> bArguments)131 ComparedElements( 132 Element a, 133 ImmutableList<TypeMirror> aArguments, 134 Element b, 135 ImmutableList<TypeMirror> bArguments) { 136 this.a = a; 137 this.aArguments = aArguments; 138 this.b = b; 139 this.bArguments = bArguments; 140 } 141 142 @Override equals(@ullable Object o)143 public boolean equals(@Nullable Object o) { 144 if (o instanceof ComparedElements) { 145 ComparedElements that = (ComparedElements) o; 146 int nArguments = aArguments.size(); 147 if (!this.a.equals(that.a) || !this.b.equals(that.b) || nArguments != bArguments.size()) { 148 // The arguments must be the same size, but we check anyway. 149 return false; 150 } 151 for (int i = 0; i < nArguments; i++) { 152 if (aArguments.get(i) != bArguments.get(i)) { 153 return false; 154 } 155 } 156 return true; 157 } else { 158 return false; 159 } 160 } 161 162 @Override hashCode()163 public int hashCode() { 164 return a.hashCode() * 31 + b.hashCode(); 165 } 166 } 167 168 private static final class EqualVisitor extends SimpleTypeVisitor8<Boolean, EqualVisitorParam> { 169 private static final EqualVisitor INSTANCE = new EqualVisitor(); 170 171 @Override defaultAction(TypeMirror a, EqualVisitorParam p)172 protected Boolean defaultAction(TypeMirror a, EqualVisitorParam p) { 173 return a.getKind().equals(p.type.getKind()); 174 } 175 176 @Override visitArray(ArrayType a, EqualVisitorParam p)177 public Boolean visitArray(ArrayType a, EqualVisitorParam p) { 178 if (p.type.getKind().equals(ARRAY)) { 179 ArrayType b = (ArrayType) p.type; 180 return equal(a.getComponentType(), b.getComponentType(), p.visiting); 181 } 182 return false; 183 } 184 185 @Override visitDeclared(DeclaredType a, EqualVisitorParam p)186 public Boolean visitDeclared(DeclaredType a, EqualVisitorParam p) { 187 if (p.type.getKind().equals(DECLARED)) { 188 DeclaredType b = (DeclaredType) p.type; 189 Element aElement = a.asElement(); 190 Element bElement = b.asElement(); 191 Set<ComparedElements> newVisiting = 192 visitingSetPlus( 193 p.visiting, aElement, a.getTypeArguments(), bElement, b.getTypeArguments()); 194 if (newVisiting.equals(p.visiting)) { 195 // We're already visiting this pair of elements. 196 // This can happen for example with Enum in Enum<E extends Enum<E>>. Return a 197 // provisional true value since if the Elements are not in fact equal the original 198 // visitor of Enum will discover that. We have to check both Elements being compared 199 // though to avoid missing the fact that one of the types being compared 200 // differs at exactly this point. 201 return true; 202 } 203 return aElement.equals(bElement) 204 && equal(enclosingType(a), enclosingType(b), newVisiting) 205 && equalLists(a.getTypeArguments(), b.getTypeArguments(), newVisiting); 206 } 207 return false; 208 } 209 210 @Override 211 @SuppressWarnings("TypeEquals") visitError(ErrorType a, EqualVisitorParam p)212 public Boolean visitError(ErrorType a, EqualVisitorParam p) { 213 return a.equals(p.type); 214 } 215 216 @Override visitExecutable(ExecutableType a, EqualVisitorParam p)217 public Boolean visitExecutable(ExecutableType a, EqualVisitorParam p) { 218 if (p.type.getKind().equals(EXECUTABLE)) { 219 ExecutableType b = (ExecutableType) p.type; 220 return equalLists(a.getParameterTypes(), b.getParameterTypes(), p.visiting) 221 && equal(a.getReturnType(), b.getReturnType(), p.visiting) 222 && equalLists(a.getThrownTypes(), b.getThrownTypes(), p.visiting) 223 && equalLists(a.getTypeVariables(), b.getTypeVariables(), p.visiting); 224 } 225 return false; 226 } 227 228 @Override visitIntersection(IntersectionType a, EqualVisitorParam p)229 public Boolean visitIntersection(IntersectionType a, EqualVisitorParam p) { 230 if (p.type.getKind().equals(INTERSECTION)) { 231 IntersectionType b = (IntersectionType) p.type; 232 return equalLists(a.getBounds(), b.getBounds(), p.visiting); 233 } 234 return false; 235 } 236 237 @Override visitTypeVariable(TypeVariable a, EqualVisitorParam p)238 public Boolean visitTypeVariable(TypeVariable a, EqualVisitorParam p) { 239 if (p.type.getKind().equals(TYPEVAR)) { 240 TypeVariable b = (TypeVariable) p.type; 241 TypeParameterElement aElement = (TypeParameterElement) a.asElement(); 242 TypeParameterElement bElement = (TypeParameterElement) b.asElement(); 243 Set<ComparedElements> newVisiting = visitingSetPlus(p.visiting, aElement, bElement); 244 if (newVisiting.equals(p.visiting)) { 245 // We're already visiting this pair of elements. 246 // This can happen with our friend Eclipse when looking at <T extends Comparable<T>>. 247 // It incorrectly reports the upper bound of T as T itself. 248 return true; 249 } 250 // We use aElement.getBounds() instead of a.getUpperBound() to avoid having to deal with 251 // the different way intersection types (like <T extends Number & Comparable<T>>) are 252 // represented before and after Java 8. We do have an issue that this code may consider 253 // that <T extends Foo & Bar> is different from <T extends Bar & Foo>, but it's very 254 // hard to avoid that, and not likely to be much of a problem in practice. 255 return equalLists(aElement.getBounds(), bElement.getBounds(), newVisiting) 256 && equal(a.getLowerBound(), b.getLowerBound(), newVisiting) 257 && a.asElement().getSimpleName().equals(b.asElement().getSimpleName()); 258 } 259 return false; 260 } 261 262 @Override visitWildcard(WildcardType a, EqualVisitorParam p)263 public Boolean visitWildcard(WildcardType a, EqualVisitorParam p) { 264 if (p.type.getKind().equals(WILDCARD)) { 265 WildcardType b = (WildcardType) p.type; 266 return equal(a.getExtendsBound(), b.getExtendsBound(), p.visiting) 267 && equal(a.getSuperBound(), b.getSuperBound(), p.visiting); 268 } 269 return false; 270 } 271 272 @Override visitUnknown(TypeMirror a, EqualVisitorParam p)273 public Boolean visitUnknown(TypeMirror a, EqualVisitorParam p) { 274 throw new UnsupportedOperationException(); 275 } 276 visitingSetPlus( Set<ComparedElements> visiting, Element a, Element b)277 private Set<ComparedElements> visitingSetPlus( 278 Set<ComparedElements> visiting, Element a, Element b) { 279 ImmutableList<TypeMirror> noArguments = ImmutableList.of(); 280 return visitingSetPlus(visiting, a, noArguments, b, noArguments); 281 } 282 visitingSetPlus( Set<ComparedElements> visiting, Element a, List<? extends TypeMirror> aArguments, Element b, List<? extends TypeMirror> bArguments)283 private Set<ComparedElements> visitingSetPlus( 284 Set<ComparedElements> visiting, 285 Element a, 286 List<? extends TypeMirror> aArguments, 287 Element b, 288 List<? extends TypeMirror> bArguments) { 289 ComparedElements comparedElements = 290 new ComparedElements( 291 a, ImmutableList.<TypeMirror>copyOf(aArguments), 292 b, ImmutableList.<TypeMirror>copyOf(bArguments)); 293 Set<ComparedElements> newVisiting = new HashSet<ComparedElements>(visiting); 294 newVisiting.add(comparedElements); 295 return newVisiting; 296 } 297 } 298 299 @SuppressWarnings("TypeEquals") equal( @ullable TypeMirror a, @Nullable TypeMirror b, Set<ComparedElements> visiting)300 private static boolean equal( 301 @Nullable TypeMirror a, @Nullable TypeMirror b, Set<ComparedElements> visiting) { 302 if (a == b) { 303 return true; 304 } 305 if (a == null || b == null) { 306 return false; 307 } 308 // TypeMirror.equals is not guaranteed to return true for types that are equal, but we can 309 // assume that if it does return true then the types are equal. This check also avoids getting 310 // stuck in infinite recursion when Eclipse decrees that the upper bound of the second K in 311 // <K extends Comparable<K>> is a distinct but equal K. 312 // The javac implementation of ExecutableType, at least in some versions, does not take thrown 313 // exceptions into account in its equals implementation, so avoid this optimization for 314 // ExecutableType. 315 @SuppressWarnings("TypesEquals") 316 boolean equal = a.equals(b); 317 if (equal && !(a instanceof ExecutableType)) { 318 return true; 319 } 320 EqualVisitorParam p = new EqualVisitorParam(); 321 p.type = b; 322 p.visiting = visiting; 323 return a.accept(EqualVisitor.INSTANCE, p); 324 } 325 326 /** 327 * Returns the type of the innermost enclosing instance, or null if there is none. This is the 328 * same as {@link DeclaredType#getEnclosingType()} except that it returns null rather than 329 * NoType for a static type. We need this because of 330 * <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=508222">this bug</a> whereby 331 * the Eclipse compiler returns a value for static classes that is not NoType. 332 */ enclosingType(DeclaredType t)333 private static @Nullable TypeMirror enclosingType(DeclaredType t) { 334 TypeMirror enclosing = t.getEnclosingType(); 335 if (enclosing.getKind().equals(TypeKind.NONE) 336 || t.asElement().getModifiers().contains(Modifier.STATIC)) { 337 return null; 338 } 339 return enclosing; 340 } 341 equalLists( List<? extends TypeMirror> a, List<? extends TypeMirror> b, Set<ComparedElements> visiting)342 private static boolean equalLists( 343 List<? extends TypeMirror> a, List<? extends TypeMirror> b, Set<ComparedElements> visiting) { 344 int size = a.size(); 345 if (size != b.size()) { 346 return false; 347 } 348 // Use iterators in case the Lists aren't RandomAccess 349 Iterator<? extends TypeMirror> aIterator = a.iterator(); 350 Iterator<? extends TypeMirror> bIterator = b.iterator(); 351 while (aIterator.hasNext()) { 352 // We checked that the lists have the same size, so we know that bIterator.hasNext() too. 353 TypeMirror nextMirrorA = aIterator.next(); 354 TypeMirror nextMirrorB = bIterator.next(); 355 if (!equal(nextMirrorA, nextMirrorB, visiting)) { 356 return false; 357 } 358 } 359 return true; 360 } 361 362 private static final int HASH_SEED = 17; 363 private static final int HASH_MULTIPLIER = 31; 364 365 private static final class HashVisitor extends SimpleTypeVisitor8<Integer, Set<Element>> { 366 private static final HashVisitor INSTANCE = new HashVisitor(); 367 hashKind(int seed, TypeMirror t)368 int hashKind(int seed, TypeMirror t) { 369 int result = seed * HASH_MULTIPLIER; 370 result += t.getKind().hashCode(); 371 return result; 372 } 373 374 @Override defaultAction(TypeMirror e, Set<Element> visiting)375 protected Integer defaultAction(TypeMirror e, Set<Element> visiting) { 376 return hashKind(HASH_SEED, e); 377 } 378 379 @Override visitArray(ArrayType t, Set<Element> visiting)380 public Integer visitArray(ArrayType t, Set<Element> visiting) { 381 int result = hashKind(HASH_SEED, t); 382 result *= HASH_MULTIPLIER; 383 result += t.getComponentType().accept(this, visiting); 384 return result; 385 } 386 387 @Override visitDeclared(DeclaredType t, Set<Element> visiting)388 public Integer visitDeclared(DeclaredType t, Set<Element> visiting) { 389 Element element = t.asElement(); 390 if (visiting.contains(element)) { 391 return 0; 392 } 393 Set<Element> newVisiting = new HashSet<Element>(visiting); 394 newVisiting.add(element); 395 int result = hashKind(HASH_SEED, t); 396 result *= HASH_MULTIPLIER; 397 result += t.asElement().hashCode(); 398 result *= HASH_MULTIPLIER; 399 result += t.getEnclosingType().accept(this, newVisiting); 400 result *= HASH_MULTIPLIER; 401 result += hashList(t.getTypeArguments(), newVisiting); 402 return result; 403 } 404 405 @Override visitExecutable(ExecutableType t, Set<Element> visiting)406 public Integer visitExecutable(ExecutableType t, Set<Element> visiting) { 407 int result = hashKind(HASH_SEED, t); 408 result *= HASH_MULTIPLIER; 409 result += hashList(t.getParameterTypes(), visiting); 410 result *= HASH_MULTIPLIER; 411 result += t.getReturnType().accept(this, visiting); 412 result *= HASH_MULTIPLIER; 413 result += hashList(t.getThrownTypes(), visiting); 414 result *= HASH_MULTIPLIER; 415 result += hashList(t.getTypeVariables(), visiting); 416 return result; 417 } 418 419 @Override visitTypeVariable(TypeVariable t, Set<Element> visiting)420 public Integer visitTypeVariable(TypeVariable t, Set<Element> visiting) { 421 int result = hashKind(HASH_SEED, t); 422 result *= HASH_MULTIPLIER; 423 result += t.getLowerBound().accept(this, visiting); 424 TypeParameterElement element = (TypeParameterElement) t.asElement(); 425 for (TypeMirror bound : element.getBounds()) { 426 result *= HASH_MULTIPLIER; 427 result += bound.accept(this, visiting); 428 } 429 return result; 430 } 431 432 @Override visitWildcard(WildcardType t, Set<Element> visiting)433 public Integer visitWildcard(WildcardType t, Set<Element> visiting) { 434 int result = hashKind(HASH_SEED, t); 435 result *= HASH_MULTIPLIER; 436 result += (t.getExtendsBound() == null) ? 0 : t.getExtendsBound().accept(this, visiting); 437 result *= HASH_MULTIPLIER; 438 result += (t.getSuperBound() == null) ? 0 : t.getSuperBound().accept(this, visiting); 439 return result; 440 } 441 442 @Override visitUnknown(TypeMirror t, Set<Element> visiting)443 public Integer visitUnknown(TypeMirror t, Set<Element> visiting) { 444 throw new UnsupportedOperationException(); 445 } 446 } 447 hashList(List<? extends TypeMirror> mirrors, Set<Element> visiting)448 private static int hashList(List<? extends TypeMirror> mirrors, Set<Element> visiting) { 449 int result = HASH_SEED; 450 for (TypeMirror mirror : mirrors) { 451 result *= HASH_MULTIPLIER; 452 result += hash(mirror, visiting); 453 } 454 return result; 455 } 456 hash(TypeMirror mirror, Set<Element> visiting)457 private static int hash(TypeMirror mirror, Set<Element> visiting) { 458 return mirror == null ? 0 : mirror.accept(HashVisitor.INSTANCE, visiting); 459 } 460 461 /** 462 * Returns the set of {@linkplain TypeElement types} that are referenced by the given {@link 463 * TypeMirror}. 464 */ referencedTypes(TypeMirror type)465 public static ImmutableSet<TypeElement> referencedTypes(TypeMirror type) { 466 checkNotNull(type); 467 ImmutableSet.Builder<TypeElement> elements = ImmutableSet.builder(); 468 type.accept(ReferencedTypes.INSTANCE, elements); 469 return elements.build(); 470 } 471 472 private static final class ReferencedTypes 473 extends SimpleTypeVisitor8<@Nullable Void, ImmutableSet.Builder<TypeElement>> { 474 private static final ReferencedTypes INSTANCE = new ReferencedTypes(); 475 476 @Override visitArray(ArrayType t, ImmutableSet.Builder<TypeElement> p)477 public @Nullable Void visitArray(ArrayType t, ImmutableSet.Builder<TypeElement> p) { 478 t.getComponentType().accept(this, p); 479 return null; 480 } 481 482 @Override visitDeclared(DeclaredType t, ImmutableSet.Builder<TypeElement> p)483 public @Nullable Void visitDeclared(DeclaredType t, ImmutableSet.Builder<TypeElement> p) { 484 p.add(MoreElements.asType(t.asElement())); 485 for (TypeMirror typeArgument : t.getTypeArguments()) { 486 typeArgument.accept(this, p); 487 } 488 return null; 489 } 490 491 @Override visitTypeVariable(TypeVariable t, ImmutableSet.Builder<TypeElement> p)492 public @Nullable Void visitTypeVariable(TypeVariable t, ImmutableSet.Builder<TypeElement> p) { 493 t.getLowerBound().accept(this, p); 494 t.getUpperBound().accept(this, p); 495 return null; 496 } 497 498 @Override visitWildcard(WildcardType t, ImmutableSet.Builder<TypeElement> p)499 public @Nullable Void visitWildcard(WildcardType t, ImmutableSet.Builder<TypeElement> p) { 500 TypeMirror extendsBound = t.getExtendsBound(); 501 if (extendsBound != null) { 502 extendsBound.accept(this, p); 503 } 504 TypeMirror superBound = t.getSuperBound(); 505 if (superBound != null) { 506 superBound.accept(this, p); 507 } 508 return null; 509 } 510 } 511 512 /** 513 * An alternate implementation of {@link Types#asElement} that does not require a {@link Types} 514 * instance with the notable difference that it will throw {@link IllegalArgumentException} 515 * instead of returning null if the {@link TypeMirror} can not be converted to an {@link Element}. 516 * 517 * @throws NullPointerException if {@code typeMirror} is {@code null} 518 * @throws IllegalArgumentException if {@code typeMirror} cannot be converted to an {@link 519 * Element} 520 */ asElement(TypeMirror typeMirror)521 public static Element asElement(TypeMirror typeMirror) { 522 return typeMirror.accept(AsElementVisitor.INSTANCE, null); 523 } 524 525 private static final class AsElementVisitor extends SimpleTypeVisitor8<Element, Void> { 526 private static final AsElementVisitor INSTANCE = new AsElementVisitor(); 527 528 @Override defaultAction(TypeMirror e, Void p)529 protected Element defaultAction(TypeMirror e, Void p) { 530 throw new IllegalArgumentException(e + " cannot be converted to an Element"); 531 } 532 533 @Override visitDeclared(DeclaredType t, Void p)534 public Element visitDeclared(DeclaredType t, Void p) { 535 return t.asElement(); 536 } 537 538 @Override visitError(ErrorType t, Void p)539 public Element visitError(ErrorType t, Void p) { 540 return t.asElement(); 541 } 542 543 @Override visitTypeVariable(TypeVariable t, Void p)544 public Element visitTypeVariable(TypeVariable t, Void p) { 545 return t.asElement(); 546 } 547 } 548 ; 549 550 // TODO(gak): consider removing these two methods as they're pretty trivial now asTypeElement(TypeMirror mirror)551 public static TypeElement asTypeElement(TypeMirror mirror) { 552 return MoreElements.asType(asElement(mirror)); 553 } 554 asTypeElements(Iterable<? extends TypeMirror> mirrors)555 public static ImmutableSet<TypeElement> asTypeElements(Iterable<? extends TypeMirror> mirrors) { 556 checkNotNull(mirrors); 557 ImmutableSet.Builder<TypeElement> builder = ImmutableSet.builder(); 558 for (TypeMirror mirror : mirrors) { 559 builder.add(asTypeElement(mirror)); 560 } 561 return builder.build(); 562 } 563 564 /** 565 * Returns a {@link ArrayType} if the {@link TypeMirror} represents an array or throws an {@link 566 * IllegalArgumentException}. 567 */ asArray(TypeMirror maybeArrayType)568 public static ArrayType asArray(TypeMirror maybeArrayType) { 569 return maybeArrayType.accept(ArrayTypeVisitor.INSTANCE, null); 570 } 571 572 private static final class ArrayTypeVisitor extends CastingTypeVisitor<ArrayType> { 573 private static final ArrayTypeVisitor INSTANCE = new ArrayTypeVisitor(); 574 ArrayTypeVisitor()575 ArrayTypeVisitor() { 576 super("array"); 577 } 578 579 @Override visitArray(ArrayType type, Void ignore)580 public ArrayType visitArray(ArrayType type, Void ignore) { 581 return type; 582 } 583 } 584 585 /** 586 * Returns a {@link DeclaredType} if the {@link TypeMirror} represents a declared type such as a 587 * class, interface, union/compound, or enum or throws an {@link IllegalArgumentException}. 588 */ asDeclared(TypeMirror maybeDeclaredType)589 public static DeclaredType asDeclared(TypeMirror maybeDeclaredType) { 590 return maybeDeclaredType.accept(DeclaredTypeVisitor.INSTANCE, null); 591 } 592 593 private static final class DeclaredTypeVisitor extends CastingTypeVisitor<DeclaredType> { 594 private static final DeclaredTypeVisitor INSTANCE = new DeclaredTypeVisitor(); 595 DeclaredTypeVisitor()596 DeclaredTypeVisitor() { 597 super("declared type"); 598 } 599 600 @Override visitDeclared(DeclaredType type, Void ignore)601 public DeclaredType visitDeclared(DeclaredType type, Void ignore) { 602 return type; 603 } 604 } 605 606 /** 607 * Returns a {@link ExecutableType} if the {@link TypeMirror} represents an executable type such 608 * as may result from missing code, or bad compiles or throws an {@link IllegalArgumentException}. 609 */ asError(TypeMirror maybeErrorType)610 public static ErrorType asError(TypeMirror maybeErrorType) { 611 return maybeErrorType.accept(ErrorTypeVisitor.INSTANCE, null); 612 } 613 614 private static final class ErrorTypeVisitor extends CastingTypeVisitor<ErrorType> { 615 private static final ErrorTypeVisitor INSTANCE = new ErrorTypeVisitor(); 616 ErrorTypeVisitor()617 ErrorTypeVisitor() { 618 super("error type"); 619 } 620 621 @Override visitError(ErrorType type, Void ignore)622 public ErrorType visitError(ErrorType type, Void ignore) { 623 return type; 624 } 625 } 626 627 /** 628 * Returns a {@link ExecutableType} if the {@link TypeMirror} represents an executable type such 629 * as a method, constructor, or initializer or throws an {@link IllegalArgumentException}. 630 */ asExecutable(TypeMirror maybeExecutableType)631 public static ExecutableType asExecutable(TypeMirror maybeExecutableType) { 632 return maybeExecutableType.accept(ExecutableTypeVisitor.INSTANCE, null); 633 } 634 635 private static final class ExecutableTypeVisitor extends CastingTypeVisitor<ExecutableType> { 636 private static final ExecutableTypeVisitor INSTANCE = new ExecutableTypeVisitor(); 637 ExecutableTypeVisitor()638 ExecutableTypeVisitor() { 639 super("executable type"); 640 } 641 642 @Override visitExecutable(ExecutableType type, Void ignore)643 public ExecutableType visitExecutable(ExecutableType type, Void ignore) { 644 return type; 645 } 646 } 647 648 /** 649 * Returns an {@link IntersectionType} if the {@link TypeMirror} represents an intersection-type 650 * or throws an {@link IllegalArgumentException}. 651 */ asIntersection(TypeMirror maybeIntersectionType)652 public static IntersectionType asIntersection(TypeMirror maybeIntersectionType) { 653 return maybeIntersectionType.accept(IntersectionTypeVisitor.INSTANCE, null); 654 } 655 656 private static final class IntersectionTypeVisitor extends CastingTypeVisitor<IntersectionType> { 657 private static final IntersectionTypeVisitor INSTANCE = new IntersectionTypeVisitor(); 658 IntersectionTypeVisitor()659 IntersectionTypeVisitor() { 660 super("intersection type"); 661 } 662 663 @Override visitIntersection(IntersectionType type, Void ignore)664 public IntersectionType visitIntersection(IntersectionType type, Void ignore) { 665 return type; 666 } 667 } 668 669 /** 670 * Returns a {@link NoType} if the {@link TypeMirror} represents an non-type such as void, or 671 * package, etc. or throws an {@link IllegalArgumentException}. 672 */ asNoType(TypeMirror maybeNoType)673 public static NoType asNoType(TypeMirror maybeNoType) { 674 return maybeNoType.accept(NoTypeVisitor.INSTANCE, null); 675 } 676 677 private static final class NoTypeVisitor extends CastingTypeVisitor<NoType> { 678 private static final NoTypeVisitor INSTANCE = new NoTypeVisitor(); 679 NoTypeVisitor()680 NoTypeVisitor() { 681 super("non-type"); 682 } 683 684 @Override visitNoType(NoType type, Void ignore)685 public NoType visitNoType(NoType type, Void ignore) { 686 return type; 687 } 688 } 689 690 /** 691 * Returns a {@link NullType} if the {@link TypeMirror} represents the null type or throws an 692 * {@link IllegalArgumentException}. 693 */ asNullType(TypeMirror maybeNullType)694 public static NullType asNullType(TypeMirror maybeNullType) { 695 return maybeNullType.accept(NullTypeVisitor.INSTANCE, null); 696 } 697 698 private static final class NullTypeVisitor extends CastingTypeVisitor<NullType> { 699 private static final NullTypeVisitor INSTANCE = new NullTypeVisitor(); 700 NullTypeVisitor()701 NullTypeVisitor() { 702 super("null"); 703 } 704 705 @Override visitNull(NullType type, Void ignore)706 public NullType visitNull(NullType type, Void ignore) { 707 return type; 708 } 709 } 710 711 /** 712 * Returns a {@link PrimitiveType} if the {@link TypeMirror} represents a primitive type or throws 713 * an {@link IllegalArgumentException}. 714 */ asPrimitiveType(TypeMirror maybePrimitiveType)715 public static PrimitiveType asPrimitiveType(TypeMirror maybePrimitiveType) { 716 return maybePrimitiveType.accept(PrimitiveTypeVisitor.INSTANCE, null); 717 } 718 719 private static final class PrimitiveTypeVisitor extends CastingTypeVisitor<PrimitiveType> { 720 private static final PrimitiveTypeVisitor INSTANCE = new PrimitiveTypeVisitor(); 721 PrimitiveTypeVisitor()722 PrimitiveTypeVisitor() { 723 super("primitive type"); 724 } 725 726 @Override visitPrimitive(PrimitiveType type, Void ignore)727 public PrimitiveType visitPrimitive(PrimitiveType type, Void ignore) { 728 return type; 729 } 730 } 731 732 // 733 // visitUnionType would go here, but isn't relevant for annotation processors 734 // 735 736 /** 737 * Returns a {@link TypeVariable} if the {@link TypeMirror} represents a type variable or throws 738 * an {@link IllegalArgumentException}. 739 */ asTypeVariable(TypeMirror maybeTypeVariable)740 public static TypeVariable asTypeVariable(TypeMirror maybeTypeVariable) { 741 return maybeTypeVariable.accept(TypeVariableVisitor.INSTANCE, null); 742 } 743 744 private static final class TypeVariableVisitor extends CastingTypeVisitor<TypeVariable> { 745 private static final TypeVariableVisitor INSTANCE = new TypeVariableVisitor(); 746 TypeVariableVisitor()747 TypeVariableVisitor() { 748 super("type variable"); 749 } 750 751 @Override visitTypeVariable(TypeVariable type, Void ignore)752 public TypeVariable visitTypeVariable(TypeVariable type, Void ignore) { 753 return type; 754 } 755 } 756 757 /** 758 * Returns a {@link WildcardType} if the {@link TypeMirror} represents a wildcard type or throws 759 * an {@link IllegalArgumentException}. 760 */ asWildcard(TypeMirror maybeWildcardType)761 public static WildcardType asWildcard(TypeMirror maybeWildcardType) { 762 return maybeWildcardType.accept(WildcardTypeVisitor.INSTANCE, null); 763 } 764 765 private static final class WildcardTypeVisitor extends CastingTypeVisitor<WildcardType> { 766 private static final WildcardTypeVisitor INSTANCE = new WildcardTypeVisitor(); 767 WildcardTypeVisitor()768 WildcardTypeVisitor() { 769 super("wildcard type"); 770 } 771 772 @Override visitWildcard(WildcardType type, Void ignore)773 public WildcardType visitWildcard(WildcardType type, Void ignore) { 774 return type; 775 } 776 } 777 778 /** 779 * Returns true if the raw type underlying the given {@link TypeMirror} represents a type that can 780 * be referenced by a {@link Class}. If this returns true, then {@link #isTypeOf} is guaranteed to 781 * not throw. 782 */ isType(TypeMirror type)783 public static boolean isType(TypeMirror type) { 784 return type.accept(IsTypeVisitor.INSTANCE, null); 785 } 786 787 private static final class IsTypeVisitor extends SimpleTypeVisitor8<Boolean, Void> { 788 private static final IsTypeVisitor INSTANCE = new IsTypeVisitor(); 789 790 @Override defaultAction(TypeMirror type, Void ignored)791 protected Boolean defaultAction(TypeMirror type, Void ignored) { 792 return false; 793 } 794 795 @Override visitNoType(NoType noType, Void p)796 public Boolean visitNoType(NoType noType, Void p) { 797 return noType.getKind().equals(TypeKind.VOID); 798 } 799 800 @Override visitPrimitive(PrimitiveType type, Void p)801 public Boolean visitPrimitive(PrimitiveType type, Void p) { 802 return true; 803 } 804 805 @Override visitArray(ArrayType array, Void p)806 public Boolean visitArray(ArrayType array, Void p) { 807 return true; 808 } 809 810 @Override visitDeclared(DeclaredType type, Void ignored)811 public Boolean visitDeclared(DeclaredType type, Void ignored) { 812 return MoreElements.isType(type.asElement()); 813 } 814 } 815 816 /** 817 * Returns true if the raw type underlying the given {@link TypeMirror} represents the same raw 818 * type as the given {@link Class} and throws an IllegalArgumentException if the {@link 819 * TypeMirror} does not represent a type that can be referenced by a {@link Class} 820 */ isTypeOf(final Class<?> clazz, TypeMirror type)821 public static boolean isTypeOf(final Class<?> clazz, TypeMirror type) { 822 checkNotNull(clazz); 823 return type.accept(new IsTypeOf(clazz), null); 824 } 825 826 private static final class IsTypeOf extends SimpleTypeVisitor8<Boolean, Void> { 827 private final Class<?> clazz; 828 IsTypeOf(Class<?> clazz)829 IsTypeOf(Class<?> clazz) { 830 this.clazz = clazz; 831 } 832 833 @Override defaultAction(TypeMirror type, Void ignored)834 protected Boolean defaultAction(TypeMirror type, Void ignored) { 835 throw new IllegalArgumentException(type + " cannot be represented as a Class<?>."); 836 } 837 838 @Override visitNoType(NoType noType, Void p)839 public Boolean visitNoType(NoType noType, Void p) { 840 if (noType.getKind().equals(TypeKind.VOID)) { 841 return clazz.equals(Void.TYPE); 842 } 843 throw new IllegalArgumentException(noType + " cannot be represented as a Class<?>."); 844 } 845 846 @Override visitError(ErrorType errorType, Void p)847 public Boolean visitError(ErrorType errorType, Void p) { 848 return false; 849 } 850 851 @Override visitPrimitive(PrimitiveType type, Void p)852 public Boolean visitPrimitive(PrimitiveType type, Void p) { 853 switch (type.getKind()) { 854 case BOOLEAN: 855 return clazz.equals(Boolean.TYPE); 856 case BYTE: 857 return clazz.equals(Byte.TYPE); 858 case CHAR: 859 return clazz.equals(Character.TYPE); 860 case DOUBLE: 861 return clazz.equals(Double.TYPE); 862 case FLOAT: 863 return clazz.equals(Float.TYPE); 864 case INT: 865 return clazz.equals(Integer.TYPE); 866 case LONG: 867 return clazz.equals(Long.TYPE); 868 case SHORT: 869 return clazz.equals(Short.TYPE); 870 default: 871 throw new IllegalArgumentException(type + " cannot be represented as a Class<?>."); 872 } 873 } 874 875 @Override visitArray(ArrayType array, Void p)876 public Boolean visitArray(ArrayType array, Void p) { 877 return clazz.isArray() && isTypeOf(clazz.getComponentType(), array.getComponentType()); 878 } 879 880 @Override visitDeclared(DeclaredType type, Void ignored)881 public Boolean visitDeclared(DeclaredType type, Void ignored) { 882 TypeElement typeElement = MoreElements.asType(type.asElement()); 883 return typeElement.getQualifiedName().contentEquals(clazz.getCanonicalName()); 884 } 885 } 886 887 /** 888 * Returns the superclass of {@code type}, with any type parameters bound by {@code type}, or 889 * {@link Optional#absent()} if {@code type} is an interface or {@link Object} or its superclass 890 * is {@link Object}. 891 */ 892 // TODO(bcorso): Remove unused parameter Elements? nonObjectSuperclass( Types types, Elements elements, DeclaredType type)893 public static Optional<DeclaredType> nonObjectSuperclass( 894 Types types, Elements elements, DeclaredType type) { 895 checkNotNull(types); 896 checkNotNull(elements); // This is no longer used, but here to avoid changing the API. 897 checkNotNull(type); 898 899 TypeMirror superclassType = asTypeElement(type).getSuperclass(); 900 if (!isType(superclassType)) { // type is Object or an interface 901 return Optional.absent(); 902 } 903 904 DeclaredType superclass = asDeclared(superclassType); 905 if (isObjectType(superclass)) { 906 return Optional.absent(); 907 } 908 909 if (superclass.getTypeArguments().isEmpty()) { 910 return Optional.of(superclass); 911 } 912 913 // In the case where the super class has type parameters, TypeElement#getSuperclass gives 914 // SuperClass<T> rather than SuperClass<Foo>, so use Types#directSupertypes instead. The javadoc 915 // for Types#directSupertypes guarantees that a super class, if it exists, comes before any 916 // interfaces. Thus, we can just get the first element in the list. 917 return Optional.of(asDeclared(types.directSupertypes(type).get(0))); 918 } 919 isObjectType(DeclaredType type)920 private static boolean isObjectType(DeclaredType type) { 921 return asTypeElement(type).getQualifiedName().contentEquals("java.lang.Object"); 922 } 923 924 /** 925 * Resolves a {@link VariableElement} parameter to a method or constructor based on the given 926 * container, or a member of a class. For parameters to a method or constructor, the variable's 927 * enclosing element must be a supertype of the container type. For example, given a 928 * {@code container} of type {@code Set<String>}, and a variable corresponding to the {@code E e} 929 * parameter in the {@code Set.add(E e)} method, this will return a TypeMirror for {@code String}. 930 */ asMemberOf( Types types, DeclaredType container, VariableElement variable)931 public static TypeMirror asMemberOf( 932 Types types, DeclaredType container, VariableElement variable) { 933 if (variable.getKind().equals(ElementKind.PARAMETER)) { 934 ExecutableElement methodOrConstructor = 935 MoreElements.asExecutable(variable.getEnclosingElement()); 936 ExecutableType resolvedMethodOrConstructor = 937 MoreTypes.asExecutable(types.asMemberOf(container, methodOrConstructor)); 938 List<? extends VariableElement> parameters = methodOrConstructor.getParameters(); 939 List<? extends TypeMirror> parameterTypes = resolvedMethodOrConstructor.getParameterTypes(); 940 checkState(parameters.size() == parameterTypes.size()); 941 for (int i = 0; i < parameters.size(); i++) { 942 // We need to capture the parameter type of the variable we're concerned about, 943 // for later printing. This is the only way to do it since we can't use 944 // types.asMemberOf on variables of methods. 945 if (parameters.get(i).equals(variable)) { 946 return parameterTypes.get(i); 947 } 948 } 949 throw new IllegalStateException("Could not find variable: " + variable); 950 } else { 951 return types.asMemberOf(container, variable); 952 } 953 } 954 955 private abstract static class CastingTypeVisitor<T> extends SimpleTypeVisitor8<T, Void> { 956 private final String label; 957 CastingTypeVisitor(String label)958 CastingTypeVisitor(String label) { 959 this.label = label; 960 } 961 962 @Override defaultAction(TypeMirror e, Void v)963 protected T defaultAction(TypeMirror e, Void v) { 964 throw new IllegalArgumentException(e + " does not represent a " + label); 965 } 966 } 967 968 /** 969 * Returns true if casting {@code Object} to the given type will elicit an unchecked warning from 970 * the compiler. Only type variables and parameterized types such as {@code List<String>} produce 971 * such warnings. There will be no warning if the type's only type parameters are simple 972 * wildcards, as in {@code Map<?, ?>}. 973 */ isConversionFromObjectUnchecked(TypeMirror type)974 public static boolean isConversionFromObjectUnchecked(TypeMirror type) { 975 return new CastingUncheckedVisitor().visit(type, null); 976 } 977 978 /** 979 * Visitor that tells whether a type is erased, in the sense of {@link #castIsUnchecked}. Each 980 * visitX method returns true if its input parameter is true or if the type being visited is 981 * erased. 982 */ 983 private static class CastingUncheckedVisitor extends SimpleTypeVisitor8<Boolean, Void> { CastingUncheckedVisitor()984 CastingUncheckedVisitor() { 985 super(false); 986 } 987 988 @Override visitUnknown(TypeMirror t, Void p)989 public Boolean visitUnknown(TypeMirror t, Void p) { 990 // We don't know whether casting is unchecked for this mysterious type but assume it is, 991 // so we will insert a possibly unnecessary @SuppressWarnings("unchecked"). 992 return true; 993 } 994 995 @Override visitArray(ArrayType t, Void p)996 public Boolean visitArray(ArrayType t, Void p) { 997 return visit(t.getComponentType(), p); 998 } 999 1000 @Override visitDeclared(DeclaredType t, Void p)1001 public Boolean visitDeclared(DeclaredType t, Void p) { 1002 return t.getTypeArguments().stream().anyMatch(CastingUncheckedVisitor::uncheckedTypeArgument); 1003 } 1004 1005 @Override visitTypeVariable(TypeVariable t, Void p)1006 public Boolean visitTypeVariable(TypeVariable t, Void p) { 1007 return true; 1008 } 1009 1010 // If a type has a type argument, then casting to the type is unchecked, except if the argument 1011 // is <?> or <? extends Object>. The same applies to all type arguments, so casting to Map<?, ?> 1012 // does not produce an unchecked warning for example. uncheckedTypeArgument(TypeMirror arg)1013 private static boolean uncheckedTypeArgument(TypeMirror arg) { 1014 if (arg.getKind().equals(TypeKind.WILDCARD)) { 1015 WildcardType wildcard = asWildcard(arg); 1016 if (wildcard.getExtendsBound() == null || isJavaLangObject(wildcard.getExtendsBound())) { 1017 // This is <?>, unless there's a super bound, in which case it is <? super Foo> and 1018 // is erased. 1019 return (wildcard.getSuperBound() != null); 1020 } 1021 } 1022 return true; 1023 } 1024 isJavaLangObject(TypeMirror type)1025 private static boolean isJavaLangObject(TypeMirror type) { 1026 if (type.getKind() != TypeKind.DECLARED) { 1027 return false; 1028 } 1029 TypeElement typeElement = asTypeElement(type); 1030 return typeElement.getQualifiedName().contentEquals("java.lang.Object"); 1031 } 1032 } 1033 MoreTypes()1034 private MoreTypes() {} 1035 } 1036