ktor-swagger-ui icon indicating copy to clipboard operation
ktor-swagger-ui copied to clipboard

processKotlinxSerialization() doesn't seem to parse annotations

Open vincentburesi-es opened this issue 6 months ago • 1 comments

When using a custom generator with type.processKotlinxSerialization(), it seems like the annotations (like @Description for example) are dropped. In schemakenerator's KotlinxSerializationTypeProcessingStep.kt the process function below uses KSerializer#descriptor

private fun process(type: KType, typeData: MutableList<BaseTypeData>): BaseTypeData {
    if (type.classifier is KClass<*>) {
        return (type.classifier as KClass<*>).serializerOrNull()
            ?.let { parse(it.descriptor, typeData, mutableMapOf()) } // <-- here we parse using KSerializer#descriptor
            ?: parseWildcard(typeData)
    } else {
        throw IllegalArgumentException("Type is not a class.")
    }
}

Later in the parsing, we have multiple specific parse functions like the one below, which don't transmit the annotations informations we would need for handleCoreAnnotations() and similar functions to work properly

private fun parseObject(descriptor: SerialDescriptor, typeData: MutableList<BaseTypeData>): BaseTypeData {
    val id = TypeId.build(descriptor.cleanSerialName())
    return typeData.find(id)
        ?: ObjectTypeData( // <-- here, we leave the annotations field blank
            id = id,
            simpleName = descriptor.simpleName(),
            qualifiedName = descriptor.qualifiedName(),
        ).also { result ->
            typeData.removeIf { it.id == result.id }
            typeData.add(result)
        }
}

To fix that, we would probably need a parseAnnotations step, similar to what is done for processReflection() in ReflectionTypeProcessingStep.kt parseClass() function, the parseAnnotations() function could even be reused as-is in both cases.

// collect annotation information
val annotations = parseAnnotations(clazz)
    // ...
return when (classType) {
    // ...
    TypeCategory.OBJECT -> ObjectTypeData(
        id = id,
        simpleName = clazz.simpleName!!,
        qualifiedName = clazz.qualifiedName!!,
        typeParameters = resolvedTypeParameters.toMutableMap(),
        subtypes = subtypes.toMutableList(),
        supertypes = supertypes.toMutableList(),
        members = members.toMutableList(),
        annotations = annotations.toMutableList() // <-- here
    )
    // ...
}

vincentburesi-es avatar Jul 31 '24 12:07 vincentburesi-es