@@ -25,6 +25,10 @@ const OpenTracingTagTrivial = "graphql.trivial"
2525const OpenTracingTagArgsPrefix = "graphql.args."
2626const OpenTracingTagError = "graphql.error"
2727
28+ type contextKey string
29+
30+ const ResolverFields contextKey = "Resolver_Fields"
31+
2832type Exec struct {
2933 queryExec iExec
3034 mutationExec iExec
@@ -494,12 +498,14 @@ func (e *objectExec) execSelectionSet(ctx context.Context, r *request, selSet *q
494498
495499 switch sel := sel .(type ) {
496500 case * query.Field :
501+ namedFields := make (map [string ]struct {})
497502 if skipByDirective (r , sel .Directives ) {
498503 continue
499504 }
500505
506+ namedFields = resolveFieldNames ("" , namedFields , sel .SelSet , r .doc )
501507 execSel (func () {
502- e .execField (ctx , r , sel , resolver , addResult )
508+ e .execField (context . WithValue ( ctx , ResolverFields , namedFields ) , r , sel , resolver , addResult )
503509 })
504510
505511 case * query.FragmentSpread :
@@ -533,6 +539,32 @@ func (e *objectExec) execSelectionSet(ctx context.Context, r *request, selSet *q
533539 wg .Wait ()
534540}
535541
542+ func resolveFieldNames (prefix string , namedFields map [string ]struct {}, selSet * query.SelectionSet , doc * query.Document ) map [string ]struct {} {
543+ if selSet != nil {
544+ for _ , selectionField := range selSet .Selections {
545+ switch selectionField := selectionField .(type ) {
546+ case * query.Field :
547+ if selectionField .SelSet != nil {
548+ namedFields = resolveFieldNames (selectionField .Name + "." , namedFields , selectionField .SelSet , doc )
549+ } else {
550+ namedFields [prefix + selectionField .Name ] = struct {}{}
551+ }
552+ case * query.FragmentSpread :
553+ frag , ok := doc .Fragments [selectionField .Name ]
554+ if ! ok {
555+ panic (fmt .Errorf ("fragment %q not found" , selectionField .Name )) // TODO proper error handling
556+ }
557+ namedFields = resolveFieldNames (prefix , namedFields , frag .SelSet , doc )
558+ case * query.InlineFragment :
559+ namedFields = resolveFieldNames (prefix , namedFields , selectionField .SelSet , doc )
560+ default :
561+ panic ("invalid type" )
562+ }
563+ }
564+ }
565+ return namedFields
566+ }
567+
536568func (e * objectExec ) execField (ctx context.Context , r * request , f * query.Field , resolver reflect.Value , addResult addResultFn ) {
537569 switch f .Name {
538570 case "__typename" :
0 commit comments