diff --git a/executor.go b/executor.go index f54951c9..44999213 100644 --- a/executor.go +++ b/executor.go @@ -152,7 +152,7 @@ func executeOperation(p ExecuteOperationParams) *Result { Fields: fields, } - if p.Operation.GetOperation() == "mutation" { + if p.Operation.GetOperation() == ast.OperationTypeMutation { return executeFieldsSerially(executeFieldsParams) } return executeFields(executeFieldsParams) @@ -166,9 +166,9 @@ func getOperationRootType(schema Schema, operation ast.Definition) (*Object, err } switch operation.GetOperation() { - case "query": + case ast.OperationTypeQuery: return schema.QueryType(), nil - case "mutation": + case ast.OperationTypeMutation: mutationType := schema.MutationType() if mutationType.PrivateName == "" { return nil, gqlerrors.NewError( @@ -181,7 +181,7 @@ func getOperationRootType(schema Schema, operation ast.Definition) (*Object, err ) } return mutationType, nil - case "subscription": + case ast.OperationTypeSubscription: subscriptionType := schema.SubscriptionType() if subscriptionType.PrivateName == "" { return nil, gqlerrors.NewError( diff --git a/language/ast/definitions.go b/language/ast/definitions.go index 7796df67..c224a9fd 100644 --- a/language/ast/definitions.go +++ b/language/ast/definitions.go @@ -15,7 +15,14 @@ type Definition interface { // Ensure that all definition types implements Definition interface var _ Definition = (*OperationDefinition)(nil) var _ Definition = (*FragmentDefinition)(nil) -var _ Definition = (TypeSystemDefinition)(nil) +var _ Definition = (TypeSystemDefinition)(nil) // experimental non-spec addition. + +// Note: subscription is an experimental non-spec addition. +const ( + OperationTypeQuery = "query" + OperationTypeMutation = "mutation" + OperationTypeSubscription = "subscription" +) // OperationDefinition implements Node, Definition type OperationDefinition struct { diff --git a/language/ast/node.go b/language/ast/node.go index 43b9d63b..cd63a0fc 100644 --- a/language/ast/node.go +++ b/language/ast/node.go @@ -30,12 +30,14 @@ var _ Node = (*Directive)(nil) var _ Node = (*Named)(nil) var _ Node = (*List)(nil) var _ Node = (*NonNull)(nil) +var _ Node = (*SchemaDefinition)(nil) +var _ Node = (*OperationTypeDefinition)(nil) +var _ Node = (*ScalarDefinition)(nil) var _ Node = (*ObjectDefinition)(nil) var _ Node = (*FieldDefinition)(nil) var _ Node = (*InputValueDefinition)(nil) var _ Node = (*InterfaceDefinition)(nil) var _ Node = (*UnionDefinition)(nil) -var _ Node = (*ScalarDefinition)(nil) var _ Node = (*EnumDefinition)(nil) var _ Node = (*EnumValueDefinition)(nil) var _ Node = (*InputObjectDefinition)(nil) diff --git a/language/ast/type_definitions.go b/language/ast/type_definitions.go index f06970fa..dd7940c9 100644 --- a/language/ast/type_definitions.go +++ b/language/ast/type_definitions.go @@ -27,10 +27,77 @@ type TypeSystemDefinition interface { GetLoc() *Location } +var _ TypeSystemDefinition = (*SchemaDefinition)(nil) var _ TypeSystemDefinition = (TypeDefinition)(nil) var _ TypeSystemDefinition = (*TypeExtensionDefinition)(nil) var _ TypeSystemDefinition = (*DirectiveDefinition)(nil) +// SchemaDefinition implements Node, Definition +type SchemaDefinition struct { + Kind string + Loc *Location + OperationTypes []*OperationTypeDefinition +} + +func NewSchemaDefinition(def *SchemaDefinition) *SchemaDefinition { + if def == nil { + def = &SchemaDefinition{} + } + return &SchemaDefinition{ + Kind: kinds.SchemaDefinition, + Loc: def.Loc, + OperationTypes: def.OperationTypes, + } +} + +func (def *SchemaDefinition) GetKind() string { + return def.Kind +} + +func (def *SchemaDefinition) GetLoc() *Location { + return def.Loc +} + +func (def *SchemaDefinition) GetVariableDefinitions() []*VariableDefinition { + return []*VariableDefinition{} +} + +func (def *SchemaDefinition) GetSelectionSet() *SelectionSet { + return &SelectionSet{} +} + +func (def *SchemaDefinition) GetOperation() string { + return "" +} + +// ScalarDefinition implements Node, Definition +type OperationTypeDefinition struct { + Kind string + Loc *Location + Operation string + Type *Named +} + +func NewOperationTypeDefinition(def *OperationTypeDefinition) *OperationTypeDefinition { + if def == nil { + def = &OperationTypeDefinition{} + } + return &OperationTypeDefinition{ + Kind: kinds.OperationTypeDefinition, + Loc: def.Loc, + Operation: def.Operation, + Type: def.Type, + } +} + +func (def *OperationTypeDefinition) GetKind() string { + return def.Kind +} + +func (def *OperationTypeDefinition) GetLoc() *Location { + return def.Loc +} + // ScalarDefinition implements Node, Definition type ScalarDefinition struct { Kind string diff --git a/language/kinds/kinds.go b/language/kinds/kinds.go index c4ca662c..40bc994e 100644 --- a/language/kinds/kinds.go +++ b/language/kinds/kinds.go @@ -37,6 +37,8 @@ const ( NonNull = "NonNull" // previously NonNull // Type System Definitions + SchemaDefinition = "SchemaDefinition" + OperationTypeDefinition = "OperationTypeDefinition" // Types Definitions ScalarDefinition = "ScalarDefinition" // previously ScalarTypeDefinition diff --git a/language/parser/parser.go b/language/parser/parser.go index db482ec6..d1e01c50 100644 --- a/language/parser/parser.go +++ b/language/parser/parser.go @@ -133,6 +133,14 @@ func parseDocument(parser *Parser) (*ast.Document, error) { return nil, err } nodes = append(nodes, node) + + // Note: the Type System IDL is an experimental non-spec addition. + case "schema": + node, err := parseSchemaDefinition(parser) + if err != nil { + return nil, err + } + nodes = append(nodes, node) case "scalar": node, err := parseScalarTypeDefinition(parser) if err != nil { @@ -204,8 +212,6 @@ func parseDocument(parser *Parser) (*ast.Document, error) { * OperationDefinition : * - SelectionSet * - OperationType Name? VariableDefinitions? Directives? SelectionSet - * - * OperationType : one of query mutation */ func parseOperationDefinition(parser *Parser) (*ast.OperationDefinition, error) { start := parser.Token.Start @@ -215,27 +221,17 @@ func parseOperationDefinition(parser *Parser) (*ast.OperationDefinition, error) return nil, err } return ast.NewOperationDefinition(&ast.OperationDefinition{ - Operation: "query", + Operation: ast.OperationTypeQuery, Directives: []*ast.Directive{}, SelectionSet: selectionSet, Loc: loc(parser, start), }), nil } - operationToken, err := expect(parser, lexer.TokenKind[lexer.NAME]) + operation, err := parseOperationType(parser) if err != nil { return nil, err } - operation := "" - switch operationToken.Value { - case "mutation": - fallthrough - case "subscription": - fallthrough - case "query": - operation = operationToken.Value - default: - return nil, unexpected(parser, operationToken) - } + var name *ast.Name if peek(parser, lexer.TokenKind[lexer.NAME]) { name, err = parseName(parser) @@ -262,6 +258,26 @@ func parseOperationDefinition(parser *Parser) (*ast.OperationDefinition, error) }), nil } +/** + * OperationType : one of query mutation subscription + */ +func parseOperationType(parser *Parser) (string, error) { + operationToken, err := expect(parser, lexer.TokenKind[lexer.NAME]) + if err != nil { + return "", err + } + switch operationToken.Value { + case ast.OperationTypeQuery: + return operationToken.Value, nil + case ast.OperationTypeMutation: + return operationToken.Value, nil + case ast.OperationTypeSubscription: + return operationToken.Value, nil + default: + return "", unexpected(parser, operationToken) + } +} + /** * VariableDefinitions : ( VariableDefinition+ ) */ @@ -860,6 +876,60 @@ func parseNamed(parser *Parser) (*ast.Named, error) { /* Implements the parsing rules in the Type Definition section. */ +/** + * SchemaDefinition : schema { OperationTypeDefinition+ } + * + * OperationTypeDefinition : OperationType : NamedType + */ +func parseSchemaDefinition(parser *Parser) (*ast.SchemaDefinition, error) { + start := parser.Token.Start + _, err := expectKeyWord(parser, "schema") + if err != nil { + return nil, err + } + operationTypesI, err := many( + parser, + lexer.TokenKind[lexer.BRACE_L], + parseOperationTypeDefinition, + lexer.TokenKind[lexer.BRACE_R], + ) + if err != nil { + return nil, err + } + operationTypes := []*ast.OperationTypeDefinition{} + for _, op := range operationTypesI { + if op, ok := op.(*ast.OperationTypeDefinition); ok { + operationTypes = append(operationTypes, op) + } + } + def := ast.NewSchemaDefinition(&ast.SchemaDefinition{ + OperationTypes: operationTypes, + Loc: loc(parser, start), + }) + return def, nil +} + +func parseOperationTypeDefinition(parser *Parser) (interface{}, error) { + start := parser.Token.Start + operation, err := parseOperationType(parser) + if err != nil { + return nil, err + } + _, err = expect(parser, lexer.TokenKind[lexer.COLON]) + if err != nil { + return nil, err + } + ttype, err := parseNamed(parser) + if err != nil { + return nil, err + } + return ast.NewOperationTypeDefinition(&ast.OperationTypeDefinition{ + Operation: operation, + Type: ttype, + Loc: loc(parser, start), + }), nil +} + /** * ScalarTypeDefinition : scalar Name */ diff --git a/language/printer/printer.go b/language/printer/printer.go index 9bfa451a..3b10f05a 100644 --- a/language/printer/printer.go +++ b/language/printer/printer.go @@ -6,6 +6,7 @@ import ( "github.com/graphql-go/graphql/language/ast" "github.com/graphql-go/graphql/language/visitor" + "github.com/kr/pretty" "reflect" ) @@ -146,7 +147,7 @@ var printDocASTReducer = map[string]visitor.VisitFunc{ "OperationDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { switch node := p.Node.(type) { case *ast.OperationDefinition: - op := node.Operation + op := string(node.Operation) name := fmt.Sprintf("%v", node.Name) varDefs := wrap("(", join(toSliceString(node.VariableDefinitions), ", "), ")") @@ -155,7 +156,7 @@ var printDocASTReducer = map[string]visitor.VisitFunc{ // Anonymous queries with no directives or variable definitions can use // the query short form. str := "" - if name == "" && directives == "" && varDefs == "" && op == "query" { + if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery { str = selectionSet } else { str = join([]string{ @@ -175,7 +176,7 @@ var printDocASTReducer = map[string]visitor.VisitFunc{ directives := join(toSliceString(getMapValue(node, "Directives")), " ") selectionSet := getMapValueString(node, "SelectionSet") str := "" - if name == "" && directives == "" && varDefs == "" && op == "query" { + if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery { str = selectionSet } else { str = join([]string{ @@ -433,6 +434,35 @@ var printDocASTReducer = map[string]visitor.VisitFunc{ }, // Type System Definitions + "SchemaDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + pretty.Println("===SchemaDefinitions", p.Node) + switch node := p.Node.(type) { + case *ast.SchemaDefinition: + operationTypesBlock := block(node.OperationTypes) + str := fmt.Sprintf("schema %v", operationTypesBlock) + return visitor.ActionUpdate, str + case map[string]interface{}: + operationTypes := toSliceString(getMapValue(node, "OperationTypes")) + operationTypesBlock := block(operationTypes) + str := fmt.Sprintf("schema %v", operationTypesBlock) + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, + "OperationTypeDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { + pretty.Println("===OperationTypeDefinition", p.Node) + switch node := p.Node.(type) { + case *ast.OperationTypeDefinition: + str := fmt.Sprintf("%v: %v", node.Operation, node.Type) + return visitor.ActionUpdate, str + case map[string]interface{}: + operation := getMapValueString(node, "Operation") + ttype := getMapValueString(node, "Type") + str := fmt.Sprintf("%v: %v", operation, ttype) + return visitor.ActionUpdate, str + } + return visitor.ActionNoChange, nil + }, "ScalarDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { switch node := p.Node.(type) { case *ast.ScalarDefinition: diff --git a/language/printer/printer_old.go b/language/printer/printer_old.go deleted file mode 100644 index 71d9157e..00000000 --- a/language/printer/printer_old.go +++ /dev/null @@ -1,359 +0,0 @@ -package printer - -import ( - "fmt" - - "github.com/graphql-go/graphql/language/ast" - "github.com/graphql-go/graphql/language/visitor" - // "log" -) - -var printDocASTReducer11 = map[string]visitor.VisitFunc{ - "Name": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.Name: - return visitor.ActionUpdate, node.Value - } - return visitor.ActionNoChange, nil - - }, - "Variable": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.Variable: - return visitor.ActionUpdate, fmt.Sprintf("$%v", node.Name) - } - return visitor.ActionNoChange, nil - }, - "Document": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.Document: - definitions := toSliceString(node.Definitions) - return visitor.ActionUpdate, join(definitions, "\n\n") + "\n" - } - return visitor.ActionNoChange, nil - }, - "OperationDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.OperationDefinition: - op := node.Operation - name := fmt.Sprintf("%v", node.Name) - - defs := wrap("(", join(toSliceString(node.VariableDefinitions), ", "), ")") - directives := join(toSliceString(node.Directives), " ") - selectionSet := fmt.Sprintf("%v", node.SelectionSet) - str := "" - if name == "" { - str = selectionSet - } else { - str = join([]string{ - op, - join([]string{name, defs}, ""), - directives, - selectionSet, - }, " ") - } - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, - "VariableDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.VariableDefinition: - variable := fmt.Sprintf("%v", node.Variable) - ttype := fmt.Sprintf("%v", node.Type) - defaultValue := fmt.Sprintf("%v", node.DefaultValue) - - return visitor.ActionUpdate, variable + ": " + ttype + wrap(" = ", defaultValue, "") - - } - return visitor.ActionNoChange, nil - }, - "SelectionSet": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.SelectionSet: - str := block(node.Selections) - return visitor.ActionUpdate, str - - } - return visitor.ActionNoChange, nil - }, - "Field": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.Field: - - alias := fmt.Sprintf("%v", node.Alias) - name := fmt.Sprintf("%v", node.Name) - args := toSliceString(node.Arguments) - directives := toSliceString(node.Directives) - selectionSet := fmt.Sprintf("%v", node.SelectionSet) - - str := join( - []string{ - wrap("", alias, ": ") + name + wrap("(", join(args, ", "), ")"), - join(directives, " "), - selectionSet, - }, - " ", - ) - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, - "Argument": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.Argument: - name := fmt.Sprintf("%v", node.Name) - value := fmt.Sprintf("%v", node.Value) - return visitor.ActionUpdate, name + ": " + value - } - return visitor.ActionNoChange, nil - }, - "FragmentSpread": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.FragmentSpread: - name := fmt.Sprintf("%v", node.Name) - directives := toSliceString(node.Directives) - return visitor.ActionUpdate, "..." + name + wrap(" ", join(directives, " "), "") - } - return visitor.ActionNoChange, nil - }, - "InlineFragment": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.InlineFragment: - typeCondition := fmt.Sprintf("%v", node.TypeCondition) - directives := toSliceString(node.Directives) - selectionSet := fmt.Sprintf("%v", node.SelectionSet) - return visitor.ActionUpdate, "... on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet - } - return visitor.ActionNoChange, nil - }, - "FragmentDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.FragmentDefinition: - name := fmt.Sprintf("%v", node.Name) - typeCondition := fmt.Sprintf("%v", node.TypeCondition) - directives := toSliceString(node.Directives) - selectionSet := fmt.Sprintf("%v", node.SelectionSet) - return visitor.ActionUpdate, "fragment " + name + " on " + typeCondition + " " + wrap("", join(directives, " "), " ") + selectionSet - } - return visitor.ActionNoChange, nil - }, - - "IntValue": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.IntValue: - return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value) - } - return visitor.ActionNoChange, nil - }, - "FloatValue": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.FloatValue: - return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value) - } - return visitor.ActionNoChange, nil - }, - "StringValue": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.StringValue: - return visitor.ActionUpdate, `"` + fmt.Sprintf("%v", node.Value) + `"` - } - return visitor.ActionNoChange, nil - }, - "BooleanValue": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.BooleanValue: - return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value) - } - return visitor.ActionNoChange, nil - }, - "EnumValue": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.EnumValue: - return visitor.ActionUpdate, fmt.Sprintf("%v", node.Value) - } - return visitor.ActionNoChange, nil - }, - "ListValue": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.ListValue: - return visitor.ActionUpdate, "[" + join(toSliceString(node.Values), ", ") + "]" - } - return visitor.ActionNoChange, nil - }, - "ObjectValue": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.ObjectValue: - return visitor.ActionUpdate, "{" + join(toSliceString(node.Fields), ", ") + "}" - } - return visitor.ActionNoChange, nil - }, - "ObjectField": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.ObjectField: - name := fmt.Sprintf("%v", node.Name) - value := fmt.Sprintf("%v", node.Value) - return visitor.ActionUpdate, name + ": " + value - } - return visitor.ActionNoChange, nil - }, - - "Directive": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.Directive: - name := fmt.Sprintf("%v", node.Name) - args := toSliceString(node.Arguments) - return visitor.ActionUpdate, "@" + name + wrap("(", join(args, ", "), ")") - } - return visitor.ActionNoChange, nil - }, - - "Named": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.Named: - return visitor.ActionUpdate, fmt.Sprintf("%v", node.Name) - } - return visitor.ActionNoChange, nil - }, - "List": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.List: - return visitor.ActionUpdate, "[" + fmt.Sprintf("%v", node.Type) + "]" - } - return visitor.ActionNoChange, nil - }, - "NonNull": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.NonNull: - return visitor.ActionUpdate, fmt.Sprintf("%v", node.Type) + "!" - } - return visitor.ActionNoChange, nil - }, - - "ObjectDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.ObjectDefinition: - name := fmt.Sprintf("%v", node.Name) - interfaces := toSliceString(node.Interfaces) - fields := node.Fields - str := "type " + name + " " + wrap("implements ", join(interfaces, ", "), " ") + block(fields) - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, - "FieldDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.FieldDefinition: - name := fmt.Sprintf("%v", node.Name) - ttype := fmt.Sprintf("%v", node.Type) - args := toSliceString(node.Arguments) - str := name + wrap("(", join(args, ", "), ")") + ": " + ttype - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, - "InputValueDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.InputValueDefinition: - name := fmt.Sprintf("%v", node.Name) - ttype := fmt.Sprintf("%v", node.Type) - defaultValue := fmt.Sprintf("%v", node.DefaultValue) - str := name + ": " + ttype + wrap(" = ", defaultValue, "") - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, - "InterfaceDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.InterfaceDefinition: - name := fmt.Sprintf("%v", node.Name) - fields := node.Fields - str := "interface " + name + " " + block(fields) - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, - "UnionDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.UnionDefinition: - name := fmt.Sprintf("%v", node.Name) - types := toSliceString(node.Types) - str := "union " + name + " = " + join(types, " | ") - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, - "ScalarDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.ScalarDefinition: - name := fmt.Sprintf("%v", node.Name) - str := "scalar " + name - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, - "EnumDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.EnumDefinition: - name := fmt.Sprintf("%v", node.Name) - values := node.Values - str := "enum " + name + " " + block(values) - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, - "EnumValueDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.EnumValueDefinition: - name := fmt.Sprintf("%v", node.Name) - return visitor.ActionUpdate, name - } - return visitor.ActionNoChange, nil - }, - "InputObjectDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.InputObjectDefinition: - name := fmt.Sprintf("%v", node.Name) - fields := node.Fields - return visitor.ActionUpdate, "input " + name + " " + block(fields) - } - return visitor.ActionNoChange, nil - }, - "TypeExtensionDefinition": func(p visitor.VisitFuncParams) (string, interface{}) { - switch node := p.Node.(type) { - case *ast.TypeExtensionDefinition: - definition := fmt.Sprintf("%v", node.Definition) - str := "extend " + definition - return visitor.ActionUpdate, str - } - return visitor.ActionNoChange, nil - }, -} - -func Print11(astNode ast.Node) (printed interface{}) { - // defer func() interface{} { - // if r := recover(); r != nil { - // log.Println("Error: %v", r) - // return printed - // } - // return printed - // }() - printed = visitor.Visit(astNode, &visitor.VisitorOptions{ - LeaveKindMap: printDocASTReducer, - }, nil) - return printed -} - -// -//func PrintMap(astNodeMap map[string]interface{}) (printed interface{}) { -// defer func() interface{} { -// if r := recover(); r != nil { -// return fmt.Sprintf("%v", astNodeMap) -// } -// return printed -// }() -// printed = visitor.Visit(astNodeMap, &visitor.VisitorOptions{ -// LeaveKindMap: printDocASTReducer, -// }, nil) -// return printed -//} diff --git a/language/printer/schema_printer_test.go b/language/printer/schema_printer_test.go index cb5b258d..3e0f6f69 100644 --- a/language/printer/schema_printer_test.go +++ b/language/printer/schema_printer_test.go @@ -53,7 +53,12 @@ func TestSchemaPrinter_PrintsKitchenSink(t *testing.T) { query := string(b) astDoc := parse(t, query) - expected := `type Foo implements Bar { + expected := `schema { + query: QueryType + mutation: MutationType +} + +type Foo implements Bar { one: Type two(argument: InputType!): Type three(argument: InputType, other: String): Int diff --git a/language/visitor/visitor.go b/language/visitor/visitor.go index 759e3c86..b59df235 100644 --- a/language/visitor/visitor.go +++ b/language/visitor/visitor.go @@ -83,6 +83,10 @@ var QueryDocumentKeys = KeyMap{ "List": []string{"Type"}, "NonNull": []string{"Type"}, + "SchemaDefinition": []string{"OperationTypes"}, + "OperationTypeDefinition": []string{"Type"}, + + "ScalarDefinition": []string{"Name"}, "ObjectDefinition": []string{ "Name", "Interfaces", @@ -106,7 +110,6 @@ var QueryDocumentKeys = KeyMap{ "Name", "Types", }, - "ScalarDefinition": []string{"Name"}, "EnumDefinition": []string{ "Name", "Values", @@ -116,8 +119,10 @@ var QueryDocumentKeys = KeyMap{ "Name", "Fields", }, + "TypeExtensionDefinition": []string{"Definition"}, - "DirectiveDefinition": []string{"Name", "Arguments", "Locations"}, + + "DirectiveDefinition": []string{"Name", "Arguments", "Locations"}, } type stack struct { diff --git a/rules.go b/rules.go index f20a3164..392b90ba 100644 --- a/rules.go +++ b/rules.go @@ -544,13 +544,13 @@ func getLocationForAppliedNode(appliedTo ast.Node) string { kind := appliedTo.GetKind() if kind == kinds.OperationDefinition { appliedTo, _ := appliedTo.(*ast.OperationDefinition) - if appliedTo.Operation == "query" { + if appliedTo.Operation == ast.OperationTypeQuery { return DirectiveLocationQuery } - if appliedTo.Operation == "mutation" { + if appliedTo.Operation == ast.OperationTypeMutation { return DirectiveLocationMutation } - if appliedTo.Operation == "subscription" { + if appliedTo.Operation == ast.OperationTypeSubscription { return DirectiveLocationSubscription } } diff --git a/schema-kitchen-sink.graphql b/schema-kitchen-sink.graphql index b67572fe..efc1b469 100644 --- a/schema-kitchen-sink.graphql +++ b/schema-kitchen-sink.graphql @@ -1,5 +1,10 @@ # Filename: schema-kitchen-sink.graphql +schema { + query: QueryType + mutation: MutationType +} + type Foo implements Bar { one: Type two(argument: InputType!): Type diff --git a/type_info.go b/type_info.go index 3c06c29b..39838295 100644 --- a/type_info.go +++ b/type_info.go @@ -110,11 +110,11 @@ func (ti *TypeInfo) Enter(node ast.Node) { } ti.directive = schema.Directive(nameVal) case *ast.OperationDefinition: - if node.Operation == "query" { + if node.Operation == ast.OperationTypeQuery { ttype = schema.QueryType() - } else if node.Operation == "mutation" { + } else if node.Operation == ast.OperationTypeMutation { ttype = schema.MutationType() - } else if node.Operation == "subscription" { + } else if node.Operation == ast.OperationTypeSubscription { ttype = schema.SubscriptionType() } ti.typeStack = append(ti.typeStack, ttype)