1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package runtime
16
17 import (
18 "path"
19 "strconv"
20
21 "cuelang.org/go/cue/ast"
22 "cuelang.org/go/cue/build"
23 "cuelang.org/go/cue/errors"
24 "cuelang.org/go/internal"
25 )
26
27
28 func (r *Runtime) ResolveFiles(p *build.Instance) (errs errors.Error) {
29 idx := r.index
30
31
32
33 allFields := map[string]ast.Node{}
34 for _, f := range p.Files {
35 if p := internal.GetPackageInfo(f); p.IsAnonymous() {
36 continue
37 }
38 for _, d := range f.Decls {
39 if f, ok := d.(*ast.Field); ok && f.Value != nil {
40 if ident, ok := f.Label.(*ast.Ident); ok {
41 allFields[ident.Name] = f.Value
42 }
43 }
44 }
45 }
46 for _, f := range p.Files {
47 if p := internal.GetPackageInfo(f); p.IsAnonymous() {
48 continue
49 }
50 err := resolveFile(idx, f, p, allFields)
51 errs = errors.Append(errs, err)
52 }
53 return errs
54 }
55
56 func resolveFile(
57 idx *index,
58 f *ast.File,
59 p *build.Instance,
60 allFields map[string]ast.Node,
61 ) errors.Error {
62 unresolved := map[string][]*ast.Ident{}
63 for _, u := range f.Unresolved {
64 unresolved[u.Name] = append(unresolved[u.Name], u)
65 }
66 fields := map[string]ast.Node{}
67 for _, d := range f.Decls {
68 if f, ok := d.(*ast.Field); ok && f.Value != nil {
69 if ident, ok := f.Label.(*ast.Ident); ok {
70 fields[ident.Name] = d
71 }
72 }
73 }
74 var errs errors.Error
75
76 specs := []*ast.ImportSpec{}
77
78 for _, spec := range f.Imports {
79 id, err := strconv.Unquote(spec.Path.Value)
80 if err != nil {
81 continue
82 }
83 name := path.Base(id)
84 if imp := p.LookupImport(id); imp != nil {
85 name = imp.PkgName
86 } else if _, ok := idx.builtinPaths[id]; !ok {
87 errs = errors.Append(errs,
88 nodeErrorf(spec, "package %q not found", id))
89 continue
90 }
91 if spec.Name != nil {
92 name = spec.Name.Name
93 }
94 if n, ok := fields[name]; ok {
95 errs = errors.Append(errs, nodeErrorf(spec,
96 "%s redeclared as imported package name\n"+
97 "\tprevious declaration at %v", name, lineStr(idx, n)))
98 continue
99 }
100 fields[name] = spec
101 used := false
102 for _, u := range unresolved[name] {
103 used = true
104 u.Node = spec
105 }
106 if !used {
107 specs = append(specs, spec)
108 }
109 }
110
111
112 if len(specs) > 0 {
113
114
115 ast.Walk(f, nil, func(n ast.Node) {
116 if x, ok := n.(*ast.Ident); ok {
117
118 if x.Node == nil {
119 return
120 }
121 for i, s := range specs {
122 if s == x.Node {
123 specs[i] = nil
124 return
125 }
126 }
127 }
128 })
129
130
131 for _, spec := range specs {
132 if spec == nil {
133 continue
134 }
135 if spec.Name == nil {
136 errs = errors.Append(errs, nodeErrorf(spec,
137 "imported and not used: %s", spec.Path.Value))
138 } else {
139 errs = errors.Append(errs, nodeErrorf(spec,
140 "imported and not used: %s as %s", spec.Path.Value, spec.Name))
141 }
142 }
143 }
144
145 k := 0
146 for _, u := range f.Unresolved {
147 if u.Node != nil {
148 continue
149 }
150 if n, ok := allFields[u.Name]; ok {
151 u.Node = n
152 u.Scope = f
153 continue
154 }
155 f.Unresolved[k] = u
156 k++
157 }
158 f.Unresolved = f.Unresolved[:k]
159
160
161
162
163
164 return errs
165 }
166
167 func lineStr(idx *index, n ast.Node) string {
168 return n.Pos().String()
169 }
170
View as plain text