Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/definitions/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ export function buildObjectTypeDefinition(
node.fields?.some((fieldNode) => fieldNode.arguments?.length),
);
if (shouldGenerateFunctions) {
const fieldsWithNoArguments = node.fields?.filter(
const atLeastOneFieldHasNoArguments = node.fields?.some(
(fieldNode) => !fieldNode.arguments?.length,
);
const constructor =
!typeInResolverInterfacesConfig && fieldsWithNoArguments?.length
? `(\n${fieldsWithNoArguments
.map((fieldNode) => {
!typeInResolverInterfacesConfig && atLeastOneFieldHasNoArguments
? `(\n${node.fields
?.map((fieldNode) => {
const typeMetadata = buildTypeMetadata(
fieldNode.type,
schema,
Expand All @@ -87,6 +87,8 @@ export function buildObjectTypeDefinition(
schema,
config,
typeMetadata,
shouldGenerateFunctions,
true,
);
})
.join(",\n")}\n)`
Expand Down
41 changes: 32 additions & 9 deletions src/helpers/build-field-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,18 @@ export function buildFieldDefinition(
config: CodegenConfigWithDefaults,
typeMetadata: TypeMetadata,
shouldGenerateFunctions?: boolean,
isConstructorField?: boolean,
) {
const modifier = buildFieldModifier(node, fieldNode, schema, config);
const fieldArguments = buildFieldArguments(node, fieldNode, schema, config);
const modifier = buildFieldModifier(
node,
fieldNode,
schema,
config,
isConstructorField,
);
const fieldArguments = isConstructorField
? ""
: buildFieldArguments(node, fieldNode, schema, config);
const fieldDefinition = `${modifier} ${fieldNode.name.value}${fieldArguments}`;
const annotations = buildAnnotations({
config,
Expand All @@ -49,19 +58,28 @@ export function buildFieldDefinition(
);
}

const notImplementedError = ` = throw NotImplementedError("${node.name.value}.${fieldNode.name.value} must be implemented.")`;
const defaultFunctionValue = `${typeMetadata.isNullable ? "?" : ""}${notImplementedError}`;
const defaultValue = shouldGenerateFunctions
? defaultFunctionValue
: typeMetadata.defaultValue;
const defaultDefinition = `${typeMetadata.typeName}${defaultValue}`;
const notImplementedError = `throw NotImplementedError("${node.name.value}.${fieldNode.name.value} must be implemented.")`;
const atLeastOneFieldHasNoArguments = node.fields?.some(
(fieldNode) => !fieldNode.arguments?.length,
);
const typeInResolverInterfacesConfig = findTypeInResolverInterfacesConfig(
node,
config,
);
const defaultImplementation =
!typeInResolverInterfacesConfig && atLeastOneFieldHasNoArguments
? fieldNode.name.value
: notImplementedError;
const defaultFunctionValue = `${typeMetadata.isNullable ? "?" : ""} = ${defaultImplementation}`;
const defaultValue =
shouldGenerateFunctions && !isConstructorField
? defaultFunctionValue
: typeMetadata.defaultValue;
const defaultDefinition = `${typeMetadata.typeName}${defaultValue}`;

const isCompletableFuture =
typeInResolverInterfacesConfig?.classMethods === "COMPLETABLE_FUTURE";
const completableFutureDefinition = `java.util.concurrent.CompletableFuture<${typeMetadata.typeName}${typeMetadata.isNullable ? "?" : ""}>${notImplementedError}`;
const completableFutureDefinition = `java.util.concurrent.CompletableFuture<${typeMetadata.typeName}${typeMetadata.isNullable ? "?" : ""}> = ${defaultImplementation}`;
const field = indent(
`${fieldDefinition}: ${isCompletableFuture ? completableFutureDefinition : defaultDefinition}`,
2,
Expand All @@ -74,6 +92,7 @@ function buildFieldModifier(
fieldNode: FieldDefinitionNode,
schema: GraphQLSchema,
config: CodegenConfigWithDefaults,
isConstructorField?: boolean,
) {
const typeInResolverInterfacesConfig = findTypeInResolverInterfacesConfig(
node,
Expand All @@ -84,6 +103,10 @@ function buildFieldModifier(
fieldNode,
schema,
);

if (isConstructorField && fieldNode.arguments?.length) {
return "private val";
}
if (!typeInResolverInterfacesConfig && !fieldNode.arguments?.length) {
return shouldOverrideField ? "override val" : "val";
}
Expand Down
7 changes: 6 additions & 1 deletion test/integration/Query.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,10 @@ import graphql.schema.DataFetchingEnvironment
import test.integration.Query as QueryInterface

class IntegrationTestQuery() : Query, QueryInterface() {
override fun testQuery(dataFetchingEnvironment: DataFetchingEnvironment): SomeType = SomeType()
override fun testQuery1(dataFetchingEnvironment: DataFetchingEnvironment): SomeType = SomeType()
override fun testQuery2(dataFetchingEnvironment: DataFetchingEnvironment): SomeHybridType =
SomeHybridType(
someField = "test",
someField2 = "test"
)
}
8 changes: 7 additions & 1 deletion test/integration/expected.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ directive @specifiedBy(
) on SCALAR

type Query {
testQuery: SomeType!
testQuery1: SomeType!
testQuery2: SomeHybridType!
}

type SomeHybridType {
someField: String!
someField2(input: String!): String
}

type SomeType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ open class TypeWithOnlyFieldArgs {
@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.OBJECT])
open class HybridType(
val nullableField: String? = null,
val nonNullableField: String
val nonNullableField: String,
private val nullableResolver: String? = null,
private val nonNullableResolver: String
) {
open fun nullableResolver(arg: String, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String? = throw NotImplementedError("HybridType.nullableResolver must be implemented.")
open fun nonNullableResolver(arg: InputTypeForResolver, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String = throw NotImplementedError("HybridType.nonNullableResolver must be implemented.")
open fun nullableResolver(arg: String, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String? = nullableResolver
open fun nonNullableResolver(arg: InputTypeForResolver, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String = nonNullableResolver
}

@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.INPUT_OBJECT])
Expand All @@ -36,8 +38,10 @@ open class TypeImplementingInterface(
val booleanField1: Boolean? = null,
val booleanField2: Boolean = false,
val integerField1: Int? = null,
val integerField2: Int
val integerField2: Int,
private val nullableListResolver: List<String?>? = null,
private val nonNullableListResolver: List<String> = emptyList()
) : HybridInterface {
override fun nullableListResolver(arg1: Int?, arg2: Int, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): List<String?>? = throw NotImplementedError("TypeImplementingInterface.nullableListResolver must be implemented.")
override fun nonNullableListResolver(arg1: Int, arg2: Int?, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): List<String> = throw NotImplementedError("TypeImplementingInterface.nonNullableListResolver must be implemented.")
override fun nullableListResolver(arg1: Int?, arg2: Int, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): List<String?>? = nullableListResolver
override fun nonNullableListResolver(arg1: Int, arg2: Int?, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): List<String> = nonNullableListResolver
}
10 changes: 9 additions & 1 deletion test/unit/should_honor_resolverInterfaces_config/expected.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,22 @@ import com.expediagroup.graphql.generator.annotations.*

@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.OBJECT])
open class MyIncludedResolverType {
open fun nullableField(dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String? = throw NotImplementedError("MyIncludedResolverType.nullableField must be implemented.")
open fun nullableField(dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): MyChildType? = throw NotImplementedError("MyIncludedResolverType.nullableField must be implemented.")
open fun nonNullableField(dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String = throw NotImplementedError("MyIncludedResolverType.nonNullableField must be implemented.")
open fun nullableResolver(arg: String, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String? = throw NotImplementedError("MyIncludedResolverType.nullableResolver must be implemented.")
open fun nonNullableResolver(arg: String, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String = throw NotImplementedError("MyIncludedResolverType.nonNullableResolver must be implemented.")
open fun nullableListResolver(arg1: Int? = null, arg2: Int, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): List<String?>? = throw NotImplementedError("MyIncludedResolverType.nullableListResolver must be implemented.")
open fun nonNullableListResolver(arg1: Int, arg2: Int? = null, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): List<String> = throw NotImplementedError("MyIncludedResolverType.nonNullableListResolver must be implemented.")
}

@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.OBJECT])
open class MyChildType(
val field: String? = null,
private val field2: String? = null
) {
open fun field2(arg: String, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String? = field2
}

@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.OBJECT])
open class MyIncludedResolverTypeWithNoFieldArgs {
open fun nullableField(dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String? = throw NotImplementedError("MyIncludedResolverTypeWithNoFieldArgs.nullableField must be implemented.")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
type MyIncludedResolverType {
nullableField: String
nullableField: MyChildType
nonNullableField: String!
nullableResolver(arg: String!): String
nonNullableResolver(arg: String!): String!
nullableListResolver(arg1: Int, arg2: Int!): [String]
nonNullableListResolver(arg1: Int!, arg2: Int): [String!]!
}

type MyChildType {
field: String
field2(arg: String!): String
}

type MyIncludedResolverTypeWithNoFieldArgs {
nullableField: String
nonNullableField: String!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ data class FederatedType(
@com.expediagroup.graphql.generator.federation.directives.KeyDirective(com.expediagroup.graphql.generator.federation.directives.FieldSet("some other field"))
@GraphQLValidObjectLocations(locations = [GraphQLValidObjectLocations.Locations.OBJECT])
open class FederatedTypeResolver(
private val field: String,
@com.expediagroup.graphql.generator.federation.directives.ExternalDirective
val field2: String? = null
) {
open fun field(arg: String, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String = throw NotImplementedError("FederatedTypeResolver.field must be implemented.")
open fun field(arg: String, dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment): String = field
}