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  }