Skip to content

Commit e23ac77

Browse files
committed
[RFC] Add Schema Definition to IDL.
This implements the schema definition in the spec proposal in graphql/graphql-spec#90 Adjusts AST, parser, printer, visitor, but also changes the API of buildASTSchema to require a schema definition instead of passing the type names into the function. Commit: 8379e71f7011fe044574f4bdef2a761d18d6cf2c [8379e71] Parents: 176076c8a6 Author: Lee Byron <[email protected]> Date: 23 March 2016 at 7:38:15 AM SGT Labels: HEAD
1 parent d66b3f3 commit e23ac77

File tree

13 files changed

+226
-392
lines changed

13 files changed

+226
-392
lines changed

executor.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func executeOperation(p ExecuteOperationParams) *Result {
152152
Fields: fields,
153153
}
154154

155-
if p.Operation.GetOperation() == "mutation" {
155+
if p.Operation.GetOperation() == ast.OperationTypeMutation {
156156
return executeFieldsSerially(executeFieldsParams)
157157
}
158158
return executeFields(executeFieldsParams)
@@ -166,9 +166,9 @@ func getOperationRootType(schema Schema, operation ast.Definition) (*Object, err
166166
}
167167

168168
switch operation.GetOperation() {
169-
case "query":
169+
case ast.OperationTypeQuery:
170170
return schema.QueryType(), nil
171-
case "mutation":
171+
case ast.OperationTypeMutation:
172172
mutationType := schema.MutationType()
173173
if mutationType.PrivateName == "" {
174174
return nil, gqlerrors.NewError(
@@ -181,7 +181,7 @@ func getOperationRootType(schema Schema, operation ast.Definition) (*Object, err
181181
)
182182
}
183183
return mutationType, nil
184-
case "subscription":
184+
case ast.OperationTypeSubscription:
185185
subscriptionType := schema.SubscriptionType()
186186
if subscriptionType.PrivateName == "" {
187187
return nil, gqlerrors.NewError(

language/ast/definitions.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@ type Definition interface {
1515
// Ensure that all definition types implements Definition interface
1616
var _ Definition = (*OperationDefinition)(nil)
1717
var _ Definition = (*FragmentDefinition)(nil)
18-
var _ Definition = (TypeSystemDefinition)(nil)
18+
var _ Definition = (TypeSystemDefinition)(nil) // experimental non-spec addition.
19+
20+
// Note: subscription is an experimental non-spec addition.
21+
const (
22+
OperationTypeQuery = "query"
23+
OperationTypeMutation = "mutation"
24+
OperationTypeSubscription = "subscription"
25+
)
1926

2027
// OperationDefinition implements Node, Definition
2128
type OperationDefinition struct {

language/ast/node.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ var _ Node = (*Directive)(nil)
3030
var _ Node = (*Named)(nil)
3131
var _ Node = (*List)(nil)
3232
var _ Node = (*NonNull)(nil)
33+
var _ Node = (*SchemaDefinition)(nil)
34+
var _ Node = (*OperationTypeDefinition)(nil)
35+
var _ Node = (*ScalarDefinition)(nil)
3336
var _ Node = (*ObjectDefinition)(nil)
3437
var _ Node = (*FieldDefinition)(nil)
3538
var _ Node = (*InputValueDefinition)(nil)
3639
var _ Node = (*InterfaceDefinition)(nil)
3740
var _ Node = (*UnionDefinition)(nil)
38-
var _ Node = (*ScalarDefinition)(nil)
3941
var _ Node = (*EnumDefinition)(nil)
4042
var _ Node = (*EnumValueDefinition)(nil)
4143
var _ Node = (*InputObjectDefinition)(nil)

language/ast/type_definitions.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,77 @@ type TypeSystemDefinition interface {
2727
GetLoc() *Location
2828
}
2929

30+
var _ TypeSystemDefinition = (*SchemaDefinition)(nil)
3031
var _ TypeSystemDefinition = (TypeDefinition)(nil)
3132
var _ TypeSystemDefinition = (*TypeExtensionDefinition)(nil)
3233
var _ TypeSystemDefinition = (*DirectiveDefinition)(nil)
3334

35+
// SchemaDefinition implements Node, Definition
36+
type SchemaDefinition struct {
37+
Kind string
38+
Loc *Location
39+
OperationTypes []*OperationTypeDefinition
40+
}
41+
42+
func NewSchemaDefinition(def *SchemaDefinition) *SchemaDefinition {
43+
if def == nil {
44+
def = &SchemaDefinition{}
45+
}
46+
return &SchemaDefinition{
47+
Kind: kinds.SchemaDefinition,
48+
Loc: def.Loc,
49+
OperationTypes: def.OperationTypes,
50+
}
51+
}
52+
53+
func (def *SchemaDefinition) GetKind() string {
54+
return def.Kind
55+
}
56+
57+
func (def *SchemaDefinition) GetLoc() *Location {
58+
return def.Loc
59+
}
60+
61+
func (def *SchemaDefinition) GetVariableDefinitions() []*VariableDefinition {
62+
return []*VariableDefinition{}
63+
}
64+
65+
func (def *SchemaDefinition) GetSelectionSet() *SelectionSet {
66+
return &SelectionSet{}
67+
}
68+
69+
func (def *SchemaDefinition) GetOperation() string {
70+
return ""
71+
}
72+
73+
// ScalarDefinition implements Node, Definition
74+
type OperationTypeDefinition struct {
75+
Kind string
76+
Loc *Location
77+
Operation string
78+
Type *Named
79+
}
80+
81+
func NewOperationTypeDefinition(def *OperationTypeDefinition) *OperationTypeDefinition {
82+
if def == nil {
83+
def = &OperationTypeDefinition{}
84+
}
85+
return &OperationTypeDefinition{
86+
Kind: kinds.OperationTypeDefinition,
87+
Loc: def.Loc,
88+
Operation: def.Operation,
89+
Type: def.Type,
90+
}
91+
}
92+
93+
func (def *OperationTypeDefinition) GetKind() string {
94+
return def.Kind
95+
}
96+
97+
func (def *OperationTypeDefinition) GetLoc() *Location {
98+
return def.Loc
99+
}
100+
34101
// ScalarDefinition implements Node, Definition
35102
type ScalarDefinition struct {
36103
Kind string

language/kinds/kinds.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ const (
3737
NonNull = "NonNull" // previously NonNull
3838

3939
// Type System Definitions
40+
SchemaDefinition = "SchemaDefinition"
41+
OperationTypeDefinition = "OperationTypeDefinition"
4042

4143
// Types Definitions
4244
ScalarDefinition = "ScalarDefinition" // previously ScalarTypeDefinition

language/parser/parser.go

Lines changed: 85 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ func parseDocument(parser *Parser) (*ast.Document, error) {
133133
return nil, err
134134
}
135135
nodes = append(nodes, node)
136+
137+
// Note: the Type System IDL is an experimental non-spec addition.
138+
case "schema":
139+
node, err := parseSchemaDefinition(parser)
140+
if err != nil {
141+
return nil, err
142+
}
143+
nodes = append(nodes, node)
136144
case "scalar":
137145
node, err := parseScalarTypeDefinition(parser)
138146
if err != nil {
@@ -204,8 +212,6 @@ func parseDocument(parser *Parser) (*ast.Document, error) {
204212
* OperationDefinition :
205213
* - SelectionSet
206214
* - OperationType Name? VariableDefinitions? Directives? SelectionSet
207-
*
208-
* OperationType : one of query mutation
209215
*/
210216
func parseOperationDefinition(parser *Parser) (*ast.OperationDefinition, error) {
211217
start := parser.Token.Start
@@ -215,27 +221,17 @@ func parseOperationDefinition(parser *Parser) (*ast.OperationDefinition, error)
215221
return nil, err
216222
}
217223
return ast.NewOperationDefinition(&ast.OperationDefinition{
218-
Operation: "query",
224+
Operation: ast.OperationTypeQuery,
219225
Directives: []*ast.Directive{},
220226
SelectionSet: selectionSet,
221227
Loc: loc(parser, start),
222228
}), nil
223229
}
224-
operationToken, err := expect(parser, lexer.TokenKind[lexer.NAME])
230+
operation, err := parseOperationType(parser)
225231
if err != nil {
226232
return nil, err
227233
}
228-
operation := ""
229-
switch operationToken.Value {
230-
case "mutation":
231-
fallthrough
232-
case "subscription":
233-
fallthrough
234-
case "query":
235-
operation = operationToken.Value
236-
default:
237-
return nil, unexpected(parser, operationToken)
238-
}
234+
239235
var name *ast.Name
240236
if peek(parser, lexer.TokenKind[lexer.NAME]) {
241237
name, err = parseName(parser)
@@ -262,6 +258,26 @@ func parseOperationDefinition(parser *Parser) (*ast.OperationDefinition, error)
262258
}), nil
263259
}
264260

261+
/**
262+
* OperationType : one of query mutation subscription
263+
*/
264+
func parseOperationType(parser *Parser) (string, error) {
265+
operationToken, err := expect(parser, lexer.TokenKind[lexer.NAME])
266+
if err != nil {
267+
return "", err
268+
}
269+
switch operationToken.Value {
270+
case ast.OperationTypeQuery:
271+
return operationToken.Value, nil
272+
case ast.OperationTypeMutation:
273+
return operationToken.Value, nil
274+
case ast.OperationTypeSubscription:
275+
return operationToken.Value, nil
276+
default:
277+
return "", unexpected(parser, operationToken)
278+
}
279+
}
280+
265281
/**
266282
* VariableDefinitions : ( VariableDefinition+ )
267283
*/
@@ -860,6 +876,60 @@ func parseNamed(parser *Parser) (*ast.Named, error) {
860876

861877
/* Implements the parsing rules in the Type Definition section. */
862878

879+
/**
880+
* SchemaDefinition : schema { OperationTypeDefinition+ }
881+
*
882+
* OperationTypeDefinition : OperationType : NamedType
883+
*/
884+
func parseSchemaDefinition(parser *Parser) (*ast.SchemaDefinition, error) {
885+
start := parser.Token.Start
886+
_, err := expectKeyWord(parser, "schema")
887+
if err != nil {
888+
return nil, err
889+
}
890+
operationTypesI, err := many(
891+
parser,
892+
lexer.TokenKind[lexer.BRACE_L],
893+
parseOperationTypeDefinition,
894+
lexer.TokenKind[lexer.BRACE_R],
895+
)
896+
if err != nil {
897+
return nil, err
898+
}
899+
operationTypes := []*ast.OperationTypeDefinition{}
900+
for _, op := range operationTypesI {
901+
if op, ok := op.(*ast.OperationTypeDefinition); ok {
902+
operationTypes = append(operationTypes, op)
903+
}
904+
}
905+
def := ast.NewSchemaDefinition(&ast.SchemaDefinition{
906+
OperationTypes: operationTypes,
907+
Loc: loc(parser, start),
908+
})
909+
return def, nil
910+
}
911+
912+
func parseOperationTypeDefinition(parser *Parser) (interface{}, error) {
913+
start := parser.Token.Start
914+
operation, err := parseOperationType(parser)
915+
if err != nil {
916+
return nil, err
917+
}
918+
_, err = expect(parser, lexer.TokenKind[lexer.COLON])
919+
if err != nil {
920+
return nil, err
921+
}
922+
ttype, err := parseNamed(parser)
923+
if err != nil {
924+
return nil, err
925+
}
926+
return ast.NewOperationTypeDefinition(&ast.OperationTypeDefinition{
927+
Operation: operation,
928+
Type: ttype,
929+
Loc: loc(parser, start),
930+
}), nil
931+
}
932+
863933
/**
864934
* ScalarTypeDefinition : scalar Name
865935
*/

language/printer/printer.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/graphql-go/graphql/language/ast"
88
"github.com/graphql-go/graphql/language/visitor"
9+
"github.com/kr/pretty"
910
"reflect"
1011
)
1112

@@ -146,7 +147,7 @@ var printDocASTReducer = map[string]visitor.VisitFunc{
146147
"OperationDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
147148
switch node := p.Node.(type) {
148149
case *ast.OperationDefinition:
149-
op := node.Operation
150+
op := string(node.Operation)
150151
name := fmt.Sprintf("%v", node.Name)
151152

152153
varDefs := wrap("(", join(toSliceString(node.VariableDefinitions), ", "), ")")
@@ -155,7 +156,7 @@ var printDocASTReducer = map[string]visitor.VisitFunc{
155156
// Anonymous queries with no directives or variable definitions can use
156157
// the query short form.
157158
str := ""
158-
if name == "" && directives == "" && varDefs == "" && op == "query" {
159+
if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery {
159160
str = selectionSet
160161
} else {
161162
str = join([]string{
@@ -175,7 +176,7 @@ var printDocASTReducer = map[string]visitor.VisitFunc{
175176
directives := join(toSliceString(getMapValue(node, "Directives")), " ")
176177
selectionSet := getMapValueString(node, "SelectionSet")
177178
str := ""
178-
if name == "" && directives == "" && varDefs == "" && op == "query" {
179+
if name == "" && directives == "" && varDefs == "" && op == ast.OperationTypeQuery {
179180
str = selectionSet
180181
} else {
181182
str = join([]string{
@@ -433,6 +434,35 @@ var printDocASTReducer = map[string]visitor.VisitFunc{
433434
},
434435

435436
// Type System Definitions
437+
"SchemaDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
438+
pretty.Println("===SchemaDefinitions", p.Node)
439+
switch node := p.Node.(type) {
440+
case *ast.SchemaDefinition:
441+
operationTypesBlock := block(node.OperationTypes)
442+
str := fmt.Sprintf("schema %v", operationTypesBlock)
443+
return visitor.ActionUpdate, str
444+
case map[string]interface{}:
445+
operationTypes := toSliceString(getMapValue(node, "OperationTypes"))
446+
operationTypesBlock := block(operationTypes)
447+
str := fmt.Sprintf("schema %v", operationTypesBlock)
448+
return visitor.ActionUpdate, str
449+
}
450+
return visitor.ActionNoChange, nil
451+
},
452+
"OperationTypeDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
453+
pretty.Println("===OperationTypeDefinition", p.Node)
454+
switch node := p.Node.(type) {
455+
case *ast.OperationTypeDefinition:
456+
str := fmt.Sprintf("%v: %v", node.Operation, node.Type)
457+
return visitor.ActionUpdate, str
458+
case map[string]interface{}:
459+
operation := getMapValueString(node, "Operation")
460+
ttype := getMapValueString(node, "Type")
461+
str := fmt.Sprintf("%v: %v", operation, ttype)
462+
return visitor.ActionUpdate, str
463+
}
464+
return visitor.ActionNoChange, nil
465+
},
436466
"ScalarDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
437467
switch node := p.Node.(type) {
438468
case *ast.ScalarDefinition:

0 commit comments

Comments
 (0)