cue: fix import shortname mapping
- resolution was broken for builtin packages
- allow exporting variables in addition to builtins
Change-Id: I5ae4381f66a9a5b6f24ba98656e79cfbd8ef6fa0
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2715
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/ast.go b/cue/ast.go
index df566c4..6e394d3 100644
--- a/cue/ast.go
+++ b/cue/ast.go
@@ -155,7 +155,7 @@
}
if v.inSelector > 0 {
if p := getBuiltinShorthandPkg(ctx, n.Name); p != nil {
- return &nodeRef{baseValue: newExpr(n), node: p}
+ return &nodeRef{newExpr(n), p, label}
}
}
}
@@ -454,7 +454,11 @@
ret = &selectorExpr{newExpr(n), ret, f}
} else {
n2 := v.mapScope(n.Node)
- ret = &nodeRef{baseValue: newExpr(n), node: n2}
+ ref := &nodeRef{baseValue: newExpr(n), node: n2}
+ ret = ref
+ if inst := v.ctx().getImportFromNode(n2); inst != nil {
+ ref.short = f
+ }
}
case *ast.BottomLit:
diff --git a/cue/build.go b/cue/build.go
index b00fd86..a76be73 100644
--- a/cue/build.go
+++ b/cue/build.go
@@ -419,13 +419,13 @@
name := path.Base(id)
if imp := p.LookupImport(id); imp != nil {
name = imp.PkgName
- if spec.Name != nil {
- name = spec.Name.Name
- }
} else if _, ok := builtins[id]; !ok {
// continue
return nodeErrorf(spec, "package %q not found", id)
}
+ if spec.Name != nil {
+ name = spec.Name.Name
+ }
if n, ok := fields[name]; ok {
return nodeErrorf(spec,
"%s redeclared as imported package name\n"+
diff --git a/cue/build_test.go b/cue/build_test.go
index 8377e8a..772ba9a 100644
--- a/cue/build_test.go
+++ b/cue/build_test.go
@@ -147,15 +147,24 @@
}{{
insts(&bimport{"", files(`test: "ok"`)}),
`{test: "ok"}`,
- // }, {
- // insts(pkg1, &bimport{"",
- // files(
- // `package test
+ }, {
+ insts(&bimport{"",
+ files(
+ `package test
- // import "math"
+ import "math"
- // "Pi: \(math.Pi)!"`)}),
- // `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
+ "Pi: \(math.Pi)!"`)}),
+ `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
+ }, {
+ insts(&bimport{"",
+ files(
+ `package test
+
+ import math2 "math"
+
+ "Pi: \(math2.Pi)!"`)}),
+ `"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
}, {
insts(pkg1, &bimport{"",
files(
@@ -172,12 +181,21 @@
`package test
import "pkg1"
- pkg1: 1
"Hello \(pkg1.Object)!"`),
}),
- `pkg1 redeclared as imported package name
- previous declaration at file0.cue:4:5`,
+ `"Hello World!"`,
+ }, {
+ insts(pkg1, &bimport{"",
+ files(
+ `package test
+
+ import pkg2 "pkg1"
+ pkg1: pkg2.Object
+
+ "Hello \(pkg1)!"`),
+ }),
+ `"Hello World!"`,
}, {
insts(pkg1, &bimport{"",
files(
diff --git a/cue/copy.go b/cue/copy.go
index f4f3f28..5a6594b 100644
--- a/cue/copy.go
+++ b/cue/copy.go
@@ -26,7 +26,7 @@
if node == x.node {
return x, false
}
- return &nodeRef{x.baseValue, node}, false
+ return &nodeRef{x.baseValue, node, x.short}, false
case *structLit:
arcs := make(arcs, len(x.arcs))
diff --git a/cue/export.go b/cue/export.go
index 61454d3..5454c68 100644
--- a/cue/export.go
+++ b/cue/export.go
@@ -164,6 +164,43 @@
panic(fmt.Sprintf("unsupported clause type %T", v))
}
+func (p *exporter) shortName(preferred, pkg string) string {
+ info, ok := p.imports[pkg]
+ short := info.short
+ if !ok {
+ short = pkg
+ if i := strings.LastIndexByte(pkg, '.'); i >= 0 {
+ short = pkg[i+1:]
+ }
+ if _, ok := p.top[p.ctx.label(short, true)]; ok && preferred != "" {
+ short = preferred
+ info.name = short
+ }
+ for {
+ if _, ok := p.top[p.ctx.label(short, true)]; !ok {
+ break
+ }
+ short += "x"
+ info.name = short
+ }
+ info.short = short
+ p.top[p.ctx.label(short, true)] = true
+ p.imports[pkg] = info
+ }
+ f := p.ctx.label(short, true)
+ for _, e := range p.stack {
+ if e.from == f {
+ if info.alias == "" {
+ info.alias = p.unique(short)
+ p.imports[pkg] = info
+ }
+ short = info.alias
+ break
+ }
+ }
+ return short
+}
+
func (p *exporter) expr(v value) ast.Expr {
if doEval(p.mode) {
e := v.evalPartial(p.ctx)
@@ -189,41 +226,19 @@
if x.pkg == 0 {
return name
}
- pkg := p.ctx.labelStr(x.pkg)
- info, ok := p.imports[pkg]
- short := info.short
- if !ok {
- info.short = ""
- short = pkg
- if i := strings.LastIndexByte(pkg, '.'); i >= 0 {
- short = pkg[i+1:]
- }
- for {
- if _, ok := p.top[p.ctx.label(short, true)]; !ok {
- break
- }
- short += "x"
- info.name = short
- }
- info.short = short
- p.top[p.ctx.label(short, true)] = true
- p.imports[pkg] = info
- }
- f := p.ctx.label(short, true)
- for _, e := range p.stack {
- if e.from == f {
- if info.alias == "" {
- info.alias = p.unique(short)
- p.imports[pkg] = info
- }
- short = info.alias
- break
- }
- }
+ short := p.shortName("", p.ctx.labelStr(x.pkg))
return &ast.SelectorExpr{X: ast.NewIdent(short), Sel: name}
case *nodeRef:
- return nil
+ if x.short == 0 {
+ return nil
+ }
+ inst := p.ctx.getImportFromNode(x.node)
+ if inst == nil {
+ return nil // should not happen!
+ }
+ short := p.ctx.labelStr(x.short)
+ return ast.NewIdent(p.shortName(short, inst.ImportPath))
case *selectorExpr:
n := p.expr(x.x)
diff --git a/cue/export_test.go b/cue/export_test.go
index 1646c5c..ef18af0 100644
--- a/cue/export_test.go
+++ b/cue/export_test.go
@@ -349,6 +349,50 @@
a: strings.ContainsAny("c")`),
}, {
in: `
+ import "time"
+
+ a: time.Time
+ `,
+ out: unindent(`
+ import "time"
+
+ a: time.Time`),
+ }, {
+ in: `
+ import "time"
+
+ {
+ a: time.Time
+ } & {
+ time: int
+ } `,
+ out: unindent(`
+ import timex "time"
+
+ time: int
+ a: timex.Time`),
+ }, {
+ in: `
+ import time2 "time"
+
+ a: time2.Time`,
+ out: unindent(`
+ import "time"
+
+ a: time.Time`),
+ }, {
+ in: `
+ import time2 "time"
+
+ time: int
+ a: time2.Time`,
+ out: unindent(`
+ import time2 "time"
+
+ time: int
+ a: time2.Time`),
+ }, {
+ in: `
import "strings"
a: strings.TrimSpace(" c ")
@@ -406,7 +450,7 @@
for _, tc := range testCases {
t.Run("", func(t *testing.T) {
var r Runtime
- inst, err := r.Parse("test", tc.in)
+ inst, err := r.Compile("test", tc.in)
if err != nil {
t.Fatal(err)
}
diff --git a/cue/value.go b/cue/value.go
index a459740..f8b6479 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -920,7 +920,8 @@
// A nodeRef is a reference to a node.
type nodeRef struct {
baseValue
- node scope
+ node scope
+ short label // only for packages, otherwise 0
}
func (x *nodeRef) kind() kind {