1 package net.florianschoppmann.java.type;
2
3 import org.testng.Assert;
4 import org.testng.ITest;
5 import org.testng.annotations.BeforeClass;
6 import org.testng.annotations.Test;
7
8 import javax.lang.model.element.TypeElement;
9 import javax.lang.model.element.TypeParameterElement;
10 import javax.lang.model.type.DeclaredType;
11 import javax.lang.model.type.PrimitiveType;
12 import javax.lang.model.type.TypeKind;
13 import javax.lang.model.type.TypeMirror;
14 import javax.lang.model.type.TypeVariable;
15 import javax.lang.model.type.WildcardType;
16 import java.io.Serializable;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.LinkedHashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Objects;
25 import java.util.Set;
26
27 import static org.testng.Assert.assertEquals;
28 import static org.testng.Assert.assertFalse;
29 import static org.testng.Assert.assertNull;
30 import static org.testng.Assert.assertTrue;
31
32
33
34
35
36
37
38 public final class AbstractTypesContract implements ITest {
39 private final AbstractTypesProvider provider;
40 private AbstractTypes types;
41 private final Map<Class<?>, TypeElement> typeElementMap = new LinkedHashMap<>();
42
43
44
45
46
47
48
49 public AbstractTypesContract(AbstractTypesProvider provider) {
50 Objects.requireNonNull(provider);
51
52 this.provider = provider;
53 }
54
55 @Override
56 public String getTestName() {
57 return provider.getClass().getName();
58 }
59
60 final TypeElement element(Class<?> clazz) {
61 return Objects.requireNonNull(typeElementMap.get(clazz));
62 }
63
64 private PrimitiveType primitiveType(Class<?> clazz) {
65 assert clazz.isPrimitive();
66
67 if (clazz.equals(double.class)) {
68 return types.getPrimitiveType(TypeKind.DOUBLE);
69 } else if (clazz.equals(float.class)) {
70 return types.getPrimitiveType(TypeKind.FLOAT);
71 } else if (clazz.equals(long.class)) {
72 return types.getPrimitiveType(TypeKind.LONG);
73 } else if (clazz.equals(int.class)) {
74 return types.getPrimitiveType(TypeKind.INT);
75 } else if (clazz.equals(short.class)) {
76 return types.getPrimitiveType(TypeKind.SHORT);
77 } else if (clazz.equals(byte.class)) {
78 return types.getPrimitiveType(TypeKind.BYTE);
79 } else if (clazz.equals(boolean.class)) {
80 return types.getPrimitiveType(TypeKind.BOOLEAN);
81 } else if (clazz.equals(char.class)) {
82 return types.getPrimitiveType(TypeKind.CHAR);
83 } else {
84 throw new IllegalArgumentException(String.format("Unexpected primitive type: %s", clazz));
85 }
86 }
87
88
89
90
91
92
93
94
95
96
97 private TypeMirror type(Class<?> clazz) {
98 if (clazz.isPrimitive()) {
99 return primitiveType(clazz);
100 } else if (clazz.isArray()) {
101 return types.getArrayType(type(clazz.getComponentType()));
102 } else if (typeElementMap.containsKey(clazz)) {
103
104 return types.getDeclaredType(typeElementMap.get(clazz));
105 }
106
107 throw new IllegalArgumentException(String.format("Unexpected type: %s", clazz));
108 }
109
110 private interface SimpleA { }
111
112 private interface SimpleB extends SimpleA { }
113
114 private interface SimpleC extends SimpleB { }
115
116 private interface SimpleParameterized<T> extends Serializable { }
117
118 private interface ExtendsParameterized<T extends SimpleC> { }
119
120 private interface SubExtendsParameterized<T extends SimpleC> extends ExtendsParameterized<T> { }
121
122 private interface RawSubExtendsParameterized<T> extends ExtendsParameterized { }
123
124 private interface DiamondA<T, U> { }
125
126 private interface DiamondB<T> extends DiamondA<T[], Integer[]> { }
127
128 private interface DiamondC<U> extends DiamondA<String[], U[]> { }
129
130 private interface DiamondD extends DiamondB<String>, DiamondC<Integer> { }
131
132 private interface SubDiamondB<T> extends DiamondB<T[]> { }
133
134 private interface SubSubDiamondB extends SubDiamondB<Integer[]> { }
135
136 private abstract static class IntegerListSet implements Set<List<Integer>>, Comparable<IntegerListSet> { }
137
138 private abstract static class ImmutableIntegerListSet extends IntegerListSet { }
139
140 private abstract static class InterdependentRecursiveBoundA<
141 T extends InterdependentRecursiveBoundA<T, U>,
142 U extends T
143 > { }
144
145 private abstract static class InterdependentRecursiveBoundB
146 extends InterdependentRecursiveBoundA<InterdependentRecursiveBoundB, InterdependentRecursiveBoundB>
147 implements Serializable {
148 private static final long serialVersionUID = -4490638717891611814L;
149 }
150
151 private static class OuterClass<T extends Number> {
152 private final class InnerClass<U extends List<?> & Serializable> { }
153 }
154
155
156
157
158 @BeforeClass
159 public void setup() {
160 provider.preContract();
161
162 List<Class<?>> classesNeeded = Arrays.asList(
163 Object.class, Enum.class, Cloneable.class, Serializable.class, Comparable.class,
164 Collection.class, List.class, ArrayList.class, Set.class,
165 Number.class, Integer.class,
166 String.class,
167 getClass(),
168 IntegerListSet.class, ImmutableIntegerListSet.class,
169 DiamondA.class, DiamondB.class, DiamondC.class, DiamondD.class, SubDiamondB.class, SubSubDiamondB.class,
170 SimpleA.class, SimpleB.class, SimpleC.class,
171 ExtendsParameterized.class, SubExtendsParameterized.class,
172 RawSubExtendsParameterized.class,
173 SimpleParameterized.class,
174 InterdependentRecursiveBoundA.class, InterdependentRecursiveBoundB.class,
175 OuterClass.class, OuterClass.InnerClass.class
176 );
177
178 for (Class<?> clazz: classesNeeded) {
179 typeElementMap.put(clazz, null);
180 }
181
182 types = provider.getTypes(typeElementMap);
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 @Test
200 public void testSetup() {
201 for (Map.Entry<Class<?>, TypeElement> entry: typeElementMap.entrySet()) {
202 Class<?> clazz = entry.getKey();
203 TypeElement typeElement = entry.getValue();
204
205 assertTrue(typeElement.getKind().isClass() || typeElement.getKind().isInterface());
206 DeclaredType prototypicalType = (DeclaredType) typeElement.asType();
207 assertEquals(typeElement.getTypeParameters().size(), prototypicalType.getTypeArguments().size());
208
209 for (TypeMirror typeArgument: prototypicalType.getTypeArguments()) {
210 assertTrue(typeArgument.getKind() == TypeKind.TYPEVAR && typeArgument instanceof TypeVariable);
211 }
212
213 DeclaredType rawType = (DeclaredType) type(clazz);
214 assertTrue(rawType.getTypeArguments().isEmpty());
215
216 assertEquals(clazz.getCanonicalName(), types.toString(rawType));
217 }
218 }
219
220
221
222
223
224 @Test(expectedExceptions = NullPointerException.class)
225 public void requireValidElement() {
226 types.requireValidElement(null);
227 }
228
229
230
231
232
233 @Test
234 public void requireValidType() {
235 types.requireValidType(null);
236 }
237
238
239
240
241
242 @Test
243 public void requireValidTypes() {
244 try {
245 types.requireValidTypes(null);
246 Assert.fail("Expected exception.");
247 } catch (NullPointerException ignored) { }
248
249 try {
250 types.requireValidTypes(new TypeMirror[] { null });
251 Assert.fail("Expected exception.");
252 } catch (NullPointerException ignored) { }
253 }
254
255 private static void typeMirrorAssertExpectedName(TypeMirror typeMirror, Class<?> clazz) {
256 assertEquals(typeMirror.getKind(), TypeKind.DECLARED);
257 TypeElement element = (TypeElement) ((DeclaredType) typeMirror).asElement();
258 assertEquals(element.getQualifiedName().toString(), clazz.getName());
259 }
260
261
262
263
264 @Test
265 public void typeMirror() {
266 typeMirrorAssertExpectedName(types.typeMirror(Object.class), Object.class);
267 typeMirrorAssertExpectedName(types.typeMirror(Serializable.class), Serializable.class);
268 typeMirrorAssertExpectedName(types.typeMirror(Cloneable.class), Cloneable.class);
269 }
270
271
272
273
274 @Test
275 public void substitute() {
276 TypeElement diamondADeclaration = element(DiamondA.class);
277 Map<TypeParameterElement, TypeMirror> substitutions = new LinkedHashMap<>();
278 substitutions.put(diamondADeclaration.getTypeParameters().get(0), type(String.class));
279 DeclaredType expectedType = types.getDeclaredType(
280 (DeclaredType) type(getClass()),
281 diamondADeclaration,
282 type(String.class), diamondADeclaration.getTypeParameters().get(1).asType()
283 );
284 assertEquals(types.substitute(diamondADeclaration.asType(), substitutions), expectedType);
285
286 WildcardType extendsStringWildcardArgument = types.getWildcardType(type(String.class), null);
287 assertEquals(types.substitute(extendsStringWildcardArgument, substitutions), extendsStringWildcardArgument);
288 }
289
290
291
292
293
294 @Test
295 public void resolveActualTypeArguments() {
296
297 assertEquals(types.resolveActualTypeArguments(element(List.class), type(List.class)), Collections.emptyList());
298
299
300 DeclaredType listOfIntegersType = types.getDeclaredType(element(List.class), type(Integer.class));
301
302
303 assertEquals(
304 types.resolveActualTypeArguments(element(List.class), listOfIntegersType),
305 Collections.singletonList(type(Integer.class))
306 );
307
308
309 assertEquals(
310 types.resolveActualTypeArguments(element(Set.class), type(IntegerListSet.class)),
311 Collections.singletonList(listOfIntegersType)
312 );
313 assertEquals(
314 types.resolveActualTypeArguments(element(Set.class), type(ImmutableIntegerListSet.class)),
315 Collections.singletonList(listOfIntegersType)
316 );
317
318
319 assertEquals(
320 types.resolveActualTypeArguments(element(IntegerListSet.class), type(ImmutableIntegerListSet.class)),
321 Collections.emptyList()
322 );
323
324
325 assertNull(
326 types.resolveActualTypeArguments(element(ImmutableIntegerListSet.class), type(IntegerListSet.class))
327 );
328 assertNull(types.resolveActualTypeArguments(element(List.class), type(Collection.class)));
329 assertNull(types.resolveActualTypeArguments(element(List.class), type(int.class)));
330 }
331
332
333
334
335
336 @Test
337 public void resolveActualTypeArgumentsRaw() {
338
339 assertEquals(
340 types.resolveActualTypeArguments(
341 element(ExtendsParameterized.class),
342 type(RawSubExtendsParameterized.class)
343 ),
344 Collections.emptyList()
345 );
346
347
348
349 assertEquals(
350 types.resolveActualTypeArguments(
351 element(ExtendsParameterized.class),
352 type(SubExtendsParameterized.class)
353 ),
354 types.resolveActualTypeArguments(
355 element(ExtendsParameterized.class),
356 element(SubExtendsParameterized.class).asType()
357 )
358 );
359 assertEquals(
360 ((DeclaredType) element(SubExtendsParameterized.class).asType()).getTypeArguments().get(0),
361 element(SubExtendsParameterized.class).getTypeParameters().get(0).asType()
362 );
363 }
364
365
366
367
368
369 @Test
370 public void resolveActualTypeArgumentsArrays() {
371
372 DeclaredType declaredType = types.getDeclaredType(element(DiamondB.class), types.getArrayType(type(String.class)));
373 assertEquals(
374 types.resolveActualTypeArguments(element(DiamondA.class), declaredType),
375 Arrays.asList(type(String[][].class), type(Integer[].class))
376 );
377
378 assertEquals(
379 types.resolveActualTypeArguments(element(DiamondA.class), type(DiamondD.class)),
380 Arrays.asList(type(String[].class), type(Integer[].class))
381 );
382
383
384
385 TypeMirror expectedTypeArgument
386 = types.getArrayType(types.getArrayType(element(SubDiamondB.class).getTypeParameters().get(0).asType()));
387 assertEquals(
388 types.resolveActualTypeArguments(element(DiamondA.class), type(SubDiamondB.class)),
389 Arrays.asList(expectedTypeArgument, type(Integer[].class))
390 );
391
392 assertEquals(
393 types.resolveActualTypeArguments(element(DiamondA.class), type(SubSubDiamondB.class)),
394 Arrays.asList(type(Integer[][][].class), type(Integer[].class))
395 );
396 }
397
398
399
400
401 @Test
402 public void testIsSubtypePrimitive() {
403
404 assertTrue(types.isSubtype(type(double.class), type(double.class)));
405 assertTrue(types.isSubtype(type(float.class), type(double.class)));
406 assertTrue(types.isSubtype(type(long.class), type(double.class)));
407 assertTrue(types.isSubtype(type(int.class), type(double.class)));
408 assertTrue(types.isSubtype(type(short.class),type(double.class)));
409 assertTrue(types.isSubtype(type(byte.class), type(double.class)));
410 assertTrue(types.isSubtype(type(char.class), type(double.class)));
411
412 assertTrue(types.isSubtype(type(int.class), type(int.class)));
413 assertTrue(types.isSubtype(type(short.class), type(int.class)));
414 assertTrue(types.isSubtype(type(byte.class), type(int.class)));
415 assertTrue(types.isSubtype(type(char.class), type(int.class)));
416
417 assertTrue(types.isSubtype(type(short.class), type(short.class)));
418 assertTrue(types.isSubtype(type(byte.class), type(short.class)));
419 assertFalse(types.isSubtype(type(char.class), type(short.class)));
420
421 assertFalse(types.isSubtype(type(Object.class), type(int.class)));
422 assertFalse(types.isSubtype(type(int.class), type(Object.class)));
423 assertFalse(types.isSubtype(type(Integer.class), type(int.class)));
424 assertFalse(types.isSubtype(type(int.class), type(Integer.class)));
425 assertFalse(types.isSubtype(type(int[].class), type(int.class)));
426 assertFalse(types.isSubtype(type(int.class), type(int[].class)));
427
428
429 assertTrue(types.isSubtype(type(Object.class), type(Object.class)));
430 assertTrue(types.isSubtype(type(Serializable.class), type(Object.class)));
431 assertFalse(types.isSubtype(type(Object.class), type(Serializable.class)));
432
433
434 assertTrue(types.isSubtype(type(Number.class), type(Object.class)));
435 assertFalse(types.isSubtype(type(Object.class), type(Number.class)));
436 }
437
438
439
440
441 @Test
442 public void testIsSubtypeNull() {
443 assertFalse(types.isSubtype(types.getNullType(), type(int.class)));
444 assertFalse(types.isSubtype(type(int.class), types.getNullType()));
445
446 assertFalse(types.isSubtype(type(Object.class), types.getNullType()));
447 assertTrue(types.isSubtype(types.getNullType(), type(Object.class)));
448 }
449
450
451
452
453 @Test
454 public void testIsSubtypeArray() {
455
456 TypeMirror arrayType
457 = types.getArrayType(types.getArrayType(types.getDeclaredType(element(List.class), type(String.class))));
458
459 assertTrue(types.isSubtype(arrayType, arrayType));
460 assertTrue(types.isSubtype(arrayType, type(Serializable.class)));
461 assertTrue(types.isSubtype(arrayType, type(Cloneable.class)));
462 assertTrue(types.isSubtype(arrayType, type(Object.class)));
463 assertTrue(types.isSubtype(arrayType, type(Object[].class)));
464 assertTrue(types.isSubtype(arrayType, type(Object[][].class)));
465
466 assertFalse(types.isSubtype(arrayType, type(Number.class)));
467 assertFalse(types.isSubtype(type(Number.class), arrayType));
468
469 assertTrue(types.isSubtype(type(int[][].class), type(int[][].class)));
470 assertTrue(types.isSubtype(type(char[][].class), type(int[][].class)));
471 assertFalse(types.isSubtype(type(int[][].class), type(char[][].class)));
472 }
473
474
475
476
477 @Test
478 public void testIsSubtypeIntersection() {
479 TypeMirror serializableAndCloneableType
480 = types.getIntersectionType(type(Serializable.class), type(Cloneable.class));
481
482 assertTrue(types.isSubtype(serializableAndCloneableType, type(Serializable.class)));
483 assertTrue(types.isSubtype(serializableAndCloneableType, type(Cloneable.class)));
484 assertTrue(types.isSubtype(serializableAndCloneableType, serializableAndCloneableType));
485 assertFalse(types.isSubtype(type(Cloneable.class), serializableAndCloneableType));
486
487 TypeMirror serializableCloneableListType
488 = types.getIntersectionType(type(Serializable.class), type(Cloneable.class), type(List.class));
489
490
491
492 assertFalse(types.isSubtype(serializableCloneableListType, serializableAndCloneableType));
493 }
494
495
496
497
498 @Test
499 public void testIsSubtypeRaw() {
500
501 assertTrue(types.isSubtype(type(DiamondB.class), type(DiamondA.class)));
502
503
504 DeclaredType aWildcardType = types.getDeclaredType(
505 element(DiamondA.class),
506 types.getWildcardType(type(Object[].class), null),
507 type(Integer[].class)
508 );
509
510 assertTrue(types.isSubtype(type(DiamondB.class), aWildcardType));
511
512
513
514 DeclaredType aType = types.getDeclaredType(element(DiamondA.class), type(Object[].class), type(Integer[].class));
515
516
517 assertFalse(types.isSubtype(type(DiamondB.class), aType));
518
519
520
521
522
523 DeclaredType rawListType = (DeclaredType) type(List.class);
524 DeclaredType anyListType = types.getDeclaredType(element(List.class), types.getWildcardType(null, null));
525 assertFalse(types.isSubtype(rawListType, anyListType));
526 assertTrue(types.isSubtype(anyListType, rawListType));
527
528 assertTrue(types.isSubtype(type(RawSubExtendsParameterized.class), type(ExtendsParameterized.class)));
529
530 DeclaredType rawParameterizedType
531 = types.getDeclaredType(element(RawSubExtendsParameterized.class), type(Integer.class));
532 assertTrue(types.isSubtype(rawParameterizedType, type(ExtendsParameterized.class)));
533
534 assertFalse(
535 types.isSubtype(
536 rawParameterizedType,
537 types.getDeclaredType(element(ExtendsParameterized.class), types.getWildcardType(null, null))
538 )
539 );
540 }
541
542 @Test
543 public void testIsSubtypeArrayTypeParameters() {
544
545 DeclaredType aType = types.getDeclaredType(
546 element(DiamondA.class),
547 types.getWildcardType(type(Serializable.class), null),
548 types.getWildcardType(type(Number[].class), null)
549 );
550
551 DeclaredType bType = types.getDeclaredType(element(DiamondB.class), types.getWildcardType(null, null));
552 assertTrue(types.isSubtype(bType, aType));
553
554
555 DeclaredType a2Type = types.getDeclaredType(
556 element(DiamondA.class),
557 types.getWildcardType(type(Object[].class), null),
558 types.getWildcardType(type(Number[].class), null)
559 );
560
561 DeclaredType b2Type = types.getDeclaredType(element(DiamondB.class), type(Integer.class));
562 assertTrue(types.isSubtype(b2Type, a2Type));
563
564
565 DeclaredType a3Type = types.getDeclaredType(
566 element(DiamondA.class),
567 types.getWildcardType(type(Serializable.class), null),
568 types.getWildcardType(type(Number[].class), null)
569 );
570 assertTrue(types.isSubtype(type(DiamondD.class), a3Type));
571 }
572
573 @Test
574 public void testIsSubtypeSimpleTypeParameters() {
575
576 DeclaredType collectionOfNumbersType = types.getDeclaredType(element(Collection.class), type(Number.class));
577
578
579 assertTrue(types.isSubtype(collectionOfNumbersType, type(Collection.class)));
580
581
582
583 assertFalse(types.isSubtype(type(Collection.class), collectionOfNumbersType));
584
585
586 DeclaredType collectionOfIntegersType = types.getDeclaredType(element(Collection.class), type(Integer.class));
587
588
589 assertFalse(types.isSubtype(collectionOfIntegersType, collectionOfNumbersType));
590
591
592 DeclaredType wildcardCollectionType = types.getDeclaredType(
593 element(Collection.class),
594 types.getWildcardType(type(Number.class), null)
595 );
596 assertTrue(types.isSubtype(collectionOfIntegersType, wildcardCollectionType));
597 }
598
599 @Test
600 public void testIsSubtypeWildcards() {
601
602 DeclaredType setType1 = types.getDeclaredType(
603 element(Set.class),
604 types.getDeclaredType(element(List.class), type(Integer.class))
605 );
606 assertTrue(types.isSubtype(type(IntegerListSet.class), setType1));
607
608
609 DeclaredType setType2 = types.getDeclaredType(
610 element(Set.class),
611 types.getWildcardType(
612 types.getDeclaredType(element(List.class), types.getWildcardType(type(Integer.class), null)),
613 null
614 )
615 );
616 assertTrue(types.isSubtype(type(IntegerListSet.class), setType2));
617
618
619 DeclaredType setType3 = types.getDeclaredType(
620 element(Set.class),
621 types.getWildcardType(
622 null,
623 types.getDeclaredType(element(List.class), types.getWildcardType(null, type(Integer.class)))
624 )
625 );
626
627 DeclaredType setType4 = types.getDeclaredType(
628 element(Set.class),
629 types.getDeclaredType(element(Collection.class), types.getWildcardType(null, type(Integer.class)))
630 );
631 assertTrue(types.isSubtype(setType4, setType3));
632
633
634 DeclaredType setType5 = types.getDeclaredType(
635 element(Set.class),
636 types.getDeclaredType(element(Collection.class), types.getWildcardType(null, type(Number.class)))
637 );
638
639
640
641 assertFalse(types.isSubtype(setType5, setType3));
642
643
644
645
646
647 assertFalse(types.isSubtype(type(IntegerListSet.class), setType3));
648
649
650 DeclaredType superType = types.getDeclaredType(
651 element(ExtendsParameterized.class),
652 types.getWildcardType(type(SimpleA.class), null)
653 );
654
655 DeclaredType subType = types.getDeclaredType(
656 element(ExtendsParameterized.class),
657 types.getWildcardType(type(SimpleB.class), null)
658 );
659 assertTrue(types.isSubtype(subType, superType));
660
661
662
663
664
665
666 assertTrue(types.isSubtype(superType, subType));
667
668
669 DeclaredType extendsParameterized1 = types.getDeclaredType(
670 element(ExtendsParameterized.class),
671 types.getWildcardType(null, type(SimpleC.class))
672 );
673 assertTrue(types.isSubtype(extendsParameterized1, superType));
674
675
676 DeclaredType extendsParameterized2
677 = types.getDeclaredType(element(ExtendsParameterized.class), type(SimpleC.class));
678 assertTrue(types.isSubtype(extendsParameterized2, superType));
679
680
681 DeclaredType simpleParameterizedType1 = types.getDeclaredType(
682 element(SimpleParameterized.class),
683 types.getWildcardType(type(SimpleA.class), null)
684 );
685
686 DeclaredType simpleParameterizedType2 = types.getDeclaredType(
687 element(SimpleParameterized.class),
688 types.getWildcardType(type(SimpleB.class), null)
689 );
690 assertTrue(types.isSubtype(simpleParameterizedType2, simpleParameterizedType1));
691
692
693 assertFalse(types.isSubtype(simpleParameterizedType1, simpleParameterizedType2));
694 }
695
696
697
698
699 @Test
700 public void capture() {
701 assertEquals(types.capture(type(Integer.class)), type(Integer.class));
702
703 DeclaredType outerClassType = types.getDeclaredType(element(OuterClass.class), type(Integer.class));
704 DeclaredType arrayListOfIntegersType = types.getDeclaredType(element(ArrayList.class), type(Integer.class));
705
706 DeclaredType innerClassType = types.getDeclaredType(
707 outerClassType,
708 element(OuterClass.InnerClass.class),
709 types.getWildcardType(arrayListOfIntegersType, null)
710 );
711
712 DeclaredType capturedType = (DeclaredType) types.capture(innerClassType);
713 TypeVariable actualTypeArgument = (TypeVariable) capturedType.getTypeArguments().get(0);
714
715
716 IntersectionType intersectionType = (IntersectionType) actualTypeArgument.getUpperBound();
717 assertTrue(isSubtypeOfOneOf(arrayListOfIntegersType, intersectionType.getBounds()));
718
719 PrimitiveType intType = types.getPrimitiveType(TypeKind.INT);
720 assertTrue(types.isSameType(types.capture(intType), intType));
721 }
722
723 @Test
724 public void captureSingleRecursiveBound() {
725
726 DeclaredType enumType = types.getDeclaredType(element(Enum.class), types.getWildcardType(null, null));
727
728
729 DeclaredType capture = (DeclaredType) types.capture(enumType);
730
731 assertEquals(capture.getTypeArguments().size(), 1);
732 TypeVariable newTypeVariable = (TypeVariable) capture.getTypeArguments().get(0);
733 DeclaredType upperBound = (DeclaredType) newTypeVariable.getUpperBound();
734 assertEquals(upperBound.getKind(), TypeKind.DECLARED);
735
736
737 assertEquals(capture, upperBound);
738
739
740 TypeElement upperBoundAsElement = (TypeElement) upperBound.asElement();
741 assertTrue(upperBoundAsElement.getQualifiedName().contentEquals(Enum.class.getName()));
742 }
743
744 @Test
745 public void captureInterdependentRecursiveBound() {
746
747 DeclaredType aType1 = types.getDeclaredType(
748 element(InterdependentRecursiveBoundA.class),
749 types.getWildcardType(null, null),
750 types.getWildcardType(null, null)
751 );
752 DeclaredType aCapture1 = (DeclaredType) types.capture(aType1);
753 TypeVariable captureForT1 = (TypeVariable) aCapture1.getTypeArguments().get(0);
754 TypeVariable captureForU1 = (TypeVariable) aCapture1.getTypeArguments().get(1);
755
756 DeclaredType captureForTUpperBound1 = (DeclaredType) captureForT1.getUpperBound();
757 assertEquals(captureForTUpperBound1.getTypeArguments().get(0), captureForT1);
758 assertEquals(captureForTUpperBound1.getTypeArguments().get(1), captureForU1);
759 assertEquals(captureForU1.getUpperBound(), captureForT1);
760
761
762
763 DeclaredType aType2 = types.getDeclaredType(
764 element(InterdependentRecursiveBoundA.class),
765 types.getWildcardType(null, type(InterdependentRecursiveBoundB.class)),
766 types.getWildcardType(type(Serializable.class), null)
767 );
768 DeclaredType aCapture2 = (DeclaredType) types.capture(aType2);
769 assertEquals(aCapture2.getTypeArguments().size(), 2);
770
771 TypeVariable captureForT2 = (TypeVariable) aCapture2.getTypeArguments().get(0);
772 TypeVariable captureForU2 = (TypeVariable) aCapture2.getTypeArguments().get(1);
773
774 DeclaredType captureForTUpperBound2 = (DeclaredType) captureForT2.getUpperBound();
775 assertEquals(captureForTUpperBound2.getTypeArguments().get(0), captureForT2);
776 assertEquals(captureForTUpperBound2.getTypeArguments().get(1), captureForU2);
777 DeclaredType captureForTLowerBound2 = (DeclaredType) captureForT2.getLowerBound();
778 assertEquals(captureForTLowerBound2, type(InterdependentRecursiveBoundB.class));
779
780 IntersectionType intersectionType = (IntersectionType) captureForU2.getUpperBound();
781 assertTrue(intersectionType.getBounds().contains(captureForT2));
782 assertTrue(intersectionType.getBounds().contains(type(Serializable.class)));
783
784
785 DeclaredType aType3 = types.getDeclaredType(
786 element(InterdependentRecursiveBoundA.class),
787 type(InterdependentRecursiveBoundB.class),
788 types.getWildcardType(null, null)
789 );
790 DeclaredType aCapture3 = (DeclaredType) types.capture(aType3);
791 assertEquals(aCapture3.getTypeArguments().get(0), type(InterdependentRecursiveBoundB.class));
792 TypeVariable captureForU3 = (TypeVariable) aCapture3.getTypeArguments().get(1);
793 assertEquals(captureForU3.getUpperBound(), type(InterdependentRecursiveBoundB.class));
794 }
795
796
797
798
799 @Test
800 public void testContainsInvalidArguments() {
801 try {
802 types.contains(type(Object.class), null);
803 Assert.fail("Exception expected.");
804 } catch (NullPointerException ignore) { }
805
806 try {
807 types.contains(null, type(Object.class));
808 Assert.fail("Exception expected.");
809 } catch (NullPointerException ignore) { }
810
811 try {
812 types.contains(null, null);
813 Assert.fail("Exception expected.");
814 } catch (NullPointerException ignore) { }
815 }
816
817
818
819
820 @Test
821 public void testContains() {
822 WildcardType extendsWildcard = types.getWildcardType(null, null);
823 WildcardType extendsObjectWildcard = types.getWildcardType(type(Object.class), null);
824 WildcardType extendsIntegerWildcard = types.getWildcardType(type(Integer.class), null);
825 WildcardType extendsNumberWildcard = types.getWildcardType(type(Number.class), null);
826 WildcardType superIntegerWildcard = types.getWildcardType(null, type(Integer.class));
827 WildcardType superNumberWildcard = types.getWildcardType(null, type(Number.class));
828
829
830 assertTrue(types.contains(extendsNumberWildcard, extendsIntegerWildcard));
831 assertFalse(types.contains(extendsIntegerWildcard, extendsNumberWildcard));
832
833
834 assertTrue(types.contains(extendsWildcard, extendsIntegerWildcard));
835 assertFalse(types.contains(extendsIntegerWildcard, extendsWildcard));
836
837
838 assertTrue(types.contains(superIntegerWildcard, superNumberWildcard));
839 assertFalse(types.contains(superNumberWildcard, superIntegerWildcard));
840
841
842 assertTrue(types.contains(extendsWildcard, superIntegerWildcard));
843 assertFalse(types.contains(superIntegerWildcard, extendsWildcard));
844
845
846 assertTrue(types.contains(extendsObjectWildcard, superIntegerWildcard));
847 assertFalse(types.contains(superIntegerWildcard, extendsObjectWildcard));
848 assertFalse(types.contains(extendsNumberWildcard, superIntegerWildcard));
849
850
851 assertTrue(types.contains(type(Integer.class), type(Integer.class)));
852 assertFalse(types.contains(type(Number.class), type(Integer.class)));
853 assertFalse(types.contains(type(Integer.class), type(Number.class)));
854
855
856 assertTrue(types.contains(extendsIntegerWildcard, type(Integer.class)));
857 assertFalse(types.contains(type(Integer.class), extendsIntegerWildcard));
858
859
860 assertTrue(types.contains(superIntegerWildcard, type(Integer.class)));
861 assertFalse(types.contains(type(Integer.class), superIntegerWildcard));
862
863
864
865
866 assertTrue(types.contains(extendsWildcard, type(Integer.class)));
867 assertFalse(types.contains(type(Integer.class), extendsWildcard));
868
869
870 assertTrue(types.contains(extendsObjectWildcard, type(Integer.class)));
871 assertFalse(types.contains(type(Integer.class), extendsObjectWildcard));
872
873
874 assertFalse(types.contains(superNumberWildcard, extendsWildcard));
875
876
877 assertTrue(types.contains(extendsObjectWildcard, extendsObjectWildcard));
878 assertTrue(types.contains(extendsObjectWildcard, extendsWildcard));
879 assertTrue(types.contains(extendsWildcard, extendsWildcard));
880 assertTrue(types.contains(extendsWildcard, extendsObjectWildcard));
881
882 assertFalse(types.contains(extendsNumberWildcard, extendsObjectWildcard));
883 assertFalse(types.contains(extendsNumberWildcard, extendsWildcard));
884 }
885
886
887
888
889 @Test
890 public void testErasureInvalidArguments() {
891 try {
892 types.erasure(null);
893 Assert.fail("Exception expected.");
894 } catch (NullPointerException ignore) { }
895 }
896
897
898
899
900 @Test
901 public void testErasure() {
902
903 DeclaredType listOfStringsType = types.getDeclaredType(element(List.class), type(String.class));
904 assertTrue(types.isSameType(types.erasure(listOfStringsType), type(List.class)));
905
906
907 DeclaredType outerClassType = types.getDeclaredType(element(OuterClass.class), type(Integer.class));
908 DeclaredType arrayListOfIntegersType = types.getDeclaredType(element(ArrayList.class), type(Integer.class));
909 DeclaredType innerClassType
910 = types.getDeclaredType(outerClassType, element(OuterClass.InnerClass.class), arrayListOfIntegersType);
911
912 DeclaredType expectedErasedNestedType
913 = types.getDeclaredType((DeclaredType) type(OuterClass.class), element(OuterClass.InnerClass.class));
914 assertTrue(types.isSameType(types.erasure(innerClassType), expectedErasedNestedType));
915
916
917 TypeMirror arrayType = types.getArrayType(listOfStringsType);
918 assertTrue(types.isSameType(types.erasure(arrayType), types.getArrayType(type(List.class))));
919
920
921 TypeElement listDeclaration = element(List.class);
922 TypeVariable simpleTypeVariable = types.createTypeVariable(listDeclaration.getTypeParameters().get(0), null);
923 types.setTypeVariableBounds(simpleTypeVariable, type(Number.class), types.getNullType());
924 assertTrue(types.isSameType(types.erasure(simpleTypeVariable), type(Number.class)));
925
926 TypeVariable multiBoundTypeVariable
927 = types.createTypeVariable(listDeclaration.getTypeParameters().get(0), null);
928 types.setTypeVariableBounds(multiBoundTypeVariable,
929 types.getIntersectionType(type(List.class), type(Serializable.class)), types.getNullType());
930 assertTrue(types.isSameType(types.erasure(multiBoundTypeVariable), type(List.class)));
931
932
933 PrimitiveType booleanType = types.getPrimitiveType(TypeKind.BOOLEAN);
934 assertTrue(types.isSameType(types.erasure(booleanType), booleanType));
935 assertTrue(types.isSameType(types.erasure(types.getNullType()), types.getNullType()));
936 }
937
938
939
940
941 @Test
942 public void asElementInvalidArguments() {
943 try {
944 types.asElement(null);
945 Assert.fail("Exception expected.");
946 } catch (NullPointerException ignore) { }
947 }
948
949
950
951
952 @Test
953 public void asElement() {
954 assertEquals(types.asElement(type(List.class)), element(List.class));
955 assertEquals(types.asElement(type(Integer.class)), element(Integer.class));
956
957 TypeElement listDeclaration = element(List.class);
958 TypeVariable simpleTypeVariable = types.createTypeVariable(listDeclaration.getTypeParameters().get(0), null);
959 types.setTypeVariableBounds(simpleTypeVariable, type(Number.class), types.getNullType());
960 assertEquals(types.asElement(simpleTypeVariable), listDeclaration.getTypeParameters().get(0));
961
962 assertNull(types.asElement(types.getPrimitiveType(TypeKind.INT)));
963 }
964
965
966
967
968 @Test
969 public void asType() {
970 DeclaredType typesContractType = (DeclaredType) type(getClass());
971 TypeElement outerClassDeclaration = element(OuterClass.class);
972 TypeElement innerClassDeclaration = element(OuterClass.InnerClass.class);
973
974 DeclaredType outerClassType= types.getDeclaredType(
975 typesContractType, outerClassDeclaration, outerClassDeclaration.getTypeParameters().get(0).asType());
976 DeclaredType innerClassType = types.getDeclaredType(
977 outerClassType, innerClassDeclaration, innerClassDeclaration.getTypeParameters().get(0).asType());
978 assertEquals(innerClassDeclaration.asType(), innerClassType);
979 }
980
981
982
983
984 @Test
985 public void testIsSameTypeInvalidArguments() {
986 try {
987 types.isSameType(null, type(Object.class));
988 Assert.fail("Exception expected.");
989 } catch (NullPointerException ignore) { }
990
991 try {
992 types.isSameType(type(Object.class), null);
993 Assert.fail("Exception expected.");
994 } catch (NullPointerException ignore) { }
995
996 try {
997 types.isSameType(null, null);
998 Assert.fail("Exception expected.");
999 } catch (NullPointerException ignore) { }
1000 }
1001
1002
1003
1004
1005 @Test
1006 public void testIsSameType() {
1007 assertTrue(types.isSameType(type(Object.class), type(Object.class)));
1008 assertFalse(types.isSameType(type(Object.class), type(Number.class)));
1009
1010 WildcardType wildcardType = types.getWildcardType(null, null);
1011 assertFalse(types.isSameType(wildcardType, wildcardType));
1012 }
1013
1014 private boolean isSubtypeOfOneOf(TypeMirror subtype, List<? extends TypeMirror> supertypes) {
1015 for (TypeMirror supertype: supertypes) {
1016 if (types.isSubtype(subtype, supertype)) {
1017 return true;
1018 }
1019 }
1020 return false;
1021 }
1022
1023
1024
1025
1026
1027 @Test
1028 public void testGetTypeVariable() {
1029 TypeElement listDeclaration = element(List.class);
1030 TypeParameterElement elementTypeParameter = listDeclaration.getTypeParameters().get(0);
1031
1032 TypeVariable typeVariable
1033 = types.getTypeVariable(elementTypeParameter, type(Integer.class), types.getNullType(), null);
1034 assertEquals(typeVariable.asElement(), elementTypeParameter);
1035 assertTrue(types.isSameType(typeVariable.getUpperBound(), type(Integer.class)));
1036 assertTrue(types.isSameType(typeVariable.getLowerBound(), types.getNullType()));
1037 assertNull(types.capturedTypeArgument(typeVariable));
1038 }
1039
1040
1041
1042
1043 @Test
1044 public void createTypeVariable() {
1045 TypeElement listDeclaration = element(List.class);
1046 TypeParameterElement elementTypeParameter = listDeclaration.getTypeParameters().get(0);
1047
1048 TypeVariable typeVariable = types.createTypeVariable(elementTypeParameter, null);
1049 try {
1050 typeVariable.getUpperBound();
1051 Assert.fail("Expected exception.");
1052 } catch (IllegalStateException ignored) { }
1053
1054 try {
1055 typeVariable.getLowerBound();
1056 Assert.fail("Expected exception.");
1057 } catch (IllegalStateException ignored) { }
1058 }
1059
1060
1061
1062
1063 @Test
1064 public void testSetTypeVariableBounds() {
1065 TypeElement listDeclaration = element(List.class);
1066 TypeParameterElement elementTypeParameter = listDeclaration.getTypeParameters().get(0);
1067
1068 TypeVariable typeVariable = types.createTypeVariable(elementTypeParameter, null);
1069 types.setTypeVariableBounds(typeVariable, type(Integer.class), types.getNullType());
1070 assertEquals(typeVariable.asElement(), elementTypeParameter);
1071 assertTrue(types.isSameType(typeVariable.getUpperBound(), type(Integer.class)));
1072 assertTrue(types.isSameType(typeVariable.getLowerBound(), types.getNullType()));
1073 assertNull(types.capturedTypeArgument(typeVariable));
1074
1075 try {
1076 types.setTypeVariableBounds(typeVariable, type(Integer.class), types.getNullType());
1077 Assert.fail("Expected exception.");
1078 } catch (IllegalStateException ignored) { }
1079 }
1080
1081 @Test
1082 public void testGetIntersectionType() {
1083 IntersectionType intersectionType = types.getIntersectionType(type(Cloneable.class), type(Serializable.class));
1084 assertTrue(isSubtypeOfOneOf(type(Serializable.class), intersectionType.getBounds()));
1085
1086 try {
1087 types.getIntersectionType();
1088 Assert.fail("Expected exception.");
1089 } catch (IllegalArgumentException ignored) { }
1090
1091 try {
1092 types.getIntersectionType(type(Cloneable.class), null);
1093 Assert.fail("Expected exception.");
1094 } catch (NullPointerException ignored) { }
1095
1096 try {
1097 types.getIntersectionType(null, type(Cloneable.class));
1098 Assert.fail("Expected exception.");
1099 } catch (NullPointerException ignored) { }
1100 }
1101
1102 @Test
1103 public void testToString() {
1104
1105 for (TypeKind primitive: Arrays.asList(TypeKind.DOUBLE, TypeKind.FLOAT, TypeKind.LONG, TypeKind.INT,
1106 TypeKind.SHORT, TypeKind.BYTE, TypeKind.CHAR, TypeKind.BOOLEAN)) {
1107 assertEquals(types.toString(types.getPrimitiveType(primitive)), primitive.toString().toLowerCase());
1108 }
1109
1110
1111 assertEquals(types.toString(types.getNullType()), "null");
1112
1113
1114 for (TypeKind noType: Arrays.asList(TypeKind.VOID, TypeKind.NONE)) {
1115 assertEquals(types.toString(types.getNoType(noType)), noType.toString().toLowerCase());
1116 }
1117
1118
1119 DeclaredType outerClassType = types.getDeclaredType(element(OuterClass.class), type(Integer.class));
1120 DeclaredType arrayListOfIntegersType = types.getDeclaredType(element(ArrayList.class), type(Integer.class));
1121
1122 DeclaredType innerClassType = types.getDeclaredType(
1123 outerClassType,
1124 element(OuterClass.InnerClass.class),
1125 types.getWildcardType(arrayListOfIntegersType, null)
1126 );
1127 assertEquals(types.toString(innerClassType), String.format("%s<%s>.%s<? extends %s<%s>>",
1128 OuterClass.class.getCanonicalName(), Integer.class.getCanonicalName(),
1129 OuterClass.InnerClass.class.getSimpleName(),
1130 ArrayList.class.getCanonicalName(), Integer.class.getCanonicalName()));
1131
1132
1133 assertEquals(types.toString(types.getArrayType(type(Integer.class))), Integer[].class.getCanonicalName());
1134
1135
1136 TypeVariable typeVariable = (TypeVariable) element(List.class).getTypeParameters().get(0).asType();
1137 assertEquals(types.toString(typeVariable), List.class.getTypeParameters()[0].getName());
1138
1139 DeclaredType listOfNumbersType
1140 = types.getDeclaredType(element(List.class), types.getWildcardType(type(Number.class), null));
1141 TypeVariable capturedTypeVariable
1142 = (TypeVariable) ((DeclaredType) types.capture(listOfNumbersType)).getTypeArguments().get(0);
1143 assertEquals(types.toString(capturedTypeVariable),
1144 String.format("capture<? extends %s>", Number.class.getCanonicalName()));
1145
1146
1147 WildcardType wildcardArgument = types.getWildcardType(null, type(Integer.class));
1148 assertEquals(types.toString(wildcardArgument), String.format("? super %s", Integer.class.getCanonicalName()));
1149
1150
1151 IntersectionType intersectionType = types.getIntersectionType(type(Cloneable.class), type(Serializable.class));
1152 assertEquals(types.toString(intersectionType),
1153 String.format("%s & %s", Cloneable.class.getCanonicalName(), Serializable.class.getCanonicalName()));
1154 }
1155
1156
1157
1158
1159 @Test
1160 public void unboxedType() {
1161 try {
1162 types.unboxedType(type(List.class));
1163 Assert.fail("Expected exception.");
1164 } catch (IllegalArgumentException ignored) { }
1165
1166 try {
1167 types.unboxedType(types.getNullType());
1168 Assert.fail("Expected exception.");
1169 } catch (IllegalArgumentException ignored) { }
1170 }
1171
1172
1173
1174
1175 @Test
1176 public void boxedClass() {
1177 try {
1178 types.boxedClass(null);
1179 Assert.fail("Expected exception.");
1180 } catch (NullPointerException ignored) { }
1181 }
1182
1183
1184
1185
1186
1187 @Test
1188 public void boxingAndUnboxing() {
1189 for (TypeKind primitive: Arrays.asList(TypeKind.DOUBLE, TypeKind.FLOAT, TypeKind.LONG, TypeKind.INT,
1190 TypeKind.SHORT, TypeKind.BYTE, TypeKind.CHAR, TypeKind.BOOLEAN)) {
1191 PrimitiveType primitiveType = types.getPrimitiveType(primitive);
1192 TypeElement boxedClass = types.boxedClass(primitiveType);
1193 PrimitiveType unboxedType = types.unboxedType(boxedClass.asType());
1194
1195 assertEquals(unboxedType, primitiveType);
1196 assertEquals(unboxedType.getKind(), primitive);
1197 }
1198 }
1199
1200
1201
1202
1203 @Test
1204 public void testGetPrimitiveType() {
1205 try {
1206 types.getPrimitiveType(null);
1207 Assert.fail("Expected exception.");
1208 } catch (NullPointerException ignored) { }
1209
1210 try {
1211 types.getPrimitiveType(TypeKind.ARRAY);
1212 Assert.fail("Expected exception.");
1213 } catch (IllegalArgumentException ignored) { }
1214 }
1215
1216 @Test
1217 public void testGetNoType() {
1218 for (TypeKind noTypeKind: Arrays.asList(TypeKind.VOID, TypeKind.NONE)) {
1219 assertEquals(types.getNoType(noTypeKind).getKind(), noTypeKind);
1220 }
1221
1222 try {
1223 types.getNoType(null);
1224 Assert.fail("Expected exception.");
1225 } catch (NullPointerException ignored) { }
1226
1227 try {
1228 types.getNoType(TypeKind.PACKAGE);
1229 Assert.fail("Expected exception.");
1230 } catch (IllegalArgumentException ignored) { }
1231 }
1232
1233 @Test
1234 public void testGetNullType() {
1235 assertEquals(types.getNullType().getKind(), TypeKind.NULL);
1236 }
1237
1238 private static void testEqualsAndHashCode(Object first, Object second) {
1239 assertTrue(first.equals(first));
1240 assertTrue(second.equals(second));
1241 assertTrue(first.equals(second));
1242 assertTrue(second.equals(first));
1243
1244 assertFalse(first.equals(null));
1245 assertFalse(first.equals(new Object()));
1246
1247 assertEquals(first.hashCode(), second.hashCode());
1248 }
1249
1250 @Test
1251 public void testEqualsAndHashCode() {
1252 testEqualsAndHashCode(types.getArrayType(type(Integer.class)), types.getArrayType(type(Integer.class)));
1253 testEqualsAndHashCode(types.getPrimitiveType(TypeKind.INT), types.getPrimitiveType(TypeKind.INT));
1254 TypeElement integerDeclaration = element(Integer.class);
1255 testEqualsAndHashCode(types.getDeclaredType(integerDeclaration), types.getDeclaredType(integerDeclaration));
1256 testEqualsAndHashCode(
1257 types.getIntersectionType(type(Serializable.class), type(Cloneable.class)),
1258 types.getIntersectionType(type(Serializable.class), type(Cloneable.class))
1259 );
1260 testEqualsAndHashCode(
1261 types.getWildcardType(type(Integer.class), null),
1262 types.getWildcardType(type(Integer.class), null)
1263 );
1264 testEqualsAndHashCode(types.getNullType(), types.getNullType());
1265 testEqualsAndHashCode(types.getNoType(TypeKind.VOID), types.getNoType(TypeKind.VOID));
1266 TypeElement listDeclaration = element(List.class);
1267 TypeParameterElement listTypeParameter = listDeclaration.getTypeParameters().get(0);
1268 TypeVariable listTypeArgument = (TypeVariable) listTypeParameter.asType();
1269 testEqualsAndHashCode(
1270 listTypeArgument,
1271 types.getTypeVariable(listTypeParameter, listTypeArgument.getUpperBound(), listTypeArgument.getLowerBound(),
1272 null)
1273 );
1274
1275 testEqualsAndHashCode(element(Serializable.class), element(Serializable.class));
1276 testEqualsAndHashCode(listTypeParameter, listTypeParameter);
1277 }
1278
1279 @Test
1280 public void typeElementTest() {
1281 TypeElement outerClassDeclaration = element(OuterClass.class);
1282 TypeElement innerClassDeclaration = element(OuterClass.InnerClass.class);
1283 assertEquals(innerClassDeclaration.getEnclosingElement(), outerClassDeclaration);
1284 assertTrue(outerClassDeclaration.getEnclosedElements().contains(innerClassDeclaration));
1285 assertTrue(outerClassDeclaration.getEnclosedElements().containsAll(outerClassDeclaration.getTypeParameters()));
1286
1287 TypeElement integerDeclaration = element(Integer.class);
1288 assertEquals(integerDeclaration.getSuperclass(), type(Number.class));
1289 DeclaredType integerComparableType = types.getDeclaredType(element(Comparable.class), type(Integer.class));
1290 assertEquals(integerDeclaration.getInterfaces(), Collections.singletonList(integerComparableType));
1291 assertEquals(integerDeclaration.getQualifiedName().toString(), Integer.class.getName());
1292 assertEquals(integerDeclaration.getSimpleName().toString(), Integer.class.getSimpleName());
1293 assertEquals(integerDeclaration.asType(), type(Integer.class));
1294
1295
1296
1297 }
1298
1299 @Test
1300 public void typeParameterElementTest() {
1301 TypeElement outerClassDeclaration = element(OuterClass.class);
1302 TypeParameterElement outerClassTypeParameter = outerClassDeclaration.getTypeParameters().get(0);
1303 assertEquals(outerClassTypeParameter.getEnclosingElement(), outerClassDeclaration);
1304 assertEquals(outerClassTypeParameter.getEnclosedElements(), Collections.emptyList());
1305 assertEquals(
1306 outerClassTypeParameter.asType(),
1307 types.getTypeVariable(outerClassTypeParameter, type(Number.class), types.getNullType(), null)
1308 );
1309 assertEquals(outerClassTypeParameter.getBounds(), Collections.singletonList(type(Number.class)));
1310 assertEquals(
1311 outerClassTypeParameter.getSimpleName().toString(),
1312 OuterClass.class.getTypeParameters()[0].getName()
1313 );
1314 assertEquals(outerClassTypeParameter.getGenericElement(), outerClassTypeParameter.getEnclosingElement());
1315 }
1316 }