@@ -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
@@ -171,6 +163,8 @@ class SchemaParser internal constructor(
171163 val name = objectDefinition.name
172164 val extensions = typeExtensions.extensionsOf<ObjectTypeExtensionDefinition >(name)
173165 val directives = sdlDirectives.directivesOf(objectDefinition, extensions)
166+ val fieldDefinitions = objectDefinition.withExtensions(typeExtensions).flatMap { it.fieldDefinitions }
167+ rejectRepeated(name, " field" , fieldDefinitions)
174168 val builder = GraphQLObjectType .newObject()
175169 .name(name)
176170 .definition(objectDefinition)
@@ -185,7 +179,7 @@ class SchemaParser internal constructor(
185179 }
186180 }
187181 .apply {
188- objectDefinition.withExtensions(typeExtensions).flatMap { it. fieldDefinitions } .forEach { fieldDefinition ->
182+ fieldDefinitions.forEach { fieldDefinition ->
189183 field { field ->
190184 createField(field, fieldDefinition, inputObjects)
191185 codeRegistryBuilder.dataFetcher(
@@ -209,6 +203,8 @@ class SchemaParser internal constructor(
209203 inputObjectsInProgress : MutableSet <String >): GraphQLInputObjectType {
210204 val extensionDefinitions = typeExtensions.extensionsOf<InputObjectTypeExtensionDefinition >(definition.name)
211205 val directives = sdlDirectives.directivesOf(definition, extensionDefinitions)
206+ val inputValueDefinitions = definition.withExtensions(typeExtensions).flatMap { it.inputValueDefinitions }
207+ rejectRepeated(definition.name, " field" , inputValueDefinitions)
212208
213209 inputObjectsInProgress.add(definition.name)
214210
@@ -219,20 +215,18 @@ class SchemaParser internal constructor(
219215 .description(getDocumentation(definition, options))
220216 .withSdlDirectives(directives, INPUT_OBJECT )
221217 .apply {
222- (extensionDefinitions + definition).forEach { typeDefinition ->
223- typeDefinition.inputValueDefinitions.forEach { fieldDefinition ->
224- field(
225- GraphQLInputObjectField .newInputObjectField()
226- .name(fieldDefinition.name)
227- .definition(fieldDefinition)
228- .description(getDocumentation(fieldDefinition, options))
229- .apply { fieldDefinition.defaultValue?.let { v -> defaultValueLiteral(v) } }
230- .apply { sdlDirectives.getDeprecated(fieldDefinition.directives)?.let { deprecate(it) } }
231- .type(determineInputType(fieldDefinition.type, inputObjects, inputObjectsInProgress))
232- .withSdlDirectives(fieldDefinition.directives, INPUT_FIELD_DEFINITION )
233- .build()
234- )
235- }
218+ inputValueDefinitions.forEach { fieldDefinition ->
219+ field(
220+ GraphQLInputObjectField .newInputObjectField()
221+ .name(fieldDefinition.name)
222+ .definition(fieldDefinition)
223+ .description(getDocumentation(fieldDefinition, options))
224+ .apply { fieldDefinition.defaultValue?.let { v -> defaultValueLiteral(v) } }
225+ .apply { sdlDirectives.getDeprecated(fieldDefinition.directives)?.let { deprecate(it) } }
226+ .type(determineInputType(fieldDefinition.type, inputObjects, inputObjectsInProgress))
227+ .withSdlDirectives(fieldDefinition.directives, INPUT_FIELD_DEFINITION )
228+ .build()
229+ )
236230 }
237231 }
238232
@@ -249,15 +243,15 @@ class SchemaParser internal constructor(
249243 val extensions = typeExtensions.extensionsOf<EnumTypeExtensionDefinition >(name)
250244 val directives = sdlDirectives.directivesOf(definition, extensions)
251245 val values = definition.withExtensions(typeExtensions).flatMap { it.enumValueDefinitions }
252- warnRepeated (name, " value" , values.map { it.name } )
246+ rejectRepeated (name, " value" , values)
253247 val builder = GraphQLEnumType .newEnum()
254248 .name(name)
255249 .definition(definition)
256250 .extensionDefinitions(extensions)
257251 .description(getDocumentation(definition, options))
258252 .withSdlDirectives(directives, ENUM )
259253 .apply {
260- values.distinctBy { it.name }. forEach { valueDefinition ->
254+ values.forEach { valueDefinition ->
261255 val enumName = valueDefinition.name
262256 val enumValue = if (enumClass == null ) {
263257 enumName
@@ -294,12 +288,7 @@ class SchemaParser internal constructor(
294288 .specifiedByUrl(getSpecifiedByUrl(directives) ? : provided.specifiedByUrl)
295289 // like graphql-java, only the schema's directives are applied
296290 .clearDirectives()
297- try {
298- builder.withSdlDirectives(directives, SCALAR )
299- } catch (e: SchemaError ) {
300- // TODO throw instead in 15.0.0 (#893), like for the other types
301- log.warn(" Scalar '$name ' is built without its directives from the schema: ${e.message} " )
302- }
291+ .withSdlDirectives(directives, SCALAR )
303292
304293 return builder.build()
305294 }
@@ -308,15 +297,15 @@ class SchemaParser internal constructor(
308297 val extensions = typeExtensions.extensionsOf<InterfaceTypeExtensionDefinition >(interfaceDefinition.name)
309298 val directives = sdlDirectives.directivesOf(interfaceDefinition, extensions)
310299 val fieldDefinitions = interfaceDefinition.withExtensions(typeExtensions).flatMap { it.fieldDefinitions }
311- warnRepeated (interfaceDefinition.name, " field" , fieldDefinitions.map { it.name } )
300+ rejectRepeated (interfaceDefinition.name, " field" , fieldDefinitions)
312301 val builder = GraphQLInterfaceType .newInterface()
313302 .name(interfaceDefinition.name)
314303 .definition(interfaceDefinition)
315304 .extensionDefinitions(extensions)
316305 .description(getDocumentation(interfaceDefinition, options))
317306 .withSdlDirectives(directives, INTERFACE )
318307 .apply {
319- fieldDefinitions.distinctBy { it.name }. forEach { fieldDefinition ->
308+ fieldDefinitions.forEach { fieldDefinition ->
320309 field { field -> createField(field, fieldDefinition, inputObjects) }
321310 }
322311 }
@@ -333,7 +322,7 @@ class SchemaParser internal constructor(
333322 private fun createUnionObject (definition : UnionTypeDefinition , types : List <GraphQLObjectType >): GraphQLUnionType {
334323 val extensions = typeExtensions.extensionsOf<UnionTypeExtensionDefinition >(definition.name)
335324 val directives = sdlDirectives.directivesOf(definition, extensions)
336- warnRepeated (definition.name, " member" , definition.withExtensions(typeExtensions).flatMap { it.memberTypes }.map { ( it as TypeName ).name })
325+ rejectRepeated (definition.name, " member" , definition.withExtensions(typeExtensions).flatMap { it.memberTypes }.map { it as TypeName })
337326 val builder = GraphQLUnionType .newUnionType()
338327 .name(definition.name)
339328 .definition(definition)
@@ -375,11 +364,10 @@ class SchemaParser internal constructor(
375364 return leafObjects
376365 }
377366
378- // TODO throw a SchemaError instead in 15.0.0 (#863), like graphql-java does
379- private fun warnRepeated (typeName : String , kind : String , names : List <String ?>) {
380- names.groupingBy { it }.eachCount().filterValues { it > 1 }.keys.forEach {
381- log.warn(" Type '$typeName ' declares $kind '$it ' more than once, only the first one is kept." )
382- }
367+ private fun rejectRepeated (typeName : String , kind : String , declarations : List <NamedNode <* >>) {
368+ val names = mutableSetOf<String ?>()
369+ val repeat = declarations.firstOrNull { ! names.add(it.name) } ? : return
370+ throw SchemaError (" Type '$typeName ' declares $kind '${repeat.name} ' more than once${repeat.sourceLocation.describe()} ." )
383371 }
384372
385373 private fun createField (field : GraphQLFieldDefinition .Builder , fieldDefinition : FieldDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLFieldDefinition .Builder {
0 commit comments