github.com/matiasanaya/gqlgen@v0.6.0/codegen/type_build.go (about) 1 package codegen 2 3 import ( 4 "go/types" 5 "strings" 6 7 "github.com/vektah/gqlparser/ast" 8 "golang.org/x/tools/go/loader" 9 ) 10 11 // namedTypeFromSchema objects for every graphql type, including scalars. There should only be one instance of Type for each thing 12 func (cfg *Config) buildNamedTypes() NamedTypes { 13 types := map[string]*NamedType{} 14 for _, schemaType := range cfg.schema.Types { 15 t := namedTypeFromSchema(schemaType) 16 17 if userEntry, ok := cfg.Models[t.GQLType]; ok && userEntry.Model != "" { 18 t.IsUserDefined = true 19 t.Package, t.GoType = pkgAndType(userEntry.Model) 20 } else if t.IsScalar { 21 t.Package = "github.com/99designs/gqlgen/graphql" 22 t.GoType = "String" 23 } 24 25 types[t.GQLType] = t 26 } 27 return types 28 } 29 30 func (cfg *Config) bindTypes(imports *Imports, namedTypes NamedTypes, destDir string, prog *loader.Program) { 31 for _, t := range namedTypes { 32 if t.Package == "" { 33 continue 34 } 35 36 def, _ := findGoType(prog, t.Package, "Marshal"+t.GoType) 37 switch def := def.(type) { 38 case *types.Func: 39 sig := def.Type().(*types.Signature) 40 cpy := t.Ref 41 t.Marshaler = &cpy 42 43 t.Package, t.GoType = pkgAndType(sig.Params().At(0).Type().String()) 44 t.Import = imports.add(t.Package) 45 } 46 } 47 } 48 49 // namedTypeFromSchema objects for every graphql type, including primitives. 50 // don't recurse into object fields or interfaces yet, lets make sure we have collected everything first. 51 func namedTypeFromSchema(schemaType *ast.Definition) *NamedType { 52 switch schemaType.Kind { 53 case ast.Scalar, ast.Enum: 54 return &NamedType{GQLType: schemaType.Name, IsScalar: true} 55 case ast.Interface, ast.Union: 56 return &NamedType{GQLType: schemaType.Name, IsInterface: true} 57 case ast.InputObject: 58 return &NamedType{GQLType: schemaType.Name, IsInput: true} 59 default: 60 return &NamedType{GQLType: schemaType.Name} 61 } 62 } 63 64 // take a string in the form github.com/package/blah.Type and split it into package and type 65 func pkgAndType(name string) (string, string) { 66 parts := strings.Split(name, ".") 67 if len(parts) == 1 { 68 return "", name 69 } 70 71 return normalizeVendor(strings.Join(parts[:len(parts)-1], ".")), parts[len(parts)-1] 72 } 73 74 func (n NamedTypes) getType(t *ast.Type) *Type { 75 orig := t 76 var modifiers []string 77 for { 78 if t.Elem != nil { 79 modifiers = append(modifiers, modList) 80 t = t.Elem 81 } else { 82 if !t.NonNull { 83 modifiers = append(modifiers, modPtr) 84 } 85 if n[t.NamedType] == nil { 86 panic("missing type " + t.NamedType) 87 } 88 res := &Type{ 89 NamedType: n[t.NamedType], 90 Modifiers: modifiers, 91 ASTType: orig, 92 } 93 94 if res.IsInterface { 95 res.StripPtr() 96 } 97 98 return res 99 } 100 } 101 }