Skip to content

Commit

Permalink
[RFC] Add Schema Definition to IDL.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sogko committed May 30, 2016
1 parent d66b3f3 commit e23ac77
Show file tree
Hide file tree
Showing 13 changed files with 226 additions and 392 deletions.
8 changes: 4 additions & 4 deletions executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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(
Expand All @@ -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(
Expand Down
9 changes: 8 additions & 1 deletion language/ast/definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 3 additions & 1 deletion language/ast/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
67 changes: 67 additions & 0 deletions language/ast/type_definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions language/kinds/kinds.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const (
NonNull = "NonNull" // previously NonNull

// Type System Definitions
SchemaDefinition = "SchemaDefinition"
OperationTypeDefinition = "OperationTypeDefinition"

// Types Definitions
ScalarDefinition = "ScalarDefinition" // previously ScalarTypeDefinition
Expand Down
100 changes: 85 additions & 15 deletions language/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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+ )
*/
Expand Down Expand Up @@ -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
*/
Expand Down
36 changes: 33 additions & 3 deletions language/printer/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/graphql-go/graphql/language/ast"
"github.com/graphql-go/graphql/language/visitor"
"github.com/kr/pretty"
"reflect"
)

Expand Down Expand Up @@ -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), ", "), ")")
Expand All @@ -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{
Expand All @@ -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{
Expand Down Expand Up @@ -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:
Expand Down
Loading

0 comments on commit e23ac77

Please sign in to comment.