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