aboutsummaryrefslogblamecommitdiffstats
path: root/vendor/github.com/99designs/gqlgen/codegen/input_build.go
blob: 70fa564da97ebe9ae1cd136959092426430c8135 (plain) (tree)
1
2
3
4
5
6
7
8




                  

                               
                                         


                                      
                                                                                              


                                              


                                                                     









                                                                                 
                                                                                        









                                                            
                                                            




                          


                                                                                       
 
                                          
                                  
                                            



                                                           











                                                                                                                                        













                                                                                                                                                               
                                                                      












                                                             
package codegen

import (
	"go/types"
	"sort"

	"github.com/pkg/errors"
	"github.com/vektah/gqlparser/ast"
	"golang.org/x/tools/go/loader"
)

func (cfg *Config) buildInputs(namedTypes NamedTypes, prog *loader.Program) (Objects, error) {
	var inputs Objects

	for _, typ := range cfg.schema.Types {
		switch typ.Kind {
		case ast.InputObject:
			input, err := cfg.buildInput(namedTypes, typ)
			if err != nil {
				return nil, err
			}

			def, err := findGoType(prog, input.Package, input.GoType)
			if err != nil {
				return nil, errors.Wrap(err, "cannot find type")
			}
			if def != nil {
				input.Marshaler = buildInputMarshaler(typ, def)
				bindErrs := bindObject(def.Type(), input, cfg.StructTag)
				if len(bindErrs) > 0 {
					return nil, bindErrs
				}
			}

			inputs = append(inputs, input)
		}
	}

	sort.Slice(inputs, func(i, j int) bool {
		return inputs[i].GQLType < inputs[j].GQLType
	})

	return inputs, nil
}

func (cfg *Config) buildInput(types NamedTypes, typ *ast.Definition) (*Object, error) {
	obj := &Object{NamedType: types[typ.Name]}
	typeEntry, entryExists := cfg.Models[typ.Name]

	for _, field := range typ.Fields {
		newField := Field{
			GQLName: field.Name,
			Type:    types.getType(field.Type),
			Object:  obj,
		}

		if entryExists {
			if typeField, ok := typeEntry.Fields[field.Name]; ok {
				newField.GoFieldName = typeField.FieldName
			}
		}

		if field.DefaultValue != nil {
			var err error
			newField.Default, err = field.DefaultValue.Value(nil)
			if err != nil {
				return nil, errors.Errorf("default value for %s.%s is not valid: %s", typ.Name, field.Name, err.Error())
			}
		}

		if !newField.Type.IsInput && !newField.Type.IsScalar {
			return nil, errors.Errorf("%s cannot be used as a field of %s. only input and scalar types are allowed", newField.GQLType, obj.GQLType)
		}

		obj.Fields = append(obj.Fields, newField)

	}
	return obj, nil
}

// if user has implemented an UnmarshalGQL method on the input type manually, use it
// otherwise we will generate one.
func buildInputMarshaler(typ *ast.Definition, def types.Object) *Ref {
	switch def := def.(type) {
	case *types.TypeName:
		namedType := def.Type().(*types.Named)
		for i := 0; i < namedType.NumMethods(); i++ {
			method := namedType.Method(i)
			if method.Name() == "UnmarshalGQL" {
				return nil
			}
		}
	}

	return &Ref{GoType: typ.Name}
}