Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public List<TypeDetails> getImplementedInterfaces() {
@Override
public List<TypeVariableDetails> getTypeParameters() {
if ( typeParameters == null ) {
this.typeParameters = determineTypeParameters( typeDescription, this, getModelContext() );
this.typeParameters = determineTypeParameters( typeDescription, getModelContext() );
}
return typeParameters;
}
Expand Down Expand Up @@ -227,15 +227,15 @@ private static ClassDetails determineSuperType(
.resolveClassDetails( typeDescription.getSuperClass().asRawType().getTypeName() );
}

private static TypeDetails determineGenericSuperType(TypeDescription typeDescription, ModelsContext modelsContext) {
private TypeDetails determineGenericSuperType(TypeDescription typeDescription, ModelsContext modelsContext) {
if ( typeDescription.getSuperClass() == null ) {
return null;
}

return TypeSwitchStandard.switchType( typeDescription.getSuperClass(), modelsContext );
return TypeSwitchStandard.switchType( typeDescription.getSuperClass(), this, modelsContext );
}

private static List<TypeDetails> determineInterfaces(
private List<TypeDetails> determineInterfaces(
TypeDescription typeDescription,
ModelsContext modelsContext) {
final TypeList.Generic interfaceTypes = typeDescription.getInterfaces();
Expand All @@ -247,16 +247,16 @@ private static List<TypeDetails> determineInterfaces(
for ( TypeDescription.Generic interfaceType : interfaceTypes ) {
final TypeDetails switchedType = TypeSwitchStandard.switchType(
interfaceType,
this,
modelsContext
);
result.add( switchedType );
}
return result;
}

private static List<TypeVariableDetails> determineTypeParameters(
private List<TypeVariableDetails> determineTypeParameters(
TypeDescription typeDescription,
ClassDetailsImpl current,
ModelsContext modelsContext) {
final TypeList.Generic typeArguments = typeDescription.getTypeVariables();
if ( CollectionHelper.isEmpty( typeArguments ) ) {
Expand All @@ -265,7 +265,7 @@ private static List<TypeVariableDetails> determineTypeParameters(

final ArrayList<TypeVariableDetails> result = arrayList( typeArguments.size() );
for ( TypeDescription.Generic typeArgument : typeArguments ) {
result.add( (TypeVariableDetails) TypeSwitchStandard.switchType( typeArgument, current, modelsContext ) );
result.add( (TypeVariableDetails) TypeSwitchStandard.switchType( typeArgument, this, modelsContext ) );
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@
*/
public class TypeSwitchStandard implements TypeSwitch<TypeDetails> {

public static TypeDetails switchType(TypeDefinition typeDescription, ModelsContext modelsContext) {
return switchType( typeDescription, null, modelsContext );
}

public static TypeDetails switchType(TypeDefinition typeDescription, ClassDetails declaringType, ModelsContext modelsContext) {
final TypeSwitchStandard switchImpl = new TypeSwitchStandard( declaringType );
return TypeSwitcher.switchType( typeDescription, switchImpl, modelsContext );
Expand All @@ -47,7 +43,7 @@ public static TypeDetails switchType(TypeDefinition typeDescription, ClassDetail

private final ClassDetails declaringType;

public TypeSwitchStandard(ClassDetails declaringType) {
private TypeSwitchStandard(ClassDetails declaringType) {
this.declaringType = declaringType;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public List<TypeDetails> getImplementedInterfaces() {
@Override
public List<TypeVariableDetails> getTypeParameters() {
if ( typeParameters == null ) {
this.typeParameters = determineTypeParameters( classInfo, this, getModelContext() );
this.typeParameters = determineTypeParameters( classInfo, getModelContext() );
}
return typeParameters;
}
Expand Down Expand Up @@ -246,15 +246,15 @@ private static ClassDetails determineSuperType(
.resolveClassDetails( classInfo.superClassType().name().toString() );
}

private static TypeDetails determineGenericSuperType(ClassInfo classInfo, ModelsContext modelsContext) {
private TypeDetails determineGenericSuperType(ClassInfo classInfo, ModelsContext modelsContext) {
if ( classInfo.superClassType() == null ) {
return null;
}

return JandexTypeSwitchStandard.switchType( classInfo.superClassType(), modelsContext );
return JandexTypeSwitchStandard.switchType( classInfo.superClassType(), this, modelsContext );
}

private static List<TypeDetails> determineInterfaces(
private List<TypeDetails> determineInterfaces(
ClassInfo classInfo,
ModelsContext modelsContext) {
final List<Type> interfaceTypes = classInfo.interfaceTypes();
Expand All @@ -266,22 +266,23 @@ private static List<TypeDetails> determineInterfaces(
for ( Type interfaceType : interfaceTypes ) {
final TypeDetails switchedType = JandexTypeSwitchStandard.switchType(
interfaceType,
this,
modelsContext
);
result.add( switchedType );
}
return result;
}

private static List<TypeVariableDetails> determineTypeParameters(ClassInfo classInfo, JandexClassDetails current, ModelsContext modelsContext) {
private List<TypeVariableDetails> determineTypeParameters(ClassInfo classInfo, ModelsContext modelsContext) {
final List<TypeVariable> jandexTypeVariables = classInfo.typeParameters();
if ( CollectionHelper.isEmpty( jandexTypeVariables ) ) {
return emptyList();
}

final ArrayList<TypeVariableDetails> result = arrayList( jandexTypeVariables.size() );
for ( TypeVariable jandexTypeVariable : jandexTypeVariables ) {
result.add( (TypeVariableDetails) JandexTypeSwitchStandard.switchType( jandexTypeVariable, current, modelsContext ) );
result.add( (TypeVariableDetails) JandexTypeSwitchStandard.switchType( jandexTypeVariable, this, modelsContext ) );
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@
* @author Steve Ebersole
*/
public class JandexTypeSwitchStandard implements JandexTypeSwitch<TypeDetails> {
public static TypeDetails switchType(Type type, ModelsContext modelsContext) {
assert type.kind() != Type.Kind.TYPE_VARIABLE;
return switchType( type, null, modelsContext );
}

public static TypeDetails switchType(Type type, ClassDetails declaringType, ModelsContext modelsContext) {
final JandexTypeSwitchStandard genericVariableSwitch = new JandexTypeSwitchStandard( declaringType );
Expand All @@ -55,7 +51,7 @@ public static TypeDetails switchType(Type type, ClassDetails declaringType, Mode

private final ClassDetails declaringType;

public JandexTypeSwitchStandard(ClassDetails declaringType) {
private JandexTypeSwitchStandard(ClassDetails declaringType) {
this.declaringType = declaringType;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
*/
package org.hibernate.models.spi;

import java.util.Collections;
import java.util.List;

import org.hibernate.models.internal.ArrayTypeDetailsImpl;
import org.hibernate.models.internal.ParameterizedTypeDetailsImpl;
import org.hibernate.models.internal.PrimitiveKind;
import org.hibernate.models.internal.util.CollectionHelper;

import java.util.Collections;
import java.util.List;

import static org.hibernate.models.internal.util.CollectionHelper.arrayList;
import static org.hibernate.models.spi.StandardTypeDetails.OBJECT_TYPE_DETAILS;

Expand Down Expand Up @@ -185,35 +185,37 @@ public static ClassDetails resolveRawClass(TypeDetails typeDetails) {
* @param parameterizedType the parameterized type used to resolve the type variable's relative type
* @param typeVariable the type variable to resolve
*
* @return the type variable's relative type, or {@code null} if not resolved
* @return the type variable's relative type
*/
public static TypeDetails resolveTypeVariableFromParameterizedType(
ParameterizedTypeDetails parameterizedType,
TypeVariableDetails typeVariable) {
final ClassDetails classDetails = parameterizedType.getRawClassDetails();
final TypeDetails typeArgument = findMatchingTypeArgument(
classDetails.getTypeParameters(),
parameterizedType.getArguments(),
typeVariable.getIdentifier()
);

// If no type argument is found, or the type variable is defined by another
// class, try resolving it in the generic super type if present
if ( typeArgument == null || classDetails != typeVariable.getDeclaringType() ) {
if ( classDetails == typeVariable.getDeclaringType() ) {
// If the type variable is defined by the parameterized class, try to find the matching type argument
return findMatchingTypeArgument(
classDetails.getTypeParameters(),
parameterizedType.getArguments(),
typeVariable.getIdentifier()
);
}
else {
// Try resolving the type variable in the generic super type
final TypeDetails genericSuper = classDetails.getGenericSuperType();
final TypeDetails resolvedType = genericSuper != null ?
genericSuper.resolveTypeVariable( typeVariable ) :
null;
if ( typeArgument == null || resolvedType != null
&& resolvedType.getTypeKind() != TypeDetails.Kind.TYPE_VARIABLE ) {
return resolvedType;
if ( resolvedType != null ) {
return resolvedType.getTypeKind() == TypeDetails.Kind.TYPE_VARIABLE ?
parameterizedType.resolveTypeVariable( resolvedType.asTypeVariable() ) :
resolvedType;
}
}

// Either we found the exact type variable's argument, or the parameterized class redefines
// a type variable with the same identifier as a supertype, and it should be ignored.
// Return the matching generic type argument
return typeArgument;
throw new IllegalArgumentException(
"Unable to resolve type variable [" + typeVariable.getIdentifier() + "] from parameterized type ["
+ parameterizedType.getName() + "]"
);
}

private static TypeDetails findMatchingTypeArgument(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ void testParameterizedHierarchy() {
final ModelsContext modelsContext = createModelContext(
Root.class,
Base1.class,
Base2.class
Base2.class,
Level1.class,
Level2.class,
Base3.class
);

final ClassDetails rootClassDetails = modelsContext.getClassDetailsRegistry().getClassDetails( Root.class.getName() );
final ClassDetails base1ClassDetails = modelsContext.getClassDetailsRegistry().getClassDetails( Base1.class.getName() );
final ClassDetails base2ClassDetails = modelsContext.getClassDetailsRegistry().getClassDetails( Base2.class.getName() );
final ClassDetails base3ClassDetails = modelsContext.getClassDetailsRegistry().getClassDetails( Base3.class.getName() );

final FieldDetails idField = rootClassDetails.findFieldByName( "id" );
final TypeDetails idFieldType = idField.getType();
Expand Down Expand Up @@ -80,6 +84,35 @@ void testParameterizedHierarchy() {
assertThat( resolvedClassType.isResolved() ).isTrue();
}

{
final TypeDetails concreteType = idField.resolveRelativeType( base3ClassDetails );
assertThat( concreteType ).isInstanceOf( ClassTypeDetails.class );
final ClassDetails concreteClassDetails = ( (ClassTypeDetails) concreteType ).getClassDetails();
assertThat( concreteClassDetails.toJavaClass() ).isEqualTo( Long.class );

final ClassBasedTypeDetails resolvedClassType = idField.resolveRelativeClassType( base3ClassDetails );
assertThat( resolvedClassType.isResolved() ).isTrue();
assertThat( resolvedClassType.getClassDetails().toJavaClass() ).isEqualTo( Long.class );
assertThat( resolvedClassType.isResolved() ).isTrue();
}

{
final ClassDetails level1Class = modelsContext.getClassDetailsRegistry().getClassDetails( Level1.class.getName() );
final FieldDetails middleField = level1Class.findFieldByName( "middle" );
final TypeDetails middleFieldType = middleField.getType();
assertThat( middleFieldType.getTypeKind() ).isEqualTo( TypeDetails.Kind.TYPE_VARIABLE );
assertThat( middleFieldType.isResolved() ).isFalse();

final TypeDetails concreteType = middleField.resolveRelativeType( base3ClassDetails );
assertThat( concreteType ).isInstanceOf( ClassTypeDetails.class );
final ClassDetails concreteClassDetails = ( (ClassTypeDetails) concreteType ).getClassDetails();
assertThat( concreteClassDetails.toJavaClass() ).isEqualTo( Short.class );

final ClassBasedTypeDetails resolvedClassType = middleField.resolveRelativeClassType( base3ClassDetails );
assertThat( resolvedClassType.isResolved() ).isTrue();
assertThat( resolvedClassType.getClassDetails().toJavaClass() ).isEqualTo( Short.class );
assertThat( resolvedClassType.isResolved() ).isTrue();
}
}

@SuppressWarnings("unused")
Expand All @@ -92,4 +125,15 @@ static class Base1 extends Root<Integer> {

static class Base2 extends Root<String> {
}

// reuse same type parameter identifier as Root
static class Level1<J, I> extends Root<J> {
I middle;
}

static class Level2<K> extends Level1<K, Short> {
}

static class Base3<K> extends Level2<Long> {
}
}
Loading