import.go

  1package templates
  2
  3import (
  4	"fmt"
  5	"go/types"
  6	"strconv"
  7
  8	"github.com/99designs/gqlgen/internal/code"
  9)
 10
 11type Import struct {
 12	Name  string
 13	Path  string
 14	Alias string
 15}
 16
 17type Imports struct {
 18	imports []*Import
 19	destDir string
 20}
 21
 22func (i *Import) String() string {
 23	if i.Alias == i.Name {
 24		return strconv.Quote(i.Path)
 25	}
 26
 27	return i.Alias + " " + strconv.Quote(i.Path)
 28}
 29
 30func (s *Imports) String() string {
 31	res := ""
 32	for i, imp := range s.imports {
 33		if i != 0 {
 34			res += "\n"
 35		}
 36		res += imp.String()
 37	}
 38	return res
 39}
 40
 41func (s *Imports) Reserve(path string, aliases ...string) (string, error) {
 42	if path == "" {
 43		panic("empty ambient import")
 44	}
 45
 46	// if we are referencing our own package we dont need an import
 47	if code.ImportPathForDir(s.destDir) == path {
 48		return "", nil
 49	}
 50
 51	name := code.NameForPackage(path)
 52	var alias string
 53	if len(aliases) != 1 {
 54		alias = name
 55	} else {
 56		alias = aliases[0]
 57	}
 58
 59	if existing := s.findByPath(path); existing != nil {
 60		if existing.Alias == alias {
 61			return "", nil
 62		}
 63		return "", fmt.Errorf("ambient import already exists")
 64	}
 65
 66	if alias := s.findByAlias(alias); alias != nil {
 67		return "", fmt.Errorf("ambient import collides on an alias")
 68	}
 69
 70	s.imports = append(s.imports, &Import{
 71		Name:  name,
 72		Path:  path,
 73		Alias: alias,
 74	})
 75
 76	return "", nil
 77}
 78
 79func (s *Imports) Lookup(path string) string {
 80	if path == "" {
 81		return ""
 82	}
 83
 84	path = code.NormalizeVendor(path)
 85
 86	// if we are referencing our own package we dont need an import
 87	if code.ImportPathForDir(s.destDir) == path {
 88		return ""
 89	}
 90
 91	if existing := s.findByPath(path); existing != nil {
 92		return existing.Alias
 93	}
 94
 95	imp := &Import{
 96		Name: code.NameForPackage(path),
 97		Path: path,
 98	}
 99	s.imports = append(s.imports, imp)
100
101	alias := imp.Name
102	i := 1
103	for s.findByAlias(alias) != nil {
104		alias = imp.Name + strconv.Itoa(i)
105		i++
106		if i > 10 {
107			panic(fmt.Errorf("too many collisions, last attempt was %s", alias))
108		}
109	}
110	imp.Alias = alias
111
112	return imp.Alias
113}
114
115func (s *Imports) LookupType(t types.Type) string {
116	return types.TypeString(t, func(i *types.Package) string {
117		return s.Lookup(i.Path())
118	})
119}
120
121func (s Imports) findByPath(importPath string) *Import {
122	for _, imp := range s.imports {
123		if imp.Path == importPath {
124			return imp
125		}
126	}
127	return nil
128}
129
130func (s Imports) findByAlias(alias string) *Import {
131	for _, imp := range s.imports {
132		if imp.Alias == alias {
133			return imp
134		}
135	}
136	return nil
137}