Skip to content

Commit a220b3b

Browse files
findleyrgopherbot
authored andcommitted
[gopls-release-branch.0.15] gopls/internal/cache: don't create Views for vendored modules
We should not create Views for vendored modules, just as we don't create Views for modules in the module cache. With this change, gopls behaves similarly to [email protected] when navigating around the Kubernetes repo. Also add some test coverage that vendored packages are not workspace packages. Fixes golang/go#65830 Change-Id: If9883dc9616774952bd49c395e1c0d37ad3c2a6a Reviewed-on: https://go-review.googlesource.com/c/tools/+/565458 Reviewed-by: Alan Donovan <[email protected]> Auto-Submit: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> (cherry picked from commit a821e61) Reviewed-on: https://go-review.googlesource.com/c/tools/+/565695
1 parent a6289fe commit a220b3b

File tree

5 files changed

+136
-9
lines changed

5 files changed

+136
-9
lines changed

gopls/internal/cache/session.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,17 @@ func selectViewDefs(ctx context.Context, fs file.Source, folders []*Folder, open
470470
folderForFile := func(uri protocol.DocumentURI) *Folder {
471471
var longest *Folder
472472
for _, folder := range folders {
473-
if (longest == nil || len(folder.Dir) > len(longest.Dir)) && folder.Dir.Encloses(uri) {
473+
// Check that this is a better match than longest, but not through a
474+
// vendor directory. Count occurrences of "/vendor/" as a quick check
475+
// that the vendor directory is between the folder and the file. Note the
476+
// addition of a trailing "/" to handle the odd case where the folder is named
477+
// vendor (which I hope is exceedingly rare in any case).
478+
//
479+
// Vendored packages are, by definition, part of an existing view.
480+
if (longest == nil || len(folder.Dir) > len(longest.Dir)) &&
481+
folder.Dir.Encloses(uri) &&
482+
strings.Count(string(uri), "/vendor/") == strings.Count(string(folder.Dir)+"/", "/vendor/") {
483+
474484
longest = folder
475485
}
476486
}

gopls/internal/test/integration/misc/definition_test.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,7 @@ const _ = b.K
495495
}
496496

497497
// Run 'go mod vendor' outside the editor.
498-
if err := env.Sandbox.RunGoCommand(env.Ctx, ".", "mod", []string{"vendor"}, nil, true); err != nil {
499-
t.Fatalf("go mod vendor: %v", err)
500-
}
498+
env.RunGoCommand("mod", "vendor")
501499

502500
// Synchronize changes to watched files.
503501
env.Await(env.DoneWithChangeWatchedFiles())

gopls/internal/test/integration/misc/references_test.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,6 @@ func _() {
360360
// implementations in vendored modules were not found. The actual fix
361361
// was the same as for #55995; see TestVendoringInvalidatesMetadata.
362362
func TestImplementationsInVendor(t *testing.T) {
363-
t.Skip("golang/go#56169: file watching does not capture vendor dirs")
364-
365363
const proxy = `
366364
-- other.com/[email protected]/go.mod --
367365
module other.com/b
@@ -415,9 +413,7 @@ var _ b.B
415413
checkVendor(env.Implementations(refLoc), false)
416414

417415
// Run 'go mod vendor' outside the editor.
418-
if err := env.Sandbox.RunGoCommand(env.Ctx, ".", "mod", []string{"vendor"}, nil, true); err != nil {
419-
t.Fatalf("go mod vendor: %v", err)
420-
}
416+
env.RunGoCommand("mod", "vendor")
421417

422418
// Synchronize changes to watched files.
423419
env.Await(env.DoneWithChangeWatchedFiles())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package workspace
6+
7+
import (
8+
"testing"
9+
10+
. "golang.org/x/tools/gopls/internal/test/integration"
11+
)
12+
13+
func TestWorkspacePackagesExcludesVendor(t *testing.T) {
14+
// This test verifies that packages in the vendor directory are not workspace
15+
// packages. This would be an easy mistake for gopls to make, since mod
16+
// vendoring excludes go.mod files, and therefore the nearest go.mod file for
17+
// vendored packages is often the workspace mod file.
18+
const proxy = `
19+
-- other.com/[email protected]/go.mod --
20+
module other.com/b
21+
22+
go 1.18
23+
24+
-- other.com/[email protected]/b.go --
25+
package b
26+
27+
type B int
28+
29+
func _() {
30+
var V int // unused
31+
}
32+
`
33+
const src = `
34+
-- go.mod --
35+
module example.com/a
36+
go 1.14
37+
require other.com/b v1.0.0
38+
39+
-- go.sum --
40+
other.com/b v1.0.0 h1:ct1+0RPozzMvA2rSYnVvIfr/GDHcd7oVnw147okdi3g=
41+
other.com/b v1.0.0/go.mod h1:bfTSZo/4ZtAQJWBYScopwW6n9Ctfsl2mi8nXsqjDXR8=
42+
43+
-- a.go --
44+
package a
45+
46+
import "other.com/b"
47+
48+
var _ b.B
49+
50+
`
51+
WithOptions(
52+
ProxyFiles(proxy),
53+
Modes(Default),
54+
).Run(t, src, func(t *testing.T, env *Env) {
55+
env.RunGoCommand("mod", "vendor")
56+
// Uncomment for updated go.sum contents.
57+
// env.DumpGoSum(".")
58+
env.OpenFile("a.go")
59+
env.AfterChange(
60+
NoDiagnostics(), // as b is not a workspace package
61+
)
62+
env.GoToDefinition(env.RegexpSearch("a.go", `b\.(B)`))
63+
env.AfterChange(
64+
Diagnostics(env.AtRegexp("vendor/other.com/b/b.go", "V"), WithMessage("not used")),
65+
)
66+
})
67+
}

gopls/internal/test/integration/workspace/zero_config_test.go

+56
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package workspace
66

77
import (
8+
"strings"
89
"testing"
910

1011
"github.com/google/go-cmp/cmp"
@@ -268,3 +269,58 @@ package b
268269
}
269270
})
270271
}
272+
273+
func TestVendorExcluded(t *testing.T) {
274+
// Test that we don't create Views for vendored modules.
275+
//
276+
// We construct the vendor directory manually here, as `go mod vendor` will
277+
// omit the go.mod file. This synthesizes the setup of Kubernetes, where the
278+
// entire module is vendored through a symlinked directory.
279+
const src = `
280+
-- go.mod --
281+
module example.com/a
282+
283+
go 1.18
284+
285+
require other.com/b v1.0.0
286+
287+
-- a.go --
288+
package a
289+
import "other.com/b"
290+
var _ b.B
291+
292+
-- vendor/modules.txt --
293+
# other.com/b v1.0.0
294+
## explicit; go 1.14
295+
other.com/b
296+
297+
-- vendor/other.com/b/go.mod --
298+
module other.com/b
299+
go 1.14
300+
301+
-- vendor/other.com/b/b.go --
302+
package b
303+
type B int
304+
305+
func _() {
306+
var V int // unused
307+
}
308+
`
309+
WithOptions(
310+
Modes(Default),
311+
).Run(t, src, func(t *testing.T, env *Env) {
312+
env.OpenFile("a.go")
313+
env.AfterChange(NoDiagnostics())
314+
loc := env.GoToDefinition(env.RegexpSearch("a.go", `b\.(B)`))
315+
if !strings.Contains(string(loc.URI), "/vendor/") {
316+
t.Fatalf("Definition(b.B) = %v, want vendored location", loc.URI)
317+
}
318+
env.AfterChange(
319+
Diagnostics(env.AtRegexp("vendor/other.com/b/b.go", "V"), WithMessage("not used")),
320+
)
321+
322+
if views := env.Views(); len(views) != 1 {
323+
t.Errorf("After opening /vendor/, got %d views, want 1. Views:\n%v", len(views), views)
324+
}
325+
})
326+
}

0 commit comments

Comments
 (0)