Skip to content

Commit 988ab2e

Browse files
committed
RFC: Directive location: schema definition (#382)
This allows directives to be defined on schema definitions. Commit: 0aa78f61a2dc150b5ea9ee4f50b68a736796f068 [0aa78f6] Parents: 1b6824bc5d Author: Lee Byron <[email protected]> Date: 7 May 2016 at 7:05:27 AM SGT Labels: HEAD
1 parent 9cbbd65 commit 988ab2e

File tree

9 files changed

+53
-9
lines changed

9 files changed

+53
-9
lines changed

directives.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const (
1111
DirectiveLocationInlineFragment = "INLINE_FRAGMENT"
1212

1313
// Schema Definitions
14+
DirectiveLocationSchema = "SCHEMA"
1415
DirectiveLocationScalar = "SCALAR"
1516
DirectiveLocationObject = "OBJECT"
1617
DirectiveLocationFieldDefinition = "FIELD_DEFINITION"

introspection.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ func init() {
135135
Value: DirectiveLocationInlineFragment,
136136
Description: "Location adjacent to an inline fragment.",
137137
},
138+
"SCHEMA": &EnumValueConfig{
139+
Value: DirectiveLocationSchema,
140+
Description: "Location adjacent to a schema definition.",
141+
},
138142
"SCALAR": &EnumValueConfig{
139143
Value: DirectiveLocationScalar,
140144
Description: "Location adjacent to a scalar definition.",

language/ast/type_definitions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var _ TypeSystemDefinition = (*DirectiveDefinition)(nil)
3636
type SchemaDefinition struct {
3737
Kind string
3838
Loc *Location
39+
Directives []*Directive
3940
OperationTypes []*OperationTypeDefinition
4041
}
4142

@@ -46,6 +47,7 @@ func NewSchemaDefinition(def *SchemaDefinition) *SchemaDefinition {
4647
return &SchemaDefinition{
4748
Kind: kinds.SchemaDefinition,
4849
Loc: def.Loc,
50+
Directives: def.Directives,
4951
OperationTypes: def.OperationTypes,
5052
}
5153
}

language/parser/parser.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,7 @@ func parseNamed(parser *Parser) (*ast.Named, error) {
877877
/* Implements the parsing rules in the Type Definition section. */
878878

879879
/**
880-
* SchemaDefinition : schema { OperationTypeDefinition+ }
880+
* SchemaDefinition : schema Directives? { OperationTypeDefinition+ }
881881
*
882882
* OperationTypeDefinition : OperationType : NamedType
883883
*/
@@ -887,6 +887,10 @@ func parseSchemaDefinition(parser *Parser) (*ast.SchemaDefinition, error) {
887887
if err != nil {
888888
return nil, err
889889
}
890+
directives, err := parseDirectives(parser)
891+
if err != nil {
892+
return nil, err
893+
}
890894
operationTypesI, err := many(
891895
parser,
892896
lexer.TokenKind[lexer.BRACE_L],
@@ -902,11 +906,11 @@ func parseSchemaDefinition(parser *Parser) (*ast.SchemaDefinition, error) {
902906
operationTypes = append(operationTypes, op)
903907
}
904908
}
905-
def := ast.NewSchemaDefinition(&ast.SchemaDefinition{
909+
return ast.NewSchemaDefinition(&ast.SchemaDefinition{
906910
OperationTypes: operationTypes,
911+
Directives: directives,
907912
Loc: loc(parser, start),
908-
})
909-
return def, nil
913+
}), nil
910914
}
911915

912916
func parseOperationTypeDefinition(parser *Parser) (interface{}, error) {

language/printer/printer.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,13 +455,27 @@ var printDocASTReducer = map[string]visitor.VisitFunc{
455455
"SchemaDefinition": func(p visitor.VisitFuncParams) (string, interface{}) {
456456
switch node := p.Node.(type) {
457457
case *ast.SchemaDefinition:
458-
operationTypesBlock := block(node.OperationTypes)
459-
str := fmt.Sprintf("schema %v", operationTypesBlock)
458+
directives := []string{}
459+
for _, directive := range node.Directives {
460+
directives = append(directives, fmt.Sprintf("%v", directive.Name))
461+
}
462+
str := join([]string{
463+
"schema",
464+
join(directives, " "),
465+
block(node.OperationTypes),
466+
}, " ")
460467
return visitor.ActionUpdate, str
461468
case map[string]interface{}:
462469
operationTypes := toSliceString(getMapValue(node, "OperationTypes"))
463-
operationTypesBlock := block(operationTypes)
464-
str := fmt.Sprintf("schema %v", operationTypesBlock)
470+
directives := []string{}
471+
for _, directive := range getMapSliceValue(node, "Directives") {
472+
directives = append(directives, fmt.Sprintf("%v", directive))
473+
}
474+
str := join([]string{
475+
"schema",
476+
join(directives, " "),
477+
block(operationTypes),
478+
}, " ")
465479
return visitor.ActionUpdate, str
466480
}
467481
return visitor.ActionNoChange, nil

language/visitor/visitor.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ var QueryDocumentKeys = KeyMap{
8383
"List": []string{"Type"},
8484
"NonNull": []string{"Type"},
8585

86-
"SchemaDefinition": []string{"OperationTypes"},
86+
"SchemaDefinition": []string{
87+
"Directives",
88+
"OperationTypes",
89+
},
8790
"OperationTypeDefinition": []string{"Type"},
8891

8992
"ScalarDefinition": []string{

rules.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,9 @@ func getDirectiveLocationForASTPath(ancestors []ast.Node) string {
617617
if kind == kinds.FragmentDefinition {
618618
return DirectiveLocationFragmentDefinition
619619
}
620+
if kind == kinds.SchemaDefinition {
621+
return DirectiveLocationSchema
622+
}
620623
if kind == kinds.ScalarDefinition {
621624
return DirectiveLocationScalar
622625
}

rules_known_directives_rule_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ func TestValidate_KnownDirectives_WithinSchemaLanguage_WithWellPlacedDirectives(
115115
input MyInput @onInputObject {
116116
myField: Int @onInputFieldDefinition
117117
}
118+
119+
schema @onSchema {
120+
query: MyQuery
121+
}
118122
`)
119123
}
120124

@@ -139,6 +143,10 @@ func TestValidate_KnownDirectives_WithinSchemaLanguage_WithMisplacedDirectives(t
139143
input MyInput @onEnum {
140144
myField: Int @onArgumentDefinition
141145
}
146+
147+
schema @onObject {
148+
query: MyQuery
149+
}
142150
`, []gqlerrors.FormattedError{
143151
testutil.RuleError(`Directive "onInterface" may not be used on OBJECT.`, 2, 43),
144152
testutil.RuleError(`Directive "onInputFieldDefinition" may not be used on ARGUMENT_DEFINITION.`, 3, 30),
@@ -152,5 +160,6 @@ func TestValidate_KnownDirectives_WithinSchemaLanguage_WithMisplacedDirectives(t
152160
testutil.RuleError(`Directive "onUnion" may not be used on ENUM_VALUE.`, 15, 20),
153161
testutil.RuleError(`Directive "onEnum" may not be used on INPUT_OBJECT.`, 18, 23),
154162
testutil.RuleError(`Directive "onArgumentDefinition" may not be used on INPUT_FIELD_DEFINITION.`, 19, 24),
163+
testutil.RuleError(`Directive "onObject" may not be used on SCHEMA.`, 22, 16),
155164
})
156165
}

testutil/rules_test_harness.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,10 @@ func init() {
485485
Name: "onInlineFragment",
486486
Locations: []string{graphql.DirectiveLocationInlineFragment},
487487
}),
488+
graphql.NewDirective(graphql.DirectiveConfig{
489+
Name: "onSchema",
490+
Locations: []string{graphql.DirectiveLocationSchema},
491+
}),
488492
graphql.NewDirective(graphql.DirectiveConfig{
489493
Name: "onScalar",
490494
Locations: []string{graphql.DirectiveLocationScalar},

0 commit comments

Comments
 (0)