Skip to content

Commit b623539

Browse files
committed
gopls/internal/cache: suppress "internal" import check on Bazel
The go command treats imports of packages whose path contains "/internal/" specially, and gopls must simulate it in several places. However, other build systems such as Bazel have their own mechanisms for representing visibility. This CL suppresses the check for packages obtained from a build system other than go list. (We derive this information from the view type, which in turn simulates the go/packages driver protocol switch using $GOPACKAGESDRIVER, etc.) Added test using Rob's new pass-through gopackagesdriver. Fixes golang/go#66856 Change-Id: I6e0671caeabe2146d397eb56d5cd4f7a40384370 Reviewed-on: https://go-review.googlesource.com/c/tools/+/587931 Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 1e9d12d commit b623539

File tree

7 files changed

+60
-12
lines changed

7 files changed

+60
-12
lines changed

gopls/internal/cache/analysis.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
257257
an = &analysisNode{
258258
fset: fset,
259259
fsource: struct{ file.Source }{s}, // expose only ReadFile
260+
viewType: s.View().Type(),
260261
mp: mp,
261262
analyzers: facty, // all nodes run at least the facty analyzers
262263
allDeps: make(map[PackagePath]*analysisNode),
@@ -522,6 +523,7 @@ func (an *analysisNode) decrefPreds() {
522523
type analysisNode struct {
523524
fset *token.FileSet // file set shared by entire batch (DAG)
524525
fsource file.Source // Snapshot.ReadFile, for use by Pass.ReadFile
526+
viewType ViewType // type of view
525527
mp *metadata.Package // metadata for this package
526528
files []file.Handle // contents of CompiledGoFiles
527529
analyzers []*analysis.Analyzer // set of analyzers to run
@@ -742,6 +744,8 @@ func (an *analysisNode) cacheKey() [sha256.Size]byte {
742744
// package metadata
743745
mp := an.mp
744746
fmt.Fprintf(hasher, "package: %s %s %s\n", mp.ID, mp.Name, mp.PkgPath)
747+
fmt.Fprintf(hasher, "viewtype: %s\n", an.viewType) // (affects diagnostics)
748+
745749
// We can ignore m.DepsBy{Pkg,Import}Path: although the logic
746750
// uses those fields, we account for them by hashing vdeps.
747751

@@ -1023,7 +1027,7 @@ func (an *analysisNode) typeCheck(parsed []*parsego.File) *analysisPackage {
10231027
}
10241028

10251029
// (Duplicates logic from check.go.)
1026-
if !metadata.IsValidImport(an.mp.PkgPath, dep.mp.PkgPath) {
1030+
if !metadata.IsValidImport(an.mp.PkgPath, dep.mp.PkgPath, an.viewType != GoPackagesDriverView) {
10271031
return nil, fmt.Errorf("invalid use of internal package %s", importPath)
10281032
}
10291033

gopls/internal/cache/check.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1632,7 +1632,7 @@ func (b *typeCheckBatch) typesConfig(ctx context.Context, inputs typeCheckInputs
16321632
// e.g. missing metadata for dependencies in buildPackageHandle
16331633
return nil, missingPkgError(inputs.id, path, inputs.viewType)
16341634
}
1635-
if !metadata.IsValidImport(inputs.pkgPath, depPH.mp.PkgPath) {
1635+
if !metadata.IsValidImport(inputs.pkgPath, depPH.mp.PkgPath, inputs.viewType != GoPackagesDriverView) {
16361636
return nil, fmt.Errorf("invalid use of internal package %q", path)
16371637
}
16381638
return b.getImportPackage(ctx, id)

gopls/internal/cache/load.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ func (s *Snapshot) load(ctx context.Context, allowNetwork bool, scopes ...loadSc
262262
if allFilesExcluded(pkg.GoFiles, filterFunc) {
263263
continue
264264
}
265-
buildMetadata(newMetadata, pkg, cfg.Dir, standalone)
265+
buildMetadata(newMetadata, pkg, cfg.Dir, standalone, s.view.typ != GoPackagesDriverView)
266266
}
267267

268268
s.mu.Lock()
@@ -354,7 +354,7 @@ func (m *moduleErrorMap) Error() string {
354354
// Returns the metadata.Package that was built (or which was already present in
355355
// updates), or nil if the package could not be built. Notably, the resulting
356356
// metadata.Package may have an ID that differs from pkg.ID.
357-
func buildMetadata(updates map[PackageID]*metadata.Package, pkg *packages.Package, loadDir string, standalone bool) *metadata.Package {
357+
func buildMetadata(updates map[PackageID]*metadata.Package, pkg *packages.Package, loadDir string, standalone, goListView bool) *metadata.Package {
358358
// Allow for multiple ad-hoc packages in the workspace (see #47584).
359359
pkgPath := PackagePath(pkg.PkgPath)
360360
id := PackageID(pkg.ID)
@@ -520,7 +520,7 @@ func buildMetadata(updates map[PackageID]*metadata.Package, pkg *packages.Packag
520520
continue
521521
}
522522

523-
dep := buildMetadata(updates, imported, loadDir, false) // only top level packages can be standalone
523+
dep := buildMetadata(updates, imported, loadDir, false, goListView) // only top level packages can be standalone
524524

525525
// Don't record edges to packages with no name, as they cause trouble for
526526
// the importer (golang/go#60952).

gopls/internal/cache/metadata/metadata.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -236,19 +236,23 @@ func RemoveIntermediateTestVariants(pmetas *[]*Package) {
236236
*pmetas = res
237237
}
238238

239-
// IsValidImport returns whether importPkgPath is importable
240-
// by pkgPath.
241-
func IsValidImport(pkgPath, importPkgPath PackagePath) bool {
242-
i := strings.LastIndex(string(importPkgPath), "/internal/")
239+
// IsValidImport returns whether from may import to.
240+
func IsValidImport(from, to PackagePath, goList bool) bool {
241+
// If the metadata came from a build system other than go list
242+
// (e.g. bazel) it is beyond our means to compute visibility.
243+
if !goList {
244+
return true
245+
}
246+
i := strings.LastIndex(string(to), "/internal/")
243247
if i == -1 {
244248
return true
245249
}
246250
// TODO(rfindley): this looks wrong: IsCommandLineArguments is meant to
247251
// operate on package IDs, not package paths.
248-
if IsCommandLineArguments(PackageID(pkgPath)) {
252+
if IsCommandLineArguments(PackageID(from)) {
249253
return true
250254
}
251255
// TODO(rfindley): this is wrong. mod.testx/p should not be able to
252256
// import mod.test/internal: https://go.dev/play/p/-Ca6P-E4V4q
253-
return strings.HasPrefix(string(pkgPath), string(importPkgPath[:i]))
257+
return strings.HasPrefix(string(from), string(to[:i]))
254258
}

gopls/internal/golang/known_packages.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func KnownPackagePaths(ctx context.Context, snapshot *cache.Snapshot, fh file.Ha
7676
continue
7777
}
7878
// make sure internal packages are importable by the file
79-
if !metadata.IsValidImport(current.PkgPath, knownPkg.PkgPath) {
79+
if !metadata.IsValidImport(current.PkgPath, knownPkg.PkgPath, snapshot.View().Type() != cache.GoPackagesDriverView) {
8080
continue
8181
}
8282
// naive check on cyclical imports

gopls/internal/test/integration/diagnostics/gopackagesdriver_test.go

+37
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,40 @@ func f() {
4646
)
4747
})
4848
}
49+
50+
func TestValidImportCheck_GoPackagesDriver(t *testing.T) {
51+
const files = `
52+
-- go.work --
53+
use .
54+
55+
-- go.mod --
56+
module example.com
57+
go 1.0
58+
59+
-- a/a.go --
60+
package a
61+
import _ "example.com/b/internal/c"
62+
63+
-- b/internal/c/c.go --
64+
package c
65+
`
66+
67+
// Note that 'go list' produces an error ("use of internal package %q not allowed")
68+
// and gopls produces another ("invalid use of internal package %q") with source=compiler.
69+
// Here we assert that the second one is not reported with a go/packages driver.
70+
// (We don't assert that the first is missing, because the test driver wraps go list!)
71+
72+
// go list
73+
Run(t, files, func(t *testing.T, env *Env) {
74+
env.OpenFile("a/a.go")
75+
env.AfterChange(Diagnostics(WithMessage(`invalid use of internal package "example.com/b/internal/c"`)))
76+
})
77+
78+
// test driver
79+
WithOptions(
80+
FakeGoPackagesDriver(t),
81+
).Run(t, files, func(t *testing.T, env *Env) {
82+
env.OpenFile("a/a.go")
83+
env.AfterChange(NoDiagnostics(WithMessage(`invalid use of internal package "example.com/b/internal/c"`)))
84+
})
85+
}

gopls/internal/test/marker/testdata/diagnostics/useinternal.txt

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ This test checks a diagnostic for invalid use of internal packages.
22

33
This list error changed in Go 1.21.
44

5+
See TestValidImportCheck_GoPackagesDriver for a test that no diagnostic
6+
is produced when using a GOPACKAGESDRIVER (such as for Bazel).
7+
58
-- flags --
69
-min_go=go1.21
710

0 commit comments

Comments
 (0)