github.com/shashank-sachan/gqlgen@v0.7.2/codegen/input_build.go (about)

     1  package codegen
     2  
     3  import (
     4  	"go/types"
     5  	"sort"
     6  
     7  	"github.com/pkg/errors"
     8  	"github.com/vektah/gqlparser/ast"
     9  	"golang.org/x/tools/go/loader"
    10  )
    11  
    12  func (cfg *Config) buildInputs(namedTypes NamedTypes, prog *loader.Program) (Objects, error) {
    13  	var inputs Objects
    14  
    15  	for _, typ := range cfg.schema.Types {
    16  		switch typ.Kind {
    17  		case ast.InputObject:
    18  			input, err := cfg.buildInput(namedTypes, typ)
    19  			if err != nil {
    20  				return nil, err
    21  			}
    22  
    23  			def, err := findGoType(prog, input.Package, input.GoType)
    24  			if err != nil {
    25  				return nil, errors.Wrap(err, "cannot find type")
    26  			}
    27  			if def != nil {
    28  				input.Marshaler = buildInputMarshaler(typ, def)
    29  				bindErrs := bindObject(def.Type(), input, cfg.StructTag)
    30  				if len(bindErrs) > 0 {
    31  					return nil, bindErrs
    32  				}
    33  			}
    34  
    35  			inputs = append(inputs, input)
    36  		}
    37  	}
    38  
    39  	sort.Slice(inputs, func(i, j int) bool {
    40  		return inputs[i].GQLType < inputs[j].GQLType
    41  	})
    42  
    43  	return inputs, nil
    44  }
    45  
    46  func (cfg *Config) buildInput(types NamedTypes, typ *ast.Definition) (*Object, error) {
    47  	obj := &Object{NamedType: types[typ.Name]}
    48  	typeEntry, entryExists := cfg.Models[typ.Name]
    49  
    50  	for _, field := range typ.Fields {
    51  		newField := Field{
    52  			GQLName: field.Name,
    53  			Type:    types.getType(field.Type),
    54  			Object:  obj,
    55  		}
    56  
    57  		if entryExists {
    58  			if typeField, ok := typeEntry.Fields[field.Name]; ok {
    59  				newField.GoFieldName = typeField.FieldName
    60  			}
    61  		}
    62  
    63  		if field.DefaultValue != nil {
    64  			var err error
    65  			newField.Default, err = field.DefaultValue.Value(nil)
    66  			if err != nil {
    67  				return nil, errors.Errorf("default value for %s.%s is not valid: %s", typ.Name, field.Name, err.Error())
    68  			}
    69  		}
    70  
    71  		if !newField.Type.IsInput && !newField.Type.IsScalar {
    72  			return nil, errors.Errorf("%s cannot be used as a field of %s. only input and scalar types are allowed", newField.GQLType, obj.GQLType)
    73  		}
    74  
    75  		obj.Fields = append(obj.Fields, newField)
    76  
    77  	}
    78  	return obj, nil
    79  }
    80  
    81  // if user has implemented an UnmarshalGQL method on the input type manually, use it
    82  // otherwise we will generate one.
    83  func buildInputMarshaler(typ *ast.Definition, def types.Object) *Ref {
    84  	switch def := def.(type) {
    85  	case *types.TypeName:
    86  		namedType := def.Type().(*types.Named)
    87  		for i := 0; i < namedType.NumMethods(); i++ {
    88  			method := namedType.Method(i)
    89  			if method.Name() == "UnmarshalGQL" {
    90  				return nil
    91  			}
    92  		}
    93  	}
    94  
    95  	return &Ref{GoType: typ.Name}
    96  }