Skip to content

Commit c7a0a36

Browse files
committed
#22 - Further work on generics / parameterized-types
1 parent fc99b48 commit c7a0a36

File tree

8 files changed

+122
-5
lines changed

8 files changed

+122
-5
lines changed

src/main/java/org/hibernate/models/internal/jandex/JandexTypeSwitchStandard.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
package org.hibernate.models.internal.jandex;
99

10+
import java.lang.reflect.InvocationTargetException;
11+
import java.lang.reflect.Method;
1012
import java.util.ArrayList;
1113
import java.util.Collections;
1214
import java.util.List;
@@ -18,6 +20,7 @@
1820
import org.hibernate.models.internal.TypeVariableDetailsImpl;
1921
import org.hibernate.models.internal.TypeVariableReferenceDetailsImpl;
2022
import org.hibernate.models.internal.VoidTypeDetailsImpl;
23+
import org.hibernate.models.internal.WildcardTypeDetailsImpl;
2124
import org.hibernate.models.internal.jdk.JdkTrackingTypeSwitch;
2225
import org.hibernate.models.internal.util.CollectionHelper;
2326
import org.hibernate.models.spi.ClassDetails;
@@ -85,7 +88,14 @@ public TypeDetails caseParameterizedType(
8588

8689
@Override
8790
public TypeDetails caseWildcardType(WildcardType wildcardType, SourceModelBuildingContext buildingContext) {
88-
throw new UnsupportedOperationException( "Not yet implemented - " + this );
91+
try {
92+
final Type bound = (Type) BOUND_METHOD.invoke( wildcardType );
93+
final boolean isExtends = (boolean) IS_EXTENDS_METHOD.invoke( wildcardType );
94+
return new WildcardTypeDetailsImpl( switchType( bound, TYPE_SWITCH_STANDARD, buildingContext ), isExtends );
95+
}
96+
catch (IllegalAccessException | InvocationTargetException e) {
97+
throw new RuntimeException( e );
98+
}
8999
}
90100

91101
@Override
@@ -146,4 +156,20 @@ public static List<TypeDetails> resolveTypes(
146156
}
147157
return result;
148158
}
159+
160+
private static final Method BOUND_METHOD;
161+
private static final Method IS_EXTENDS_METHOD;
162+
163+
static {
164+
try {
165+
BOUND_METHOD = WildcardType.class.getDeclaredMethod( "bound" );
166+
IS_EXTENDS_METHOD = WildcardType.class.getDeclaredMethod( "isExtends" );
167+
168+
BOUND_METHOD.trySetAccessible();
169+
IS_EXTENDS_METHOD.trySetAccessible();
170+
}
171+
catch (NoSuchMethodException e) {
172+
throw new RuntimeException( e );
173+
}
174+
}
149175
}

src/main/java/org/hibernate/models/internal/jdk/JdkTrackingTypeSwitch.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.hibernate.models.internal.PrimitiveTypeDetailsImpl;
2323
import org.hibernate.models.internal.TypeVariableDetailsImpl;
2424
import org.hibernate.models.internal.VoidTypeDetailsImpl;
25+
import org.hibernate.models.internal.WildcardTypeDetailsImpl;
2526
import org.hibernate.models.internal.util.CollectionHelper;
2627
import org.hibernate.models.spi.ArrayTypeDetails;
2728
import org.hibernate.models.spi.ClassBasedTypeDetails;
@@ -77,7 +78,21 @@ public ParameterizedTypeDetails caseParameterizedType(ParameterizedType paramete
7778
}
7879

7980
public WildcardTypeDetails caseWildcardType(WildcardType wildcardType) {
80-
throw new UnsupportedOperationException( "Not yet implemented" );
81+
final Type[] lowerBounds = wildcardType.getLowerBounds();
82+
if ( CollectionHelper.isEmpty( lowerBounds ) ) {
83+
// should indicate an extends
84+
final int numberOfBounds = CollectionHelper.length( wildcardType.getUpperBounds() );
85+
final TypeDetails upper = numberOfBounds == 1
86+
? switcher.switchType( wildcardType.getUpperBounds()[0] )
87+
: ClassBasedTypeDetails.OBJECT_TYPE_DETAILS;
88+
return new WildcardTypeDetailsImpl( upper, true );
89+
}
90+
91+
final int numberOfBounds = CollectionHelper.length( lowerBounds );
92+
final TypeDetails lower = numberOfBounds == 1
93+
? switcher.switchType( lowerBounds[0] )
94+
: ClassBasedTypeDetails.OBJECT_TYPE_DETAILS;
95+
return new WildcardTypeDetailsImpl( lower, false );
8196
}
8297

8398
public TypeVariableDetails caseTypeVariable(TypeVariable<?> typeVariable) {

src/main/java/org/hibernate/models/spi/ClassTypeDetails.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
/**
1111
* Models a class type.
1212
*
13-
* @see org.jboss.jandex.ClassType
1413
* @see Class
14+
* @see org.jboss.jandex.ClassType
1515
*
1616
* @author Steve Ebersole
1717
*/

src/main/java/org/hibernate/models/spi/TypeDetails.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
* Abstraction for what Hibernate understands about a "type", generally before it has access to
1212
* the actual {@link java.lang.reflect.Type} reference.
1313
*
14+
* @see org.jboss.jandex.Type
15+
*
1416
* @author Steve Ebersole
1517
*/
1618
public interface TypeDetails extends TypeVariableScope {

src/main/java/org/hibernate/models/spi/TypeVariableDetails.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
* </pre>
2323
* In this case, the identifier is {@code T}, while the name is {@code java.lang.Number}.
2424
*
25-
* @see org.jboss.jandex.TypeVariable
2625
* @see java.lang.reflect.TypeVariable
26+
* @see org.jboss.jandex.TypeVariable
2727
*
2828
* @author Steve Ebersole
2929
*/

src/main/java/org/hibernate/models/spi/VoidTypeDetails.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
package org.hibernate.models.spi;
99

1010
/**
11-
* Models Java's void (or {@linkplain Void}) type
11+
* Models Java's {@code void} (or {@linkplain Void}) type
1212
*
1313
* @author Steve Ebersole
1414
*/

src/main/java/org/hibernate/models/spi/WildcardTypeDetails.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
/**
1313
* Models a wildcard type declaration.
1414
*
15+
* @see java.lang.reflect.WildcardType
16+
* @see org.jboss.jandex.WildcardType
17+
*
1518
* @author Steve Ebersole
1619
*/
1720
public interface WildcardTypeDetails extends TypeDetails {

src/test/java/org/hibernate/models/generics/CollectionTests.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.hibernate.models.spi.ParameterizedTypeDetails;
2222
import org.hibernate.models.spi.TypeDetails;
2323
import org.hibernate.models.spi.TypeVariableDetails;
24+
import org.hibernate.models.spi.WildcardTypeDetails;
2425

2526
import org.junit.jupiter.api.Test;
2627

@@ -177,6 +178,59 @@ void testArrays(Index index) {
177178
}
178179
}
179180

181+
@Test
182+
void testWildcardWithJandex() {
183+
testWildcard( SourceModelTestHelper.buildJandexIndex( Stuff.class, Things.class ) );
184+
}
185+
186+
@Test
187+
void testWildcardWithoutJandex() {
188+
testWildcard( null );
189+
}
190+
191+
void testWildcard(Index index) {
192+
final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext(
193+
index,
194+
Things.class
195+
);
196+
197+
final ClassDetails classDetails = buildingContext.getClassDetailsRegistry().getClassDetails( Things.class.getName() );
198+
199+
final FieldDetails extendsStuffField = classDetails.findFieldByName( "extendsStuff" );
200+
final TypeDetails extendsStuffFieldType = extendsStuffField.getType();
201+
assertThat( extendsStuffFieldType.isImplementor( Collection.class ) ).isTrue();
202+
assertThat( extendsStuffFieldType.isImplementor( List.class ) ).isTrue();
203+
assertThat( extendsStuffFieldType.isImplementor( Set.class ) ).isFalse();
204+
assertThat( extendsStuffFieldType.isImplementor( Map.class ) ).isFalse();
205+
assertThat( extendsStuffFieldType.getTypeKind() ).isEqualTo( TypeDetails.Kind.PARAMETERIZED_TYPE );
206+
assertThat( extendsStuffFieldType.asParameterizedType().getArguments() ).hasSize( 1 );
207+
assertThat( extendsStuffFieldType.asParameterizedType().getArguments().get( 0 ).getTypeKind() ).isEqualTo( TypeDetails.Kind.WILDCARD_TYPE );
208+
final WildcardTypeDetails extendsStuffFieldWildcardType = extendsStuffFieldType.asParameterizedType()
209+
.getArguments()
210+
.get( 0 )
211+
.asWildcardType();
212+
assertThat( extendsStuffFieldWildcardType.isExtends() ).isTrue();
213+
assertThat( extendsStuffFieldWildcardType.getBound().getTypeKind() ).isEqualTo( TypeDetails.Kind.CLASS );
214+
assertThat( extendsStuffFieldWildcardType.getBound().asClassType().getClassDetails().getName() ).endsWith( "Stuff" );
215+
216+
final FieldDetails superStuffField = classDetails.findFieldByName( "superStuff" );
217+
final TypeDetails superStuffFieldType = superStuffField.getType();
218+
assertThat( superStuffFieldType.isImplementor( Collection.class ) ).isTrue();
219+
assertThat( superStuffFieldType.isImplementor( List.class ) ).isTrue();
220+
assertThat( superStuffFieldType.isImplementor( Set.class ) ).isFalse();
221+
assertThat( superStuffFieldType.isImplementor( Map.class ) ).isFalse();
222+
assertThat( superStuffFieldType.getTypeKind() ).isEqualTo( TypeDetails.Kind.PARAMETERIZED_TYPE );
223+
assertThat( superStuffFieldType.asParameterizedType().getArguments() ).hasSize( 1 );
224+
assertThat( superStuffFieldType.asParameterizedType().getArguments().get( 0 ).getTypeKind() ).isEqualTo( TypeDetails.Kind.WILDCARD_TYPE );
225+
final WildcardTypeDetails superStuffFieldWildcardType = superStuffFieldType.asParameterizedType()
226+
.getArguments()
227+
.get( 0 )
228+
.asWildcardType();
229+
assertThat( superStuffFieldWildcardType.isExtends() ).isFalse();
230+
assertThat( superStuffFieldWildcardType.getBound().getTypeKind() ).isEqualTo( TypeDetails.Kind.CLASS );
231+
assertThat( superStuffFieldWildcardType.getBound().asClassType().getClassDetails().getName() ).endsWith( "Stuff" );
232+
}
233+
180234
@SuppressWarnings("unused")
181235
static class ClassOfCollections<T> {
182236
List<String> listOfString;
@@ -196,4 +250,21 @@ static class ClassOfArrays<T> {
196250

197251
T[] tArray;
198252
}
253+
254+
static class Item {
255+
}
256+
257+
static class Stuff extends Item {
258+
}
259+
260+
static class Coat extends Stuff {
261+
}
262+
263+
static class Hat extends Stuff {
264+
}
265+
266+
static class Things {
267+
List<? extends Stuff> extendsStuff;
268+
List<? super Stuff> superStuff;
269+
}
199270
}

0 commit comments

Comments
 (0)