fun generateKotlin2Interfaces()

in graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin2/GenerateKotlin2Interfaces.kt [45:179]


fun generateKotlin2Interfaces(
    config: CodeGenConfig,
    document: Document,
): List<FileSpec> {
    if (!config.generateDataTypes) {
        return emptyList()
    }

    val typeLookup = Kotlin2TypeLookup(config, document)

    val interfaceClasses =
        document
            .getDefinitionsOfType(InterfaceTypeDefinition::class.java)
            .excludeSchemaTypeExtension()
            .filter { !it.shouldSkip(config) }
            .map { interfaceDefinition ->

                logger.info("Generating interface type ${interfaceDefinition.name}")

                // get all types that implement this interface
                val implementations =
                    document
                        .getDefinitionsOfType(ObjectTypeDefinition::class.java)
                        .filter { node -> node.implements.any { it.isEqualTo(TypeName(interfaceDefinition.name)) } }
                        .map { node -> ClassName(config.packageNameTypes, node.name) }

                // get all interfaces that this interface implements
                val implementedInterfaces = typeLookup.implementedInterfaces(interfaceDefinition)

                // get any fields defined via schema extensions
                val extensionTypes = findInterfaceExtensions(interfaceDefinition.name, document.definitions)

                // get all fields defined on the type itself or any extension types
                val fields =
                    listOf(interfaceDefinition)
                        .plus(extensionTypes)
                        .flatMap { it.fieldDefinitions }
                        .filterSkipped()

                // get a list of fields to override
                val overrideFields = typeLookup.overrideFields(implementedInterfaces)

                // create the interface
                val interfaceSpec =
                    TypeSpec
                        .interfaceBuilder(interfaceDefinition.name)
                        .addOptionalGeneratedAnnotation(config)
                        .addModifiers(KModifier.SEALED)
                        // add docs if available
                        .apply {
                            if (interfaceDefinition.description != null) {
                                addKdoc("%L", interfaceDefinition.description.sanitizeKdoc())
                            }
                        }
                        // add jackson annotations
                        .addAnnotation(jsonTypeInfoAnnotation())
                        .apply {
                            if (implementations.isNotEmpty()) {
                                addAnnotation(jsonSubTypesAnnotation(implementations))
                            }
                        }
                        // add interfaces to implement
                        .addSuperinterfaces(
                            implementedInterfaces.map { typeLookup.findKtInterfaceName(it, config.packageNameTypes) },
                        )
                        // add fields, overriding if needed
                        .addProperties(
                            fields.map { field ->
                                PropertySpec
                                    .builder(
                                        name = field.name,
                                        type = typeLookup.findReturnType(config.packageNameTypes, field.type),
                                    ).apply {
                                        if (field.description != null) {
                                            addKdoc("%L", field.description.sanitizeKdoc())
                                        }
                                    }.apply {
                                        if (field.name in overrideFields) {
                                            addModifiers(KModifier.OVERRIDE)
                                        }
                                    }.addAnnotation(suppressInapplicableJvmNameAnnotation())
                                    .addAnnotation(jvmNameAnnotation(field.name))
                                    .build()
                            },
                        ).build()

                // return a file per interface
                FileSpec.get(config.packageNameTypes, interfaceSpec)
            }

    val unionClasses =
        document
            .getDefinitionsOfType(UnionTypeDefinition::class.java)
            .excludeSchemaTypeExtension()
            .filter { !it.shouldSkip(config) }
            .map { unionDefinition ->

                logger.info("Generating union type ${unionDefinition.name}")

                // get any members defined via schema extensions
                val extensionTypes = findUnionExtensions(unionDefinition.name, document.definitions)

                // get all types that implement this union
                val implementations =
                    unionDefinition.memberTypes
                        .plus(extensionTypes.flatMap { it.memberTypes })
                        .filterIsInstance<NamedNode<*>>()
                        .map { node -> ClassName(config.packageNameTypes, node.name) }

                // create the interface
                val interfaceSpec =
                    TypeSpec
                        .interfaceBuilder(unionDefinition.name)
                        .addOptionalGeneratedAnnotation(config)
                        .addModifiers(KModifier.SEALED)
                        // add docs if available
                        .apply {
                            if (unionDefinition.description != null) {
                                addKdoc("%L", unionDefinition.description.sanitizeKdoc())
                            }
                        }
                        // add jackson annotations
                        .addAnnotation(jsonTypeInfoAnnotation())
                        .apply {
                            if (implementations.isNotEmpty()) {
                                addAnnotation(jsonSubTypesAnnotation(implementations))
                            }
                        }.build()

                // return a file per interface
                FileSpec.get(config.packageNameTypes, interfaceSpec)
            }

    return interfaceClasses.plus(unionClasses)
}