github.com/HaswinVidanage/gqlgen@v0.8.1-0.20220609041233-69528c1bf712/codegen/object.go (about) 1 package codegen 2 3 import ( 4 "go/types" 5 "strconv" 6 "strings" 7 "unicode" 8 9 "github.com/HaswinVidanage/gqlgen/codegen/config" 10 "github.com/pkg/errors" 11 "github.com/vektah/gqlparser/ast" 12 ) 13 14 type GoFieldType int 15 16 const ( 17 GoFieldUndefined GoFieldType = iota 18 GoFieldMethod 19 GoFieldVariable 20 ) 21 22 type Object struct { 23 *ast.Definition 24 25 Type types.Type 26 ResolverInterface types.Type 27 Root bool 28 Fields []*Field 29 Implements []*ast.Definition 30 DisableConcurrency bool 31 Stream bool 32 Directives []*Directive 33 } 34 35 func (b *builder) buildObject(typ *ast.Definition) (*Object, error) { 36 dirs, err := b.getDirectives(typ.Directives) 37 if err != nil { 38 return nil, errors.Wrap(err, typ.Name) 39 } 40 41 obj := &Object{ 42 Definition: typ, 43 Root: b.Schema.Query == typ || b.Schema.Mutation == typ || b.Schema.Subscription == typ, 44 DisableConcurrency: typ == b.Schema.Mutation, 45 Stream: typ == b.Schema.Subscription, 46 Directives: dirs, 47 ResolverInterface: types.NewNamed( 48 types.NewTypeName(0, b.Config.Exec.Pkg(), typ.Name+"Resolver", nil), 49 nil, 50 nil, 51 ), 52 } 53 54 if !obj.Root { 55 goObject, err := b.Binder.DefaultUserObject(typ.Name) 56 if err != nil { 57 return nil, err 58 } 59 obj.Type = goObject 60 } 61 62 for _, intf := range b.Schema.GetImplements(typ) { 63 obj.Implements = append(obj.Implements, b.Schema.Types[intf.Name]) 64 } 65 66 for _, field := range typ.Fields { 67 if strings.HasPrefix(field.Name, "__") { 68 continue 69 } 70 71 var f *Field 72 f, err = b.buildField(obj, field) 73 if err != nil { 74 return nil, err 75 } 76 77 obj.Fields = append(obj.Fields, f) 78 } 79 80 return obj, nil 81 } 82 83 type Objects []*Object 84 85 func (o *Object) Implementors() string { 86 satisfiedBy := strconv.Quote(o.Name) 87 for _, s := range o.Implements { 88 satisfiedBy += ", " + strconv.Quote(s.Name) 89 } 90 return "[]string{" + satisfiedBy + "}" 91 } 92 93 func (o *Object) HasResolvers() bool { 94 for _, f := range o.Fields { 95 if f.IsResolver { 96 return true 97 } 98 } 99 return false 100 } 101 102 func (o *Object) HasUnmarshal() bool { 103 if o.Type == config.MapType { 104 return true 105 } 106 for i := 0; i < o.Type.(*types.Named).NumMethods(); i++ { 107 switch o.Type.(*types.Named).Method(i).Name() { 108 case "UnmarshalGQL": 109 return true 110 } 111 } 112 return false 113 } 114 115 func (o *Object) HasDirectives() bool { 116 if len(o.Directives) > 0 { 117 return true 118 } 119 for _, f := range o.Fields { 120 if f.HasDirectives() { 121 return true 122 } 123 } 124 125 return false 126 } 127 128 func (o *Object) IsConcurrent() bool { 129 for _, f := range o.Fields { 130 if f.IsConcurrent() { 131 return true 132 } 133 } 134 return false 135 } 136 137 func (o *Object) IsReserved() bool { 138 return strings.HasPrefix(o.Definition.Name, "__") 139 } 140 141 func (o *Object) Description() string { 142 return o.Definition.Description 143 } 144 145 func (os Objects) ByName(name string) *Object { 146 for i, o := range os { 147 if strings.EqualFold(o.Definition.Name, name) { 148 return os[i] 149 } 150 } 151 return nil 152 } 153 154 func ucFirst(s string) string { 155 if s == "" { 156 return "" 157 } 158 159 r := []rune(s) 160 r[0] = unicode.ToUpper(r[0]) 161 return string(r) 162 }