github.com/mariuspot/gqlgen@v0.7.2/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(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  		}
    45  	}
    46  }
    47  
    48  // namedTypeFromSchema objects for every graphql type, including primitives.
    49  // don't recurse into object fields or interfaces yet, lets make sure we have collected everything first.
    50  func namedTypeFromSchema(schemaType *ast.Definition) *NamedType {
    51  	switch schemaType.Kind {
    52  	case ast.Scalar, ast.Enum:
    53  		return &NamedType{GQLType: schemaType.Name, IsScalar: true}
    54  	case ast.Interface, ast.Union:
    55  		return &NamedType{GQLType: schemaType.Name, IsInterface: true}
    56  	case ast.InputObject:
    57  		return &NamedType{GQLType: schemaType.Name, IsInput: true}
    58  	default:
    59  		return &NamedType{GQLType: schemaType.Name}
    60  	}
    61  }
    62  
    63  // take a string in the form github.com/package/blah.Type and split it into package and type
    64  func pkgAndType(name string) (string, string) {
    65  	parts := strings.Split(name, ".")
    66  	if len(parts) == 1 {
    67  		return "", name
    68  	}
    69  
    70  	return normalizeVendor(strings.Join(parts[:len(parts)-1], ".")), parts[len(parts)-1]
    71  }
    72  
    73  func (n NamedTypes) getType(t *ast.Type) *Type {
    74  	orig := t
    75  	var modifiers []string
    76  	for {
    77  		if t.Elem != nil {
    78  			modifiers = append(modifiers, modList)
    79  			t = t.Elem
    80  		} else {
    81  			if !t.NonNull {
    82  				modifiers = append(modifiers, modPtr)
    83  			}
    84  			if n[t.NamedType] == nil {
    85  				panic("missing type " + t.NamedType)
    86  			}
    87  			res := &Type{
    88  				NamedType: n[t.NamedType],
    89  				Modifiers: modifiers,
    90  				ASTType:   orig,
    91  			}
    92  
    93  			if res.IsInterface {
    94  				res.StripPtr()
    95  			}
    96  
    97  			return res
    98  		}
    99  	}
   100  }