github.com/shish-dev/gqlgen@v0.99.0/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/shish-dev/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  }