Skip to content

Commit ddd4bde

Browse files
committed
gopls/internal/golang: avoid PackageSymbols errors with missing packages
As reported in golang/vscode-go#3681, spurious errors from gopls.package_symbols can cause very distracting popups in VS Code. For now, err on the side of silence. In the future, we may want to revisit this behavior. For golang/vscode-go#3681 Change-Id: I67f8b8e1e299ef88dabbb284a151aada131652f8 Reviewed-on: https://go-review.googlesource.com/c/tools/+/649257 Reviewed-by: Hongxiang Jiang <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 44b61a1 commit ddd4bde

File tree

3 files changed

+80
-57
lines changed

3 files changed

+80
-57
lines changed

gopls/internal/golang/symbols.go

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,22 @@ func PackageSymbols(ctx context.Context, snapshot *cache.Snapshot, uri protocol.
8686
ctx, done := event.Start(ctx, "source.PackageSymbols")
8787
defer done()
8888

89-
mp, err := NarrowestMetadataForFile(ctx, snapshot, uri)
90-
if err != nil {
91-
return command.PackageSymbolsResult{}, err
89+
pkgFiles := []protocol.DocumentURI{uri}
90+
91+
// golang/vscode-go#3681: do our best if the file is not in a package.
92+
// TODO(rfindley): revisit this in the future once there is more graceful
93+
// handling in VS Code.
94+
if mp, err := NarrowestMetadataForFile(ctx, snapshot, uri); err == nil {
95+
pkgFiles = mp.CompiledGoFiles
9296
}
93-
pkgfiles := mp.CompiledGoFiles
94-
// Maps receiver name to the methods that use it
95-
receiverToMethods := make(map[string][]command.PackageSymbol)
96-
// Maps type symbol name to its index in symbols
97-
typeSymbolToIdx := make(map[string]int)
98-
var symbols []command.PackageSymbol
99-
for fidx, f := range pkgfiles {
97+
98+
var (
99+
pkgName string
100+
symbols []command.PackageSymbol
101+
receiverToMethods = make(map[string][]command.PackageSymbol) // receiver name -> methods
102+
typeSymbolToIdx = make(map[string]int) // type name -> index in symbols
103+
)
104+
for fidx, f := range pkgFiles {
100105
fh, err := snapshot.ReadFile(ctx, f)
101106
if err != nil {
102107
return command.PackageSymbolsResult{}, err
@@ -105,6 +110,9 @@ func PackageSymbols(ctx context.Context, snapshot *cache.Snapshot, uri protocol.
105110
if err != nil {
106111
return command.PackageSymbolsResult{}, err
107112
}
113+
if pkgName == "" && pgf.File != nil && pgf.File.Name != nil {
114+
pkgName = pgf.File.Name.Name
115+
}
108116
for _, decl := range pgf.File.Decls {
109117
switch decl := decl.(type) {
110118
case *ast.FuncDecl:
@@ -154,8 +162,8 @@ func PackageSymbols(ctx context.Context, snapshot *cache.Snapshot, uri protocol.
154162
}
155163
}
156164
return command.PackageSymbolsResult{
157-
PackageName: string(mp.Name),
158-
Files: pkgfiles,
165+
PackageName: pkgName,
166+
Files: pkgFiles,
159167
Symbols: symbols,
160168
}, nil
161169

gopls/internal/server/command.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,6 +1741,10 @@ func (c *commandHandler) PackageSymbols(ctx context.Context, args command.Packag
17411741
err := c.run(ctx, commandConfig{
17421742
forURI: args.URI,
17431743
}, func(ctx context.Context, deps commandDeps) error {
1744+
if deps.snapshot.FileKind(deps.fh) != file.Go {
1745+
// golang/vscode-go#3681: fail silently, to avoid spurious error popups.
1746+
return nil
1747+
}
17441748
res, err := golang.PackageSymbols(ctx, deps.snapshot, args.URI)
17451749
if err != nil {
17461750
return err

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

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import (
1616

1717
func TestPackageSymbols(t *testing.T) {
1818
const files = `
19+
-- go.mod --
20+
module example.com
21+
22+
go 1.20
23+
1924
-- a.go --
2025
package a
2126
@@ -33,68 +38,74 @@ func (s *S) M2() {}
3338
func (s *S) M3() {}
3439
3540
func F() {}
41+
-- unloaded.go --
42+
//go:build unloaded
43+
44+
package a
45+
46+
var Unloaded int
3647
`
3748
integration.Run(t, files, func(t *testing.T, env *integration.Env) {
38-
a_uri := env.Sandbox.Workdir.URI("a.go")
39-
b_uri := env.Sandbox.Workdir.URI("b.go")
49+
aURI := env.Sandbox.Workdir.URI("a.go")
50+
bURI := env.Sandbox.Workdir.URI("b.go")
4051
args, err := command.MarshalArgs(command.PackageSymbolsArgs{
41-
URI: a_uri,
52+
URI: aURI,
4253
})
4354
if err != nil {
44-
t.Fatalf("failed to MarshalArgs: %v", err)
55+
t.Fatal(err)
4556
}
4657

4758
var res command.PackageSymbolsResult
4859
env.ExecuteCommand(&protocol.ExecuteCommandParams{
49-
Command: "gopls.package_symbols",
60+
Command: command.PackageSymbols.String(),
5061
Arguments: args,
5162
}, &res)
5263

5364
want := command.PackageSymbolsResult{
5465
PackageName: "a",
55-
Files: []protocol.DocumentURI{a_uri, b_uri},
66+
Files: []protocol.DocumentURI{aURI, bURI},
5667
Symbols: []command.PackageSymbol{
57-
{
58-
Name: "A",
59-
Kind: protocol.Variable,
60-
File: 0,
61-
},
62-
{
63-
Name: "F",
64-
Kind: protocol.Function,
65-
File: 1,
66-
},
67-
{
68-
Name: "S",
69-
Kind: protocol.Struct,
70-
File: 0,
71-
Children: []command.PackageSymbol{
72-
{
73-
Name: "M1",
74-
Kind: protocol.Method,
75-
File: 0,
76-
},
77-
{
78-
Name: "M2",
79-
Kind: protocol.Method,
80-
File: 1,
81-
},
82-
{
83-
Name: "M3",
84-
Kind: protocol.Method,
85-
File: 1,
86-
},
87-
},
88-
},
89-
{
90-
Name: "b",
91-
Kind: protocol.Variable,
92-
File: 1,
93-
},
68+
{Name: "A", Kind: protocol.Variable, File: 0},
69+
{Name: "F", Kind: protocol.Function, File: 1},
70+
{Name: "S", Kind: protocol.Struct, File: 0, Children: []command.PackageSymbol{
71+
{Name: "M1", Kind: protocol.Method, File: 0},
72+
{Name: "M2", Kind: protocol.Method, File: 1},
73+
{Name: "M3", Kind: protocol.Method, File: 1},
74+
}},
75+
{Name: "b", Kind: protocol.Variable, File: 1},
9476
},
9577
}
96-
if diff := cmp.Diff(want, res, cmpopts.IgnoreFields(command.PackageSymbol{}, "Range", "SelectionRange", "Detail")); diff != "" {
97-
t.Errorf("gopls.package_symbols returned unexpected diff (-want +got):\n%s", diff)
78+
ignore := cmpopts.IgnoreFields(command.PackageSymbol{}, "Range", "SelectionRange", "Detail")
79+
if diff := cmp.Diff(want, res, ignore); diff != "" {
80+
t.Errorf("package_symbols returned unexpected diff (-want +got):\n%s", diff)
81+
}
82+
83+
for file, want := range map[string]command.PackageSymbolsResult{
84+
"go.mod": {},
85+
"unloaded.go": {
86+
PackageName: "a",
87+
Files: []protocol.DocumentURI{env.Sandbox.Workdir.URI("unloaded.go")},
88+
Symbols: []command.PackageSymbol{
89+
{Name: "Unloaded", Kind: protocol.Variable, File: 0},
90+
},
91+
},
92+
} {
93+
uri := env.Sandbox.Workdir.URI(file)
94+
args, err := command.MarshalArgs(command.PackageSymbolsArgs{
95+
URI: uri,
96+
})
97+
if err != nil {
98+
t.Fatal(err)
99+
}
100+
var res command.PackageSymbolsResult
101+
env.ExecuteCommand(&protocol.ExecuteCommandParams{
102+
Command: command.PackageSymbols.String(),
103+
Arguments: args,
104+
}, &res)
105+
106+
if diff := cmp.Diff(want, res, ignore); diff != "" {
107+
t.Errorf("package_symbols returned unexpected diff (-want +got):\n%s", diff)
108+
}
98109
}
99110
})
100111
}

0 commit comments

Comments
 (0)