Skip to content

Commit

Permalink
added support for use_function_syntax_for_execution_context (#3407)
Browse files Browse the repository at this point in the history
* introduced usefunctionsyntaxforexecutioncontext

* added coverage execption for testdata

* updated test cases to resolve linting issues in them

* fixed lint issues and test failures
  • Loading branch information
kanodia-parag authored Dec 9, 2024
1 parent f29901a commit b9e4d51
Show file tree
Hide file tree
Showing 33 changed files with 16,814 additions and 40 deletions.
28 changes: 27 additions & 1 deletion codegen/args.gotpl
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
{{ $useFunctionSyntaxForExecutionContext := .Config.UseFunctionSyntaxForExecutionContext }}

{{ range $name, $args := .Args }}
{{ if $useFunctionSyntaxForExecutionContext -}}
func {{ $name }}(ctx context.Context, ec *executionContext, rawArgs map[string]interface{}) (map[string]interface{}, error) {
{{- else -}}
func (ec *executionContext) {{ $name }}(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
{{- end }}
var err error
args := map[string]interface{}{}

{{- range $i, $arg := . }}
{{ if $useFunctionSyntaxForExecutionContext -}}
arg{{$i}}, err := {{ $name }}{{$arg.Name | go}}(ctx, ec, rawArgs)
{{- else -}}
arg{{$i}}, err := ec.{{ $name }}{{$arg.Name | go}}(ctx, rawArgs)
{{- end }}
if err != nil {
return nil, err
}
Expand All @@ -14,10 +24,18 @@ func (ec *executionContext) {{ $name }}(ctx context.Context, rawArgs map[string]
}

{{- range $i, $arg := . }}
{{ if $useFunctionSyntaxForExecutionContext -}}
func {{ $name }}{{$arg.Name | go}}(
ctx context.Context,
ec *executionContext,
rawArgs map[string]interface{},
) ({{ $arg.TypeReference.GO | ref}}, error) {
{{- else -}}
func (ec *executionContext) {{ $name }}{{$arg.Name | go}}(
ctx context.Context,
rawArgs map[string]interface{},
) ({{ $arg.TypeReference.GO | ref}}, error) {
{{- end }}
{{- if not .CallArgumentDirectivesWithNull}}
// We won't call the directive if the argument is null.
// Set call_argument_directives_with_null to true to call directives
Expand All @@ -36,9 +54,13 @@ func (ec *executionContext) {{ $name }}(ctx context.Context, rawArgs map[string]
var zeroVal {{ $arg.TypeReference.GO | ref}}
return zeroVal, nil
}
{{ if $useFunctionSyntaxForExecutionContext -}}
return {{ $arg.TypeReference.UnmarshalFunc }}(ctx, ec, tmp)
{{- else -}}
return ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, tmp)
{{- end }}
}
{{ template "implDirectives" $arg }}
{{ template "implDirectives" (dict "Field" $arg "UseFunctionSyntaxForExecutionContext" $useFunctionSyntaxForExecutionContext) }}
tmp, err := directive{{$arg.ImplDirectives|len}}(ctx)
if err != nil {
var zeroVal {{ $arg.TypeReference.GO | ref}}
Expand All @@ -57,7 +79,11 @@ func (ec *executionContext) {{ $name }}(ctx context.Context, rawArgs map[string]
}
{{- else }}
if tmp, ok := rawArgs[{{$arg.Name|quote}}]; ok {
{{ if $useFunctionSyntaxForExecutionContext -}}
return {{ $arg.TypeReference.UnmarshalFunc }}(ctx, ec, tmp)
{{- else -}}
return ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, tmp)
{{- end }}
}

var zeroVal {{ $arg.TypeReference.GO | ref}}
Expand Down
41 changes: 21 additions & 20 deletions codegen/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,27 @@ import (
)

type Config struct {
SchemaFilename StringList `yaml:"schema,omitempty"`
Exec ExecConfig `yaml:"exec"`
Model PackageConfig `yaml:"model,omitempty"`
Federation PackageConfig `yaml:"federation,omitempty"`
Resolver ResolverConfig `yaml:"resolver,omitempty"`
AutoBind []string `yaml:"autobind"`
Models TypeMap `yaml:"models,omitempty"`
StructTag string `yaml:"struct_tag,omitempty"`
Directives map[string]DirectiveConfig `yaml:"directives,omitempty"`
GoBuildTags StringList `yaml:"go_build_tags,omitempty"`
GoInitialisms GoInitialismsConfig `yaml:"go_initialisms,omitempty"`
OmitSliceElementPointers bool `yaml:"omit_slice_element_pointers,omitempty"`
OmitGetters bool `yaml:"omit_getters,omitempty"`
OmitInterfaceChecks bool `yaml:"omit_interface_checks,omitempty"`
OmitComplexity bool `yaml:"omit_complexity,omitempty"`
OmitGQLGenFileNotice bool `yaml:"omit_gqlgen_file_notice,omitempty"`
OmitGQLGenVersionInFileNotice bool `yaml:"omit_gqlgen_version_in_file_notice,omitempty"`
OmitRootModels bool `yaml:"omit_root_models,omitempty"`
OmitResolverFields bool `yaml:"omit_resolver_fields,omitempty"`
OmitPanicHandler bool `yaml:"omit_panic_handler,omitempty"`
SchemaFilename StringList `yaml:"schema,omitempty"`
Exec ExecConfig `yaml:"exec"`
Model PackageConfig `yaml:"model,omitempty"`
Federation PackageConfig `yaml:"federation,omitempty"`
Resolver ResolverConfig `yaml:"resolver,omitempty"`
AutoBind []string `yaml:"autobind"`
Models TypeMap `yaml:"models,omitempty"`
StructTag string `yaml:"struct_tag,omitempty"`
Directives map[string]DirectiveConfig `yaml:"directives,omitempty"`
GoBuildTags StringList `yaml:"go_build_tags,omitempty"`
GoInitialisms GoInitialismsConfig `yaml:"go_initialisms,omitempty"`
OmitSliceElementPointers bool `yaml:"omit_slice_element_pointers,omitempty"`
OmitGetters bool `yaml:"omit_getters,omitempty"`
OmitInterfaceChecks bool `yaml:"omit_interface_checks,omitempty"`
OmitComplexity bool `yaml:"omit_complexity,omitempty"`
OmitGQLGenFileNotice bool `yaml:"omit_gqlgen_file_notice,omitempty"`
OmitGQLGenVersionInFileNotice bool `yaml:"omit_gqlgen_version_in_file_notice,omitempty"`
OmitRootModels bool `yaml:"omit_root_models,omitempty"`
OmitResolverFields bool `yaml:"omit_resolver_fields,omitempty"`
OmitPanicHandler bool `yaml:"omit_panic_handler,omitempty"`
UseFunctionSyntaxForExecutionContext bool `yaml:"use_function_syntax_for_execution_context,omitempty"`
// If this is set to true, argument directives that
// decorate a field with a null value will still be called.
//
Expand Down
53 changes: 47 additions & 6 deletions codegen/directives.gotpl
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
{{ define "implDirectives" }}{{ $in := .DirectiveObjName }}
{{ $zeroVal := .TypeReference.GO | ref}}
{{- range $i, $directive := .ImplDirectives -}}
{{ $useFunctionSyntaxForExecutionContext := .Config.UseFunctionSyntaxForExecutionContext }}

{{ define "implDirectives" }}
{{ $in := .Field.DirectiveObjName }}
{{ $useFunctionSyntaxForExecutionContext := .UseFunctionSyntaxForExecutionContext }}
{{ $zeroVal := .Field.TypeReference.GO | ref}}
{{- range $i, $directive := .Field.ImplDirectives -}}
directive{{add $i 1}} := func(ctx context.Context) (interface{}, error) {
{{- range $arg := $directive.Args }}
{{- if notNil "Value" $arg }}
{{ if $useFunctionSyntaxForExecutionContext -}}
{{ $arg.VarName }}, err := {{ $arg.TypeReference.UnmarshalFunc }}(ctx, ec, {{ $arg.Value | dump }})
{{- else -}}
{{ $arg.VarName }}, err := ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, {{ $arg.Value | dump }})
{{- end }}
if err != nil{
var zeroVal {{$zeroVal}}
return zeroVal, err
}
{{- else if notNil "Default" $arg }}
{{ if $useFunctionSyntaxForExecutionContext -}}
{{ $arg.VarName }}, err := {{ $arg.TypeReference.UnmarshalFunc }}(ctx, ec, {{ $arg.Default | dump }})
{{- else -}}
{{ $arg.VarName }}, err := ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, {{ $arg.Default | dump }})
{{- end }}
if err != nil{
var zeroVal {{$zeroVal}}
return zeroVal, err
Expand All @@ -29,13 +41,18 @@
{{ end }}

{{define "queryDirectives"}}
{{ $useFunctionSyntaxForExecutionContext := .UseFunctionSyntaxForExecutionContext }}
for _, d := range obj.Directives {
switch d.Name {
{{- range $directive := . }}
{{- range $directive := .DirectiveList }}
case "{{$directive.Name}}":
{{- if $directive.Args }}
rawArgs := d.ArgumentMap(ec.Variables)
{{ if $useFunctionSyntaxForExecutionContext -}}
args, err := {{ $directive.ArgsFunc }}(ctx,ec,rawArgs)
{{- else -}}
args, err := ec.{{ $directive.ArgsFunc }}(ctx,rawArgs)
{{- end }}
if err != nil {
ec.Error(ctx, err)
return graphql.Null
Expand Down Expand Up @@ -70,26 +87,42 @@
{{end}}

{{ if .Directives.LocationDirectives "QUERY" }}
{{ if $useFunctionSyntaxForExecutionContext -}}
func _queryMiddleware(ctx context.Context, ec *executionContext, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) graphql.Marshaler {
{{- else -}}
func (ec *executionContext) _queryMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) graphql.Marshaler {
{{ template "queryDirectives" .Directives.LocationDirectives "QUERY" }}
{{- end }}
{{ template "queryDirectives" (dict "DirectiveList" (.Directives.LocationDirectives "QUERY") "UseFunctionSyntaxForExecutionContext" $useFunctionSyntaxForExecutionContext) }}
}
{{ end }}

{{ if .Directives.LocationDirectives "MUTATION" }}
{{ if $useFunctionSyntaxForExecutionContext -}}
func _mutationMiddleware(ctx context.Context, ec *executionContext, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) graphql.Marshaler {
{{- else -}}
func (ec *executionContext) _mutationMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) graphql.Marshaler {
{{ template "queryDirectives" .Directives.LocationDirectives "MUTATION" }}
{{- end }}
{{ template "queryDirectives" (dict "DirectiveList" (.Directives.LocationDirectives "MUTATION") "UseFunctionSyntaxForExecutionContext" $useFunctionSyntaxForExecutionContext) }}
}
{{ end }}

{{ if .Directives.LocationDirectives "SUBSCRIPTION" }}
{{ if $useFunctionSyntaxForExecutionContext -}}
func _subscriptionMiddleware(ctx context.Context, ec *executionContext, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) func(ctx context.Context) graphql.Marshaler {
{{- else -}}
func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) func(ctx context.Context) graphql.Marshaler {
{{- end }}
for _, d := range obj.Directives {
switch d.Name {
{{- range $directive := .Directives.LocationDirectives "SUBSCRIPTION" }}
case "{{$directive.Name}}":
{{- if $directive.Args }}
rawArgs := d.ArgumentMap(ec.Variables)
{{ if $useFunctionSyntaxForExecutionContext -}}
args, err := {{ $directive.ArgsFunc }}(ctx,ec,rawArgs)
{{- else -}}
args, err := ec.{{ $directive.ArgsFunc }}(ctx,rawArgs)
{{- end }}
if err != nil {
ec.Error(ctx, err)
return func(ctx context.Context) graphql.Marshaler {
Expand Down Expand Up @@ -122,7 +155,11 @@ func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *as
{{ end }}

{{ if .Directives.LocationDirectives "FIELD" }}
{{ if $useFunctionSyntaxForExecutionContext -}}
func _fieldMiddleware(ctx context.Context, ec *executionContext, obj interface{}, next graphql.Resolver) interface{} {
{{- else -}}
func (ec *executionContext) _fieldMiddleware(ctx context.Context, obj interface{}, next graphql.Resolver) interface{} {
{{- end }}
{{- if .Directives.LocationDirectives "FIELD" }}
fc := graphql.GetFieldContext(ctx)
for _, d := range fc.Field.Directives {
Expand All @@ -131,7 +168,11 @@ func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *as
case "{{$directive.Name}}":
{{- if $directive.Args }}
rawArgs := d.ArgumentMap(ec.Variables)
{{ if $useFunctionSyntaxForExecutionContext -}}
args, err := {{ $directive.ArgsFunc }}(ctx,ec,rawArgs)
{{- else -}}
args, err := ec.{{ $directive.ArgsFunc }}(ctx,rawArgs)
{{- end }}
if err != nil {
ec.Error(ctx, err)
return nil
Expand Down
57 changes: 48 additions & 9 deletions codegen/field.gotpl
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
{{ $useFunctionSyntaxForExecutionContext := .Config.UseFunctionSyntaxForExecutionContext }}

{{- range $object := .Objects }}{{- range $field := $object.Fields }}

{{ if $useFunctionSyntaxForExecutionContext -}}
func _{{$object.Name}}_{{$field.Name}}(ctx context.Context, ec *executionContext, field graphql.CollectedField{{ if not $object.Root }}, obj {{$object.Reference | ref}}{{end}}) (ret {{ if $object.Stream }}func(ctx context.Context){{ end }}graphql.Marshaler) {
{{- else -}}
func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField{{ if not $object.Root }}, obj {{$object.Reference | ref}}{{end}}) (ret {{ if $object.Stream }}func(ctx context.Context){{ end }}graphql.Marshaler) {
{{- end }}
{{- $null := "graphql.Null" }}
{{- if $object.Stream }}
{{- $null = "nil" }}
{{- end }}
{{ if $useFunctionSyntaxForExecutionContext -}}
fc, err := {{ $field.FieldContextFunc }}(ctx, ec, field)
{{- else -}}
fc, err := ec.{{ $field.FieldContextFunc }}(ctx, field)
{{- end }}
if err != nil {
return {{ $null }}
}
Expand All @@ -25,15 +35,23 @@ func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Contex
res := {{ $field.TypeReference.GO | ref }}{}
{{- end }}
fc.Result = res
{{ if $useFunctionSyntaxForExecutionContext -}}
return {{ $field.TypeReference.MarshalFunc }}(ctx, ec, field.Selections, res)
{{- else -}}
return ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res)
{{- end }}
{{- else}}
{{- if $.AllDirectives.LocationDirectives "FIELD" }}
{{ if $useFunctionSyntaxForExecutionContext -}}
resTmp := _fieldMiddleware(ctx, ec, {{if $object.Root}}nil{{else}}obj{{end}}, func(rctx context.Context) (interface{}, error) {
{{- else -}}
resTmp := ec._fieldMiddleware(ctx, {{if $object.Root}}nil{{else}}obj{{end}}, func(rctx context.Context) (interface{}, error) {
{{ template "field" $field }}
{{- end }}
{{ template "field" (dict "Field" $field "UseFunctionSyntaxForExecutionContext" $useFunctionSyntaxForExecutionContext) }}
})
{{ else }}
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
{{ template "field" $field }}
{{ template "field" (dict "Field" $field "UseFunctionSyntaxForExecutionContext" $useFunctionSyntaxForExecutionContext) }}
})
if err != nil {
ec.Error(ctx, err)
Expand All @@ -59,7 +77,11 @@ func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Contex
w.Write([]byte{'{'})
graphql.MarshalString(field.Alias).MarshalGQL(w)
w.Write([]byte{':'})
{{ if $useFunctionSyntaxForExecutionContext -}}
{{ $field.TypeReference.MarshalFunc }}(ctx, ec, field.Selections, res).MarshalGQL(w)
{{- else -}}
ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res).MarshalGQL(w)
{{- end }}
w.Write([]byte{'}'})
})
case <-ctx.Done():
Expand All @@ -69,12 +91,20 @@ func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Contex
{{- else }}
res := resTmp.({{$field.TypeReference.GO | ref}})
fc.Result = res
{{ if $useFunctionSyntaxForExecutionContext -}}
return {{ $field.TypeReference.MarshalFunc }}(ctx, ec, field.Selections, res)
{{- else -}}
return ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res)
{{- end }}
{{- end }}
{{- end }}
}

{{ if $useFunctionSyntaxForExecutionContext -}}
func {{ $field.FieldContextFunc }}({{ if not $field.Args }}_{{ else }}ctx{{ end }} context.Context, ec *executionContext, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
{{- else -}}
func (ec *executionContext) {{ $field.FieldContextFunc }}({{ if not $field.Args }}_{{ else }}ctx{{ end }} context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
{{- end }}
fc = &graphql.FieldContext{
Object: {{quote $field.Object.Name}},
Field: field,
Expand All @@ -89,7 +119,11 @@ func (ec *executionContext) {{ $field.FieldContextFunc }}({{ if not $field.Args
switch field.Name {
{{- range $f := $field.TypeReference.Definition.Fields }}
case "{{ $f.Name }}":
{{ if $useFunctionSyntaxForExecutionContext -}}
return {{ $field.ChildFieldContextFunc $f.Name }}(ctx, ec, field)
{{- else -}}
return ec.{{ $field.ChildFieldContextFunc $f.Name }}(ctx, field)
{{- end }}
{{- end }}
}
return nil, fmt.Errorf("no field named %q was found under type {{ $field.TypeReference.Definition.Name }}", field.Name)
Expand All @@ -106,7 +140,11 @@ func (ec *executionContext) {{ $field.FieldContextFunc }}({{ if not $field.Args
}()
{{- end }}
ctx = graphql.WithFieldContext(ctx, fc)
{{ if $useFunctionSyntaxForExecutionContext -}}
if fc.Args, err = {{ $field.ArgsFunc }}(ctx, ec, field.ArgumentMap(ec.Variables)); err != nil {
{{- else -}}
if fc.Args, err = ec.{{ $field.ArgsFunc }}(ctx, field.ArgumentMap(ec.Variables)); err != nil {
{{- end }}
ec.Error(ctx, err)
return fc, err
}
Expand All @@ -117,26 +155,27 @@ func (ec *executionContext) {{ $field.FieldContextFunc }}({{ if not $field.Args
{{- end }}{{- end}}

{{ define "field" }}
{{- if .HasDirectives -}}
{{- $useFunctionSyntaxForExecutionContext := .UseFunctionSyntaxForExecutionContext -}}
{{- if .Field.HasDirectives -}}
directive0 := func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
{{ template "fieldDefinition" . }}
{{ template "fieldDefinition" .Field }}
}
{{ template "implDirectives" . }}
tmp, err := directive{{.ImplDirectives|len}}(rctx)
{{ template "implDirectives" (dict "Field" .Field "UseFunctionSyntaxForExecutionContext" $useFunctionSyntaxForExecutionContext) }}
tmp, err := directive{{.Field.ImplDirectives|len}}(rctx)
if err != nil {
return nil, graphql.ErrorOnPath(ctx, err)
}
if tmp == nil {
return nil, nil
}
if data, ok := tmp.({{if .Stream}}<-chan {{end}}{{ .TypeReference.GO | ref }}) ; ok {
if data, ok := tmp.({{if .Field.Stream}}<-chan {{end}}{{ .Field.TypeReference.GO | ref }}) ; ok {
return data, nil
}
return nil, fmt.Errorf(`unexpected type %T from directive, should be {{if .Stream}}<-chan {{end}}{{ .TypeReference.GO }}`, tmp)
return nil, fmt.Errorf(`unexpected type %T from directive, should be {{if .Field.Stream}}<-chan {{end}}{{ .Field.TypeReference.GO }}`, tmp)
{{- else -}}
ctx = rctx // use context from middleware stack in children
{{ template "fieldDefinition" . }}
{{ template "fieldDefinition" .Field }}
{{- end -}}
{{ end }}

Expand Down
Loading

0 comments on commit b9e4d51

Please sign in to comment.