1package templates
2
3import (
4 "fmt"
5 "go/build"
6 "strconv"
7
8 "github.com/99designs/gqlgen/internal/gopath"
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 {
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 gopath.MustDir2Import(s.destDir) == path {
48 return ""
49 }
50
51 pkg, err := build.Default.Import(path, s.destDir, 0)
52 if err != nil {
53 panic(err)
54 }
55
56 var alias string
57 if len(aliases) != 1 {
58 alias = pkg.Name
59 } else {
60 alias = aliases[0]
61 }
62
63 if existing := s.findByPath(path); existing != nil {
64 panic("ambient import already exists")
65 }
66
67 if alias := s.findByAlias(alias); alias != nil {
68 panic("ambient import collides on an alias")
69 }
70
71 s.imports = append(s.imports, &Import{
72 Name: pkg.Name,
73 Path: path,
74 Alias: alias,
75 })
76
77 return ""
78}
79
80func (s *Imports) Lookup(path string) string {
81 if path == "" {
82 return ""
83 }
84
85 // if we are referencing our own package we dont need an import
86 if gopath.MustDir2Import(s.destDir) == path {
87 return ""
88 }
89
90 if existing := s.findByPath(path); existing != nil {
91 return existing.Alias
92 }
93
94 pkg, err := build.Default.Import(path, s.destDir, 0)
95 if err != nil {
96 panic(err)
97 }
98
99 imp := &Import{
100 Name: pkg.Name,
101 Path: path,
102 }
103 s.imports = append(s.imports, imp)
104
105 alias := imp.Name
106 i := 1
107 for s.findByAlias(alias) != nil {
108 alias = imp.Name + strconv.Itoa(i)
109 i++
110 if i > 10 {
111 panic(fmt.Errorf("too many collisions, last attempt was %s", alias))
112 }
113 }
114 imp.Alias = alias
115
116 return imp.Alias
117}
118
119func (s Imports) findByPath(importPath string) *Import {
120 for _, imp := range s.imports {
121 if imp.Path == importPath {
122 return imp
123 }
124 }
125 return nil
126}
127
128func (s Imports) findByAlias(alias string) *Import {
129 for _, imp := range s.imports {
130 if imp.Alias == alias {
131 return imp
132 }
133 }
134 return nil
135}