aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/99designs/gqlgen/codegen/object.go
diff options
context:
space:
mode:
authorAmine Hilaly <hilalyamine@gmail.com>2019-04-09 21:45:24 +0200
committerAmine Hilaly <hilalyamine@gmail.com>2019-04-09 21:45:24 +0200
commit26b5343e2160de172969e6834074cf8482ceb845 (patch)
tree04f27aa660a903d65f7b3d951bd1c6f92c59c0c3 /vendor/github.com/99designs/gqlgen/codegen/object.go
parent6e8496f4c1767ca8a8b95716a04f1b492bef7397 (diff)
downloadgit-bug-26b5343e2160de172969e6834074cf8482ceb845.tar.gz
Update Gopkg.*
Diffstat (limited to 'vendor/github.com/99designs/gqlgen/codegen/object.go')
-rw-r--r--vendor/github.com/99designs/gqlgen/codegen/object.go483
1 files changed, 91 insertions, 392 deletions
diff --git a/vendor/github.com/99designs/gqlgen/codegen/object.go b/vendor/github.com/99designs/gqlgen/codegen/object.go
index 656af297..539c3164 100644
--- a/vendor/github.com/99designs/gqlgen/codegen/object.go
+++ b/vendor/github.com/99designs/gqlgen/codegen/object.go
@@ -1,13 +1,13 @@
package codegen
import (
- "bytes"
- "fmt"
+ "go/types"
"strconv"
"strings"
- "text/template"
"unicode"
+ "github.com/99designs/gqlgen/codegen/config"
+ "github.com/pkg/errors"
"github.com/vektah/gqlparser/ast"
)
@@ -17,337 +17,150 @@ const (
GoFieldUndefined GoFieldType = iota
GoFieldMethod
GoFieldVariable
+ GoFieldMap
)
type Object struct {
- *NamedType
+ *ast.Definition
- Fields []Field
- Satisfies []string
- Implements []*NamedType
- ResolverInterface *Ref
+ Type types.Type
+ ResolverInterface types.Type
Root bool
+ Fields []*Field
+ Implements []*ast.Definition
DisableConcurrency bool
Stream bool
+ Directives []*Directive
}
-type Field struct {
- *Type
- Description string // Description of a field
- GQLName string // The name of the field in graphql
- GoFieldType GoFieldType // The field type in go, if any
- GoReceiverName string // The name of method & var receiver in go, if any
- GoFieldName string // The name of the method or var in go, if any
- Args []FieldArgument // A list of arguments to be passed to this field
- ForceResolver bool // Should be emit Resolver method
- MethodHasContext bool // If this is bound to a go method, does the method also take a context
- NoErr bool // If this is bound to a go method, does that method have an error as the second argument
- Object *Object // A link back to the parent object
- Default interface{} // The default value
-}
-
-type FieldArgument struct {
- *Type
-
- GQLName string // The name of the argument in graphql
- GoVarName string // The name of the var in go
- Object *Object // A link back to the parent object
- Default interface{} // The default value
-}
-
-type Objects []*Object
-
-func (o *Object) Implementors() string {
- satisfiedBy := strconv.Quote(o.GQLType)
- for _, s := range o.Satisfies {
- satisfiedBy += ", " + strconv.Quote(s)
- }
- return "[]string{" + satisfiedBy + "}"
-}
-
-func (o *Object) HasResolvers() bool {
- for _, f := range o.Fields {
- if f.IsResolver() {
- return true
+func (b *builder) buildObject(typ *ast.Definition) (*Object, error) {
+ dirs, err := b.getDirectives(typ.Directives)
+ if err != nil {
+ return nil, errors.Wrap(err, typ.Name)
+ }
+
+ obj := &Object{
+ Definition: typ,
+ Root: b.Schema.Query == typ || b.Schema.Mutation == typ || b.Schema.Subscription == typ,
+ DisableConcurrency: typ == b.Schema.Mutation,
+ Stream: typ == b.Schema.Subscription,
+ Directives: dirs,
+ ResolverInterface: types.NewNamed(
+ types.NewTypeName(0, b.Config.Exec.Pkg(), typ.Name+"Resolver", nil),
+ nil,
+ nil,
+ ),
+ }
+
+ if !obj.Root {
+ goObject, err := b.Binder.DefaultUserObject(typ.Name)
+ if err != nil {
+ return nil, err
}
+ obj.Type = goObject
}
- return false
-}
-func (o *Object) IsConcurrent() bool {
- for _, f := range o.Fields {
- if f.IsConcurrent() {
- return true
- }
+ for _, intf := range b.Schema.GetImplements(typ) {
+ obj.Implements = append(obj.Implements, b.Schema.Types[intf.Name])
}
- return false
-}
-
-func (o *Object) IsReserved() bool {
- return strings.HasPrefix(o.GQLType, "__")
-}
-func (f *Field) IsResolver() bool {
- return f.GoFieldName == ""
-}
-
-func (f *Field) IsReserved() bool {
- return strings.HasPrefix(f.GQLName, "__")
-}
-
-func (f *Field) IsMethod() bool {
- return f.GoFieldType == GoFieldMethod
-}
+ for _, field := range typ.Fields {
+ if strings.HasPrefix(field.Name, "__") {
+ continue
+ }
-func (f *Field) IsVariable() bool {
- return f.GoFieldType == GoFieldVariable
-}
+ var f *Field
+ f, err = b.buildField(obj, field)
+ if err != nil {
+ return nil, err
+ }
-func (f *Field) IsConcurrent() bool {
- if f.Object.DisableConcurrency {
- return false
+ obj.Fields = append(obj.Fields, f)
}
- return f.MethodHasContext || f.IsResolver()
-}
-func (f *Field) GoNameExported() string {
- return lintName(ucFirst(f.GQLName))
+ return obj, nil
}
-func (f *Field) GoNameUnexported() string {
- return lintName(f.GQLName)
-}
-
-func (f *Field) ShortInvocation() string {
- if !f.IsResolver() {
- return ""
+func (o *Object) Reference() types.Type {
+ switch o.Type.(type) {
+ case *types.Pointer, *types.Slice, *types.Map:
+ return o.Type
}
- return fmt.Sprintf("%s().%s(%s)", f.Object.GQLType, f.GoNameExported(), f.CallArgs())
+ return types.NewPointer(o.Type)
}
-func (f *Field) ArgsFunc() string {
- if len(f.Args) == 0 {
- return ""
- }
-
- return "field_" + f.Object.GQLType + "_" + f.GQLName + "_args"
-}
+type Objects []*Object
-func (f *Field) ResolverType() string {
- if !f.IsResolver() {
- return ""
+func (o *Object) Implementors() string {
+ satisfiedBy := strconv.Quote(o.Name)
+ for _, s := range o.Implements {
+ satisfiedBy += ", " + strconv.Quote(s.Name)
}
-
- return fmt.Sprintf("%s().%s(%s)", f.Object.GQLType, f.GoNameExported(), f.CallArgs())
+ return "[]string{" + satisfiedBy + "}"
}
-func (f *Field) ShortResolverDeclaration() string {
- if !f.IsResolver() {
- return ""
- }
- res := fmt.Sprintf("%s(ctx context.Context", f.GoNameExported())
-
- if !f.Object.Root {
- res += fmt.Sprintf(", obj *%s", f.Object.FullName())
- }
- for _, arg := range f.Args {
- res += fmt.Sprintf(", %s %s", arg.GoVarName, arg.Signature())
- }
-
- result := f.Signature()
- if f.Object.Stream {
- result = "<-chan " + result
+func (o *Object) HasResolvers() bool {
+ for _, f := range o.Fields {
+ if f.IsResolver {
+ return true
+ }
}
-
- res += fmt.Sprintf(") (%s, error)", result)
- return res
+ return false
}
-func (f *Field) ResolverDeclaration() string {
- if !f.IsResolver() {
- return ""
- }
- res := fmt.Sprintf("%s_%s(ctx context.Context", f.Object.GQLType, f.GoNameUnexported())
-
- if !f.Object.Root {
- res += fmt.Sprintf(", obj *%s", f.Object.FullName())
+func (o *Object) HasUnmarshal() bool {
+ if o.Type == config.MapType {
+ return true
}
- for _, arg := range f.Args {
- res += fmt.Sprintf(", %s %s", arg.GoVarName, arg.Signature())
- }
-
- result := f.Signature()
- if f.Object.Stream {
- result = "<-chan " + result
+ for i := 0; i < o.Type.(*types.Named).NumMethods(); i++ {
+ switch o.Type.(*types.Named).Method(i).Name() {
+ case "UnmarshalGQL":
+ return true
+ }
}
-
- res += fmt.Sprintf(") (%s, error)", result)
- return res
+ return false
}
-func (f *Field) ComplexitySignature() string {
- res := fmt.Sprintf("func(childComplexity int")
- for _, arg := range f.Args {
- res += fmt.Sprintf(", %s %s", arg.GoVarName, arg.Signature())
+func (o *Object) HasDirectives() bool {
+ if len(o.Directives) > 0 {
+ return true
}
- res += ") int"
- return res
-}
-
-func (f *Field) ComplexityArgs() string {
- var args []string
- for _, arg := range f.Args {
- args = append(args, "args["+strconv.Quote(arg.GQLName)+"].("+arg.Signature()+")")
+ for _, f := range o.Fields {
+ if f.HasDirectives() {
+ return true
+ }
}
- return strings.Join(args, ", ")
+ return false
}
-func (f *Field) CallArgs() string {
- var args []string
-
- if f.IsResolver() {
- args = append(args, "rctx")
-
- if !f.Object.Root {
- args = append(args, "obj")
- }
- } else {
- if f.MethodHasContext {
- args = append(args, "ctx")
+func (o *Object) IsConcurrent() bool {
+ for _, f := range o.Fields {
+ if f.IsConcurrent() {
+ return true
}
}
-
- for _, arg := range f.Args {
- args = append(args, "args["+strconv.Quote(arg.GQLName)+"].("+arg.Signature()+")")
- }
-
- return strings.Join(args, ", ")
-}
-
-// should be in the template, but its recursive and has a bunch of args
-func (f *Field) WriteJson() string {
- return f.doWriteJson("res", f.Type.Modifiers, f.ASTType, false, 1)
+ return false
}
-func (f *Field) doWriteJson(val string, remainingMods []string, astType *ast.Type, isPtr bool, depth int) string {
- switch {
- case len(remainingMods) > 0 && remainingMods[0] == modPtr:
- return tpl(`
- if {{.val}} == nil {
- {{- if .nonNull }}
- if !ec.HasError(rctx) {
- ec.Errorf(ctx, "must not be null")
- }
- {{- end }}
- return graphql.Null
- }
- {{.next }}`, map[string]interface{}{
- "val": val,
- "nonNull": astType.NonNull,
- "next": f.doWriteJson(val, remainingMods[1:], astType, true, depth+1),
- })
-
- case len(remainingMods) > 0 && remainingMods[0] == modList:
- if isPtr {
- val = "*" + val
- }
- var arr = "arr" + strconv.Itoa(depth)
- var index = "idx" + strconv.Itoa(depth)
- var usePtr bool
- if len(remainingMods) == 1 && !isPtr {
- usePtr = true
- }
-
- return tpl(`
- {{.arr}} := make(graphql.Array, len({{.val}}))
- {{ if and .top (not .isScalar) }} var wg sync.WaitGroup {{ end }}
- {{ if not .isScalar }}
- isLen1 := len({{.val}}) == 1
- if !isLen1 {
- wg.Add(len({{.val}}))
- }
- {{ end }}
- for {{.index}} := range {{.val}} {
- {{- if not .isScalar }}
- {{.index}} := {{.index}}
- rctx := &graphql.ResolverContext{
- Index: &{{.index}},
- Result: {{ if .usePtr }}&{{end}}{{.val}}[{{.index}}],
- }
- ctx := graphql.WithResolverContext(ctx, rctx)
- f := func({{.index}} int) {
- if !isLen1 {
- defer wg.Done()
- }
- {{.arr}}[{{.index}}] = func() graphql.Marshaler {
- {{ .next }}
- }()
- }
- if isLen1 {
- f({{.index}})
- } else {
- go f({{.index}})
- }
- {{ else }}
- {{.arr}}[{{.index}}] = func() graphql.Marshaler {
- {{ .next }}
- }()
- {{- end}}
- }
- {{ if and .top (not .isScalar) }} wg.Wait() {{ end }}
- return {{.arr}}`, map[string]interface{}{
- "val": val,
- "arr": arr,
- "index": index,
- "top": depth == 1,
- "arrayLen": len(val),
- "isScalar": f.IsScalar,
- "usePtr": usePtr,
- "next": f.doWriteJson(val+"["+index+"]", remainingMods[1:], astType.Elem, false, depth+1),
- })
-
- case f.IsScalar:
- if isPtr {
- val = "*" + val
- }
- return f.Marshal(val)
-
- default:
- if !isPtr {
- val = "&" + val
- }
- return tpl(`
- return ec._{{.type}}(ctx, field.Selections, {{.val}})`, map[string]interface{}{
- "type": f.GQLType,
- "val": val,
- })
- }
+func (o *Object) IsReserved() bool {
+ return strings.HasPrefix(o.Definition.Name, "__")
}
-func (f *FieldArgument) Stream() bool {
- return f.Object != nil && f.Object.Stream
+func (o *Object) Description() string {
+ return o.Definition.Description
}
func (os Objects) ByName(name string) *Object {
for i, o := range os {
- if strings.EqualFold(o.GQLType, name) {
+ if strings.EqualFold(o.Definition.Name, name) {
return os[i]
}
}
return nil
}
-func tpl(tpl string, vars map[string]interface{}) string {
- b := &bytes.Buffer{}
- err := template.Must(template.New("inline").Parse(tpl)).Execute(b, vars)
- if err != nil {
- panic(err)
- }
- return b.String()
-}
-
func ucFirst(s string) string {
if s == "" {
return ""
@@ -357,117 +170,3 @@ func ucFirst(s string) string {
r[0] = unicode.ToUpper(r[0])
return string(r)
}
-
-// copy from https://github.com/golang/lint/blob/06c8688daad7faa9da5a0c2f163a3d14aac986ca/lint.go#L679
-
-// lintName returns a different name if it should be different.
-func lintName(name string) (should string) {
- // Fast path for simple cases: "_" and all lowercase.
- if name == "_" {
- return name
- }
- allLower := true
- for _, r := range name {
- if !unicode.IsLower(r) {
- allLower = false
- break
- }
- }
- if allLower {
- return name
- }
-
- // Split camelCase at any lower->upper transition, and split on underscores.
- // Check each word for common initialisms.
- runes := []rune(name)
- w, i := 0, 0 // index of start of word, scan
- for i+1 <= len(runes) {
- eow := false // whether we hit the end of a word
- if i+1 == len(runes) {
- eow = true
- } else if runes[i+1] == '_' {
- // underscore; shift the remainder forward over any run of underscores
- eow = true
- n := 1
- for i+n+1 < len(runes) && runes[i+n+1] == '_' {
- n++
- }
-
- // Leave at most one underscore if the underscore is between two digits
- if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) {
- n--
- }
-
- copy(runes[i+1:], runes[i+n+1:])
- runes = runes[:len(runes)-n]
- } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) {
- // lower->non-lower
- eow = true
- }
- i++
- if !eow {
- continue
- }
-
- // [w,i) is a word.
- word := string(runes[w:i])
- if u := strings.ToUpper(word); commonInitialisms[u] {
- // Keep consistent case, which is lowercase only at the start.
- if w == 0 && unicode.IsLower(runes[w]) {
- u = strings.ToLower(u)
- }
- // All the common initialisms are ASCII,
- // so we can replace the bytes exactly.
- copy(runes[w:], []rune(u))
- } else if w > 0 && strings.ToLower(word) == word {
- // already all lowercase, and not the first word, so uppercase the first character.
- runes[w] = unicode.ToUpper(runes[w])
- }
- w = i
- }
- return string(runes)
-}
-
-// commonInitialisms is a set of common initialisms.
-// Only add entries that are highly unlikely to be non-initialisms.
-// For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
-var commonInitialisms = map[string]bool{
- "ACL": true,
- "API": true,
- "ASCII": true,
- "CPU": true,
- "CSS": true,
- "DNS": true,
- "EOF": true,
- "GUID": true,
- "HTML": true,
- "HTTP": true,
- "HTTPS": true,
- "ID": true,
- "IP": true,
- "JSON": true,
- "LHS": true,
- "QPS": true,
- "RAM": true,
- "RHS": true,
- "RPC": true,
- "SLA": true,
- "SMTP": true,
- "SQL": true,
- "SSH": true,
- "TCP": true,
- "TLS": true,
- "TTL": true,
- "UDP": true,
- "UI": true,
- "UID": true,
- "UUID": true,
- "URI": true,
- "URL": true,
- "UTF8": true,
- "VM": true,
- "XML": true,
- "XMPP": true,
- "XSRF": true,
- "XSS": true,
-}