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