diff options
author | Michael Muré <batolettre@gmail.com> | 2018-12-23 17:11:37 +0100 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2018-12-23 17:11:37 +0100 |
commit | 1410a1af75b1ab9ea3f980a7e372728f9a123abf (patch) | |
tree | e24db8f84c48b20158b1f1fd6d281d700421279c /vendor/github.com/vektah/gqlparser/validator | |
parent | 8fc15a032f021c855abf66ed303c003d57c340ea (diff) | |
download | git-bug-1410a1af75b1ab9ea3f980a7e372728f9a123abf.tar.gz |
upgrade gqlgen to v0.7.1
Diffstat (limited to 'vendor/github.com/vektah/gqlparser/validator')
7 files changed, 271 insertions, 24 deletions
diff --git a/vendor/github.com/vektah/gqlparser/validator/prelude.go b/vendor/github.com/vektah/gqlparser/validator/prelude.go index 80ce8a21..c7a4d35b 100644 --- a/vendor/github.com/vektah/gqlparser/validator/prelude.go +++ b/vendor/github.com/vektah/gqlparser/validator/prelude.go @@ -2,4 +2,8 @@ package validator import "github.com/vektah/gqlparser/ast" -var Prelude = &ast.Source{Name: "prelude.graphql", Input: "# This file defines all the implicitly declared types that are required by the graphql spec. It is implicitly included by calls to LoadSchema\n\n# The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.\nscalar Int\n\n# The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).\nscalar Float\n\n# The `String`scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.\nscalar String\n\n# The `Boolean` scalar type represents ` + \"`\" + `true` + \"`\" + ` or ` + \"`\" + `false` + \"`\" + `.\nscalar Boolean\n\n# The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as \"4\") or integer (such as 4) input value will be accepted as an ID.\nscalar ID\n\n# The @include directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional inclusion during execution as described by the if argument.\ndirective @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT\n\n# The @skip directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional exclusion during execution as described by the if argument.\ndirective @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT\n\n# The @deprecated directive is used within the type system definition language to indicate deprecated portions of a GraphQL service’s schema, such as deprecated fields on a type or deprecated enum values.\ndirective @deprecated(reason: String = \"No longer supported\") on FIELD_DEFINITION | ENUM_VALUE\n\ntype __Schema {\n types: [__Type!]!\n queryType: __Type!\n mutationType: __Type\n subscriptionType: __Type\n directives: [__Directive!]!\n}\n\ntype __Type {\n kind: __TypeKind!\n name: String\n description: String\n\n # OBJECT and INTERFACE only\n fields(includeDeprecated: Boolean = false): [__Field!]\n\n # OBJECT only\n interfaces: [__Type!]\n\n # INTERFACE and UNION only\n possibleTypes: [__Type!]\n\n # ENUM only\n enumValues(includeDeprecated: Boolean = false): [__EnumValue!]\n\n # INPUT_OBJECT only\n inputFields: [__InputValue!]\n\n # NON_NULL and LIST only\n ofType: __Type\n}\n\ntype __Field {\n name: String!\n description: String\n args: [__InputValue!]!\n type: __Type!\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\ntype __InputValue {\n name: String!\n description: String\n type: __Type!\n defaultValue: String\n}\n\ntype __EnumValue {\n name: String!\n description: String\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\nenum __TypeKind {\n SCALAR\n OBJECT\n INTERFACE\n UNION\n ENUM\n INPUT_OBJECT\n LIST\n NON_NULL\n}\n\ntype __Directive {\n name: String!\n description: String\n locations: [__DirectiveLocation!]!\n args: [__InputValue!]!\n}\n\nenum __DirectiveLocation {\n QUERY\n MUTATION\n SUBSCRIPTION\n FIELD\n FRAGMENT_DEFINITION\n FRAGMENT_SPREAD\n INLINE_FRAGMENT\n SCHEMA\n SCALAR\n OBJECT\n FIELD_DEFINITION\n ARGUMENT_DEFINITION\n INTERFACE\n UNION\n ENUM\n ENUM_VALUE\n INPUT_OBJECT\n INPUT_FIELD_DEFINITION\n}\n"} +var Prelude = &ast.Source{ + Name: "prelude.graphql", + Input: "# This file defines all the implicitly declared types that are required by the graphql spec. It is implicitly included by calls to LoadSchema\n\n# The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.\nscalar Int\n\n# The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).\nscalar Float\n\n# The `String`scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.\nscalar String\n\n# The `Boolean` scalar type represents ` + \"`\" + `true` + \"`\" + ` or ` + \"`\" + `false` + \"`\" + `.\nscalar Boolean\n\n# The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as \"4\") or integer (such as 4) input value will be accepted as an ID.\nscalar ID\n\n# The @include directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional inclusion during execution as described by the if argument.\ndirective @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT\n\n# The @skip directive may be provided for fields, fragment spreads, and inline fragments, and allows for conditional exclusion during execution as described by the if argument.\ndirective @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT\n\n# The @deprecated directive is used within the type system definition language to indicate deprecated portions of a GraphQL service’s schema, such as deprecated fields on a type or deprecated enum values.\ndirective @deprecated(reason: String = \"No longer supported\") on FIELD_DEFINITION | ENUM_VALUE\n\ntype __Schema {\n types: [__Type!]!\n queryType: __Type!\n mutationType: __Type\n subscriptionType: __Type\n directives: [__Directive!]!\n}\n\ntype __Type {\n kind: __TypeKind!\n name: String\n description: String\n\n # OBJECT and INTERFACE only\n fields(includeDeprecated: Boolean = false): [__Field!]\n\n # OBJECT only\n interfaces: [__Type!]\n\n # INTERFACE and UNION only\n possibleTypes: [__Type!]\n\n # ENUM only\n enumValues(includeDeprecated: Boolean = false): [__EnumValue!]\n\n # INPUT_OBJECT only\n inputFields: [__InputValue!]\n\n # NON_NULL and LIST only\n ofType: __Type\n}\n\ntype __Field {\n name: String!\n description: String\n args: [__InputValue!]!\n type: __Type!\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\ntype __InputValue {\n name: String!\n description: String\n type: __Type!\n defaultValue: String\n}\n\ntype __EnumValue {\n name: String!\n description: String\n isDeprecated: Boolean!\n deprecationReason: String\n}\n\nenum __TypeKind {\n SCALAR\n OBJECT\n INTERFACE\n UNION\n ENUM\n INPUT_OBJECT\n LIST\n NON_NULL\n}\n\ntype __Directive {\n name: String!\n description: String\n locations: [__DirectiveLocation!]!\n args: [__InputValue!]!\n}\n\nenum __DirectiveLocation {\n QUERY\n MUTATION\n SUBSCRIPTION\n FIELD\n FRAGMENT_DEFINITION\n FRAGMENT_SPREAD\n INLINE_FRAGMENT\n SCHEMA\n SCALAR\n OBJECT\n FIELD_DEFINITION\n ARGUMENT_DEFINITION\n INTERFACE\n UNION\n ENUM\n ENUM_VALUE\n INPUT_OBJECT\n INPUT_FIELD_DEFINITION\n}\n", + BuiltIn: true, +} diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/known_argument_names.go b/vendor/github.com/vektah/gqlparser/validator/rules/known_argument_names.go index 83b47387..1a46431d 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/known_argument_names.go +++ b/vendor/github.com/vektah/gqlparser/validator/rules/known_argument_names.go @@ -9,7 +9,7 @@ func init() { AddRule("KnownArgumentNames", func(observers *Events, addError AddErrFunc) { // A GraphQL field is only valid if all supplied arguments are defined by that field. observers.OnField(func(walker *Walker, field *ast.Field) { - if field.Definition == nil { + if field.Definition == nil || field.ObjectDefinition == nil { return } for _, arg := range field.Arguments { diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go b/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go index 52eab3a2..bb2f1831 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go +++ b/vendor/github.com/vektah/gqlparser/validator/rules/overlapping_fields_can_be_merged.go @@ -292,7 +292,11 @@ func (m *overlappingFieldsCanBeMergedManager) collectConflictsBetweenFieldsAndFr // (E) Then collect any conflicts between the provided collection of fields // and any fragment names found in the given fragment. + baseFragmentSpread := fragmentSpread for _, fragmentSpread := range fragmentSpreads { + if fragmentSpread.Name == baseFragmentSpread.Name { + continue + } m.collectConflictsBetweenFieldsAndFragment(conflicts, areMutuallyExclusive, fieldsMap, fragmentSpread) } } diff --git a/vendor/github.com/vektah/gqlparser/validator/rules/possible_fragment_spreads.go b/vendor/github.com/vektah/gqlparser/validator/rules/possible_fragment_spreads.go index 971decbf..04611834 100644 --- a/vendor/github.com/vektah/gqlparser/validator/rules/possible_fragment_spreads.go +++ b/vendor/github.com/vektah/gqlparser/validator/rules/possible_fragment_spreads.go @@ -20,7 +20,7 @@ func init() { case ast.Interface, ast.Union: parentDefs = walker.Schema.GetPossibleTypes(parentDef) default: - panic("unexpected type") + return } fragmentDefType := walker.Schema.Types[fragmentName] diff --git a/vendor/github.com/vektah/gqlparser/validator/schema.go b/vendor/github.com/vektah/gqlparser/validator/schema.go index 8fa18d7e..57d2022e 100644 --- a/vendor/github.com/vektah/gqlparser/validator/schema.go +++ b/vendor/github.com/vektah/gqlparser/validator/schema.go @@ -4,6 +4,7 @@ package validator import ( "strconv" + "strings" . "github.com/vektah/gqlparser/ast" "github.com/vektah/gqlparser/gqlerror" @@ -11,20 +12,19 @@ import ( ) func LoadSchema(inputs ...*Source) (*Schema, *gqlerror.Error) { - ast := &SchemaDocument{} - for _, input := range inputs { - inputAst, err := parser.ParseSchema(input) - if err != nil { - return nil, err - } - - ast.Merge(inputAst) + ast, err := parser.ParseSchemas(inputs...) + if err != nil { + return nil, err } + return ValidateSchemaDocument(ast) +} +func ValidateSchemaDocument(ast *SchemaDocument) (*Schema, *gqlerror.Error) { schema := Schema{ Types: map[string]*Definition{}, Directives: map[string]*DirectiveDefinition{}, PossibleTypes: map[string][]*Definition{}, + Implements: map[string][]*Definition{}, } for i, def := range ast.Definitions { @@ -32,13 +32,6 @@ func LoadSchema(inputs ...*Source) (*Schema, *gqlerror.Error) { return nil, gqlerror.ErrorPosf(def.Position, "Cannot redeclare type %s.", def.Name) } schema.Types[def.Name] = ast.Definitions[i] - - if def.Kind != Interface { - for _, intf := range def.Interfaces { - schema.AddPossibleType(intf, ast.Definitions[i]) - } - schema.AddPossibleType(def.Name, ast.Definitions[i]) - } } for _, ext := range ast.Extensions { @@ -58,6 +51,22 @@ func LoadSchema(inputs ...*Source) (*Schema, *gqlerror.Error) { def.EnumValues = append(def.EnumValues, ext.EnumValues...) } + for _, def := range ast.Definitions { + switch def.Kind { + case Union: + for _, t := range def.Types { + schema.AddPossibleType(def.Name, schema.Types[t]) + schema.AddImplements(t, def) + } + case InputObject, Object: + for _, intf := range def.Interfaces { + schema.AddPossibleType(intf, def) + schema.AddImplements(def.Name, schema.Types[intf]) + } + schema.AddPossibleType(def.Name, def) + } + } + for i, dir := range ast.Directives { if schema.Directives[dir.Name] != nil { return nil, gqlerror.ErrorPosf(dir.Position, "Cannot redeclare directive %s.", dir.Name) @@ -150,11 +159,20 @@ func LoadSchema(inputs ...*Source) (*Schema, *gqlerror.Error) { } func validateDirective(schema *Schema, def *DirectiveDefinition) *gqlerror.Error { + if err := validateName(def.Position, def.Name); err != nil { + // now, GraphQL spec doesn't have reserved directive name + return err + } + return validateArgs(schema, def.Arguments, def) } func validateDefinition(schema *Schema, def *Definition) *gqlerror.Error { for _, field := range def.Fields { + if err := validateName(field.Position, field.Name); err != nil { + // now, GraphQL spec doesn't have reserved field name + return err + } if err := validateTypeRef(schema, field.Type); err != nil { return err } @@ -176,6 +194,37 @@ func validateDefinition(schema *Schema, def *Definition) *gqlerror.Error { } } + switch def.Kind { + case Object, Interface: + if len(def.Fields) == 0 { + return gqlerror.ErrorPosf(def.Position, "%s must define one or more fields.", def.Kind) + } + case Enum: + if len(def.EnumValues) == 0 { + return gqlerror.ErrorPosf(def.Position, "%s must define one or more unique enum values.", def.Kind) + } + case InputObject: + if len(def.Fields) == 0 { + return gqlerror.ErrorPosf(def.Position, "%s must define one or more input fields.", def.Kind) + } + } + + for idx, field1 := range def.Fields { + for _, field2 := range def.Fields[idx+1:] { + if field1.Name == field2.Name { + return gqlerror.ErrorPosf(field2.Position, "Field %s.%s can only be defined once.", def.Name, field2.Name) + } + } + } + + if !def.BuiltIn { + // GraphQL spec has reserved type names a lot! + err := validateName(def.Position, def.Name) + if err != nil { + return err + } + } + return validateDirectives(schema, def.Directives, nil) } @@ -188,6 +237,10 @@ func validateTypeRef(schema *Schema, typ *Type) *gqlerror.Error { func validateArgs(schema *Schema, args ArgumentDefinitionList, currentDirective *DirectiveDefinition) *gqlerror.Error { for _, arg := range args { + if err := validateName(arg.Position, arg.Name); err != nil { + // now, GraphQL spec doesn't have reserved argument name + return err + } if err := validateTypeRef(schema, arg.Type); err != nil { return err } @@ -200,6 +253,10 @@ func validateArgs(schema *Schema, args ArgumentDefinitionList, currentDirective func validateDirectives(schema *Schema, dirs DirectiveList, currentDirective *DirectiveDefinition) *gqlerror.Error { for _, dir := range dirs { + if err := validateName(dir.Position, dir.Name); err != nil { + // now, GraphQL spec doesn't have reserved directive name + return err + } if currentDirective != nil && dir.Name == currentDirective.Name { return gqlerror.ErrorPosf(dir.Position, "Directive %s cannot refer to itself.", currentDirective.Name) } @@ -210,3 +267,10 @@ func validateDirectives(schema *Schema, dirs DirectiveList, currentDirective *Di } return nil } + +func validateName(pos *Position, name string) *gqlerror.Error { + if strings.HasPrefix(name, "__") { + return gqlerror.ErrorPosf(pos, `Name "%s" must not begin with "__", which is reserved by GraphQL introspection.`, name) + } + return nil +} diff --git a/vendor/github.com/vektah/gqlparser/validator/schema_test.yml b/vendor/github.com/vektah/gqlparser/validator/schema_test.yml index 59e7145c..abc8dd7e 100644 --- a/vendor/github.com/vektah/gqlparser/validator/schema_test.yml +++ b/vendor/github.com/vektah/gqlparser/validator/schema_test.yml @@ -10,6 +10,84 @@ types: error: message: "Cannot redeclare type A." locations: [{line: 4, column: 6}] + - name: cannot be duplicated field at same definition 1 + input: | + type A { + name: String + name: String + } + error: + message: "Field A.name can only be defined once." + locations: [{line: 3, column: 3}] + - name: cannot be duplicated field at same definition 2 + input: | + type A { + name: String + } + extend type A { + name: String + } + error: + message: "Field A.name can only be defined once." + locations: [{line: 5, column: 3}] + - name: cannot be duplicated field at same definition 3 + input: | + type A { + name: String + } + extend type A { + age: Int + age: Int + } + error: + message: "Field A.age can only be defined once." + locations: [{line: 6, column: 3}] + +object types: + - name: must define one or more fields + input: | + directive @D on OBJECT + + # This pattern rejected by parser + # type InvalidObject1 {} + + type InvalidObject2 @D + + type ValidObject { + id: ID + } + extend type ValidObject @D + extend type ValidObject { + b: Int + } + error: + message: 'OBJECT must define one or more fields.' + locations: [{line: 6, column: 6}] + - name: check reserved names on type name + input: | + type __FooBar { + id: ID + } + error: + message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.' + locations: [{line: 1, column: 6}] + - name: check reserved names on type field + input: | + type FooBar { + __id: ID + } + error: + message: 'Name "__id" must not begin with "__", which is reserved by GraphQL introspection.' + locations: [{line: 2, column: 3}] + + - name: check reserved names on type field argument + input: | + type FooBar { + foo(__bar: ID): ID + } + error: + message: 'Name "__bar" must not begin with "__", which is reserved by GraphQL introspection.' + locations: [{line: 2, column: 7}] interfaces: - name: must exist @@ -42,6 +120,93 @@ interfaces: message: '"Object" is a non interface type OBJECT.' locations: [{line: 1, column: 6}] + - name: must define one or more fields + input: | + directive @D on INTERFACE + + # This pattern rejected by parser + # interface InvalidInterface1 {} + + interface InvalidInterface2 @D + + interface ValidInterface { + id: ID + } + extend interface ValidInterface @D + extend interface ValidInterface { + b: Int + } + error: + message: 'INTERFACE must define one or more fields.' + locations: [{line: 6, column: 11}] + - name: check reserved names on type name + input: | + interface __FooBar { + id: ID + } + error: + message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.' + locations: [{line: 1, column: 11}] + +inputs: + - name: must define one or more input fields + input: | + directive @D on INPUT_OBJECT + + # This pattern rejected by parser + # input InvalidInput1 {} + + input InvalidInput2 @D + + input ValidInput { + id: ID + } + extend input ValidInput @D + extend input ValidInput { + b: Int + } + error: + message: 'INPUT_OBJECT must define one or more input fields.' + locations: [{line: 6, column: 7}] + - name: check reserved names on type name + input: | + input __FooBar { + id: ID + } + error: + message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.' + locations: [{line: 1, column: 7}] + +enums: + - name: must define one or more unique enum values + input: | + directive @D on ENUM + + # This pattern rejected by parser + # enum InvalidEmum1 {} + + enum InvalidEnum2 @D + + enum ValidEnum { + FOO + } + extend enum ValidEnum @D + extend enum ValidEnum { + BAR + } + error: + message: 'ENUM must define one or more unique enum values.' + locations: [{line: 6, column: 6}] + - name: check reserved names on type name + input: | + enum __FooBar { + A + B + } + error: + message: 'Name "__FooBar" must not begin with "__", which is reserved by GraphQL introspection.' + locations: [{line: 1, column: 6}] + type extensions: - name: cannot extend non existant types input: | @@ -86,6 +251,12 @@ directives: error: message: "Directive A cannot refer to itself." locations: [{line: 1, column: 25}] + - name: check reserved names on type name + input: | + directive @__A on FIELD_DEFINITION + error: + message: 'Name "__A" must not begin with "__", which is reserved by GraphQL introspection.' + locations: [{line: 1, column: 12}] entry points: - name: multiple schema entry points diff --git a/vendor/github.com/vektah/gqlparser/validator/vars.go b/vendor/github.com/vektah/gqlparser/validator/vars.go index 0743f5cc..aaf3a0d1 100644 --- a/vendor/github.com/vektah/gqlparser/validator/vars.go +++ b/vendor/github.com/vektah/gqlparser/validator/vars.go @@ -73,12 +73,19 @@ type varValidator struct { } func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerror.Error { + currentPath := v.path + resetPath := func() { + v.path = currentPath + } + defer resetPath() + if typ.Elem != nil { if val.Kind() != reflect.Slice { return gqlerror.ErrorPathf(v.path, "must be an array") } for i := 0; i < val.Len(); i++ { + resetPath() v.path = append(v.path, i) field := val.Index(i) @@ -92,8 +99,6 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr if err := v.validateVarType(typ.Elem, field); err != nil { return err } - - v.path = v.path[0 : len(v.path)-1] } return nil @@ -150,15 +155,16 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr for _, name := range val.MapKeys() { val.MapIndex(name) fieldDef := def.Fields.ForName(name.String()) - v.path = append(v.path, name) + resetPath() + v.path = append(v.path, name.String()) if fieldDef == nil { return gqlerror.ErrorPathf(v.path, "unknown field") } - v.path = v.path[0 : len(v.path)-1] } for _, fieldDef := range def.Fields { + resetPath() v.path = append(v.path, fieldDef.Name) field := val.MapIndex(reflect.ValueOf(fieldDef.Name)) @@ -184,8 +190,6 @@ func (v *varValidator) validateVarType(typ *ast.Type, val reflect.Value) *gqlerr if err != nil { return err } - - v.path = v.path[0 : len(v.path)-1] } default: panic(fmt.Errorf("unsupported type %s", def.Kind)) |