Skip to content

Commit 21d9f01

Browse files
findleyrdennypenta
authored andcommitted
go/packages: add Dir and ForTest fields to Package
Add a new Dir field, and export ForTest, per golang/go#38445. The needInternalForTest mode bit is promoted to NeedForTest, but no mode bit is added for Dir as it is logically related to NeedFiles. A test is added for the new fields using a simpler txtar-based setup, since I did not have time to page in the quite heavyweight packagestest framework. For golang/go#38445 Change-Id: I92026462f7ed7e237db1f4e50a3bbf2936802fbb Reviewed-on: https://go-review.googlesource.com/c/tools/+/626495 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Alan Donovan <[email protected]>
1 parent 031a90d commit 21d9f01

File tree

9 files changed

+129
-22
lines changed

9 files changed

+129
-22
lines changed

go/packages/golist.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,13 +505,14 @@ func (state *golistState) createDriverResponse(words ...string) (*DriverResponse
505505
pkg := &Package{
506506
Name: p.Name,
507507
ID: p.ImportPath,
508+
Dir: p.Dir,
508509
GoFiles: absJoin(p.Dir, p.GoFiles, p.CgoFiles),
509510
CompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles),
510511
OtherFiles: absJoin(p.Dir, otherFiles(p)...),
511512
EmbedFiles: absJoin(p.Dir, p.EmbedFiles),
512513
EmbedPatterns: absJoin(p.Dir, p.EmbedPatterns),
513514
IgnoredFiles: absJoin(p.Dir, p.IgnoredGoFiles, p.IgnoredOtherFiles),
514-
forTest: p.ForTest,
515+
ForTest: p.ForTest,
515516
depsErrors: p.DepsErrors,
516517
Module: p.Module,
517518
}
@@ -795,7 +796,7 @@ func jsonFlag(cfg *Config, goVersion int) string {
795796
// Request Dir in the unlikely case Export is not absolute.
796797
addFields("Dir", "Export")
797798
}
798-
if cfg.Mode&needInternalForTest != 0 {
799+
if cfg.Mode&NeedForTest != 0 {
799800
addFields("ForTest")
800801
}
801802
if cfg.Mode&needInternalDepsErrors != 0 {

go/packages/loadmode_string.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var modes = [...]struct {
2323
{NeedSyntax, "NeedSyntax"},
2424
{NeedTypesInfo, "NeedTypesInfo"},
2525
{NeedTypesSizes, "NeedTypesSizes"},
26+
{NeedForTest, "NeedForTest"},
2627
{NeedModule, "NeedModule"},
2728
{NeedEmbedFiles, "NeedEmbedFiles"},
2829
{NeedEmbedPatterns, "NeedEmbedPatterns"},

go/packages/packages.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const (
5555
// NeedName adds Name and PkgPath.
5656
NeedName LoadMode = 1 << iota
5757

58-
// NeedFiles adds GoFiles, OtherFiles, and IgnoredFiles
58+
// NeedFiles adds Dir, GoFiles, OtherFiles, and IgnoredFiles
5959
NeedFiles
6060

6161
// NeedCompiledGoFiles adds CompiledGoFiles.
@@ -86,9 +86,10 @@ const (
8686
// needInternalDepsErrors adds the internal deps errors field for use by gopls.
8787
needInternalDepsErrors
8888

89-
// needInternalForTest adds the internal forTest field.
89+
// NeedForTest adds ForTest.
90+
//
9091
// Tests must also be set on the context for this field to be populated.
91-
needInternalForTest
92+
NeedForTest
9293

9394
// typecheckCgo enables full support for type checking cgo. Requires Go 1.15+.
9495
// Modifies CompiledGoFiles and Types, and has no effect on its own.
@@ -434,6 +435,12 @@ type Package struct {
434435
// PkgPath is the package path as used by the go/types package.
435436
PkgPath string
436437

438+
// Dir is the directory associated with the package, if it exists.
439+
//
440+
// For packages listed by the go command, this is the directory containing
441+
// the package files.
442+
Dir string
443+
437444
// Errors contains any errors encountered querying the metadata
438445
// of the package, or while parsing or type-checking its files.
439446
Errors []Error
@@ -521,8 +528,8 @@ type Package struct {
521528

522529
// -- internal --
523530

524-
// forTest is the package under test, if any.
525-
forTest string
531+
// ForTest is the package under test, if any.
532+
ForTest string
526533

527534
// depsErrors is the DepsErrors field from the go list response, if any.
528535
depsErrors []*packagesinternal.PackageError
@@ -551,9 +558,6 @@ type ModuleError struct {
551558
}
552559

553560
func init() {
554-
packagesinternal.GetForTest = func(p interface{}) string {
555-
return p.(*Package).forTest
556-
}
557561
packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError {
558562
return p.(*Package).depsErrors
559563
}
@@ -565,7 +569,6 @@ func init() {
565569
}
566570
packagesinternal.TypecheckCgo = int(typecheckCgo)
567571
packagesinternal.DepsErrors = int(needInternalDepsErrors)
568-
packagesinternal.ForTest = int(needInternalForTest)
569572
}
570573

571574
// An Error describes a problem with a package's metadata, syntax, or types.

go/packages/packages_test.go

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ import (
2626
"testing/fstest"
2727
"time"
2828

29+
"github.com/google/go-cmp/cmp"
2930
"golang.org/x/tools/go/packages"
3031
"golang.org/x/tools/internal/packagesinternal"
3132
"golang.org/x/tools/internal/packagestest"
3233
"golang.org/x/tools/internal/testenv"
3334
"golang.org/x/tools/internal/testfiles"
35+
"golang.org/x/tools/txtar"
3436
)
3537

3638
// testCtx is canceled when the test binary is about to time out.
@@ -2324,6 +2326,10 @@ func TestLoadModeStrings(t *testing.T) {
23242326
packages.NeedName | packages.NeedExportFile,
23252327
"(NeedName|NeedExportFile)",
23262328
},
2329+
{
2330+
packages.NeedForTest | packages.NeedEmbedFiles | packages.NeedEmbedPatterns,
2331+
"(NeedForTest|NeedEmbedFiles|NeedEmbedPatterns)",
2332+
},
23272333
{
23282334
packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedExportFile | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes,
23292335
"(NeedName|NeedFiles|NeedCompiledGoFiles|NeedImports|NeedDeps|NeedExportFile|NeedTypes|NeedSyntax|NeedTypesInfo|NeedTypesSizes)",
@@ -2425,8 +2431,7 @@ func testForTestField(t *testing.T, exporter packagestest.Exporter) {
24252431
if !hasTestFile {
24262432
continue
24272433
}
2428-
got := packagesinternal.GetForTest(pkg)
2429-
if got != forTest {
2434+
if got := pkg.ForTest; got != forTest {
24302435
t.Errorf("expected %q, got %q", forTest, got)
24312436
}
24322437
}
@@ -3209,3 +3214,102 @@ func foo() int {
32093214
t.Errorf("expected types info to be present but got nil")
32103215
}
32113216
}
3217+
3218+
// TestDirAndForTest tests the new fields added as part of golang/go#38445.
3219+
func TestDirAndForTest(t *testing.T) {
3220+
dir := writeTree(t, `
3221+
-- go.mod --
3222+
module example.com
3223+
3224+
go 1.18
3225+
3226+
-- a/a.go --
3227+
package a
3228+
3229+
func Foo() int { return 1 }
3230+
3231+
-- a/a_test.go --
3232+
package a
3233+
3234+
func Bar() int { return 2 }
3235+
3236+
-- a/a_x_test.go --
3237+
package a_test
3238+
3239+
import (
3240+
"testing"
3241+
3242+
"example.com/a"
3243+
"example.com/b"
3244+
)
3245+
3246+
func TestFooBar(t *testing.T) {
3247+
if got := a.Foo() + a.Bar() + b.Baz(); got != 6 {
3248+
t.Errorf("whoops!")
3249+
}
3250+
}
3251+
3252+
-- b/b.go --
3253+
package b
3254+
3255+
import "example.com/a"
3256+
3257+
func Baz() int { return 3 }
3258+
3259+
func Foo() int { return a.Foo() }
3260+
`)
3261+
3262+
pkgs, err := packages.Load(&packages.Config{
3263+
Mode: packages.NeedName |
3264+
packages.NeedFiles |
3265+
packages.NeedForTest |
3266+
packages.NeedImports,
3267+
Dir: dir,
3268+
Tests: true,
3269+
}, "./...")
3270+
if err != nil {
3271+
t.Fatal(err)
3272+
}
3273+
type result struct{ Dir, ForTest string }
3274+
got := make(map[string]result)
3275+
packages.Visit(pkgs, nil, func(pkg *packages.Package) {
3276+
if strings.Contains(pkg.PkgPath, ".") { // ignore std
3277+
rel, err := filepath.Rel(dir, pkg.Dir)
3278+
if err != nil {
3279+
t.Errorf("Rel(%q, %q) failed: %v", dir, pkg.Dir, err)
3280+
return
3281+
}
3282+
got[pkg.ID] = result{
3283+
Dir: rel,
3284+
ForTest: pkg.ForTest,
3285+
}
3286+
}
3287+
})
3288+
want := map[string]result{
3289+
"example.com/a": {"a", ""},
3290+
"example.com/a.test": {"a", ""},
3291+
"example.com/a [example.com/a.test]": {"a", "example.com/a"}, // test variant
3292+
"example.com/a_test [example.com/a.test]": {"a", "example.com/a"}, // x_test
3293+
"example.com/b [example.com/a.test]": {"b", "example.com/a"}, // intermediate test variant
3294+
"example.com/b": {"b", ""},
3295+
}
3296+
if diff := cmp.Diff(want, got); diff != "" {
3297+
t.Errorf("Load returned mismatching ForTest fields (ID->result -want +got):\n%s", diff)
3298+
}
3299+
t.Logf("Packages: %+v", pkgs)
3300+
}
3301+
3302+
func writeTree(t *testing.T, archive string) string {
3303+
root := t.TempDir()
3304+
3305+
for _, f := range txtar.Parse([]byte(archive)).Files {
3306+
filename := filepath.Join(root, f.Name)
3307+
if err := os.MkdirAll(filepath.Dir(filename), 0777); err != nil {
3308+
t.Fatal(err)
3309+
}
3310+
if err := os.WriteFile(filename, f.Data, 0666); err != nil {
3311+
t.Fatal(err)
3312+
}
3313+
}
3314+
return root
3315+
}

gopls/internal/cache/load.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func (s *Snapshot) load(ctx context.Context, allowNetwork bool, scopes ...loadSc
194194
return errorf("go/packages returned multiple standalone packages")
195195
}
196196
standalonePkg = pkg
197-
} else if packagesinternal.GetForTest(pkg) == "" && !strings.HasSuffix(pkg.ID, ".test") {
197+
} else if pkg.ForTest == "" && !strings.HasSuffix(pkg.ID, ".test") {
198198
return errorf("go/packages returned unexpected package %q for standalone file", pkg.ID)
199199
}
200200
}
@@ -259,7 +259,7 @@ func (s *Snapshot) load(ctx context.Context, allowNetwork bool, scopes ...loadSc
259259
s.setBuiltin(pkg.GoFiles[0])
260260
continue
261261
}
262-
if packagesinternal.GetForTest(pkg) == "builtin" {
262+
if pkg.ForTest == "builtin" {
263263
// We don't care about test variants of builtin. This caused test
264264
// failures in https://go.dev/cl/620196, when a test file was added to
265265
// builtin.
@@ -416,7 +416,7 @@ func buildMetadata(updates map[PackageID]*metadata.Package, pkg *packages.Packag
416416
ID: id,
417417
PkgPath: pkgPath,
418418
Name: PackageName(pkg.Name),
419-
ForTest: PackagePath(packagesinternal.GetForTest(pkg)),
419+
ForTest: PackagePath(pkg.ForTest),
420420
TypesSizes: pkg.TypesSizes,
421421
LoadDir: loadDir,
422422
Module: pkg.Module,

gopls/internal/cache/snapshot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ func (s *Snapshot) config(ctx context.Context, inv *gocommand.Invocation) *packa
385385
packages.NeedModule |
386386
packages.NeedEmbedFiles |
387387
packages.LoadMode(packagesinternal.DepsErrors) |
388-
packages.LoadMode(packagesinternal.ForTest),
388+
packages.NeedForTest,
389389
Fset: nil, // we do our own parsing
390390
Overlay: s.buildOverlays(),
391391
ParseFile: func(*token.FileSet, string, []byte) (*ast.File, error) {

gopls/internal/cache/typerefs/pkgrefs_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ func loadPackages(query string, needExport bool) (map[PackageID]string, Metadata
342342
packages.NeedModule |
343343
packages.NeedEmbedFiles |
344344
packages.LoadMode(packagesinternal.DepsErrors) |
345-
packages.LoadMode(packagesinternal.ForTest),
345+
packages.NeedForTest,
346346
Tests: true,
347347
}
348348
if needExport {
@@ -364,7 +364,7 @@ func loadPackages(query string, needExport bool) (map[PackageID]string, Metadata
364364
ID: id,
365365
PkgPath: PackagePath(pkg.PkgPath),
366366
Name: packageName(pkg.Name),
367-
ForTest: PackagePath(packagesinternal.GetForTest(pkg)),
367+
ForTest: PackagePath(pkg.ForTest),
368368
TypesSizes: pkg.TypesSizes,
369369
LoadDir: cfg.Dir,
370370
Module: pkg.Module,

internal/drivertest/driver_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ package lib
6868
packages.NeedModule |
6969
packages.NeedEmbedFiles |
7070
packages.LoadMode(packagesinternal.DepsErrors) |
71-
packages.LoadMode(packagesinternal.ForTest),
71+
packages.NeedForTest,
7272
}
7373

7474
tests := []struct {

internal/packagesinternal/packages.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// Package packagesinternal exposes internal-only fields from go/packages.
66
package packagesinternal
77

8-
var GetForTest = func(p interface{}) string { return "" }
98
var GetDepsErrors = func(p interface{}) []*PackageError { return nil }
109

1110
type PackageError struct {
@@ -16,7 +15,6 @@ type PackageError struct {
1615

1716
var TypecheckCgo int
1817
var DepsErrors int // must be set as a LoadMode to call GetDepsErrors
19-
var ForTest int // must be set as a LoadMode to call GetForTest
2018

2119
var SetModFlag = func(config interface{}, value string) {}
2220
var SetModFile = func(config interface{}, value string) {}

0 commit comments

Comments
 (0)