Skip to content

Commit

Permalink
Merge pull request #519 from Netflix/fix-constructor
Browse files Browse the repository at this point in the history
Fix constructor
  • Loading branch information
srinivasankavitha authored Jan 26, 2023
2 parents c2f7376 + 3b66fdd commit 4cd0b11
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ data class CodeGenConfig(
/** If enabled, the names of the classes available via the DgsConstant class will be snake cased.*/
val snakeCaseConstantNames: Boolean = false,
val generateInterfaceSetters: Boolean = true,
val generateInterfaceMethodsForInterfaceFields: Boolean = false,
val includeImports: Map<String, String> = emptyMap(),
val includeEnumImports: Map<String, Map<String, String>> = emptyMap(),
val includeClassImports: Map<String, Map<String, String>> = emptyMap(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class DataTypeGenerator(config: CodeGenConfig, document: Document) : BaseDataTyp
.map {
Field(
it.name,
typeUtils.findReturnType(it.type, useInterfaceType),
typeUtils.findReturnType(it.type, useInterfaceType, true),
overrideGetter = overrideGetter,
description = it.description,
directives = it.directives
Expand All @@ -97,7 +97,7 @@ class DataTypeGenerator(config: CodeGenConfig, document: Document) : BaseDataTyp
extensions.flatMap { it.fieldDefinitions }.filterSkipped().map {
Field(
it.name,
typeUtils.findReturnType(it.type, useInterfaceType),
typeUtils.findReturnType(it.type, useInterfaceType, true),
overrideGetter = overrideGetter,
description = it.description,
directives = it.directives
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class InterfaceGenerator(private val config: CodeGenConfig, private val document
// implementation classes. This is not an issue if the overridden field has the same base type,
// however.
// Ref: https://github.com/graphql/graphql-js/issues/776
if (!isFieldAnInterface(it)) {
if (!isFieldAnInterface(it) || config.generateInterfaceMethodsForInterfaceFields) {
addInterfaceMethod(it, javaType)
}
}
Expand Down Expand Up @@ -110,7 +110,7 @@ class InterfaceGenerator(private val config: CodeGenConfig, private val document
}

private fun addInterfaceMethod(fieldDefinition: FieldDefinition, javaType: TypeSpec.Builder) {
val returnType = typeUtils.findReturnType(fieldDefinition.type, useInterfaceType)
val returnType = typeUtils.findReturnType(fieldDefinition.type, useInterfaceType, true)

val fieldName = fieldDefinition.name
val getterBuilder = MethodSpec.methodBuilder(typeUtils.transformIfDefaultClassMethodExists("get${fieldName.capitalized()}", TypeUtils.Companion.getClass))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class TypeUtils(private val packageName: String, private val config: CodeGenConf
if (useWildcardType) {
if (typeName is ClassName) {
if (document.definitions.filterIsInstance<ObjectTypeDefinition>()
.any { e -> "I${e.name}" == typeName.simpleName() }
.any { e -> "I${e.name}" == typeName.simpleName() } || (config.generateInterfaces && document.definitions.filterIsInstance<InterfaceTypeDefinition>().any { e -> "${e.name}" == typeName.simpleName() })
) {
canUseWildcardType = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2416,6 +2416,121 @@ class CodeGenTest {
assertCompilesJava(dataTypes + interfaces)
}

@Test
fun generateInterfaceMethodsForInterfaceFields() {
val schema = """
interface Fruit {
seeds: [Seed]
}
interface FruitCategory {
color: String
fruit: Fruit
}
type Apple implements Fruit {
seeds: [Seed]
}
type Seed {
shape: String
}
""".trimIndent()

val result = CodeGen(
CodeGenConfig(
schemas = setOf(schema),
packageName = basePackageName,
generateInterfaceMethodsForInterfaceFields = true
)
).generate()

val interfaces = result.javaInterfaces
val dataTypes = result.javaDataTypes

val fruit = interfaces[0]
assertThat(fruit.typeSpec.name).isEqualTo("Fruit")
assertThat(fruit.typeSpec.fieldSpecs).isEmpty()
assertThat(fruit.typeSpec.methodSpecs.size).isEqualTo(2)
assertThat(fruit.typeSpec.methodSpecs[0].name).isEqualTo("getSeeds")
assertThat(fruit.typeSpec.methodSpecs[1].name).isEqualTo("setSeeds")

val category = interfaces[1]
assertThat(category.typeSpec.name).isEqualTo("FruitCategory")
assertThat(category.typeSpec.fieldSpecs).isEmpty()
assertThat(category.typeSpec.methodSpecs.size).isEqualTo(4)
assertThat(category.typeSpec.methodSpecs[0].name).isEqualTo("getColor")
assertThat(category.typeSpec.methodSpecs[1].name).isEqualTo("setColor")
assertThat(category.typeSpec.methodSpecs[2].name).isEqualTo("getFruit")
assertThat(category.typeSpec.methodSpecs[3].name).isEqualTo("setFruit")

assertCompilesJava(dataTypes + interfaces)
}

@Test
fun generateInterfacesWithMethodsForInterfaceFields() {
val schema = """
interface Fruit {
seeds: [Seed]
}
interface FruitCategory {
color: String
fruit: Fruit
}
type Apple implements Fruit {
seeds: [Seed]
}
type Seed {
shape: String
}
""".trimIndent()

val result = CodeGen(
CodeGenConfig(
schemas = setOf(schema),
packageName = basePackageName,
generateInterfaceMethodsForInterfaceFields = true,
generateInterfaces = true
)
).generate()

val interfaces = result.javaInterfaces
val dataTypes = result.javaDataTypes

val iapple = interfaces[0]
assertThat(iapple.typeSpec.name).isEqualTo("IApple")

val iseed = interfaces[1]
assertThat(iseed.typeSpec.name).isEqualTo("ISeed")
assertThat(iseed.typeSpec.fieldSpecs).isEmpty()
assertThat(iseed.typeSpec.methodSpecs.size).isEqualTo(1)
assertThat(iseed.typeSpec.methodSpecs[0].name).isEqualTo("getShape")

val fruit = interfaces[2]
assertThat(fruit.typeSpec.name).isEqualTo("Fruit")
assertThat(fruit.typeSpec.fieldSpecs).isEmpty()
assertThat(fruit.typeSpec.methodSpecs.size).isEqualTo(2)
assertThat(fruit.typeSpec.methodSpecs[0].name).isEqualTo("getSeeds")
val parameterizedTypeName = fruit.typeSpec.methodSpecs[0].returnType as ParameterizedTypeName
val wildcardTypeName = parameterizedTypeName.typeArguments[0] as WildcardTypeName
assertThat(wildcardTypeName.upperBounds[0]).extracting("simpleName").isEqualTo("ISeed")
assertThat(fruit.typeSpec.methodSpecs[1].name).isEqualTo("setSeeds")

val category = interfaces[3]
assertThat(category.typeSpec.name).isEqualTo("FruitCategory")
assertThat(category.typeSpec.fieldSpecs).isEmpty()
assertThat(category.typeSpec.methodSpecs.size).isEqualTo(4)
assertThat(category.typeSpec.methodSpecs[0].name).isEqualTo("getColor")
assertThat(category.typeSpec.methodSpecs[1].name).isEqualTo("setColor")
assertThat(category.typeSpec.methodSpecs[2].name).isEqualTo("getFruit")
assertThat(category.typeSpec.methodSpecs[3].name).isEqualTo("setFruit")

assertCompilesJava(dataTypes + interfaces)
}

@Test
fun generateObjectTypeInterfaceWithInterfaceInheritance() {
val schema = """
Expand Down Expand Up @@ -2669,7 +2784,8 @@ class CodeGenTest {
assertThat(moviePage.typeSpec.fieldSpecs).extracting("name").containsExactly("items")
parameterizedTypeName = moviePage.typeSpec.fieldSpecs[0].type as ParameterizedTypeName
assertThat(parameterizedTypeName.rawType).extracting("simpleName").isEqualTo("List")
assertThat(parameterizedTypeName.typeArguments[0]).extracting("simpleName").isEqualTo("IMovie")
val movieTypeName = parameterizedTypeName.typeArguments[0] as WildcardTypeName
assertThat(movieTypeName.upperBounds[0]).extracting("simpleName").isEqualTo("IMovie")

val genre = dataTypes[2]
assertThat(genre.typeSpec.name).isEqualTo("Genre")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ import java.io.File
import java.nio.file.Paths
import java.util.*

@CacheableTask
open class GenerateJavaTask : DefaultTask() {
@Input
var generatedSourcesDir: String = project.buildDir.absolutePath

@PathSensitive(PathSensitivity.RELATIVE)
@InputFiles
var schemaPaths = mutableListOf<Any>("${project.projectDir}/src/main/resources/schema")

Expand Down Expand Up @@ -83,6 +81,9 @@ open class GenerateJavaTask : DefaultTask() {
@Input
var generateInterfaceSetters = true

@Input
var generateInterfaceMethodsForInterfaceFields = false

@Input
var implementSerializable = false

Expand Down Expand Up @@ -181,6 +182,7 @@ open class GenerateJavaTask : DefaultTask() {
generateKotlinClosureProjections = generateKotlinClosureProjections,
generateInterfaces = generateInterfaces,
generateInterfaceSetters = generateInterfaceSetters,
generateInterfaceMethodsForInterfaceFields = generateInterfaceMethodsForInterfaceFields,
typeMapping = typeMapping,
includeQueries = includeQueries.toSet(),
includeMutations = includeMutations.toSet(),
Expand Down

0 comments on commit 4cd0b11

Please sign in to comment.