github.com/jepp2078/gqlgen@v0.7.2/codegen/type.go (about)

     1  package codegen
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  
     7  	"github.com/99designs/gqlgen/codegen/templates"
     8  
     9  	"github.com/vektah/gqlparser/ast"
    10  )
    11  
    12  type NamedTypes map[string]*NamedType
    13  
    14  type NamedType struct {
    15  	Ref
    16  	IsScalar    bool
    17  	IsInterface bool
    18  	IsInput     bool
    19  	GQLType     string // Name of the graphql type
    20  	Marshaler   *Ref   // If this type has an external marshaler this will be set
    21  }
    22  
    23  type Ref struct {
    24  	GoType        string // Name of the go type
    25  	Package       string // the package the go type lives in
    26  	IsUserDefined bool   // does the type exist in the typemap
    27  }
    28  
    29  type Type struct {
    30  	*NamedType
    31  
    32  	Modifiers   []string
    33  	ASTType     *ast.Type
    34  	AliasedType *Ref
    35  }
    36  
    37  const (
    38  	modList = "[]"
    39  	modPtr  = "*"
    40  )
    41  
    42  func (t Ref) FullName() string {
    43  	return t.PkgDot() + t.GoType
    44  }
    45  
    46  func (t Ref) PkgDot() string {
    47  	name := templates.CurrentImports.Lookup(t.Package)
    48  	if name == "" {
    49  		return ""
    50  
    51  	}
    52  
    53  	return name + "."
    54  }
    55  
    56  func (t Type) Signature() string {
    57  	if t.AliasedType != nil {
    58  		return strings.Join(t.Modifiers, "") + t.AliasedType.FullName()
    59  	}
    60  	return strings.Join(t.Modifiers, "") + t.FullName()
    61  }
    62  
    63  func (t Type) FullSignature() string {
    64  	pkg := ""
    65  	if t.Package != "" {
    66  		pkg = t.Package + "."
    67  	}
    68  
    69  	return strings.Join(t.Modifiers, "") + pkg + t.GoType
    70  }
    71  
    72  func (t Type) IsPtr() bool {
    73  	return len(t.Modifiers) > 0 && t.Modifiers[0] == modPtr
    74  }
    75  
    76  func (t *Type) StripPtr() {
    77  	if !t.IsPtr() {
    78  		return
    79  	}
    80  	t.Modifiers = t.Modifiers[0 : len(t.Modifiers)-1]
    81  }
    82  
    83  func (t Type) IsSlice() bool {
    84  	return len(t.Modifiers) > 0 && t.Modifiers[0] == modList ||
    85  		len(t.Modifiers) > 1 && t.Modifiers[0] == modPtr && t.Modifiers[1] == modList
    86  }
    87  
    88  func (t NamedType) IsMarshaled() bool {
    89  	return t.Marshaler != nil
    90  }
    91  
    92  func (t Type) Unmarshal(result, raw string) string {
    93  	return t.unmarshal(result, raw, t.Modifiers, 1)
    94  }
    95  
    96  func (t Type) unmarshal(result, raw string, remainingMods []string, depth int) string {
    97  	switch {
    98  	case len(remainingMods) > 0 && remainingMods[0] == modPtr:
    99  		ptr := "ptr" + strconv.Itoa(depth)
   100  		return tpl(`var {{.ptr}} {{.mods}}{{.t.FullName}}
   101  			if {{.raw}} != nil {
   102  				{{.next}}
   103  				{{.result}} = &{{.ptr -}}
   104  			}
   105  		`, map[string]interface{}{
   106  			"ptr":    ptr,
   107  			"t":      t,
   108  			"raw":    raw,
   109  			"result": result,
   110  			"mods":   strings.Join(remainingMods[1:], ""),
   111  			"next":   t.unmarshal(ptr, raw, remainingMods[1:], depth+1),
   112  		})
   113  
   114  	case len(remainingMods) > 0 && remainingMods[0] == modList:
   115  		var rawIf = "rawIf" + strconv.Itoa(depth)
   116  		var index = "idx" + strconv.Itoa(depth)
   117  
   118  		return tpl(`var {{.rawSlice}} []interface{}
   119  			if {{.raw}} != nil {
   120  				if tmp1, ok := {{.raw}}.([]interface{}); ok {
   121  					{{.rawSlice}} = tmp1
   122  				} else {
   123  					{{.rawSlice}} = []interface{}{ {{.raw}} }
   124  				}
   125  			}
   126  			{{.result}} = make({{.type}}, len({{.rawSlice}}))
   127  			for {{.index}} := range {{.rawSlice}} {
   128  				{{ .next -}}
   129  			}`, map[string]interface{}{
   130  			"raw":      raw,
   131  			"rawSlice": rawIf,
   132  			"index":    index,
   133  			"result":   result,
   134  			"type":     strings.Join(remainingMods, "") + t.NamedType.FullName(),
   135  			"next":     t.unmarshal(result+"["+index+"]", rawIf+"["+index+"]", remainingMods[1:], depth+1),
   136  		})
   137  	}
   138  
   139  	realResult := result
   140  	if t.AliasedType != nil {
   141  		result = "castTmp"
   142  	}
   143  
   144  	return tpl(`{{- if .t.AliasedType }}
   145  			var castTmp {{.t.FullName}}
   146  		{{ end }}
   147  			{{- if eq .t.GoType "map[string]interface{}" }}
   148  				{{- .result }} = {{.raw}}.(map[string]interface{})
   149  			{{- else if .t.Marshaler }}
   150  				{{- .result }}, err = {{ .t.Marshaler.PkgDot }}Unmarshal{{.t.Marshaler.GoType}}({{.raw}})
   151  			{{- else -}}
   152  				err = (&{{.result}}).UnmarshalGQL({{.raw}})
   153  			{{- end }}
   154  		{{- if .t.AliasedType }}
   155  			{{ .realResult }} = {{.t.AliasedType.FullName}}(castTmp)
   156  		{{- end }}`, map[string]interface{}{
   157  		"realResult": realResult,
   158  		"result":     result,
   159  		"raw":        raw,
   160  		"t":          t,
   161  	})
   162  }
   163  
   164  func (t Type) Marshal(val string) string {
   165  	if t.AliasedType != nil {
   166  		val = t.GoType + "(" + val + ")"
   167  	}
   168  
   169  	if t.Marshaler != nil {
   170  		return "return " + t.Marshaler.PkgDot() + "Marshal" + t.Marshaler.GoType + "(" + val + ")"
   171  	}
   172  
   173  	return "return " + val
   174  }