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