@@ -22,6 +22,7 @@ import org.jetbrains.kotlinx.dataframe.impl.isGetterLike
2222import org.jetbrains.kotlinx.dataframe.impl.isJavaRecord
2323import org.jetbrains.kotlinx.dataframe.impl.projectUpTo
2424import org.jetbrains.kotlinx.dataframe.impl.recordComponentNames
25+ import org.jetbrains.kotlinx.dataframe.impl.replace
2526import org.jetbrains.kotlinx.dataframe.impl.schema.sortWithConstructor
2627import java.lang.reflect.InvocationTargetException
2728import java.lang.reflect.Method
@@ -31,13 +32,13 @@ import kotlin.reflect.KCallable
3132import kotlin.reflect.KClass
3233import kotlin.reflect.KProperty
3334import kotlin.reflect.KType
35+ import kotlin.reflect.KTypeParameter
3436import kotlin.reflect.KVisibility
3537import kotlin.reflect.full.isSubclassOf
3638import kotlin.reflect.full.memberFunctions
3739import kotlin.reflect.full.memberProperties
3840import kotlin.reflect.full.primaryConstructor
3941import kotlin.reflect.full.starProjectedType
40- import kotlin.reflect.full.valueParameters
4142import kotlin.reflect.full.withNullability
4243import kotlin.reflect.jvm.isAccessible
4344import kotlin.reflect.jvm.javaField
@@ -237,6 +238,8 @@ internal fun convertToDataFrame(
237238 return dataFrameOf(column)
238239 }
239240
241+ val substitution: Map <KTypeParameter , KType > = type.typeParametersSubstitution()
242+
240243 val properties: List <KCallable <* >> = roots
241244 .ifEmpty {
242245 clazz.properties()
@@ -307,7 +310,7 @@ internal fun convertToDataFrame(
307310 }
308311 }
309312
310- val returnType = property.returnType.let { type ->
313+ val returnType = property.returnType.replace(substitution). let { type ->
311314 if (type.classifier is KClass <* >) {
312315 type
313316 } else {
@@ -429,6 +432,13 @@ internal fun convertToDataFrame(
429432
430433private fun KType.classifierOrAny (): KClass <* > = classifier as ? KClass <* > ? : Any ::class
431434
435+ internal fun KType.typeParametersSubstitution (): Map <KTypeParameter , KType > {
436+ val klass = classifier as ? KClass <* > ? : return emptyMap()
437+ return klass.typeParameters.zip(arguments).mapNotNull { (param, projection) ->
438+ projection.type?.let { param to it }
439+ }.toMap()
440+ }
441+
432442private fun KClass <* >.properties (): List <KCallable <* >> {
433443 // fall back to getter functions for pojo-like classes if no member properties were found
434444 return memberProperties
0 commit comments