@@ -23,7 +23,6 @@ import graphql.language.*
2323import graphql.schema.*
2424import graphql.schema.idl.RuntimeWiring
2525import graphql.schema.idl.ScalarInfo
26- import graphql.schema.visibility.BlockedFields
2726import org.slf4j.LoggerFactory
2827import kotlin.reflect.KClass
2928
@@ -79,13 +78,6 @@ class SchemaParser internal constructor(
7978 * Parses the given schema with respect to the given dictionary and returns GraphQL objects.
8079 */
8180 fun parseSchemaObjects (): SchemaObjects {
82- if (! options.introspectionEnabled) {
83- // What the deprecated NoIntrospectionGraphqlFieldVisibility does. Its suggested replacement,
84- // Introspection.enabledJvmWide, would also turn introspection off for every other schema in the JVM.
85- // TODO deprecate introspectionEnabled and remove this in 15.0.0 (#858)
86- codeRegistryBuilder.fieldVisibility(BlockedFields .newBlock().addPattern(" __.*" ).build())
87- }
88- // this overrides the above introspection enabled setting obviously... todo: add documentation
8981 options.fieldVisibility?.let { codeRegistryBuilder.fieldVisibility(it) }
9082
9183 // Create GraphQL objects
@@ -172,6 +164,8 @@ class SchemaParser internal constructor(
172164 val name = objectDefinition.name
173165 val extensions = typeExtensions.extensionsOf<ObjectTypeExtensionDefinition >(name)
174166 val directives = sdlDirectives.directivesOf(objectDefinition, extensions)
167+ val fieldDefinitions = objectDefinition.withExtensions(typeExtensions).flatMap { it.fieldDefinitions }
168+ rejectRepeated(name, " field" , fieldDefinitions)
175169 val builder = GraphQLObjectType .newObject()
176170 .name(name)
177171 .definition(objectDefinition)
@@ -186,7 +180,7 @@ class SchemaParser internal constructor(
186180 }
187181 }
188182 .apply {
189- objectDefinition.withExtensions(typeExtensions).flatMap { it. fieldDefinitions } .forEach { fieldDefinition ->
183+ fieldDefinitions.forEach { fieldDefinition ->
190184 field { field ->
191185 createField(field, fieldDefinition, inputObjects)
192186 codeRegistryBuilder.dataFetcher(
@@ -210,6 +204,8 @@ class SchemaParser internal constructor(
210204 inputObjectsInProgress : MutableSet <String >): GraphQLInputObjectType {
211205 val extensionDefinitions = typeExtensions.extensionsOf<InputObjectTypeExtensionDefinition >(definition.name)
212206 val directives = sdlDirectives.directivesOf(definition, extensionDefinitions)
207+ val inputValueDefinitions = definition.withExtensions(typeExtensions).flatMap { it.inputValueDefinitions }
208+ rejectRepeated(definition.name, " field" , inputValueDefinitions)
213209
214210 inputObjectsInProgress.add(definition.name)
215211
@@ -220,20 +216,18 @@ class SchemaParser internal constructor(
220216 .description(getDocumentation(definition, options))
221217 .withSdlDirectives(directives, INPUT_OBJECT )
222218 .apply {
223- (extensionDefinitions + definition).forEach { typeDefinition ->
224- typeDefinition.inputValueDefinitions.forEach { fieldDefinition ->
225- field(
226- GraphQLInputObjectField .newInputObjectField()
227- .name(fieldDefinition.name)
228- .definition(fieldDefinition)
229- .description(getDocumentation(fieldDefinition, options))
230- .apply { fieldDefinition.defaultValue?.let { v -> defaultValueLiteral(v) } }
231- .apply { sdlDirectives.getDeprecated(fieldDefinition.directives)?.let { deprecate(it) } }
232- .type(determineInputType(fieldDefinition.type, inputObjects, inputObjectsInProgress))
233- .withSdlDirectives(fieldDefinition.directives, INPUT_FIELD_DEFINITION )
234- .build()
235- )
236- }
219+ inputValueDefinitions.forEach { fieldDefinition ->
220+ field(
221+ GraphQLInputObjectField .newInputObjectField()
222+ .name(fieldDefinition.name)
223+ .definition(fieldDefinition)
224+ .description(getDocumentation(fieldDefinition, options))
225+ .apply { fieldDefinition.defaultValue?.let { v -> defaultValueLiteral(v) } }
226+ .apply { sdlDirectives.getDeprecated(fieldDefinition.directives)?.let { deprecate(it) } }
227+ .type(determineInputType(fieldDefinition.type, inputObjects, inputObjectsInProgress))
228+ .withSdlDirectives(fieldDefinition.directives, INPUT_FIELD_DEFINITION )
229+ .build()
230+ )
237231 }
238232 }
239233
@@ -250,15 +244,15 @@ class SchemaParser internal constructor(
250244 val extensions = typeExtensions.extensionsOf<EnumTypeExtensionDefinition >(name)
251245 val directives = sdlDirectives.directivesOf(definition, extensions)
252246 val values = definition.withExtensions(typeExtensions).flatMap { it.enumValueDefinitions }
253- warnRepeated (name, " value" , values.map { it.name } )
247+ rejectRepeated (name, " value" , values)
254248 val builder = GraphQLEnumType .newEnum()
255249 .name(name)
256250 .definition(definition)
257251 .extensionDefinitions(extensions)
258252 .description(getDocumentation(definition, options))
259253 .withSdlDirectives(directives, ENUM )
260254 .apply {
261- values.distinctBy { it.name }. forEach { valueDefinition ->
255+ values.forEach { valueDefinition ->
262256 val enumName = valueDefinition.name
263257 val enumValue = if (enumClass == null ) {
264258 enumName
@@ -295,12 +289,7 @@ class SchemaParser internal constructor(
295289 .specifiedByUrl(getSpecifiedByUrl(directives) ? : provided.specifiedByUrl)
296290 // like graphql-java, only the schema's directives are applied
297291 .clearDirectives()
298- try {
299- builder.withSdlDirectives(directives, SCALAR )
300- } catch (e: SchemaError ) {
301- // TODO throw instead in 15.0.0 (#893), like for the other types
302- log.warn(" Scalar '$name ' is built without its directives from the schema: ${e.message} " )
303- }
292+ .withSdlDirectives(directives, SCALAR )
304293
305294 return builder.build()
306295 }
@@ -309,15 +298,15 @@ class SchemaParser internal constructor(
309298 val extensions = typeExtensions.extensionsOf<InterfaceTypeExtensionDefinition >(interfaceDefinition.name)
310299 val directives = sdlDirectives.directivesOf(interfaceDefinition, extensions)
311300 val fieldDefinitions = interfaceDefinition.withExtensions(typeExtensions).flatMap { it.fieldDefinitions }
312- warnRepeated (interfaceDefinition.name, " field" , fieldDefinitions.map { it.name } )
301+ rejectRepeated (interfaceDefinition.name, " field" , fieldDefinitions)
313302 val builder = GraphQLInterfaceType .newInterface()
314303 .name(interfaceDefinition.name)
315304 .definition(interfaceDefinition)
316305 .extensionDefinitions(extensions)
317306 .description(getDocumentation(interfaceDefinition, options))
318307 .withSdlDirectives(directives, INTERFACE )
319308 .apply {
320- fieldDefinitions.distinctBy { it.name }. forEach { fieldDefinition ->
309+ fieldDefinitions.forEach { fieldDefinition ->
321310 field { field -> createField(field, fieldDefinition, inputObjects) }
322311 }
323312 }
@@ -334,7 +323,7 @@ class SchemaParser internal constructor(
334323 private fun createUnionObject (definition : UnionTypeDefinition , types : List <GraphQLObjectType >): GraphQLUnionType {
335324 val extensions = typeExtensions.extensionsOf<UnionTypeExtensionDefinition >(definition.name)
336325 val directives = sdlDirectives.directivesOf(definition, extensions)
337- warnRepeated (definition.name, " member" , definition.withExtensions(typeExtensions).flatMap { it.memberTypes }.map { ( it as TypeName ).name })
326+ rejectRepeated (definition.name, " member" , definition.withExtensions(typeExtensions).flatMap { it.memberTypes }.map { it as TypeName })
338327 val builder = GraphQLUnionType .newUnionType()
339328 .name(definition.name)
340329 .definition(definition)
@@ -376,11 +365,10 @@ class SchemaParser internal constructor(
376365 return leafObjects
377366 }
378367
379- // TODO throw a SchemaError instead in 15.0.0 (#863), like graphql-java does
380- private fun warnRepeated (typeName : String , kind : String , names : List <String ?>) {
381- names.groupingBy { it }.eachCount().filterValues { it > 1 }.keys.forEach {
382- log.warn(" Type '$typeName ' declares $kind '$it ' more than once, only the first one is kept." )
383- }
368+ private fun rejectRepeated (typeName : String , kind : String , declarations : List <NamedNode <* >>) {
369+ val names = mutableSetOf<String ?>()
370+ val repeat = declarations.firstOrNull { ! names.add(it.name) } ? : return
371+ throw SchemaError (" Type '$typeName ' declares $kind '${repeat.name} ' more than once${repeat.sourceLocation.describe()} ." )
384372 }
385373
386374 private fun createField (field : GraphQLFieldDefinition .Builder , fieldDefinition : FieldDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLFieldDefinition .Builder {
0 commit comments