@@ -12,7 +12,7 @@ import java.lang.reflect.WildcardType
1212/* *
1313 * @author Andrew Potter
1414 */
15- internal open class GenericType (protected val mostSpecificType : JavaType , protected val options : SchemaParserOptions ) {
15+ internal class GenericType (private val mostSpecificType : JavaType , private val options : SchemaParserOptions ) {
1616
1717 fun isTypeAssignableFromRawClass (type : ParameterizedType , clazz : Class <* >) =
1818 clazz.isAssignableFrom(getRawClass(type.rawType))
@@ -23,125 +23,69 @@ internal open class GenericType(protected val mostSpecificType: JavaType, protec
2323
2424 fun isAssignableFrom (type : JavaType ) = TypeUtils .isAssignable(type, mostSpecificType)
2525
26- fun relativeToPotentialParent (declaringType : JavaType ): RelativeTo {
27- if (declaringType !is Class <* > || declaringType.isInterface) {
28- return relativeToType(declaringType)
29- }
30-
31- val type = getGenericSuperType(mostSpecificType, declaringType)
32- if (type == null ) {
33- error(" Unable to find generic type of class ${TypeUtils .toString(declaringType)} relative to ${TypeUtils .toString(mostSpecificType)} " )
34- } else {
35- return relativeToType(type)
36- }
37- }
38-
39- fun relativeToType (declaringType : JavaType ) = RelativeTo (declaringType, mostSpecificType, options)
40-
41- fun getGenericInterface (targetInterface : Class <* >) = getGenericInterface(mostSpecificType, targetInterface)
42-
43- private fun getGenericInterface (type : JavaType ? , targetInterface : Class <* >): JavaType ? {
44- if (type == null ) {
45- return null
46- }
47-
48- val raw = type as ? Class <* > ? : getRawClass(type)
49-
50- if (raw == targetInterface) {
51- return type
52- }
53-
54- val possibleSubInterface = raw.genericInterfaces.find { genericInterface ->
55- TypeUtils .isAssignable(genericInterface, targetInterface)
56- } ? : raw.interfaces.find { iface ->
57- TypeUtils .isAssignable(iface, targetInterface)
58- } ? : getGenericInterface(raw.genericSuperclass, targetInterface) ? : return null
59-
60- return getGenericInterface(possibleSubInterface, targetInterface)
61- }
62-
63- fun getGenericSuperType (targetSuperClass : Class <* >) = getGenericSuperType(mostSpecificType, targetSuperClass)
64-
65- private fun getGenericSuperType (type : JavaType ? , targetSuperClass : Class <* >): JavaType ? {
66- if (type == null ) {
67- return null
68- }
69-
70- val raw = type as ? Class <* > ? : TypeUtils .getRawType(type, type)
26+ /* *
27+ * Unwrap certain Java types to find the "real" class.
28+ */
29+ fun unwrapGenericType (javaType : JavaType ): JavaType {
30+ return when (val type = replaceTypeVariable(javaType)) {
31+ is ParameterizedType -> {
32+ val rawType = type.rawType
33+ val genericType = options.genericWrappers.find { it.type == rawType }
34+ ? : return type
35+
36+ val typeArguments = type.actualTypeArguments
37+ if (typeArguments.size <= genericType.index) {
38+ throw IndexOutOfBoundsException (" Generic type '${TypeUtils .toString(type)} ' does not have a type argument at index ${genericType.index} !" )
39+ }
7140
72- if (raw == targetSuperClass) {
73- return type
41+ val unwrapsTo = genericType.schemaWrapper.invoke(typeArguments[genericType.index])
42+ unwrapGenericType(unwrapsTo)
43+ }
44+ is TypeVariable <* > -> error(" Could not resolve type variable '${TypeUtils .toLongString(type)} ' relative to ${TypeUtils .toString(mostSpecificType)} " )
45+ is WildcardType -> type.upperBounds.firstOrNull()
46+ ? : error(" Unable to unwrap type, wildcard has no upper bound: $type " )
47+ is Class <* > -> if (type.isPrimitive) Primitives .wrap(type) else type
48+ else -> error(" Unable to unwrap type: $type " )
7449 }
75-
76- return getGenericSuperType(raw.genericSuperclass, targetSuperClass)
7750 }
7851
79- class RelativeTo (private val declaringType : JavaType , mostSpecificType : JavaType , options : SchemaParserOptions ) : GenericType(mostSpecificType, options) {
80-
81- /* *
82- * Unwrap certain Java types to find the "real" class.
83- */
84- fun unwrapGenericType (javaType : JavaType ): JavaType {
85- return when (val type = replaceTypeVariable(javaType)) {
86- is ParameterizedType -> {
87- val rawType = type.rawType
88- val genericType = options.genericWrappers.find { it.type == rawType }
89- ? : return type
90-
91- val typeArguments = type.actualTypeArguments
92- if (typeArguments.size <= genericType.index) {
93- throw IndexOutOfBoundsException (" Generic type '${TypeUtils .toString(type)} ' does not have a type argument at index ${genericType.index} !" )
94- }
95-
96- val unwrapsTo = genericType.schemaWrapper.invoke(typeArguments[genericType.index])
97- unwrapGenericType(unwrapsTo)
98- }
99- is TypeVariable <* > -> error(" Could not resolve type variable '${TypeUtils .toLongString(type)} ' of ${TypeUtils .toString(declaringType)} relative to ${TypeUtils .toString(mostSpecificType)} " )
100- is WildcardType -> type.upperBounds.firstOrNull()
101- ? : error(" Unable to unwrap type, wildcard has no upper bound: $type " )
102- is Class <* > -> if (type.isPrimitive) Primitives .wrap(type) else type
103- else -> error(" Unable to unwrap type: $type " )
52+ private fun replaceTypeVariable (type : JavaType , resolving : Set <TypeVariable <* >> = emptySet()): JavaType {
53+ return when (type) {
54+ is ParameterizedType -> {
55+ val actualTypeArguments = type.actualTypeArguments.map { replaceTypeVariable(it, resolving) }.toTypedArray()
56+ ParameterizedTypeImpl (type.rawType as Class <* >, actualTypeArguments, type.ownerType?.let { replaceTypeVariable(it, resolving) })
10457 }
105- }
106-
107- private fun replaceTypeVariable (type : JavaType , resolving : Set <TypeVariable <* >> = emptySet()): JavaType {
108- return when (type) {
109- is ParameterizedType -> {
110- val actualTypeArguments = type.actualTypeArguments.map { replaceTypeVariable(it, resolving) }.toTypedArray()
111- ParameterizedTypeImpl (type.rawType as Class <* >, actualTypeArguments, type.ownerType?.let { replaceTypeVariable(it, resolving) })
112- }
113- is WildcardType -> TypeUtils .wildcardType()
114- .withUpperBounds(* type.upperBounds.map { replaceTypeVariable(it, resolving) }.toTypedArray())
115- .withLowerBounds(* type.lowerBounds.map { replaceTypeVariable(it, resolving) }.toTypedArray())
116- .build()
117- is ResolvedType -> {
118- if (type.typeParameters.isEmpty()) {
119- type.erasedType
120- } else {
121- val actualTypeArguments = type.typeParameters.map { replaceTypeVariable(it) }.toTypedArray()
122- ParameterizedTypeImpl (type.erasedType, actualTypeArguments, null )
123- }
58+ is WildcardType -> TypeUtils .wildcardType()
59+ .withUpperBounds(* type.upperBounds.map { replaceTypeVariable(it, resolving) }.toTypedArray())
60+ .withLowerBounds(* type.lowerBounds.map { replaceTypeVariable(it, resolving) }.toTypedArray())
61+ .build()
62+ is ResolvedType -> {
63+ if (type.typeParameters.isEmpty()) {
64+ type.erasedType
65+ } else {
66+ val actualTypeArguments = type.typeParameters.map { replaceTypeVariable(it) }.toTypedArray()
67+ ParameterizedTypeImpl (type.erasedType, actualTypeArguments, null )
12468 }
125- is TypeVariable <* > -> {
126- val genericDeclaration = type.genericDeclaration
127- when {
128- // only a variable leaked from a raw type can be bound to a type containing itself (e.g. T -> List<T>),
129- // erase it like the raw type does instead of expanding it forever
130- type in resolving -> TypeUtils .getRawType(type.bounds.first(), null ) ? : Any ::class .java
131- // the most specific type binds the variables of all its supertypes
132- genericDeclaration is Class <* > -> generateSequence(mostSpecificType) { (it as ? ParameterizedType )?.ownerType }
133- // an inner class can also use the variables of its outer class, those are bound by its owner type (e.g. Connection<Owner>.Entry)
134- .firstNotNullOfOrNull { TypeUtils .getTypeArguments(it, genericDeclaration)?.get(type) }
135- // keep the full type argument (e.g. List<Foo>) rather than its raw class so nested generics aren't lost
136- ?.let { replaceTypeVariable(it, resolving + type) }
137- ? : type
138- else -> type
139- }
140- }
141- else -> {
142- type
69+ }
70+ is TypeVariable <* > -> {
71+ val genericDeclaration = type.genericDeclaration
72+ when {
73+ // only a variable leaked from a raw type can be bound to a type containing itself (e.g. T -> List<T>),
74+ // erase it like the raw type does instead of expanding it forever
75+ type in resolving -> TypeUtils .getRawType(type.bounds.first(), null ) ? : Any ::class .java
76+ // the most specific type binds the variables of all its supertypes
77+ genericDeclaration is Class <* > -> generateSequence(mostSpecificType) { (it as ? ParameterizedType )?.ownerType }
78+ // an inner class can also use the variables of its outer class, those are bound by its owner type (e.g. Connection<Owner>.Entry)
79+ .firstNotNullOfOrNull { TypeUtils .getTypeArguments(it, genericDeclaration)?.get(type) }
80+ // keep the full type argument (e.g. List<Foo>) rather than its raw class so nested generics aren't lost
81+ ?.let { replaceTypeVariable(it, resolving + type) }
82+ ? : type
83+ else -> type
14384 }
14485 }
86+ else -> {
87+ type
88+ }
14589 }
14690 }
14791}
0 commit comments