diff --git a/cue/types.go b/cue/types.go index 9e2b5d97c60..a30725a9ae8 100644 --- a/cue/types.go +++ b/cue/types.go @@ -26,6 +26,7 @@ import ( "github.com/cockroachdb/apd/v2" "cuelang.org/go/cue/ast" + "cuelang.org/go/cue/build" "cuelang.org/go/cue/errors" "cuelang.org/go/cue/token" "cuelang.org/go/internal" @@ -1088,6 +1089,18 @@ func (v Value) Source() ast.Node { return v.v.Value().Source() } +// If v exactly represents a package, BuildInstance returns +// the build instance corresponding to the value; otherwise it returns nil. +// +// The value returned by Value.ReferencePath will commonly represent +// a package. +func (v Value) BuildInstance() *build.Instance { + if v.idx == nil { + return nil + } + return v.idx.GetInstanceFromNode(v.v) +} + // Err returns the error represented by v or nil v is not an error. func (v Value) Err() error { if err := v.checkKind(v.ctx(), adt.BottomKind); err != nil { diff --git a/cue/types_test.go b/cue/types_test.go index 8166d2ff2a7..d7aa5d3d578 100644 --- a/cue/types_test.go +++ b/cue/types_test.go @@ -2858,9 +2858,10 @@ func TestTrimZeros(t *testing.T) { func TestReferencePath(t *testing.T) { testCases := []struct { - input string - want string - alt string + input string + want string + wantImportPath string + alt string }{{ input: "v: w: x: _|_", want: "", @@ -2926,8 +2927,9 @@ func TestReferencePath(t *testing.T) { v: w: x: math.Pi `, - want: "Pi", - alt: "3.14159265358979323846264338327950288419716939937510582097494459", + want: "Pi", + wantImportPath: "math", + alt: "3.14159265358979323846264338327950288419716939937510582097494459", }} for _, tc := range testCases { t.Run("", func(t *testing.T) { @@ -2939,7 +2941,6 @@ func TestReferencePath(t *testing.T) { if got := path.String(); got != tc.want { t.Errorf("\n got %v;\nwant %v", got, tc.want) } - if tc.want != "" { want := "1" if tc.alt != "" { @@ -2949,6 +2950,13 @@ func TestReferencePath(t *testing.T) { if v != want { t.Errorf("path resolved to %s; want %s", v, want) } + buildInst := root.BuildInstance() + if buildInst == nil { + t.Fatalf("no build instance found for reference path root") + } + if got, want := buildInst.ImportPath, tc.wantImportPath; got != want { + t.Errorf("unexpected import path; got %q want %q", got, want) + } } inst, a := v.Reference() @@ -2970,6 +2978,13 @@ func TestReferencePath(t *testing.T) { } } +func TestZeroValueBuildInstance(t *testing.T) { + inst := Value{}.BuildInstance() + if inst != nil { + t.Error("unexpected non-nil instance") + } +} + func TestPos(t *testing.T) { testCases := []struct { value string