diff --git a/validator/known_argument_names.go b/validator/known_argument_names.go index e934e3f1..cf291e1d 100644 --- a/validator/known_argument_names.go +++ b/validator/known_argument_names.go @@ -6,7 +6,7 @@ import ( func init() { fieldVisitors = append(fieldVisitors, knownFieldArgumentNames) - directiveVisitors = append(directiveVisitors, knowDirectiveArgumentNames) + directiveVisitors = append(directiveVisitors, knownDirectiveArgumentNames) } // A GraphQL field is only valid if all supplied arguments are defined by that field. @@ -33,7 +33,7 @@ func knownFieldArgumentNames(ctx *vctx, parentDef *gqlparser.Definition, fieldDe } } -func knowDirectiveArgumentNames(ctx *vctx, parentDef *gqlparser.Definition, directiveDef *gqlparser.DirectiveDefinition, directive *gqlparser.Directive, location gqlparser.DirectiveLocation) { +func knownDirectiveArgumentNames(ctx *vctx, parentDef *gqlparser.Definition, directiveDef *gqlparser.DirectiveDefinition, directive *gqlparser.Directive, location gqlparser.DirectiveLocation) { if directiveDef == nil { return } diff --git a/validator/unique_argument_names.go b/validator/unique_argument_names.go new file mode 100644 index 00000000..0d51ce45 --- /dev/null +++ b/validator/unique_argument_names.go @@ -0,0 +1,34 @@ +package validator + +import ( + "github.com/vektah/gqlparser" +) + +func init() { + fieldVisitors = append(fieldVisitors, uniqueFieldArgumentNames) + directiveVisitors = append(directiveVisitors, uniqueDirectiveArgumentNames) +} + +func checkUniqueArgs(ctx *vctx, args []gqlparser.Argument) { + knownArgNames := map[string]bool{} + + for _, arg := range args { + if knownArgNames[arg.Name] { + ctx.errors = append(ctx.errors, Error( + Rule("UniqueArgumentNames"), + Message(`There can be only one argument named "%s".`, arg.Name), + )) + } + + knownArgNames[arg.Name] = true + } +} + +// A GraphQL field is only valid if all supplied arguments are defined by that field. +func uniqueFieldArgumentNames(ctx *vctx, parentDef *gqlparser.Definition, fieldDef *gqlparser.FieldDefinition, field *gqlparser.Field) { + checkUniqueArgs(ctx, field.Arguments) +} + +func uniqueDirectiveArgumentNames(ctx *vctx, parentDef *gqlparser.Definition, directiveDef *gqlparser.DirectiveDefinition, directive *gqlparser.Directive, location gqlparser.DirectiveLocation) { + checkUniqueArgs(ctx, directive.Arguments) +} diff --git a/validator/validate_test.go b/validator/validate_test.go index eae5ec69..a04d1afe 100644 --- a/validator/validate_test.go +++ b/validator/validate_test.go @@ -43,6 +43,7 @@ func TestSpec(t *testing.T) { t.Run("ScalarLeafs", runSpec(schemas, deviations, "../spec/validation/ScalarLeafs.yml")) t.Run("SingleFieldSubscriptions", runSpec(schemas, deviations, "../spec/validation/SingleFieldSubscriptions.yml")) + t.Run("UniqueArgumentNames", runSpec(schemas, deviations, "../spec/validation/UniqueArgumentNames.yml")) } func runSpec(schemas []*gqlparser.Schema, deviations map[string]*Spec, filename string) func(t *testing.T) {