From 10bfc60131755762b58b52d047045c75aa0f08e0 Mon Sep 17 00:00:00 2001 From: Patrick Strawderman Date: Sun, 21 Jul 2024 20:36:01 -0700 Subject: [PATCH] Create singleton empty CodeGenResult instance Create a singleton empty CodeGenResult instance, CodeGenResult.EMPTY, and update the merge method to more intelligently handle merging to avoid excessive copying. --- .../netflix/graphql/dgs/codegen/CodeGen.kt | 240 ++++++++---------- ...ntitiesRepresentationTypeGeneratorUtils.kt | 4 +- .../generators/java/ClientApiGenerator.kt | 33 ++- .../generators/java/ConstantsGenerator.kt | 72 ++++-- .../generators/java/DataTypeGenerator.kt | 6 +- .../EntitiesRepresentationTypeGenerator.kt | 12 +- .../generators/java/EnumTypeGenerator.kt | 2 +- .../generators/java/InterfaceGenerator.kt | 2 +- .../dgs/codegen/generators/java/TypeUtils.kt | 40 +-- .../generators/java/UnionTypeGenerator.kt | 4 +- .../kotlin/KotlinDataTypeGenerator.kt | 11 +- ...tlinEntitiesRepresentationTypeGenerator.kt | 10 +- .../kotlin/KotlinEnumTypeGenerator.kt | 2 +- .../kotlin/KotlinInterfaceTypeGenerator.kt | 2 +- .../kotlin/KotlinUnionTypeGenerator.kt | 2 +- .../codegen/generators/shared/DocGenerator.kt | 32 +-- 16 files changed, 236 insertions(+), 238 deletions(-) diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/CodeGen.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/CodeGen.kt index b0404855d..6a86e9fd3 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/CodeGen.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/CodeGen.kt @@ -35,16 +35,32 @@ import com.squareup.javapoet.JavaFile import com.squareup.javapoet.TypeSpec import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier -import graphql.language.* +import graphql.language.Definition +import graphql.language.DirectivesContainer +import graphql.language.Document +import graphql.language.EnumTypeDefinition +import graphql.language.FieldDefinition +import graphql.language.InputObjectTypeDefinition +import graphql.language.InterfaceTypeDefinition +import graphql.language.NamedNode +import graphql.language.ObjectTypeDefinition +import graphql.language.ObjectTypeExtensionDefinition +import graphql.language.ScalarTypeDefinition +import graphql.language.Type +import graphql.language.TypeDefinition +import graphql.language.TypeName +import graphql.language.UnionTypeDefinition import graphql.parser.InvalidSyntaxException import graphql.parser.MultiSourceReader import graphql.parser.Parser import graphql.parser.ParserOptions +import graphql.schema.idl.ScalarInfo +import graphql.schema.idl.TypeUtil import org.slf4j.Logger import org.slf4j.LoggerFactory -import java.io.* +import java.io.File +import java.io.Reader import java.lang.annotation.RetentionPolicy -import java.nio.charset.StandardCharsets import java.nio.file.Path import java.nio.file.Paths import java.util.zip.ZipFile @@ -66,7 +82,6 @@ class CodeGen(private val config: CodeGenConfig) { config = config ) - @Suppress("DuplicatedCode") fun generate(): CodeGenResult { val codeGenResult = when (config.language) { Language.JAVA -> generateJava() @@ -115,14 +130,15 @@ class CodeGen(private val config: CodeGenConfig) { loadSchemaReaders(readerBuilder, debugReaderBuilder) // process schema from dependencies - config.schemaJarFilesFromDependencies.forEach { - val zipFile = ZipFile(it) - zipFile.entries().toList().forEach { entry -> - if (!entry.isDirectory && entry.name.startsWith("META-INF") && - (entry.name.endsWith(".graphqls") || entry.name.endsWith(".graphql")) - ) { - logger.info("Generating schema from ${it.name}: ${entry.name}") - readerBuilder.reader(InputStreamReader(zipFile.getInputStream(entry), StandardCharsets.UTF_8), "codegen") + config.schemaJarFilesFromDependencies.forEach { file -> + ZipFile(file).use { zipFile -> + for (entry in zipFile.entries()) { + if (!entry.isDirectory && entry.name.startsWith("META-INF") && + (entry.name.endsWith(".graphqls") || entry.name.endsWith(".graphql")) + ) { + logger.info("Generating schema from {}: {}", file.name, entry.name) + readerBuilder.reader(zipFile.getInputStream(entry).reader(), "codegen") + } } } } @@ -132,7 +148,7 @@ class CodeGen(private val config: CodeGenConfig) { parser.parseDocument(reader, options) } catch (exception: InvalidSyntaxException) { // check if the schema is empty - if (exception.sourcePreview.trim() == "") { + if (exception.sourcePreview.isBlank()) { logger.warn("Schema is empty") // return an empty document return Document.newDocument().build() @@ -150,7 +166,8 @@ class CodeGen(private val config: CodeGenConfig) { */ private fun loadSchemaReaders(vararg readerBuilders: MultiSourceReader.Builder) { readerBuilders.forEach { rb -> - val schemaFiles = config.schemaFiles.sorted() + val schemaFiles = config.schemaFiles.asSequence() + .sorted() .flatMap { it.walkTopDown() } .filter { it.isFile } .filter { it.name.endsWith(".graphql") || it.name.endsWith(".graphqls") } @@ -180,7 +197,7 @@ class CodeGen(private val config: CodeGenConfig) { // Data Fetchers val dataFetchersResult = generateJavaDataFetchers(definitions) val generatedAnnotation = generateJavaGeneratedAnnotation(config) - var docFiles = generateDocFiles(definitions) + val docFiles = generateDocFiles(definitions) return dataTypesResult .merge(dataFetchersResult) @@ -202,7 +219,7 @@ class CodeGen(private val config: CodeGenConfig) { .excludeSchemaTypeExtension() .filter { config.generateDataTypes || config.generateInterfaces || it.name in requiredTypeCollector.requiredTypes } .map { EnumTypeGenerator(config).generate(it, findEnumExtensions(it.name, definitions)) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } private fun generateJavaUnions(definitions: Collection>): CodeGenResult { @@ -211,7 +228,7 @@ class CodeGen(private val config: CodeGenConfig) { .excludeSchemaTypeExtension() .filter { config.generateDataTypes || config.generateInterfaces || it.name in requiredTypeCollector.requiredTypes } .map { UnionTypeGenerator(config, document).generate(it, findUnionExtensions(it.name, definitions)) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } private fun generateJavaInterfaces(definitions: Collection>): CodeGenResult { @@ -223,7 +240,7 @@ class CodeGen(private val config: CodeGenConfig) { val extensions = findInterfaceExtensions(it.name, definitions) InterfaceGenerator(config, document).generate(it, extensions) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } private fun generateJavaClientApi(definitions: Collection>): CodeGenResult { @@ -236,8 +253,8 @@ class CodeGen(private val config: CodeGenConfig) { .map { ClientApiGenerator(config, document).generate(it, methodNames) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } - } else CodeGenResult() + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } + } else CodeGenResult.EMPTY } private fun generateJavaClientEntitiesApi(definitions: Collection>): CodeGenResult { @@ -247,7 +264,7 @@ class CodeGen(private val config: CodeGenConfig) { .filter { it.hasDirective("key") } .toList() ClientApiGenerator(config, document).generateEntities(federatedDefinitions) - } else CodeGenResult() + } else CodeGenResult.EMPTY } private fun generateJavaClientEntitiesRepresentations(definitions: Collection>): CodeGenResult { @@ -258,8 +275,8 @@ class CodeGen(private val config: CodeGenConfig) { .filter { it.hasDirective("key") } .map { d -> EntitiesRepresentationTypeGenerator(config, document).generate(d, generatedRepresentations) - }.fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } - } else CodeGenResult() + }.fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } + } else CodeGenResult.EMPTY } private fun generateJavaDataFetchers(definitions: Collection>): CodeGenResult { @@ -267,13 +284,13 @@ class CodeGen(private val config: CodeGenConfig) { .filterIsInstance() .filter { it.name == "Query" } .map { DatafetcherGenerator(config, document).generate(it) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } private fun generateJavaGeneratedAnnotation(config: CodeGenConfig): CodeGenResult { return if (config.addGeneratedAnnotation) { val retention = AnnotationSpec.builder(java.lang.annotation.Retention::class.java) - .addMember("value", "${'$'}T.${'$'}N", RetentionPolicy::class.java, "CLASS") + .addMember("value", "\$T.\$L", RetentionPolicy::class.java, RetentionPolicy.CLASS.name) .build() val generated = TypeSpec.annotationBuilder(ClassName.get(config.packageName, "Generated")) @@ -283,7 +300,7 @@ class CodeGen(private val config: CodeGenConfig) { val generatedFile = JavaFile.builder(config.packageName, generated).build() CodeGenResult(javaInterfaces = listOf(generatedFile)) } else { - CodeGenResult() + CodeGenResult.EMPTY } } @@ -295,7 +312,7 @@ class CodeGen(private val config: CodeGenConfig) { .filter { config.generateInterfaces || config.generateDataTypes || it.name in requiredTypeCollector.requiredTypes } .map { DataTypeGenerator(config, document).generate(it, findTypeExtensions(it.name, definitions)) - }.fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + }.fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } private fun generateJavaInputType(definitions: Collection>): CodeGenResult { @@ -308,7 +325,7 @@ class CodeGen(private val config: CodeGenConfig) { return inputTypes .map { d -> InputTypeGenerator(config, document).generate(d, findInputExtensions(d.name, definitions), inputTypeDefinitions) - }.fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + }.fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } private fun generateKotlin(): CodeGenResult { @@ -340,7 +357,7 @@ class CodeGen(private val config: CodeGenConfig) { val extensions = findUnionExtensions(it.name, definitions) KotlinUnionTypeGenerator(config).generate(it, extensions) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } val enumsResult = definitions.asSequence() .filterIsInstance() @@ -350,7 +367,7 @@ class CodeGen(private val config: CodeGenConfig) { val extensions = findEnumExtensions(it.name, definitions) KotlinEnumTypeGenerator(config).generate(it, extensions) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } val constantsClass = KotlinConstantsGenerator(config, document).generate() @@ -387,7 +404,7 @@ class CodeGen(private val config: CodeGenConfig) { .addAnnotation( KAnnotationSpec .builder(Retention::class) - .addMember("value = %T.%N", AnnotationRetention::class, "BINARY") + .addMember("value = %T.%L", AnnotationRetention::class, AnnotationRetention.BINARY.name) .build() ) .build() @@ -395,22 +412,10 @@ class CodeGen(private val config: CodeGenConfig) { FileSpec.builder(config.packageName, "Generated").addType(generated).build() CodeGenResult(kotlinInterfaces = listOf(generatedFile)) } else { - CodeGenResult() + CodeGenResult.EMPTY } } - private fun generateKotlinClientEntitiesRepresentations(definitions: Collection>): CodeGenResult { - return if (config.generateClientApi) { - val generatedRepresentations = mutableMapOf() - return definitions.asSequence() - .filterIsInstance() - .filter { it.hasDirective("key") } - .map { d -> - KotlinEntitiesRepresentationTypeGenerator(config, document).generate(d, generatedRepresentations) - }.fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } - } else CodeGenResult() - } - private fun generateKotlinInputTypes(definitions: Collection>): CodeGenResult { val inputTypeDefinitions = definitions .filterIsInstance() @@ -420,7 +425,7 @@ class CodeGen(private val config: CodeGenConfig) { .map { KotlinInputTypeGenerator(config, document).generate(it, findInputExtensions(it.name, definitions), inputTypeDefinitions) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } private fun generateKotlinDataTypes(definitions: Collection>): CodeGenResult { @@ -433,12 +438,12 @@ class CodeGen(private val config: CodeGenConfig) { val extensions = findTypeExtensions(it.name, definitions) KotlinDataTypeGenerator(config, document).generate(it, extensions) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } private fun generateKotlinInterfaceTypes(definitions: Collection>): CodeGenResult { if (!config.generateDataTypes && !config.generateInterfaces) { - return CodeGenResult() + return CodeGenResult.EMPTY } return definitions.asSequence() @@ -448,26 +453,26 @@ class CodeGen(private val config: CodeGenConfig) { val extensions = findInterfaceExtensions(it.name, definitions) KotlinInterfaceTypeGenerator(config, document).generate(it, extensions) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } private fun generateDocFiles(definitions: Collection>): CodeGenResult { if (!config.generateDocs) { - return CodeGenResult() + return CodeGenResult.EMPTY } return definitions.asSequence() .map { DocGenerator(config, document).generate(it) } - .fold(CodeGenResult()) { t: CodeGenResult, u: CodeGenResult -> t.merge(u) } + .fold(CodeGenResult.EMPTY) { result, next -> result.merge(next) } } } class CodeGenConfig( var schemas: Set = emptySet(), var schemaFiles: Set = emptySet(), - var schemaJarFilesFromDependencies: List = emptyList(), + var schemaJarFilesFromDependencies: List = emptyList(), var outputDir: Path = Paths.get("generated"), var examplesOutputDir: Path = Paths.get("generated-examples"), var writeToFiles: Boolean = false, @@ -562,39 +567,32 @@ data class CodeGenResult( val kotlinClientTypes: List = listOf(), val docFiles: List = listOf() ) { + companion object { + val EMPTY = CodeGenResult() + } fun merge(current: CodeGenResult): CodeGenResult { - val javaDataTypes = this.javaDataTypes.plus(current.javaDataTypes) - val javaInterfaces = this.javaInterfaces.plus(current.javaInterfaces) - val javaEnumTypes = this.javaEnumTypes.plus(current.javaEnumTypes) - val javaDataFetchers = this.javaDataFetchers.plus(current.javaDataFetchers) - val javaQueryTypes = this.javaQueryTypes.plus(current.javaQueryTypes) - val clientProjections = this.clientProjections.plus(current.clientProjections).distinct() - val javaConstants = this.javaConstants.plus(current.javaConstants) - val kotlinDataTypes = this.kotlinDataTypes.plus(current.kotlinDataTypes) - val kotlinInputTypes = this.kotlinInputTypes.plus(current.kotlinInputTypes) - val kotlinInterfaces = this.kotlinInterfaces.plus(current.kotlinInterfaces) - val kotlinEnumTypes = this.kotlinEnumTypes.plus(current.kotlinEnumTypes) - val kotlinDataFetchers = this.kotlinDataFetchers.plus(current.kotlinDataFetchers) - val kotlinConstants = this.kotlinConstants.plus(current.kotlinConstants) - val kotlinClientTypes = this.kotlinClientTypes.plus(current.kotlinClientTypes) - val docFiles = this.docFiles.plus(current.docFiles) - + if (current === EMPTY) { + return this + } + if (this === EMPTY) { + return current + } return CodeGenResult( - javaDataTypes = javaDataTypes, - javaInterfaces = javaInterfaces, - javaEnumTypes = javaEnumTypes, - javaDataFetchers = javaDataFetchers, - javaQueryTypes = javaQueryTypes, - clientProjections = clientProjections, - javaConstants = javaConstants, - kotlinDataTypes = kotlinDataTypes, - kotlinInputTypes = kotlinInputTypes, - kotlinInterfaces = kotlinInterfaces, - kotlinEnumTypes = kotlinEnumTypes, - kotlinDataFetchers = kotlinDataFetchers, - kotlinConstants = kotlinConstants, - kotlinClientTypes = kotlinClientTypes, - docFiles = docFiles + javaDataTypes = javaDataTypes.concat(current.javaDataTypes), + javaInterfaces = javaInterfaces.concat(current.javaInterfaces), + javaEnumTypes = javaEnumTypes.concat(current.javaEnumTypes), + javaDataFetchers = javaDataFetchers.concat(current.javaDataFetchers), + javaQueryTypes = javaQueryTypes.concat(current.javaQueryTypes), + clientProjections = clientProjections.concat(current.clientProjections).distinct(), + javaConstants = javaConstants.concat(current.javaConstants), + kotlinDataTypes = kotlinDataTypes.concat(current.kotlinDataTypes), + kotlinInputTypes = kotlinInputTypes.concat(current.kotlinInputTypes), + kotlinInterfaces = kotlinInterfaces.concat(current.kotlinInterfaces), + kotlinEnumTypes = kotlinEnumTypes.concat(current.kotlinEnumTypes), + kotlinDataFetchers = kotlinDataFetchers.concat(current.kotlinDataFetchers), + kotlinConstants = kotlinConstants.concat(current.kotlinConstants), + kotlinClientTypes = kotlinClientTypes.concat(current.kotlinClientTypes), + docFiles = docFiles.concat(current.docFiles) ) } @@ -620,6 +618,16 @@ data class CodeGenResult( .plus(kotlinClientTypes) .toList() } + + private fun List.concat(other: List): List { + if (other.isEmpty()) { + return this + } + if (isEmpty()) { + return other + } + return this + other + } } fun List.filterSkipped(): List { @@ -677,70 +685,26 @@ fun Type<*>.findTypeDefinition( includeBaseTypes: Boolean = false, includeScalarTypes: Boolean = false ): TypeDefinition<*>? { - return when (this) { - is NonNullType -> { - this.type.findTypeDefinition(document, excludeExtensions, includeBaseTypes, includeScalarTypes) - } - is ListType -> { - this.type.findTypeDefinition(document, excludeExtensions, includeBaseTypes, includeScalarTypes) - } - else -> { - if (includeBaseTypes && this.isBaseType()) { - this.findBaseTypeDefinition() + val unwrapped = TypeUtil.unwrapAll(this) + return if (includeBaseTypes && unwrapped.isBaseType()) { + unwrapped.findBaseTypeDefinition() + } else { + document.definitions.asSequence().filterIsInstance>().find { + if (it is ScalarTypeDefinition) { + includeScalarTypes && it.name == unwrapped.name } else { - document.definitions.asSequence().filterIsInstance>().find { - if (it is ScalarTypeDefinition) { - includeScalarTypes && it.name == (this as TypeName).name - } else { - it.name == (this as TypeName).name && (!excludeExtensions || it !is ObjectTypeExtensionDefinition) - } - } + it.name == unwrapped.name && (!excludeExtensions || it !is ObjectTypeExtensionDefinition) } } } } -fun Type<*>.isBaseType(): Boolean { - return when (this) { - is NonNullType -> { - this.type.isBaseType() - } - is ListType -> { - this.type.isBaseType() - } - is TypeName -> { - when (this.name) { - "String", "Boolean", "Float", "Int" -> true - else -> false - } - } - else -> { - false - } - } +private fun TypeName.isBaseType(): Boolean { + return ScalarInfo.isGraphqlSpecifiedScalar(name) } -fun Type<*>.findBaseTypeDefinition(): TypeDefinition<*>? { - return when (this) { - is NonNullType -> { - this.type.findBaseTypeDefinition() - } - is ListType -> { - this.type.findBaseTypeDefinition() - } - is TypeName -> { - when (this.name) { - "String" -> ScalarTypeDefinition.newScalarTypeDefinition().name("String").build() - "Boolean" -> ScalarTypeDefinition.newScalarTypeDefinition().name("Boolean").build() - "Float" -> ScalarTypeDefinition.newScalarTypeDefinition().name("Float").build() - "Int" -> ScalarTypeDefinition.newScalarTypeDefinition().name("Int").build() - else -> null - } - } - else -> { - null - } - } +private fun TypeName.findBaseTypeDefinition(): TypeDefinition<*>? { + return ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS[name] } class CodeGenSchemaParsingException( diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/EntitiesRepresentationTypeGeneratorUtils.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/EntitiesRepresentationTypeGeneratorUtils.kt index c74dcc40c..5b1d43953 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/EntitiesRepresentationTypeGeneratorUtils.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/EntitiesRepresentationTypeGeneratorUtils.kt @@ -41,11 +41,11 @@ object EntitiesRepresentationTypeGeneratorUtils { representationGenerator: RepresentationGenerator ): CodeGenResult { if (config.skipEntityQueries) { - return CodeGenResult() + return CodeGenResult.EMPTY } val representationName = toRepresentationName(definition) if (representationName in generatedRepresentations) { - return CodeGenResult() + return CodeGenResult.EMPTY } val directiveArg = diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ClientApiGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ClientApiGenerator.kt index f42c80b38..2bcd857f0 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ClientApiGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ClientApiGenerator.kt @@ -38,24 +38,23 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document val rootProjection = it.type.findTypeDefinition(document, true)?.let { typeDefinition -> createRootProjection(typeDefinition, it.name.capitalized()) } - ?: CodeGenResult() + ?: CodeGenResult.EMPTY CodeGenResult(javaQueryTypes = listOf(javaFile)).merge(rootProjection) - }.fold(CodeGenResult()) { total, current -> total.merge(current) } + }.fold(CodeGenResult.EMPTY) { total, current -> total.merge(current) } } fun generateEntities(definitions: List): CodeGenResult { if (config.skipEntityQueries) { - return CodeGenResult() + return CodeGenResult.EMPTY } - var entitiesRootProjection = CodeGenResult() // generate for federation types, if present val federatedTypes = definitions.filter { it.hasDirective("key") } if (federatedTypes.isNotEmpty()) { // create entities root projection - entitiesRootProjection = createEntitiesRootProjection(federatedTypes) + return createEntitiesRootProjection(federatedTypes) } - return CodeGenResult().merge(entitiesRootProjection) + return CodeGenResult.EMPTY } private fun createQueryClass(it: FieldDefinition, operation: String, methodNames: MutableSet): JavaFile { @@ -270,7 +269,7 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document .build() ) - if (generatedClasses.contains(clazzName)) return CodeGenResult() else generatedClasses.add(clazzName) + if (generatedClasses.contains(clazzName)) return CodeGenResult.EMPTY else generatedClasses.add(clazzName) val fieldDefinitions = type.fieldDefinitions() + document.definitions.filterIsInstance().filter { it.name == type.name }.flatMap { it.fieldDefinitions } @@ -317,7 +316,7 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document 1 ) } - .fold(CodeGenResult()) { total, current -> total.merge(current) } + .fold(CodeGenResult.EMPTY) { total, current -> total.merge(current) } fieldDefinitions.filterSkipped().forEach { val objectTypeDefinition = it.type.findTypeDefinition(document) @@ -399,7 +398,7 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document .build() ) - if (generatedClasses.contains(clazzName)) return CodeGenResult() else generatedClasses.add(clazzName) + if (generatedClasses.contains(clazzName)) return CodeGenResult.EMPTY else generatedClasses.add(clazzName) val codeGenResult = federatedTypes.map { objTypeDef -> val projectionName = "Entities${objTypeDef.name.capitalized()}KeyProjection" @@ -419,7 +418,7 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document ) val processedEdges = mutableSetOf>() createFragment(objTypeDef, javaType.build(), javaType.build(), "Entities${objTypeDef.name.capitalized()}Key", processedEdges, 0) - }.fold(CodeGenResult()) { total, current -> total.merge(current) } + }.fold(CodeGenResult.EMPTY) { total, current -> total.merge(current) } val javaFile = JavaFile.builder(getPackageName(), javaType.build()).build() return CodeGenResult(clientProjections = listOf(javaFile)).merge(codeGenResult) @@ -432,9 +431,9 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document } concreteTypes.map { addFragmentProjectionMethod(javaType, root, prefix, it, processedEdges, queryDepth) - }.fold(CodeGenResult()) { total, current -> total.merge(current) } + }.fold(CodeGenResult.EMPTY) { total, current -> total.merge(current) } } else { - CodeGenResult() + CodeGenResult.EMPTY } } @@ -443,9 +442,9 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document val memberTypes = type.memberTypes.mapNotNull { it.findTypeDefinition(document, true) }.toList() memberTypes.map { addFragmentProjectionMethod(javaType, rootType, prefix, it, processedEdges, queryDepth) - }.fold(CodeGenResult()) { total, current -> total.merge(current) } + }.fold(CodeGenResult.EMPTY) { total, current -> total.merge(current) } } else { - CodeGenResult() + CodeGenResult.EMPTY } } @@ -475,7 +474,7 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document private fun createFragment(type: ObjectTypeDefinition, parent: TypeSpec, root: TypeSpec, prefix: String, processedEdges: Set>, queryDepth: Int): CodeGenResult { val subProjection = createSubProjectionType(type, parent, root, prefix, processedEdges, queryDepth) - ?: return CodeGenResult() + ?: return CodeGenResult.EMPTY val javaType = subProjection.first val codeGenResult = subProjection.second @@ -518,7 +517,7 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document private fun createSubProjection(type: TypeDefinition<*>, parent: TypeSpec, root: TypeSpec, prefix: String, processedEdges: Set>, queryDepth: Int): CodeGenResult { val subProjection = createSubProjectionType(type, parent, root, prefix, processedEdges, queryDepth) - ?: return CodeGenResult() + ?: return CodeGenResult.EMPTY val javaType = subProjection.first val codeGenResult = subProjection.second @@ -609,7 +608,7 @@ class ClientApiGenerator(private val config: CodeGenConfig, private val document queryDepth + 1 ) } - .fold(CodeGenResult()) { total, current -> total.merge(current) } + .fold(CodeGenResult.EMPTY) { total, current -> total.merge(current) } fieldDefinitions .filterSkipped() diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ConstantsGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ConstantsGenerator.kt index 0830c4a17..fbf0db9d3 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ConstantsGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ConstantsGenerator.kt @@ -26,9 +26,9 @@ import com.netflix.graphql.dgs.codegen.generators.shared.SchemaExtensionsUtils.f import com.netflix.graphql.dgs.codegen.generators.shared.SchemaExtensionsUtils.findInterfaceExtensions import com.netflix.graphql.dgs.codegen.generators.shared.SchemaExtensionsUtils.findTypeExtensions import com.netflix.graphql.dgs.codegen.generators.shared.excludeSchemaTypeExtension +import com.squareup.javapoet.ClassName import com.squareup.javapoet.FieldSpec import com.squareup.javapoet.JavaFile -import com.squareup.javapoet.TypeName import com.squareup.javapoet.TypeSpec import graphql.language.* import javax.lang.model.element.Modifier @@ -48,7 +48,11 @@ class ConstantsGenerator(private val config: CodeGenConfig, private val document val extensions = findTypeExtensions(it.name, document.definitions) val fields = it.fieldDefinitions + extensions.flatMap { ext -> ext.fieldDefinitions } - constantsType.addField(FieldSpec.builder(TypeName.get(String::class.java), "TYPE_NAME").addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer(""""${it.name}"""").build()) + constantsType.addField( + FieldSpec.builder(ClassName.get(String::class.java), "TYPE_NAME") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("\$S", it.name).build() + ) fields.forEach { field -> addFieldNameConstant(constantsType, field.name) @@ -63,13 +67,21 @@ class ConstantsGenerator(private val config: CodeGenConfig, private val document .excludeSchemaTypeExtension() .forEach { val constantsType = createConstantTypeBuilder(config, it.name) - constantsType.addField(FieldSpec.builder(TypeName.get(String::class.java), "TYPE_NAME").addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer(""""${it.name}"""").build()) + constantsType.addField( + FieldSpec.builder(ClassName.get(String::class.java), "TYPE_NAME") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("\$S", it.name).build() + ) + + for (definition in it.inputValueDefinitions) { + addFieldNameConstant(constantsType, definition.name) + } val extensions = findInputExtensions(it.name, document.definitions) - val fields = it.inputValueDefinitions + extensions.flatMap { ext -> ext.inputValueDefinitions } - - fields.forEach { field -> - addFieldNameConstant(constantsType, field.name) + for (extension in extensions) { + for (definition in extension.inputValueDefinitions) { + addFieldNameConstant(constantsType, definition.name) + } } javaType.addType(constantsType.build()) @@ -81,13 +93,21 @@ class ConstantsGenerator(private val config: CodeGenConfig, private val document .forEach { val constantsType = createConstantTypeBuilder(config, it.name) - constantsType.addField(FieldSpec.builder(TypeName.get(String::class.java), "TYPE_NAME").addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer(""""${it.name}"""").build()) + constantsType.addField( + FieldSpec.builder(ClassName.get(String::class.java), "TYPE_NAME") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("\$S", it.name).build() + ) - val extensions = findInterfaceExtensions(it.name, document.definitions) - val merged = it.fieldDefinitions + extensions.flatMap { ext -> ext.fieldDefinitions } + for (definition in it.fieldDefinitions) { + addFieldNameConstant(constantsType, definition.name) + } - merged.forEach { field -> - addFieldNameConstant(constantsType, field.name) + val extensions = findInterfaceExtensions(it.name, document.definitions) + for (extension in extensions) { + for (definition in extension.fieldDefinitions) { + addFieldNameConstant(constantsType, definition.name) + } } javaType.addType(constantsType.build()) @@ -98,17 +118,33 @@ class ConstantsGenerator(private val config: CodeGenConfig, private val document .excludeSchemaTypeExtension() .forEach { val constantsType = createConstantTypeBuilder(config, it.name) - constantsType.addField(FieldSpec.builder(TypeName.get(String::class.java), "TYPE_NAME").addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer(""""${it.name}"""").build()) + constantsType.addField( + FieldSpec.builder(ClassName.get(String::class.java), "TYPE_NAME") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("\$S", it.name).build() + ) } if (document.definitions.any { it is ObjectTypeDefinition && it.name == "Query" }) { - javaType.addField(FieldSpec.builder(TypeName.get(String::class.java), "QUERY_TYPE").addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer(""""Query"""").build()) + javaType.addField( + FieldSpec.builder(ClassName.get(String::class.java), "QUERY_TYPE") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer(""""Query"""").build() + ) } if (document.definitions.any { it is ObjectTypeDefinition && it.name == "Mutation" }) { - javaType.addField(FieldSpec.builder(TypeName.get(String::class.java), "MUTATION_TYPE").addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer(""""Mutation"""").build()) + javaType.addField( + FieldSpec.builder(ClassName.get(String::class.java), "MUTATION_TYPE") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer(""""Mutation"""").build() + ) } if (document.definitions.any { it is ObjectTypeDefinition && it.name == "Subscription" }) { - javaType.addField(FieldSpec.builder(TypeName.get(String::class.java), "SUBSCRIPTION_TYPE").addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer(""""Subscription"""").build()) + javaType.addField( + FieldSpec.builder(ClassName.get(String::class.java), "SUBSCRIPTION_TYPE") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer(""""Subscription"""").build() + ) } val javaFile = JavaFile.builder(config.packageName, javaType.build()).build() @@ -132,10 +168,10 @@ class ConstantsGenerator(private val config: CodeGenConfig, private val document private fun addFieldNameConstant(constantsType: TypeSpec.Builder, fieldName: String) { constantsType.addField( FieldSpec.builder( - TypeName.get(String::class.java), + ClassName.get(String::class.java), ReservedKeywordSanitizer.sanitize(fieldName.capitalized()) ) - .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer(""""$fieldName"""").build() + .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer("\$S", fieldName).build() ) } diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/DataTypeGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/DataTypeGenerator.kt index ad5b0fc00..34b37c60f 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/DataTypeGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/DataTypeGenerator.kt @@ -66,7 +66,7 @@ class DataTypeGenerator(config: CodeGenConfig, document: Document) : BaseDataTyp fun generate(definition: ObjectTypeDefinition, extensions: List): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } logger.info("Generating data type {}", definition.name) @@ -80,7 +80,7 @@ class DataTypeGenerator(config: CodeGenConfig, document: Document) : BaseDataTyp var useInterfaceType = false var overrideGetter = false - var interfaceCodeGenResult = CodeGenResult() + var interfaceCodeGenResult = CodeGenResult.EMPTY if (config.generateInterfaces) { useInterfaceType = true @@ -162,7 +162,7 @@ class InputTypeGenerator(config: CodeGenConfig, document: Document) : BaseDataTy inputTypeDefinitions: List ): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } logger.info("Generating input type {}", definition.name) diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/EntitiesRepresentationTypeGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/EntitiesRepresentationTypeGenerator.kt index 4648848a2..d12b92226 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/EntitiesRepresentationTypeGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/EntitiesRepresentationTypeGenerator.kt @@ -31,6 +31,7 @@ import graphql.language.EnumTypeDefinition import graphql.language.FieldDefinition import graphql.language.InterfaceTypeDefinition import graphql.language.ObjectTypeDefinition +import org.slf4j.Logger import org.slf4j.LoggerFactory @Suppress("UNCHECKED_CAST") @@ -59,9 +60,9 @@ class EntitiesRepresentationTypeGenerator( keyFields: Map ): CodeGenResult { if (generatedRepresentations.containsKey(representationName)) { - return CodeGenResult() + return CodeGenResult.EMPTY } - var fieldsCodeGenAccumulator = CodeGenResult() + var fieldsCodeGenAccumulator = CodeGenResult.EMPTY // generate representations of entity types that have @key, including the __typename field, and the key fields val typeName = Field("__typename", ClassName.get(String::class.java), CodeBlock.of("\$S", definitionName)) val fieldDefinitions = @@ -84,7 +85,7 @@ class EntitiesRepresentationTypeGenerator( .replace(type.name, fieldTypeRepresentationName) if (generatedRepresentations.containsKey(fieldTypeRepresentationName)) { - logger.trace("Representation fo $fieldTypeRepresentationName was already generated.") + logger.trace("Representation for {} was already generated.", fieldTypeRepresentationName) } else { logger.debug("Generating entity representation {} ...", fieldTypeRepresentationName) val fieldTypeRepresentation = generateRepresentations( @@ -106,7 +107,7 @@ class EntitiesRepresentationTypeGenerator( val parentRepresentationCodeGen = super.generate( name = representationName, interfaces = emptyList(), - fields = fieldDefinitions.plus(typeName), + fields = fieldDefinitions + typeName, description = null, directives = emptyList() ) @@ -116,7 +117,6 @@ class EntitiesRepresentationTypeGenerator( } companion object { - private val logger: org.slf4j.Logger = - LoggerFactory.getLogger(EntitiesRepresentationTypeGenerator::class.java) + private val logger: Logger = LoggerFactory.getLogger(EntitiesRepresentationTypeGenerator::class.java) } } diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/EnumTypeGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/EnumTypeGenerator.kt index 235bafbb7..40eaab1f8 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/EnumTypeGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/EnumTypeGenerator.kt @@ -35,7 +35,7 @@ class EnumTypeGenerator(private val config: CodeGenConfig) { fun generate(definition: EnumTypeDefinition, extensions: List): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } logger.info("Generating enum type ${definition.name}") diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/InterfaceGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/InterfaceGenerator.kt index e0590d17e..391f97fc4 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/InterfaceGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/InterfaceGenerator.kt @@ -44,7 +44,7 @@ class InterfaceGenerator(private val config: CodeGenConfig, private val document extensions: List ): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } logger.info("Generating type ${definition.name}") diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/TypeUtils.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/TypeUtils.kt index 59b6e1876..10aa057ed 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/TypeUtils.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/TypeUtils.kt @@ -34,21 +34,26 @@ import java.util.* import com.squareup.javapoet.TypeName as JavaTypeName class TypeUtils(private val packageName: String, private val config: CodeGenConfig, private val document: Document) { - private val commonScalars = mapOf( - "LocalTime" to ClassName.get(LocalTime::class.java), - "LocalDate" to ClassName.get(LocalDate::class.java), - "LocalDateTime" to ClassName.get(LocalDateTime::class.java), - "TimeZone" to ClassName.get(String::class.java), - "Date" to ClassName.get(LocalDate::class.java), - "DateTime" to ClassName.get(OffsetDateTime::class.java), - "Currency" to ClassName.get(Currency::class.java), - "Instant" to ClassName.get(Instant::class.java), - "RelayPageInfo" to ClassName.get(PageInfo::class.java), - "PageInfo" to ClassName.get(PageInfo::class.java), - "PresignedUrlResponse" to ClassName.get("com.netflix.graphql.types.core.resolvers", "PresignedUrlResponse"), - "Header" to ClassName.get("com.netflix.graphql.types.core.resolvers", "PresignedUrlResponse", "Header"), - "Upload" to ClassName.get("org.springframework.web.multipart", "MultipartFile") - ) + + companion object { + private val commonScalars = mapOf( + "LocalTime" to ClassName.get(LocalTime::class.java), + "LocalDate" to ClassName.get(LocalDate::class.java), + "LocalDateTime" to ClassName.get(LocalDateTime::class.java), + "TimeZone" to ClassName.get(String::class.java), + "Date" to ClassName.get(LocalDate::class.java), + "DateTime" to ClassName.get(OffsetDateTime::class.java), + "Currency" to ClassName.get(Currency::class.java), + "Instant" to ClassName.get(Instant::class.java), + "RelayPageInfo" to ClassName.get(PageInfo::class.java), + "PageInfo" to ClassName.get(PageInfo::class.java), + "PresignedUrlResponse" to ClassName.get("com.netflix.graphql.types.core.resolvers", "PresignedUrlResponse"), + "Header" to ClassName.get("com.netflix.graphql.types.core.resolvers", "PresignedUrlResponse", "Header"), + "Upload" to ClassName.get("org.springframework.web.multipart", "MultipartFile") + ) + const val getClass = "getClass" + const val setClass = "setClass" + } fun qualifyName(name: String): String { return "$packageName.$name" @@ -251,9 +256,4 @@ class TypeUtils(private val packageName: String, private val config: CodeGenConf private fun isFieldTypeDefinedInDocument(name: String): Boolean = document.definitions.filterIsInstance().any { e -> e.name == name } || document.definitions.filterIsInstance().any { e -> e.name == name } - - companion object { - const val getClass = "getClass" - const val setClass = "setClass" - } } diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/UnionTypeGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/UnionTypeGenerator.kt index 6e514ae62..f2f465e0d 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/UnionTypeGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/UnionTypeGenerator.kt @@ -37,14 +37,14 @@ class UnionTypeGenerator(private val config: CodeGenConfig, private val document fun generate(definition: UnionTypeDefinition, extensions: List): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } val javaType = TypeSpec.interfaceBuilder(definition.name) .addOptionalGeneratedAnnotation(config) .addModifiers(Modifier.PUBLIC) - val memberTypes = definition.memberTypes.plus(extensions.flatMap { it.memberTypes }).asSequence() + val memberTypes = definition.memberTypes.asSequence().plus(extensions.asSequence().flatMap { it.memberTypes }) .filterIsInstance() .map { member -> typeUtils.findJavaInterfaceName(member.name, packageName) diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinDataTypeGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinDataTypeGenerator.kt index 21603f431..1bab79f69 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinDataTypeGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinDataTypeGenerator.kt @@ -53,7 +53,7 @@ class KotlinDataTypeGenerator(config: CodeGenConfig, document: Document) : fun generate(definition: ObjectTypeDefinition, extensions: List): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } logger.info("Generating data type {}", definition.name) @@ -90,7 +90,10 @@ class KotlinDataTypeGenerator(config: CodeGenConfig, document: Document) : class KotlinInputTypeGenerator(config: CodeGenConfig, document: Document) : AbstractKotlinDataTypeGenerator(packageName = config.packageNameTypes, config = config, document = document) { - private val logger: Logger = LoggerFactory.getLogger(InputTypeGenerator::class.java) + + companion object { + private val logger: Logger = LoggerFactory.getLogger(InputTypeGenerator::class.java) + } fun generate( definition: InputObjectTypeDefinition, @@ -98,10 +101,10 @@ class KotlinInputTypeGenerator(config: CodeGenConfig, document: Document) : inputTypeDefinitions: Collection ): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } - logger.info("Generating input type ${definition.name}") + logger.info("Generating input type {}", definition.name) val fields = definition.inputValueDefinitions .filter(ReservedKeywordFilter.filterInvalidNames) diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinEntitiesRepresentationTypeGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinEntitiesRepresentationTypeGenerator.kt index f1666b427..9c0cfc27d 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinEntitiesRepresentationTypeGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinEntitiesRepresentationTypeGenerator.kt @@ -35,6 +35,7 @@ import graphql.language.EnumTypeDefinition import graphql.language.FieldDefinition import graphql.language.InterfaceTypeDefinition import graphql.language.ObjectTypeDefinition +import org.slf4j.Logger import org.slf4j.LoggerFactory class KotlinEntitiesRepresentationTypeGenerator(config: CodeGenConfig, document: Document) : @@ -60,9 +61,9 @@ class KotlinEntitiesRepresentationTypeGenerator(config: CodeGenConfig, document: keyFields: Map ): CodeGenResult { if (representationName in generatedRepresentations) { - return CodeGenResult() + return CodeGenResult.EMPTY } - var fieldsCodeGenAccumulator = CodeGenResult() + var fieldsCodeGenAccumulator = CodeGenResult.EMPTY // generate representations of entity types that have @key, including the __typename field, and the key fields val typeName = Field("__typename", STRING, false, CodeBlock.of("%S", definitionName)) val fieldDefinitions = @@ -85,7 +86,7 @@ class KotlinEntitiesRepresentationTypeGenerator(config: CodeGenConfig, document: .replace(type.name, fieldTypeRepresentationName).removeSuffix("?") if (generatedRepresentations.containsKey(fieldTypeRepresentationName)) { - logger.trace("Representation fo $fieldTypeRepresentationName was already generated.") + logger.trace("Representation for {} was already generated.", fieldTypeRepresentationName) } else { logger.debug("Generating entity representation {} ...", fieldTypeRepresentationName) val fieldTypeRepresentation = generateRepresentations( @@ -134,7 +135,6 @@ class KotlinEntitiesRepresentationTypeGenerator(config: CodeGenConfig, document: } companion object { - private val logger: org.slf4j.Logger = - LoggerFactory.getLogger(KotlinEntitiesRepresentationTypeGenerator::class.java) + private val logger: Logger = LoggerFactory.getLogger(KotlinEntitiesRepresentationTypeGenerator::class.java) } } diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinEnumTypeGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinEnumTypeGenerator.kt index 4c48ec115..eaa098747 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinEnumTypeGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinEnumTypeGenerator.kt @@ -36,7 +36,7 @@ class KotlinEnumTypeGenerator(private val config: CodeGenConfig) { fun generate(definition: EnumTypeDefinition, extensions: List): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } logger.info("Generating enum type ${definition.name}") diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinInterfaceTypeGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinInterfaceTypeGenerator.kt index 23f7261f6..7cc8f3321 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinInterfaceTypeGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinInterfaceTypeGenerator.kt @@ -41,7 +41,7 @@ class KotlinInterfaceTypeGenerator(private val config: CodeGenConfig, private va extensions: List ): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } logger.info("Generating type {}", definition.name) diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinUnionTypeGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinUnionTypeGenerator.kt index 33b5e18a4..18bb93bfc 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinUnionTypeGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/kotlin/KotlinUnionTypeGenerator.kt @@ -34,7 +34,7 @@ class KotlinUnionTypeGenerator(private val config: CodeGenConfig) { fun generate(definition: UnionTypeDefinition, extensions: List): CodeGenResult { if (definition.shouldSkip(config)) { - return CodeGenResult() + return CodeGenResult.EMPTY } val interfaceBuilder = TypeSpec.interfaceBuilder(definition.name) diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/shared/DocGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/shared/DocGenerator.kt index 681dcfd07..ec878f25b 100644 --- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/shared/DocGenerator.kt +++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/shared/DocGenerator.kt @@ -28,39 +28,35 @@ import kotlinx.serialization.json.* import java.math.BigDecimal import java.math.BigInteger -@Suppress("FoldInitializerAndIfToElvis") class DocGenerator(private val config: CodeGenConfig, private val document: Document) { private val gqlParser = Parser() - private val packageName = config.packageNameDocs fun generate( definition: Definition<*> ): CodeGenResult { if (definition !is ObjectTypeDefinition) { - return CodeGenResult() + return CodeGenResult.EMPTY } val docFiles: MutableList = mutableListOf() - if (definition.name.equals("Query")) { + if (definition.name == "Query") { definition.fieldDefinitions.forEach { - val markdownText: String? = getFieldDefinitionMarkdown(it, definition) - if (markdownText != null) { - docFiles.add(DocFileSpec.get("${definition.name}.${it.name}", markdownText)) - } + val markdownText = getFieldDefinitionMarkdown(it, definition) + docFiles += DocFileSpec.get("${definition.name}.${it.name}", markdownText) } } if (definition.directivesByName["key"] != null) { val entitiesMarkdown: String? = getEntitiesMarkdown(definition) if (entitiesMarkdown != null) { - docFiles.add(DocFileSpec.get("Entities.${definition.name}", entitiesMarkdown)) + docFiles += DocFileSpec.get("Entities.${definition.name}", entitiesMarkdown) } } return CodeGenResult(docFiles = docFiles) } - private fun getFieldDefinitionMarkdown(field: FieldDefinition, definition: ObjectTypeDefinition): String? { + private fun getFieldDefinitionMarkdown(field: FieldDefinition, definition: ObjectTypeDefinition): String { return """ |# ${definition.name}.${field.name}: ${AstPrinter.printAst(field.type)} ${if (field.inputValueDefinitions.size > 0) { @@ -132,10 +128,8 @@ class DocGenerator(private val config: CodeGenConfig, private val document: Docu private fun getExampleEntitiesQueryVariables(definition: ObjectTypeDefinition): String? { val representations: MutableList = mutableListOf() - val fieldsArgument: Argument? = definition.getDirectives("key")?.get(0)?.getArgument("fields") - if (fieldsArgument == null) { - return null - } + val fieldsArgument: Argument = definition.getDirectives("key")?.get(0)?.getArgument("fields") + ?: return null if (fieldsArgument.value is StringValue) { val strValue: StringValue = fieldsArgument.value as StringValue @@ -169,15 +163,17 @@ class DocGenerator(private val config: CodeGenConfig, private val document: Docu return JsonObject(map) } - var fieldValue: MutableMap? + val fieldValue: Map? if (definition is ObjectTypeDefinition) { val gqlValue: Value<*> = getMockGQLValue(definition.fieldDefinitions.first { it.name.equals(field.name) }?.type) val mockedValue: JsonElement = toJsonPrimitive(gqlValue) - fieldValue = mutableMapOf(field.name to mockedValue) - fieldValue.put("__typename", JsonPrimitive(definition.name)) + fieldValue = mapOf( + field.name to mockedValue, + "__typename" to JsonPrimitive(definition.name) + ) } else { - fieldValue = mutableMapOf(field.name to JsonPrimitive("foo")) + fieldValue = mapOf(field.name to JsonPrimitive("foo")) } return JsonObject(fieldValue)