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.truth.Truth.assertThat; 19 import static java.util.Objects.requireNonNull; 20 import static javax.lang.model.type.TypeKind.NONE; 21 import static javax.lang.model.type.TypeKind.VOID; 22 import static org.junit.Assert.assertThrows; 23 import static org.junit.Assert.fail; 24 25 import com.google.common.base.Optional; 26 import com.google.common.collect.FluentIterable; 27 import com.google.common.collect.ImmutableList; 28 import com.google.common.collect.ImmutableMap; 29 import com.google.common.collect.ImmutableSet; 30 import com.google.common.collect.Iterables; 31 import com.google.common.testing.EquivalenceTester; 32 import com.google.common.truth.Expect; 33 import com.google.testing.compile.CompilationRule; 34 import java.lang.annotation.Annotation; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.Set; 38 import javax.lang.model.element.AnnotationMirror; 39 import javax.lang.model.element.Element; 40 import javax.lang.model.element.TypeElement; 41 import javax.lang.model.element.TypeParameterElement; 42 import javax.lang.model.element.VariableElement; 43 import javax.lang.model.type.DeclaredType; 44 import javax.lang.model.type.ErrorType; 45 import javax.lang.model.type.PrimitiveType; 46 import javax.lang.model.type.TypeKind; 47 import javax.lang.model.type.TypeMirror; 48 import javax.lang.model.type.TypeVisitor; 49 import javax.lang.model.type.WildcardType; 50 import javax.lang.model.util.ElementFilter; 51 import javax.lang.model.util.Elements; 52 import javax.lang.model.util.Types; 53 import org.checkerframework.checker.nullness.qual.Nullable; 54 import org.junit.Rule; 55 import org.junit.Test; 56 import org.junit.runner.RunWith; 57 import org.junit.runners.JUnit4; 58 59 @RunWith(JUnit4.class) 60 public class MoreTypesTest { 61 @Rule public final CompilationRule compilationRule = new CompilationRule(); 62 @Rule public final Expect expect = Expect.create(); 63 64 @Test equivalence()65 public void equivalence() { 66 Types types = compilationRule.getTypes(); 67 Elements elements = compilationRule.getElements(); 68 TypeMirror objectType = elements.getTypeElement(Object.class.getCanonicalName()).asType(); 69 TypeMirror stringType = elements.getTypeElement(String.class.getCanonicalName()).asType(); 70 TypeElement mapElement = elements.getTypeElement(Map.class.getCanonicalName()); 71 TypeElement setElement = elements.getTypeElement(Set.class.getCanonicalName()); 72 TypeElement enumElement = elements.getTypeElement(Enum.class.getCanonicalName()); 73 TypeElement container = elements.getTypeElement(Container.class.getCanonicalName()); 74 TypeElement contained = elements.getTypeElement(Container.Contained.class.getCanonicalName()); 75 TypeElement funkyBounds = elements.getTypeElement(FunkyBounds.class.getCanonicalName()); 76 TypeElement funkyBounds2 = elements.getTypeElement(FunkyBounds2.class.getCanonicalName()); 77 TypeElement funkierBounds = elements.getTypeElement(FunkierBounds.class.getCanonicalName()); 78 TypeMirror funkyBoundsVar = ((DeclaredType) funkyBounds.asType()).getTypeArguments().get(0); 79 TypeMirror funkyBounds2Var = ((DeclaredType) funkyBounds2.asType()).getTypeArguments().get(0); 80 TypeMirror funkierBoundsVar = ((DeclaredType) funkierBounds.asType()).getTypeArguments().get(0); 81 DeclaredType mapOfObjectToObjectType = 82 types.getDeclaredType(mapElement, objectType, objectType); 83 TypeMirror mapType = mapElement.asType(); 84 DeclaredType setOfSetOfObject = 85 types.getDeclaredType(setElement, types.getDeclaredType(setElement, objectType)); 86 DeclaredType setOfSetOfString = 87 types.getDeclaredType(setElement, types.getDeclaredType(setElement, stringType)); 88 DeclaredType setOfSetOfSetOfObject = types.getDeclaredType(setElement, setOfSetOfObject); 89 DeclaredType setOfSetOfSetOfString = types.getDeclaredType(setElement, setOfSetOfString); 90 WildcardType wildcard = types.getWildcardType(null, null); 91 DeclaredType containerOfObject = types.getDeclaredType(container, objectType); 92 DeclaredType containerOfString = types.getDeclaredType(container, stringType); 93 TypeMirror containedInObject = types.asMemberOf(containerOfObject, contained); 94 TypeMirror containedInString = types.asMemberOf(containerOfString, contained); 95 EquivalenceTester<TypeMirror> tester = 96 EquivalenceTester.<TypeMirror>of(MoreTypes.equivalence()) 97 .addEquivalenceGroup(types.getNullType()) 98 .addEquivalenceGroup(types.getNoType(NONE)) 99 .addEquivalenceGroup(types.getNoType(VOID)) 100 .addEquivalenceGroup(objectType) 101 .addEquivalenceGroup(stringType) 102 .addEquivalenceGroup(containedInObject) 103 .addEquivalenceGroup(containedInString) 104 .addEquivalenceGroup(funkyBounds.asType()) 105 .addEquivalenceGroup(funkyBounds2.asType()) 106 .addEquivalenceGroup(funkierBounds.asType()) 107 .addEquivalenceGroup(funkyBoundsVar, funkyBounds2Var) 108 .addEquivalenceGroup(funkierBoundsVar) 109 // Enum<E extends Enum<E>> 110 .addEquivalenceGroup(enumElement.asType()) 111 // Map<K, V> 112 .addEquivalenceGroup(mapType) 113 .addEquivalenceGroup(mapOfObjectToObjectType) 114 // Map<?, ?> 115 .addEquivalenceGroup(types.getDeclaredType(mapElement, wildcard, wildcard)) 116 // Map 117 .addEquivalenceGroup(types.erasure(mapType), types.erasure(mapOfObjectToObjectType)) 118 .addEquivalenceGroup(types.getDeclaredType(mapElement, objectType, stringType)) 119 .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType, objectType)) 120 .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType, stringType)) 121 .addEquivalenceGroup(setOfSetOfObject) 122 .addEquivalenceGroup(setOfSetOfString) 123 .addEquivalenceGroup(setOfSetOfSetOfObject) 124 .addEquivalenceGroup(setOfSetOfSetOfString) 125 .addEquivalenceGroup(wildcard) 126 // ? extends Object 127 .addEquivalenceGroup(types.getWildcardType(objectType, null)) 128 // ? extends String 129 .addEquivalenceGroup(types.getWildcardType(stringType, null)) 130 // ? super String 131 .addEquivalenceGroup(types.getWildcardType(null, stringType)) 132 // Map<String, Map<String, Set<Object>>> 133 .addEquivalenceGroup( 134 types.getDeclaredType( 135 mapElement, 136 stringType, 137 types.getDeclaredType( 138 mapElement, stringType, types.getDeclaredType(setElement, objectType)))) 139 .addEquivalenceGroup(FAKE_ERROR_TYPE); 140 141 for (TypeKind kind : TypeKind.values()) { 142 if (kind.isPrimitive()) { 143 PrimitiveType primitiveType = types.getPrimitiveType(kind); 144 TypeMirror boxedPrimitiveType = types.boxedClass(primitiveType).asType(); 145 tester.addEquivalenceGroup(primitiveType, types.unboxedType(boxedPrimitiveType)); 146 tester.addEquivalenceGroup(boxedPrimitiveType); 147 tester.addEquivalenceGroup(types.getArrayType(primitiveType)); 148 tester.addEquivalenceGroup(types.getArrayType(boxedPrimitiveType)); 149 } 150 } 151 152 ImmutableSet<Class<?>> testClasses = 153 ImmutableSet.of( 154 ExecutableElementsGroupA.class, 155 ExecutableElementsGroupB.class, 156 ExecutableElementsGroupC.class, 157 ExecutableElementsGroupD.class, 158 ExecutableElementsGroupE.class); 159 for (Class<?> testClass : testClasses) { 160 ImmutableList<TypeMirror> equivalenceGroup = 161 FluentIterable.from( 162 elements.getTypeElement(testClass.getCanonicalName()).getEnclosedElements()) 163 .transform(Element::asType) 164 .toList(); 165 tester.addEquivalenceGroup(equivalenceGroup); 166 } 167 168 tester.test(); 169 } 170 171 @SuppressWarnings("unused") 172 private static final class ExecutableElementsGroupA { ExecutableElementsGroupA()173 ExecutableElementsGroupA() {} 174 a()175 void a() {} 176 b()177 public static void b() {} 178 } 179 180 @SuppressWarnings("unused") 181 private static final class ExecutableElementsGroupB { ExecutableElementsGroupB(String s)182 ExecutableElementsGroupB(String s) {} 183 a(String s)184 void a(String s) {} 185 b(String s)186 public static void b(String s) {} 187 } 188 189 @SuppressWarnings("unused") 190 private static final class ExecutableElementsGroupC { ExecutableElementsGroupC()191 ExecutableElementsGroupC() throws Exception {} 192 a()193 void a() throws Exception {} 194 b()195 public static void b() throws Exception {} 196 } 197 198 @SuppressWarnings("unused") 199 private static final class ExecutableElementsGroupD { ExecutableElementsGroupD()200 ExecutableElementsGroupD() throws RuntimeException {} 201 a()202 void a() throws RuntimeException {} 203 b()204 public static void b() throws RuntimeException {} 205 } 206 207 @SuppressWarnings("unused") 208 private static final class ExecutableElementsGroupE { ExecutableElementsGroupE()209 <T> ExecutableElementsGroupE() {} 210 a()211 <T> void a() {} 212 b()213 public static <T> void b() {} 214 } 215 216 @SuppressWarnings("unused") 217 private static final class Container<T> { 218 private final class Contained {} 219 } 220 221 @SuppressWarnings("unused") 222 private static final class FunkyBounds<T extends Number & Comparable<T>> {} 223 224 @SuppressWarnings("unused") 225 private static final class FunkyBounds2<T extends Number & Comparable<T>> {} 226 227 @SuppressWarnings("unused") 228 private static final class FunkierBounds<T extends Number & Comparable<T> & Cloneable> {} 229 230 @Test testReferencedTypes()231 public void testReferencedTypes() { 232 Elements elements = compilationRule.getElements(); 233 TypeElement testDataElement = 234 elements.getTypeElement(ReferencedTypesTestData.class.getCanonicalName()); 235 ImmutableMap<String, VariableElement> fieldIndex = 236 FluentIterable.from(ElementFilter.fieldsIn(testDataElement.getEnclosedElements())) 237 .uniqueIndex(input -> input.getSimpleName().toString()); 238 239 TypeElement objectElement = elements.getTypeElement(Object.class.getCanonicalName()); 240 TypeElement stringElement = elements.getTypeElement(String.class.getCanonicalName()); 241 TypeElement integerElement = elements.getTypeElement(Integer.class.getCanonicalName()); 242 TypeElement setElement = elements.getTypeElement(Set.class.getCanonicalName()); 243 TypeElement mapElement = elements.getTypeElement(Map.class.getCanonicalName()); 244 TypeElement charSequenceElement = 245 elements.getTypeElement(CharSequence.class.getCanonicalName()); 246 247 assertThat(referencedTypes(fieldIndex, "f1")).containsExactly(objectElement); 248 assertThat(referencedTypes(fieldIndex, "f2")).containsExactly(setElement, stringElement); 249 assertThat(referencedTypes(fieldIndex, "f3")) 250 .containsExactly(mapElement, stringElement, objectElement); 251 assertThat(referencedTypes(fieldIndex, "f4")).containsExactly(integerElement); 252 assertThat(referencedTypes(fieldIndex, "f5")).containsExactly(setElement); 253 assertThat(referencedTypes(fieldIndex, "f6")).containsExactly(setElement, charSequenceElement); 254 assertThat(referencedTypes(fieldIndex, "f7")) 255 .containsExactly(mapElement, stringElement, setElement, charSequenceElement); 256 assertThat(referencedTypes(fieldIndex, "f8")).containsExactly(stringElement); 257 assertThat(referencedTypes(fieldIndex, "f9")).containsExactly(stringElement); 258 assertThat(referencedTypes(fieldIndex, "f10")).isEmpty(); 259 assertThat(referencedTypes(fieldIndex, "f11")).isEmpty(); 260 assertThat(referencedTypes(fieldIndex, "f12")).containsExactly(setElement, stringElement); 261 } 262 referencedTypes( ImmutableMap<String, VariableElement> fieldIndex, String fieldName)263 private static ImmutableSet<TypeElement> referencedTypes( 264 ImmutableMap<String, VariableElement> fieldIndex, String fieldName) { 265 VariableElement field = fieldIndex.get(fieldName); 266 requireNonNull(field, fieldName); 267 return MoreTypes.referencedTypes(field.asType()); 268 } 269 270 @SuppressWarnings("unused") // types used in compiler tests 271 private static final class ReferencedTypesTestData { 272 Object f1; 273 Set<String> f2; 274 Map<String, Object> f3; 275 Integer f4; 276 Set<?> f5; 277 Set<? extends CharSequence> f6; 278 Map<String, Set<? extends CharSequence>> f7; 279 String[] f8; 280 String[][] f9; 281 int f10; 282 int[] f11; 283 Set<? super String> f12; 284 } 285 286 private static class Parent<T> {} 287 288 private static class ChildA extends Parent<Number> {} 289 290 private static class ChildB extends Parent<String> {} 291 292 private static class GenericChild<T> extends Parent<T> {} 293 294 private interface InterfaceType {} 295 296 @Test asElement_throws()297 public void asElement_throws() { 298 TypeMirror javaDotLang = compilationRule.getElements().getPackageElement("java.lang").asType(); 299 try { 300 MoreTypes.asElement(javaDotLang); 301 fail(); 302 } catch (IllegalArgumentException expected) { 303 } 304 } 305 306 @Test asElement()307 public void asElement() { 308 Elements elements = compilationRule.getElements(); 309 TypeElement stringElement = elements.getTypeElement("java.lang.String"); 310 assertThat(MoreTypes.asElement(stringElement.asType())).isEqualTo(stringElement); 311 TypeParameterElement setParameterElement = 312 Iterables.getOnlyElement( 313 compilationRule.getElements().getTypeElement("java.util.Set").getTypeParameters()); 314 assertThat(MoreTypes.asElement(setParameterElement.asType())).isEqualTo(setParameterElement); 315 // we don't test error types because those are very hard to get predictably 316 } 317 318 @Test testNonObjectSuperclass()319 public void testNonObjectSuperclass() { 320 Types types = compilationRule.getTypes(); 321 Elements elements = compilationRule.getElements(); 322 TypeMirror numberType = elements.getTypeElement(Number.class.getCanonicalName()).asType(); 323 TypeMirror stringType = elements.getTypeElement(String.class.getCanonicalName()).asType(); 324 TypeMirror integerType = elements.getTypeElement(Integer.class.getCanonicalName()).asType(); 325 TypeElement parent = elements.getTypeElement(Parent.class.getCanonicalName()); 326 TypeElement childA = elements.getTypeElement(ChildA.class.getCanonicalName()); 327 TypeElement childB = elements.getTypeElement(ChildB.class.getCanonicalName()); 328 TypeElement genericChild = elements.getTypeElement(GenericChild.class.getCanonicalName()); 329 TypeMirror genericChildOfNumber = types.getDeclaredType(genericChild, numberType); 330 TypeMirror genericChildOfInteger = types.getDeclaredType(genericChild, integerType); 331 TypeMirror objectType = elements.getTypeElement(Object.class.getCanonicalName()).asType(); 332 TypeMirror interfaceType = 333 elements.getTypeElement(InterfaceType.class.getCanonicalName()).asType(); 334 335 assertThat(MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) objectType)) 336 .isAbsent(); 337 assertThat(MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) interfaceType)) 338 .isAbsent(); 339 assertThat(MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) parent.asType())) 340 .isAbsent(); 341 342 Optional<DeclaredType> parentOfChildA = 343 MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) childA.asType()); 344 Optional<DeclaredType> parentOfChildB = 345 MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) childB.asType()); 346 Optional<DeclaredType> parentOfGenericChild = 347 MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) genericChild.asType()); 348 Optional<DeclaredType> parentOfGenericChildOfNumber = 349 MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) genericChildOfNumber); 350 Optional<DeclaredType> parentOfGenericChildOfInteger = 351 MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) genericChildOfInteger); 352 353 EquivalenceTester<TypeMirror> tester = 354 EquivalenceTester.<TypeMirror>of(MoreTypes.equivalence()) 355 .addEquivalenceGroup( 356 parentOfChildA.get(), 357 types.getDeclaredType(parent, numberType), 358 parentOfGenericChildOfNumber.get()) 359 .addEquivalenceGroup(parentOfChildB.get(), types.getDeclaredType(parent, stringType)) 360 .addEquivalenceGroup(parentOfGenericChild.get(), parent.asType()) 361 .addEquivalenceGroup( 362 parentOfGenericChildOfInteger.get(), types.getDeclaredType(parent, integerType)); 363 364 tester.test(); 365 } 366 367 @Test testAsMemberOf_variableElement()368 public void testAsMemberOf_variableElement() { 369 Types types = compilationRule.getTypes(); 370 Elements elements = compilationRule.getElements(); 371 TypeMirror numberType = elements.getTypeElement(Number.class.getCanonicalName()).asType(); 372 TypeMirror stringType = elements.getTypeElement(String.class.getCanonicalName()).asType(); 373 TypeMirror integerType = elements.getTypeElement(Integer.class.getCanonicalName()).asType(); 374 375 TypeElement paramsElement = elements.getTypeElement(Params.class.getCanonicalName()); 376 VariableElement tParam = 377 Iterables.getOnlyElement( 378 Iterables.getOnlyElement(ElementFilter.methodsIn(paramsElement.getEnclosedElements())) 379 .getParameters()); 380 VariableElement tField = 381 Iterables.getOnlyElement(ElementFilter.fieldsIn(paramsElement.getEnclosedElements())); 382 383 DeclaredType numberParams = 384 (DeclaredType) elements.getTypeElement(NumberParams.class.getCanonicalName()).asType(); 385 DeclaredType stringParams = 386 (DeclaredType) elements.getTypeElement(StringParams.class.getCanonicalName()).asType(); 387 TypeElement genericParams = elements.getTypeElement(GenericParams.class.getCanonicalName()); 388 DeclaredType genericParamsOfNumber = types.getDeclaredType(genericParams, numberType); 389 DeclaredType genericParamsOfInteger = types.getDeclaredType(genericParams, integerType); 390 391 TypeMirror fieldOfNumberParams = MoreTypes.asMemberOf(types, numberParams, tField); 392 TypeMirror paramOfNumberParams = MoreTypes.asMemberOf(types, numberParams, tParam); 393 TypeMirror fieldOfStringParams = MoreTypes.asMemberOf(types, stringParams, tField); 394 TypeMirror paramOfStringParams = MoreTypes.asMemberOf(types, stringParams, tParam); 395 TypeMirror fieldOfGenericOfNumber = MoreTypes.asMemberOf(types, genericParamsOfNumber, tField); 396 TypeMirror paramOfGenericOfNumber = MoreTypes.asMemberOf(types, genericParamsOfNumber, tParam); 397 TypeMirror fieldOfGenericOfInteger = 398 MoreTypes.asMemberOf(types, genericParamsOfInteger, tField); 399 TypeMirror paramOfGenericOfInteger = 400 MoreTypes.asMemberOf(types, genericParamsOfInteger, tParam); 401 402 EquivalenceTester<TypeMirror> tester = 403 EquivalenceTester.<TypeMirror>of(MoreTypes.equivalence()) 404 .addEquivalenceGroup( 405 fieldOfNumberParams, 406 paramOfNumberParams, 407 fieldOfGenericOfNumber, 408 paramOfGenericOfNumber, 409 numberType) 410 .addEquivalenceGroup(fieldOfStringParams, paramOfStringParams, stringType) 411 .addEquivalenceGroup(fieldOfGenericOfInteger, paramOfGenericOfInteger, integerType); 412 tester.test(); 413 } 414 415 private static class Params<T> { 416 @SuppressWarnings("unused") 417 T t; 418 419 @SuppressWarnings("unused") add(T t)420 void add(T t) {} 421 } 422 423 private static class NumberParams extends Params<Number> {} 424 425 private static class StringParams extends Params<String> {} 426 427 private static class GenericParams<T> extends Params<T> {} 428 429 private static final ErrorType FAKE_ERROR_TYPE = 430 new ErrorType() { 431 @Override 432 public TypeKind getKind() { 433 return TypeKind.ERROR; 434 } 435 436 @Override 437 public <R, P> R accept(TypeVisitor<R, P> v, P p) { 438 return v.visitError(this, p); 439 } 440 441 @Override 442 public ImmutableList<? extends TypeMirror> getTypeArguments() { 443 return ImmutableList.of(); 444 } 445 446 @Override 447 public @Nullable TypeMirror getEnclosingType() { 448 return null; 449 } 450 451 @Override 452 public @Nullable Element asElement() { 453 return null; 454 } 455 456 @Override 457 public <A extends Annotation> A @Nullable [] getAnnotationsByType(Class<A> annotationType) { 458 return null; 459 } 460 461 @Override 462 public <A extends Annotation> @Nullable A getAnnotation(Class<A> annotationType) { 463 return null; 464 } 465 466 @Override 467 @SuppressWarnings("MutableMethodReturnType") 468 public List<? extends AnnotationMirror> getAnnotationMirrors() { 469 return ImmutableList.of(); 470 } 471 }; 472 473 @Test testIsConversionFromObjectUnchecked_yes()474 public void testIsConversionFromObjectUnchecked_yes() { 475 Elements elements = compilationRule.getElements(); 476 TypeElement unchecked = elements.getTypeElement(Unchecked.class.getCanonicalName()); 477 for (VariableElement field : ElementFilter.fieldsIn(unchecked.getEnclosedElements())) { 478 TypeMirror type = field.asType(); 479 expect 480 .withMessage("Casting to %s is unchecked", type) 481 .that(MoreTypes.isConversionFromObjectUnchecked(type)) 482 .isTrue(); 483 } 484 } 485 486 @Test testIsConversionFromObjectUnchecked_no()487 public void testIsConversionFromObjectUnchecked_no() { 488 Elements elements = compilationRule.getElements(); 489 TypeElement notUnchecked = elements.getTypeElement(NotUnchecked.class.getCanonicalName()); 490 for (VariableElement field : ElementFilter.fieldsIn(notUnchecked.getEnclosedElements())) { 491 TypeMirror type = field.asType(); 492 expect 493 .withMessage("Casting to %s is not unchecked", type) 494 .that(MoreTypes.isConversionFromObjectUnchecked(type)) 495 .isFalse(); 496 } 497 } 498 499 @Test testIsTypeOf()500 public void testIsTypeOf() { 501 Types types = compilationRule.getTypes(); 502 PrimitiveType intType = types.getPrimitiveType(TypeKind.INT); 503 TypeMirror integerType = types.boxedClass(intType).asType(); 504 WildcardType wildcardType = types.getWildcardType(null, null); 505 expect.that(MoreTypes.isTypeOf(int.class, intType)).isTrue(); 506 expect.that(MoreTypes.isTypeOf(Integer.class, integerType)).isTrue(); 507 expect.that(MoreTypes.isTypeOf(Integer.class, intType)).isFalse(); 508 expect.that(MoreTypes.isTypeOf(int.class, integerType)).isFalse(); 509 expect.that(MoreTypes.isTypeOf(Integer.class, FAKE_ERROR_TYPE)).isFalse(); 510 assertThrows( 511 IllegalArgumentException.class, () -> MoreTypes.isTypeOf(Integer.class, wildcardType)); 512 } 513 514 // The type of every field here is such that casting to it provokes an "unchecked" warning. 515 @SuppressWarnings("unused") 516 private static class Unchecked<T> { 517 private List<String> listOfString; 518 private List<? extends CharSequence> listOfExtendsCharSequence; 519 private List<? super CharSequence> listOfSuperCharSequence; 520 private List<T> listOfT; 521 private List<T[]> listOfArrayOfT; 522 private T t; 523 private T[] arrayOfT; 524 private List<T>[] arrayOfListOfT; 525 private Map<?, String> mapWildcardToString; 526 private Map<String, ?> mapStringToWildcard; 527 } 528 529 // The type of every field here is such that casting to it doesn't provoke an "unchecked" warning. 530 @SuppressWarnings("unused") 531 private static class NotUnchecked { 532 private String string; 533 private int integer; 534 private String[] arrayOfString; 535 private int[] arrayOfInt; 536 private Thread.State threadStateEnum; 537 private List<?> listOfWildcard; 538 private List<? extends Object> listOfWildcardExtendsObject; 539 private Map<?, ?> mapWildcardToWildcard; 540 } 541 } 542