Skip to content

Commit 54f5d62

Browse files
authored
Merge pull request #916 from graphql-java-kickstart/feature/863-reject-repeated-extensions
Reject fields, values and members that a type and its extensions declare twice
2 parents 296ac4b + 058575a commit 54f5d62

2 files changed

Lines changed: 161 additions & 172 deletions

File tree

‎src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt‎

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ class SchemaParser internal constructor(
173173
val extensions = typeExtensions.extensionsOf<ObjectTypeExtensionDefinition>(name)
174174
val directives = sdlDirectives.directivesOf(objectDefinition, extensions)
175175
val fieldDefinitions = objectDefinition.withExtensions(typeExtensions).flatMap { it.fieldDefinitions }
176-
warnRepeatedFields(name, fieldDefinitions)
176+
rejectRepeated(name, "field", fieldDefinitions)
177177
val builder = GraphQLObjectType.newObject()
178178
.name(name)
179179
.definition(objectDefinition)
@@ -212,8 +212,8 @@ class SchemaParser internal constructor(
212212
inputObjectsInProgress: MutableSet<String>): GraphQLInputObjectType {
213213
val extensionDefinitions = typeExtensions.extensionsOf<InputObjectTypeExtensionDefinition>(definition.name)
214214
val directives = sdlDirectives.directivesOf(definition, extensionDefinitions)
215-
val fieldDefinitions = (extensionDefinitions + definition).flatMap { it.inputValueDefinitions }
216-
warnRepeatedFields(definition.name, fieldDefinitions)
215+
val inputValueDefinitions = definition.withExtensions(typeExtensions).flatMap { it.inputValueDefinitions }
216+
rejectRepeated(definition.name, "field", inputValueDefinitions)
217217

218218
inputObjectsInProgress.add(definition.name)
219219

@@ -224,7 +224,7 @@ class SchemaParser internal constructor(
224224
.description(getDocumentation(definition, options))
225225
.withSdlDirectives(directives, INPUT_OBJECT)
226226
.apply {
227-
fieldDefinitions.forEach { fieldDefinition ->
227+
inputValueDefinitions.forEach { fieldDefinition ->
228228
field(
229229
GraphQLInputObjectField.newInputObjectField()
230230
.name(fieldDefinition.name)
@@ -252,15 +252,15 @@ class SchemaParser internal constructor(
252252
val extensions = typeExtensions.extensionsOf<EnumTypeExtensionDefinition>(name)
253253
val directives = sdlDirectives.directivesOf(definition, extensions)
254254
val values = definition.withExtensions(typeExtensions).flatMap { it.enumValueDefinitions }
255-
warnRepeated(name, "value", values.map { it.name })
255+
rejectRepeated(name, "value", values)
256256
val builder = GraphQLEnumType.newEnum()
257257
.name(name)
258258
.definition(definition)
259259
.extensionDefinitions(extensions)
260260
.description(getDocumentation(definition, options))
261261
.withSdlDirectives(directives, ENUM)
262262
.apply {
263-
values.distinctBy { it.name }.forEach { valueDefinition ->
263+
values.forEach { valueDefinition ->
264264
val enumName = valueDefinition.name
265265
val enumValue = if (enumClass == null) {
266266
enumName
@@ -306,15 +306,15 @@ class SchemaParser internal constructor(
306306
val extensions = typeExtensions.extensionsOf<InterfaceTypeExtensionDefinition>(interfaceDefinition.name)
307307
val directives = sdlDirectives.directivesOf(interfaceDefinition, extensions)
308308
val fieldDefinitions = interfaceDefinition.withExtensions(typeExtensions).flatMap { it.fieldDefinitions }
309-
warnRepeated(interfaceDefinition.name, "field", fieldDefinitions.map { it.name })
309+
rejectRepeated(interfaceDefinition.name, "field", fieldDefinitions)
310310
val builder = GraphQLInterfaceType.newInterface()
311311
.name(interfaceDefinition.name)
312312
.definition(interfaceDefinition)
313313
.extensionDefinitions(extensions)
314314
.description(getDocumentation(interfaceDefinition, options))
315315
.withSdlDirectives(directives, INTERFACE)
316316
.apply {
317-
fieldDefinitions.distinctBy { it.name }.forEach { fieldDefinition ->
317+
fieldDefinitions.forEach { fieldDefinition ->
318318
field { field -> createField(field, fieldDefinition, inputObjects) }
319319
}
320320
}
@@ -331,7 +331,7 @@ class SchemaParser internal constructor(
331331
private fun createUnionObject(definition: UnionTypeDefinition, types: List<GraphQLObjectType>): GraphQLUnionType {
332332
val extensions = typeExtensions.extensionsOf<UnionTypeExtensionDefinition>(definition.name)
333333
val directives = sdlDirectives.directivesOf(definition, extensions)
334-
warnRepeated(definition.name, "member", definition.withExtensions(typeExtensions).flatMap { it.memberTypes }.map { (it as TypeName).name })
334+
rejectRepeated(definition.name, "member", definition.withExtensions(typeExtensions).flatMap { it.memberTypes }.map { it as TypeName })
335335
val builder = GraphQLUnionType.newUnionType()
336336
.name(definition.name)
337337
.definition(definition)
@@ -373,21 +373,10 @@ class SchemaParser internal constructor(
373373
return leafObjects
374374
}
375375

376-
// TODO throw a SchemaError instead in 15.0.0 (#863), like graphql-java does
377-
private fun warnRepeated(typeName: String, kind: String, names: List<String?>) {
378-
names.groupingBy { it }.eachCount().filterValues { it > 1 }.keys.forEach {
379-
log.warn("Type '$typeName' declares $kind '$it' more than once, only the first one is kept.")
380-
}
381-
}
382-
383-
// TODO throw a SchemaError instead in 15.0.0 (#865), like graphql-java does
384-
private fun warnRepeatedFields(typeName: String, fieldDefinitions: List<NamedNode<*>>) {
385-
fieldDefinitions.groupBy { it.name }.values.filter { it.size > 1 }.forEach { declarations ->
386-
val kept = declarations.last()
387-
val location = kept.sourceLocation.describe()
388-
val which = if (location.isEmpty()) "one of them" else "the one$location"
389-
log.warn("Type '$typeName' declares field '${kept.name}' more than once, only $which is kept.")
390-
}
376+
private fun rejectRepeated(typeName: String, kind: String, declarations: List<NamedNode<*>>) {
377+
val names = mutableSetOf<String?>()
378+
val repeat = declarations.firstOrNull { !names.add(it.name) } ?: return
379+
throw SchemaError("Type '$typeName' declares $kind '${repeat.name}' more than once${repeat.sourceLocation.describe()}.")
391380
}
392381

393382
private fun createField(field: GraphQLFieldDefinition.Builder, fieldDefinition: FieldDefinition, inputObjects: List<GraphQLInputObjectType>): GraphQLFieldDefinition.Builder {

0 commit comments

Comments
 (0)