import.go

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