Skip to content

Commit b648cf4

Browse files
uhthomasmvdan
andcommitted
cmd/cue: find packages by canonical path in get go
Most Go APIs like go/types.Package.Path and go/packages.Package.PkgPath use full canonical package paths, whereas go/packages.Package.Imports uses source import paths as they appear in the import declarations. We mixed the two, using paths from go/types to index into Imports, resulting in nil packages in the edge cases when they are different. One such instance is vendored packages, whose full path may be "vendor/foo/bar" when they are simply imported as "foo/bar". This also fixes a similar panic with some type aliases, in particular when an alias points to an indirectly imported package, as such a package would be missing from the Imports map. The two added testscripts reproduced both panics without the fix, and now work as expected with the fix. Fixes #1607. Fixes #2046. Change-Id: I51df3465da76b39f031855982b48552604817f80 Signed-off-by: Thomas Way <[email protected]> Co-authored-by: Daniel Martí <[email protected]> Signed-off-by: Daniel Martí <[email protected]> Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1173100 Reviewed-by: Paul Jolly <[email protected]> Unity-Result: CUE porcuepine <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 5489392 commit b648cf4

File tree

3 files changed

+100
-9
lines changed

3 files changed

+100
-9
lines changed

cmd/cue/cmd/get_go.go

+24-9
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,10 @@ func (e *extractor) filter(name string) bool {
246246
type extractor struct {
247247
cmd *Command
248248

249-
stderr io.Writer
250-
pkgs []*packages.Package
251-
done map[string]bool
249+
stderr io.Writer
250+
pkgs []*packages.Package
251+
allPkgs map[string]*packages.Package
252+
done map[string]bool
252253

253254
// per package
254255
orig map[types.Type]*ast.StructType
@@ -395,10 +396,11 @@ func extract(cmd *Command, args []string) error {
395396
}
396397

397398
e := extractor{
398-
cmd: cmd,
399-
stderr: cmd.Stderr(),
400-
pkgs: pkgs,
401-
orig: map[types.Type]*ast.StructType{},
399+
cmd: cmd,
400+
stderr: cmd.Stderr(),
401+
pkgs: pkgs,
402+
allPkgs: map[string]*packages.Package{},
403+
orig: map[types.Type]*ast.StructType{},
402404
}
403405

404406
e.initExclusions(flagExclude.String(cmd))
@@ -407,6 +409,7 @@ func extract(cmd *Command, args []string) error {
407409

408410
for _, p := range pkgs {
409411
e.done[p.PkgPath] = true
412+
e.addPackage(p)
410413
}
411414

412415
for _, p := range pkgs {
@@ -417,6 +420,19 @@ func extract(cmd *Command, args []string) error {
417420
return nil
418421
}
419422

423+
func (e *extractor) addPackage(p *packages.Package) {
424+
if pkg, ok := e.allPkgs[p.PkgPath]; ok {
425+
if p != pkg {
426+
panic(fmt.Sprintf("duplicate package %s", p.PkgPath))
427+
}
428+
return
429+
}
430+
e.allPkgs[p.PkgPath] = p
431+
for _, pkg := range p.Imports {
432+
e.addPackage(pkg)
433+
}
434+
}
435+
420436
func (e *extractor) recordTypeInfo(p *packages.Package) {
421437
for _, f := range p.Syntax {
422438
ast.Inspect(f, func(n ast.Node) bool {
@@ -546,8 +562,7 @@ func (e *extractor) extractPkg(root string, p *packages.Package) error {
546562
for path := range e.usedPkgs {
547563
if !e.done[path] {
548564
e.done[path] = true
549-
p := p.Imports[path]
550-
if err := e.extractPkg(root, p); err != nil {
565+
if err := e.extractPkg(root, e.allPkgs[p.PkgPath]); err != nil {
551566
return err
552567
}
553568
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Issue 1607
2+
3+
exec cue get go --local ./x
4+
cmp x/x_go_gen.cue x_go_gen.cue.golden
5+
6+
-- go.mod --
7+
module mod.test
8+
9+
go 1.21
10+
-- x/x.go --
11+
package x
12+
13+
import "mod.test/y"
14+
15+
type X = y.Y
16+
17+
-- y/y.go --
18+
package y
19+
20+
import "mod.test/z"
21+
22+
type Y = z.Z
23+
24+
-- z/z.go --
25+
package z
26+
27+
type Z int
28+
29+
-- x_go_gen.cue.golden --
30+
// Code generated by cue get go. DO NOT EDIT.
31+
32+
//cue:generate cue get go mod.test/x
33+
34+
package x
35+
36+
import "mod.test/z"
37+
38+
#X: z.#Z
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Issue 1607
2+
3+
exec cue get go --local ./x
4+
cmp x/x_go_gen.cue x_go_gen.cue.golden
5+
6+
-- go.mod --
7+
module mod.test
8+
9+
go 1.21
10+
-- x/x.go --
11+
package x
12+
13+
import "mod.test/y"
14+
15+
type X = y.Y
16+
17+
-- y/y.go --
18+
package y
19+
20+
import "mod.test/z"
21+
22+
type Y = z.Z
23+
24+
-- z/z.go --
25+
package z
26+
27+
type Z int
28+
29+
-- x_go_gen.cue.golden --
30+
// Code generated by cue get go. DO NOT EDIT.
31+
32+
//cue:generate cue get go mod.test/x
33+
34+
package x
35+
36+
import "mod.test/z"
37+
38+
#X: z.#Z

0 commit comments

Comments
 (0)