Skip to content

Commit 1c54297

Browse files
committed
cmd/cue/cmd: fix get go package handling
A referenced alias in a different file in the same package for a package that was not used within the file in which the alias was referenced itself, resulted in improper handling. Implementation now uses astutil.Sanitize, which allow for more local import handling, resulting in more robust generation. This also allows eliminating some package tracking and the `usedInFile` field. We could rely more on Sanitize, but that is left up to a next round. Fixes #464 Change-Id: Iaaf98f321a7947a6f24ced85edd5218139cbe785 Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6961 Reviewed-by: Marcel van Lohuizen <[email protected]> Reviewed-by: CUE cueckoo <[email protected]>
1 parent 30ca062 commit 1c54297

File tree

8 files changed

+125
-41
lines changed

8 files changed

+125
-41
lines changed

cmd/cue/cmd/get_go.go

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"path/filepath"
2828
"reflect"
2929
"regexp"
30-
"sort"
3130
"strconv"
3231
"strings"
3332
"unicode"
@@ -36,6 +35,7 @@ import (
3635
"golang.org/x/tools/go/packages"
3736

3837
cueast "cuelang.org/go/cue/ast"
38+
"cuelang.org/go/cue/ast/astutil"
3939
"cuelang.org/go/cue/format"
4040
"cuelang.org/go/cue/load"
4141
"cuelang.org/go/cue/parser"
@@ -259,11 +259,10 @@ type extractor struct {
259259
usedPkgs map[string]bool
260260

261261
// per file
262-
cmap ast.CommentMap
263-
pkg *packages.Package
264-
consts map[string][]string
265-
pkgNames map[string]pkgInfo
266-
usedInFile map[string]bool
262+
cmap ast.CommentMap
263+
pkg *packages.Package
264+
consts map[string][]string
265+
pkgNames map[string]pkgInfo
267266

268267
exclusions []*regexp.Regexp
269268
exclude string
@@ -282,7 +281,6 @@ func (e *extractor) logf(format string, args ...interface{}) {
282281

283282
func (e *extractor) usedPkg(pkg string) {
284283
e.usedPkgs[pkg] = true
285-
e.usedInFile[pkg] = true
286284
}
287285

288286
func initInterfaces() error {
@@ -427,7 +425,6 @@ func (e *extractor) extractPkg(root string, p *packages.Package) error {
427425
e.cmap = ast.NewCommentMap(p.Fset, f, f.Comments)
428426

429427
e.pkgNames = map[string]pkgInfo{}
430-
e.usedInFile = map[string]bool{}
431428

432429
for _, spec := range f.Imports {
433430
pkgPath, _ := strconv.Unquote(spec.Path.Value)
@@ -457,12 +454,6 @@ func (e *extractor) extractPkg(root string, p *packages.Package) error {
457454
continue
458455
}
459456

460-
pkgs := []string{}
461-
for k := range e.usedInFile {
462-
pkgs = append(pkgs, k)
463-
}
464-
sort.Strings(pkgs)
465-
466457
pName := flagPackage.String(e.cmd)
467458
if pName == "" {
468459
pName = p.Name
@@ -478,22 +469,12 @@ func (e *extractor) extractPkg(root string, p *packages.Package) error {
478469
}},
479470
pkg,
480471
}}
472+
f.Decls = append(f.Decls, decls...)
481473

482-
if len(pkgs) > 0 {
483-
imports := &cueast.ImportDecl{}
484-
f.Decls = append(f.Decls, imports)
485-
for _, s := range pkgs {
486-
info := e.pkgNames[s]
487-
spec := cueast.NewImport(nil, info.id)
488-
if p.Imports[s].Name != info.name {
489-
spec.Name = e.ident(info.name, false)
490-
}
491-
imports.Specs = append(imports.Specs, spec)
492-
}
474+
if err := astutil.Sanitize(f); err != nil {
475+
return err
493476
}
494477

495-
f.Decls = append(f.Decls, decls...)
496-
497478
file := filepath.Base(p.CompiledGoFiles[i])
498479

499480
file = strings.Replace(file, ".go", "_go", 1)
@@ -936,9 +917,12 @@ func (e *extractor) makeType(expr types.Type) (result cueast.Expr) {
936917
// builtin type.
937918
switch obj.Type().String() {
938919
case "time.Time":
939-
e.usedInFile["time"] = true
940920
ref := e.ident(e.pkgNames[obj.Pkg().Path()].name, false)
941-
ref.Node = cueast.NewImport(nil, "time")
921+
var name *cueast.Ident
922+
if ref.Name != "time" {
923+
name = e.ident(ref.Name, false)
924+
}
925+
ref.Node = cueast.NewImport(name, "time")
942926
return cueast.NewSel(ref, obj.Name())
943927

944928
case "math/big.Int":
@@ -956,16 +940,26 @@ func (e *extractor) makeType(expr types.Type) (result cueast.Expr) {
956940
}
957941

958942
result = e.ident(obj.Name(), true)
959-
if pkg := obj.Pkg(); pkg != nil {
960-
if info := e.pkgNames[pkg.Path()]; info.name != "" {
961-
p := e.ident(info.name, false)
962-
// TODO: set package name et. at.
963-
p.Node = cueast.NewImport(nil, pkg.Path())
964-
// makeType is always called to describe a type, so whatever
965-
// this is referring to, it must be a definition.
966-
result = cueast.NewSel(p, "#"+obj.Name())
967-
e.usedPkg(pkg.Path())
943+
if pkg := obj.Pkg(); pkg != nil && pkg != e.pkg.Types {
944+
info := e.pkgNames[pkg.Path()]
945+
if info.name == "" {
946+
info.name = pkg.Name()
947+
}
948+
p := e.ident(info.name, false)
949+
var name *cueast.Ident
950+
if info.name != pkg.Name() {
951+
name = e.ident(info.name, false)
952+
}
953+
if info.id == "" {
954+
// This may happen if an alias is defined in a different file
955+
// within this package referring to yet another package.
956+
info.id = pkg.Path()
968957
}
958+
p.Node = cueast.NewImport(name, info.id)
959+
// makeType is always called to describe a type, so whatever
960+
// this is referring to, it must be a definition.
961+
result = cueast.NewSel(p, "#"+obj.Name())
962+
e.usedPkg(pkg.Path())
969963
}
970964
return
971965
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2020 CUE Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package pkg1
16+
17+
import p3 "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg3"
18+
19+
type MyBarzer = p3.Barzer

cmd/cue/cmd/testdata/code/go/pkg1/file1.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ type Foozer struct {
4747

4848
Barzer p2.Barzer
4949

50+
Alias1 *MyBarzer
51+
5052
Map map[string]*CustomJSON
5153
Slice1 []int
5254
Slice2 []interface{}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2020 CUE Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package pkg3
16+
17+
import pkgtwo "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2"
18+
19+
type Barzer = pkgtwo.Barzer
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Code generated by cue get go. DO NOT EDIT.
2+
3+
//cue:generate cue get go cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg1
4+
5+
package pkg1
6+
7+
import "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2"
8+
9+
#MyBarzer: pkgtwo.#Barzer

cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg1/file1_go_gen.cue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
package pkg1
77

88
import (
9-
p2 "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2:pkgtwo"
109
"time"
10+
p2 "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2:pkgtwo"
1111
)
1212

1313
// Foozer foozes a jaman.
@@ -24,8 +24,9 @@ import (
2424
bar?: int & >10 @go(Bar)
2525

2626
// Time is mapped to CUE's internal type.
27-
Time: time.Time
28-
Barzer: p2.#Barzer
27+
Time: time.Time
28+
Barzer: p2.#Barzer
29+
Alias1?: null | p2.#Barzer @go(,*p2.Barzer)
2930
Map: {[string]: null | #CustomJSON} @go(,map[string]*CustomJSON)
3031
Slice1: [...int] @go(,[]int)
3132
Slice2: [...] @go(,[]interface{})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Code generated by cue get go. DO NOT EDIT.
2+
3+
//cue:generate cue get go cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg3
4+
5+
package pkg3
6+
7+
import "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2:pkgtwo"
8+
9+
#Barzer: pkgtwo.#Barzer

cue/testdata/eval/errunifiy.txtar

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Incomplete errors should not unify with values.
2+
3+
-- in.cue --
4+
a: or([])
5+
a: "t"
6+
7+
b: _|_
8+
b: "t"
9+
10+
-- out/eval --
11+
Errors:
12+
from source:
13+
./in.cue:4:4
14+
15+
Result:
16+
(_|_){
17+
// [user]
18+
a: (string){ "t" }
19+
b: (_|_){
20+
// [user] from source:
21+
// ./in.cue:4:4
22+
}
23+
}
24+
-- out/compile --
25+
--- in.cue
26+
{
27+
a: or([])
28+
a: "t"
29+
b: _|_(from source)
30+
b: "t"
31+
}

0 commit comments

Comments
 (0)