@@ -72,9 +72,9 @@ type NamedType interface {
72
72
//
73
73
// http://facebook.github.io/graphql/draft/#sec-Scalars
74
74
type Scalar struct {
75
- Name string
76
- Desc string
77
- // TODO: Add a list of directives?
75
+ Name string
76
+ Desc string
77
+ Directives common. DirectiveList
78
78
}
79
79
80
80
// Object types represent a list of named fields, each of which yield a value of a specific type.
@@ -89,7 +89,7 @@ type Object struct {
89
89
Interfaces []* Interface
90
90
Fields FieldList
91
91
Desc string
92
- // TODO: Add a list of directives?
92
+ Directives common. DirectiveList
93
93
94
94
interfaceNames []string
95
95
}
@@ -105,7 +105,7 @@ type Interface struct {
105
105
PossibleTypes []* Object
106
106
Fields FieldList // NOTE: the spec refers to this as `FieldsDefinition`.
107
107
Desc string
108
- // TODO: Add a list of directives?
108
+ Directives common. DirectiveList
109
109
}
110
110
111
111
// Union types represent objects that could be one of a list of GraphQL object types, but provides no
@@ -119,7 +119,7 @@ type Union struct {
119
119
Name string
120
120
PossibleTypes []* Object // NOTE: the spec refers to this as `UnionMemberTypes`.
121
121
Desc string
122
- // TODO: Add a list of directives?
122
+ Directives common. DirectiveList
123
123
124
124
typeNames []string
125
125
}
@@ -130,10 +130,10 @@ type Union struct {
130
130
//
131
131
// http://facebook.github.io/graphql/draft/#sec-Enums
132
132
type Enum struct {
133
- Name string
134
- Values []* EnumValue // NOTE: the spec refers to this as `EnumValuesDefinition`.
135
- Desc string
136
- // TODO: Add a list of directives?
133
+ Name string
134
+ Values []* EnumValue // NOTE: the spec refers to this as `EnumValuesDefinition`.
135
+ Desc string
136
+ Directives common. DirectiveList
137
137
}
138
138
139
139
// EnumValue types are unique values that may be serialized as a string: the name of the
@@ -144,7 +144,6 @@ type EnumValue struct {
144
144
Name string
145
145
Directives common.DirectiveList
146
146
Desc string
147
- // TODO: Add a list of directives?
148
147
}
149
148
150
149
// InputObject types define a set of input fields; the input fields are either scalars, enums, or
@@ -154,19 +153,19 @@ type EnumValue struct {
154
153
//
155
154
// http://facebook.github.io/graphql/draft/#sec-Input-Objects
156
155
type InputObject struct {
157
- Name string
158
- Desc string
159
- Values common.InputValueList
160
- // TODO: Add a list of directives?
156
+ Name string
157
+ Desc string
158
+ Values common.InputValueList
159
+ Directives common. DirectiveList
161
160
}
162
161
163
162
// Extension type defines a GraphQL type extension.
164
163
// Schemas, Objects, Inputs and Scalars can be extended.
165
164
//
166
165
// https://facebook.github.io/graphql/draft/#sec-Type-System-Extensions
167
166
type Extension struct {
168
- Type NamedType
169
- // TODO: Add a list of directives
167
+ Type NamedType
168
+ Directives common. DirectiveList
170
169
}
171
170
172
171
// FieldsList is a list of an Object's Fields.
@@ -314,6 +313,14 @@ func (s *Schema) Parse(schemaString string, useStringDescriptions bool) error {
314
313
315
314
for _ , obj := range s .objects {
316
315
obj .Interfaces = make ([]* Interface , len (obj .interfaceNames ))
316
+ if err := resolveDirectives (s , obj .Directives , "OBJECT" ); err != nil {
317
+ return err
318
+ }
319
+ for _ , field := range obj .Fields {
320
+ if err := resolveDirectives (s , field .Directives , "FIELD_DEFINITION" ); err != nil {
321
+ return err
322
+ }
323
+ }
317
324
for i , intfName := range obj .interfaceNames {
318
325
t , ok := s .Types [intfName ]
319
326
if ! ok {
@@ -334,6 +341,9 @@ func (s *Schema) Parse(schemaString string, useStringDescriptions bool) error {
334
341
}
335
342
336
343
for _ , union := range s .unions {
344
+ if err := resolveDirectives (s , union .Directives , "UNION" ); err != nil {
345
+ return err
346
+ }
337
347
union .PossibleTypes = make ([]* Object , len (union .typeNames ))
338
348
for i , name := range union .typeNames {
339
349
t , ok := s .Types [name ]
@@ -349,8 +359,11 @@ func (s *Schema) Parse(schemaString string, useStringDescriptions bool) error {
349
359
}
350
360
351
361
for _ , enum := range s .enums {
362
+ if err := resolveDirectives (s , enum .Directives , "ENUM" ); err != nil {
363
+ return err
364
+ }
352
365
for _ , value := range enum .Values {
353
- if err := resolveDirectives (s , value .Directives ); err != nil {
366
+ if err := resolveDirectives (s , value .Directives , "ENUM_VALUE" ); err != nil {
354
367
return err
355
368
}
356
369
}
@@ -469,19 +482,29 @@ func resolveField(s *Schema, f *Field) error {
469
482
return err
470
483
}
471
484
f .Type = t
472
- if err := resolveDirectives (s , f .Directives ); err != nil {
485
+ if err := resolveDirectives (s , f .Directives , "FIELD_DEFINITION" ); err != nil {
473
486
return err
474
487
}
475
488
return resolveInputObject (s , f .Args )
476
489
}
477
490
478
- func resolveDirectives (s * Schema , directives common.DirectiveList ) error {
491
+ func resolveDirectives (s * Schema , directives common.DirectiveList , loc string ) error {
479
492
for _ , d := range directives {
480
493
dirName := d .Name .Name
481
494
dd , ok := s .Directives [dirName ]
482
495
if ! ok {
483
496
return errors .Errorf ("directive %q not found" , dirName )
484
497
}
498
+ validLoc := false
499
+ for _ , l := range dd .Locs {
500
+ if l == loc {
501
+ validLoc = true
502
+ break
503
+ }
504
+ }
505
+ if ! validLoc {
506
+ return errors .Errorf ("invalid location %q for directive %q (must be one of %v)" , loc , dirName , dd .Locs )
507
+ }
485
508
for _ , arg := range d .Args {
486
509
if dd .Args .Get (arg .Name .Name ) == nil {
487
510
return errors .Errorf ("invalid argument %q for directive %q" , arg .Name .Name , dirName )
@@ -554,7 +577,8 @@ func parseSchema(s *Schema, l *common.Lexer) {
554
577
555
578
case "scalar" :
556
579
name := l .ConsumeIdent ()
557
- s .Types [name ] = & Scalar {Name : name , Desc : desc }
580
+ directives := common .ParseDirectives (l )
581
+ s .Types [name ] = & Scalar {Name : name , Desc : desc , Directives : directives }
558
582
559
583
case "directive" :
560
584
directive := parseDirectiveDef (l )
@@ -574,16 +598,30 @@ func parseSchema(s *Schema, l *common.Lexer) {
574
598
func parseObjectDef (l * common.Lexer ) * Object {
575
599
object := & Object {Name : l .ConsumeIdent ()}
576
600
577
- if l .Peek () == scanner .Ident {
578
- l .ConsumeKeyword ("implements" )
601
+ for {
602
+ if l .Peek () == '{' {
603
+ break
604
+ }
579
605
580
- for l .Peek () != '{' {
581
- if l .Peek () == '&' {
582
- l .ConsumeToken ('&' )
583
- }
606
+ if l .Peek () == '@' {
607
+ object .Directives = common .ParseDirectives (l )
608
+ continue
609
+ }
610
+
611
+ if l .Peek () == scanner .Ident {
612
+ l .ConsumeKeyword ("implements" )
584
613
585
- object .interfaceNames = append (object .interfaceNames , l .ConsumeIdent ())
614
+ for l .Peek () != '{' && l .Peek () != '@' {
615
+ if l .Peek () == '&' {
616
+ l .ConsumeToken ('&' )
617
+ }
618
+
619
+ object .interfaceNames = append (object .interfaceNames , l .ConsumeIdent ())
620
+ }
621
+ continue
586
622
}
623
+
624
+ l .SyntaxError (fmt .Sprintf (`unexpected %q, expecting "implements", "directive" or "{"` , l .Peek ()))
587
625
}
588
626
589
627
l .ConsumeToken ('{' )
@@ -596,6 +634,7 @@ func parseObjectDef(l *common.Lexer) *Object {
596
634
func parseInterfaceDef (l * common.Lexer ) * Interface {
597
635
i := & Interface {Name : l .ConsumeIdent ()}
598
636
637
+ i .Directives = common .ParseDirectives (l )
599
638
l .ConsumeToken ('{' )
600
639
i .Fields = parseFieldsDef (l )
601
640
l .ConsumeToken ('}' )
@@ -606,6 +645,7 @@ func parseInterfaceDef(l *common.Lexer) *Interface {
606
645
func parseUnionDef (l * common.Lexer ) * Union {
607
646
union := & Union {Name : l .ConsumeIdent ()}
608
647
648
+ union .Directives = common .ParseDirectives (l )
609
649
l .ConsumeToken ('=' )
610
650
union .typeNames = []string {l .ConsumeIdent ()}
611
651
for l .Peek () == '|' {
@@ -619,6 +659,7 @@ func parseUnionDef(l *common.Lexer) *Union {
619
659
func parseInputDef (l * common.Lexer ) * InputObject {
620
660
i := & InputObject {}
621
661
i .Name = l .ConsumeIdent ()
662
+ i .Directives = common .ParseDirectives (l )
622
663
l .ConsumeToken ('{' )
623
664
for l .Peek () != '}' {
624
665
i .Values = append (i .Values , common .ParseInputValue (l ))
@@ -630,6 +671,7 @@ func parseInputDef(l *common.Lexer) *InputObject {
630
671
func parseEnumDef (l * common.Lexer ) * Enum {
631
672
enum := & Enum {Name : l .ConsumeIdent ()}
632
673
674
+ enum .Directives = common .ParseDirectives (l )
633
675
l .ConsumeToken ('{' )
634
676
for l .Peek () != '}' {
635
677
v := & EnumValue {
0 commit comments