diff --git a/codegen/field.go b/codegen/field.go index 86fee340d4a..0833c1ebfba 100644 --- a/codegen/field.go +++ b/codegen/field.go @@ -461,7 +461,7 @@ func (f *Field) GoNameUnexported() string { } func (f *Field) ShortInvocation() string { - return fmt.Sprintf("%s().%s(%s)", f.Object.Definition.Name, f.GoFieldName, f.CallArgs()) + return fmt.Sprintf("%s().%s(%s)", strings.Title(f.Object.Definition.Name), f.GoFieldName, f.CallArgs()) } func (f *Field) ArgsFunc() string { diff --git a/codegen/generated!.gotpl b/codegen/generated!.gotpl index 864d15deb55..e3304d1d8b3 100644 --- a/codegen/generated!.gotpl +++ b/codegen/generated!.gotpl @@ -32,7 +32,7 @@ type Config struct { type ResolverRoot interface { {{- range $object := .Objects -}} {{ if $object.HasResolvers -}} - {{$object.Name}}() {{$object.Name}}Resolver + {{ucFirst $object.Name}}() {{ucFirst $object.Name}}Resolver {{ end }} {{- end }} } @@ -46,7 +46,7 @@ type DirectiveRoot struct { type ComplexityRoot struct { {{ range $object := .Objects }} {{ if not $object.IsReserved -}} - {{ $object.Name|go }} struct { + {{ucFirst $object.Name|go }} struct { {{ range $_, $fields := $object.UniqueFields }} {{- $field := index $fields 0 -}} {{ if not $field.IsReserved -}} @@ -60,7 +60,7 @@ type ComplexityRoot struct { {{ range $object := .Objects -}} {{ if $object.HasResolvers }} - type {{$object.Name}}Resolver interface { + type {{ucFirst $object.Name}}Resolver interface { {{ range $field := $object.Fields -}} {{- if $field.IsResolver }} {{- $field.GoFieldName}}{{ $field.ShortResolverDeclaration }} diff --git a/codegen/object.go b/codegen/object.go index f730a7e1e31..6cf922d47c4 100644 --- a/codegen/object.go +++ b/codegen/object.go @@ -46,7 +46,7 @@ func (b *builder) buildObject(typ *ast.Definition) (*Object, error) { Stream: typ == b.Schema.Subscription, Directives: dirs, ResolverInterface: types.NewNamed( - types.NewTypeName(0, b.Config.Exec.Pkg(), typ.Name+"Resolver", nil), + types.NewTypeName(0, b.Config.Exec.Pkg(), strings.Title(typ.Name)+"Resolver", nil), nil, nil, ), diff --git a/example/config/generated.go b/example/config/generated.go index 5c1c8afad4d..192997e0b7d 100644 --- a/example/config/generated.go +++ b/example/config/generated.go @@ -37,6 +37,7 @@ type ResolverRoot interface { Mutation() MutationResolver Query() QueryResolver Todo() TodoResolver + Role() RoleResolver } type DirectiveRoot struct { @@ -62,6 +63,11 @@ type ComplexityRoot struct { User struct { FullName func(childComplexity int) int ID func(childComplexity int) int + Role func(childComplexity int) int + } + + Role struct { + Name func(childComplexity int) int } } @@ -74,6 +80,9 @@ type QueryResolver interface { type TodoResolver interface { ID(ctx context.Context, obj *Todo) (string, error) } +type RoleResolver interface { + Name(ctx context.Context, obj *UserRole) (string, error) +} type executableSchema struct { resolvers ResolverRoot @@ -158,6 +167,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.User.ID(childComplexity), true + case "User.role": + if e.complexity.User.Role == nil { + break + } + + return e.complexity.User.Role(childComplexity), true + + case "role.name": + if e.complexity.Role.Name == nil { + break + } + + return e.complexity.Role.Name(childComplexity), true + } return 0, false } @@ -250,6 +273,12 @@ input NewTodo { @goModel(model:"github.com/99designs/gqlgen/example/config.User") { id: ID! name: String! @goField(name:"FullName") + role: role! +} + +type role +@goModel(model:"github.com/99designs/gqlgen/example/config.UserRole") { + name: String! } `, BuiltIn: false}, } @@ -720,6 +749,41 @@ func (ec *executionContext) _User_name(ctx context.Context, field graphql.Collec return ec.marshalNString2string(ctx, field.Selections, res) } +func (ec *executionContext) _User_role(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Role, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(UserRole) + fc.Result = res + return ec.marshalNrole2githubᚗcomᚋ99designsᚋgqlgenᚋexampleᚋconfigᚐUserRole(ctx, field.Selections, res) +} + func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -1838,6 +1902,41 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } +func (ec *executionContext) _role_name(ctx context.Context, field graphql.CollectedField, obj *UserRole) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "role", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Role().Name(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + // endregion **************************** field.gotpl ***************************** // region **************************** input.gotpl ***************************** @@ -2033,6 +2132,11 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { invalids++ } + case "role": + out.Values[i] = ec._User_role(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -2290,6 +2394,42 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o return out } +var roleImplementors = []string{"role"} + +func (ec *executionContext) _role(ctx context.Context, sel ast.SelectionSet, obj *UserRole) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, roleImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("role") + case "name": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._role_name(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + // endregion **************************** object.gotpl **************************** // region ***************************** type.gotpl ***************************** @@ -2684,6 +2824,10 @@ func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel a return res } +func (ec *executionContext) marshalNrole2githubᚗcomᚋ99designsᚋgqlgenᚋexampleᚋconfigᚐUserRole(ctx context.Context, sel ast.SelectionSet, v UserRole) graphql.Marshaler { + return ec._role(ctx, sel, &v) +} + func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { res, err := graphql.UnmarshalBoolean(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/example/config/model.go b/example/config/model.go index 46038be7f88..4632c4eadef 100644 --- a/example/config/model.go +++ b/example/config/model.go @@ -5,8 +5,13 @@ import "fmt" type User struct { ID string FirstName, LastName string + Role UserRole } func (user *User) FullName() string { return fmt.Sprintf("%s %s", user.FirstName, user.LastName) } + +type UserRole struct { + RoleName string +} diff --git a/example/config/user.graphql b/example/config/user.graphql index 52c688bd331..5fb3772fc2f 100644 --- a/example/config/user.graphql +++ b/example/config/user.graphql @@ -2,4 +2,10 @@ type User @goModel(model:"github.com/99designs/gqlgen/example/config.User") { id: ID! name: String! @goField(name:"FullName") + role: role! +} + +type role +@goModel(model:"github.com/99designs/gqlgen/example/config.UserRole") { + name: String! } diff --git a/example/config/user.resolvers.go b/example/config/user.resolvers.go new file mode 100644 index 00000000000..1d819f99433 --- /dev/null +++ b/example/config/user.resolvers.go @@ -0,0 +1,20 @@ +package config + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. + +import ( + "context" +) + +func (r *roleResolver) Name(ctx context.Context, obj *UserRole) (string, error) { + if obj == nil { + return "", nil + } + return obj.RoleName, nil +} + +// Role returns RoleResolver implementation. +func (r *Resolver) Role() RoleResolver { return &roleResolver{r} } + +type roleResolver struct{ *Resolver } diff --git a/plugin/resolvergen/resolver.go b/plugin/resolvergen/resolver.go index b4985426246..857f5ea31d6 100644 --- a/plugin/resolvergen/resolver.go +++ b/plugin/resolvergen/resolver.go @@ -95,7 +95,7 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error { } rewriter.MarkStructCopied(templates.LcFirst(o.Name) + templates.UcFirst(data.Config.Resolver.Type)) - rewriter.GetMethodBody(data.Config.Resolver.Type, o.Name) + rewriter.GetMethodBody(data.Config.Resolver.Type, strings.Title(o.Name)) files[fn].Objects = append(files[fn].Objects, o) } for _, f := range o.Fields { diff --git a/plugin/resolvergen/resolver.gotpl b/plugin/resolvergen/resolver.gotpl index 543bf136e85..16c684d6283 100644 --- a/plugin/resolvergen/resolver.gotpl +++ b/plugin/resolvergen/resolver.gotpl @@ -26,8 +26,8 @@ {{ end }} {{ range $object := .Objects -}} - // {{$object.Name}} returns {{ $object.ResolverInterface | ref }} implementation. - func (r *{{$.ResolverType}}) {{$object.Name}}() {{ $object.ResolverInterface | ref }} { return &{{lcFirst $object.Name}}{{ucFirst $.ResolverType}}{r} } + // {{ucFirst $object.Name}} returns {{ $object.ResolverInterface | ref }} implementation. + func (r *{{$.ResolverType}}) {{ucFirst $object.Name}}() {{ $object.ResolverInterface | ref }} { return &{{lcFirst $object.Name}}{{ucFirst $.ResolverType}}{r} } {{ end }} {{ range $object := .Objects -}}