Skip to content

Commit d034ae1

Browse files
adonovangopherbot
authored andcommitted
gopls/internal/cmd: check: print RelatedInformation
The check command previously ignored Diagnostic.RelatedInformation, which confused me as I was trying to run an experiment related to golang/go#64547. This change causes it print the related errors. + test (Aside: there's a lot of weirdness in the way that check.typeErrorsToDiagnostics constructs the response, as you will see if you run the test on c.go not c2.go, but that's not the test's concern.) Change-Id: I14efbf8f2e47ac00c2e7d6eceeacbaaecab88213 Reviewed-on: https://go-review.googlesource.com/c/tools/+/576656 Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 3c000ca commit d034ae1

File tree

4 files changed

+72
-19
lines changed

4 files changed

+72
-19
lines changed

gopls/internal/cache/check.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1852,6 +1852,7 @@ func typeErrorsToDiagnostics(pkg *syntaxPackage, errs []types.Error, linkTarget
18521852
var result []*Diagnostic
18531853

18541854
// batch records diagnostics for a set of related types.Errors.
1855+
// (related[0] is the primary error.)
18551856
batch := func(related []types.Error) {
18561857
var diags []*Diagnostic
18571858
for i, e := range related {
@@ -1935,7 +1936,7 @@ func typeErrorsToDiagnostics(pkg *syntaxPackage, errs []types.Error, linkTarget
19351936
bug.Reportf("internal error: could not compute pos to range for %v: %v", e, err)
19361937
continue
19371938
}
1938-
msg := related[0].Msg
1939+
msg := related[0].Msg // primary
19391940
if i > 0 {
19401941
if supportsRelatedInformation {
19411942
msg += " (see details)"

gopls/internal/cmd/check.go

+46-11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"fmt"
1111

1212
"golang.org/x/tools/gopls/internal/protocol"
13+
"golang.org/x/tools/gopls/internal/settings"
14+
"golang.org/x/tools/gopls/internal/util/slices"
1315
)
1416

1517
// check implements the check verb for gopls.
@@ -34,17 +36,30 @@ Example: show the diagnostic results of this file:
3436
// results to stdout.
3537
func (c *check) Run(ctx context.Context, args ...string) error {
3638
if len(args) == 0 {
37-
// no files, so no results
3839
return nil
3940
}
40-
checking := map[protocol.DocumentURI]*cmdFile{}
41-
var uris []protocol.DocumentURI
42-
// now we ready to kick things off
41+
42+
// TODO(adonovan): formally, we are required to set this
43+
// option if we want RelatedInformation, but it appears to
44+
// have no effect on the server, even though the default is
45+
// false. Investigate.
46+
origOptions := c.app.options
47+
c.app.options = func(opts *settings.Options) {
48+
origOptions(opts)
49+
opts.RelatedInformationSupported = true
50+
}
51+
4352
conn, err := c.app.connect(ctx, nil)
4453
if err != nil {
4554
return err
4655
}
4756
defer conn.terminate(ctx)
57+
58+
// Open and diagnose the requested files.
59+
var (
60+
uris []protocol.DocumentURI
61+
checking = make(map[protocol.DocumentURI]*cmdFile)
62+
)
4863
for _, arg := range args {
4964
uri := protocol.URIFromPath(arg)
5065
uris = append(uris, uri)
@@ -57,16 +72,36 @@ func (c *check) Run(ctx context.Context, args ...string) error {
5772
if err := conn.diagnoseFiles(ctx, uris); err != nil {
5873
return err
5974
}
60-
conn.client.filesMu.Lock()
61-
defer conn.client.filesMu.Unlock()
75+
76+
// print prints a single element of a diagnostic.
77+
print := func(uri protocol.DocumentURI, rng protocol.Range, message string) error {
78+
file, err := conn.openFile(ctx, uri)
79+
if err != nil {
80+
return err
81+
}
82+
spn, err := file.rangeSpan(rng)
83+
if err != nil {
84+
return fmt.Errorf("could not convert position %v for %q", rng, message)
85+
}
86+
fmt.Printf("%v: %v\n", spn, message)
87+
return nil
88+
}
6289

6390
for _, file := range checking {
64-
for _, d := range file.diagnostics {
65-
spn, err := file.rangeSpan(d.Range)
66-
if err != nil {
67-
return fmt.Errorf("Could not convert position %v for %q", d.Range, d.Message)
91+
file.diagnosticsMu.Lock()
92+
diags := slices.Clone(file.diagnostics)
93+
file.diagnosticsMu.Unlock()
94+
95+
for _, diag := range diags {
96+
if err := print(file.uri, diag.Range, diag.Message); err != nil {
97+
return err
6898
}
69-
fmt.Printf("%v: %v\n", spn, d.Message)
99+
for _, rel := range diag.RelatedInformation {
100+
if err := print(rel.Location.URI, rel.Location.Range, "- "+rel.Message); err != nil {
101+
return err
102+
}
103+
}
104+
70105
}
71106
}
72107
return nil

gopls/internal/cmd/cmd.go

+10-7
Original file line numberDiff line numberDiff line change
@@ -399,15 +399,16 @@ type cmdClient struct {
399399
app *Application
400400
onProgress func(*protocol.ProgressParams)
401401

402-
filesMu sync.Mutex // guards files map and each cmdFile.diagnostics
402+
filesMu sync.Mutex // guards files map
403403
files map[protocol.DocumentURI]*cmdFile
404404
}
405405

406406
type cmdFile struct {
407-
uri protocol.DocumentURI
408-
mapper *protocol.Mapper
409-
err error
410-
diagnostics []protocol.Diagnostic
407+
uri protocol.DocumentURI
408+
mapper *protocol.Mapper
409+
err error
410+
diagnosticsMu sync.Mutex
411+
diagnostics []protocol.Diagnostic
411412
}
412413

413414
func newClient(app *Application, onProgress func(*protocol.ProgressParams)) *cmdClient {
@@ -595,9 +596,11 @@ func (c *cmdClient) PublishDiagnostics(ctx context.Context, p *protocol.PublishD
595596
}
596597

597598
c.filesMu.Lock()
598-
defer c.filesMu.Unlock()
599-
600599
file := c.getFile(p.URI)
600+
c.filesMu.Unlock()
601+
602+
file.diagnosticsMu.Lock()
603+
defer file.diagnosticsMu.Unlock()
601604
file.diagnostics = append(file.diagnostics, p.Diagnostics...)
602605

603606
// Perform a crude in-place deduplication.

gopls/internal/cmd/integration_test.go

+14
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ var _ = fmt.Sprintf("%s", 123)
103103
package a
104104
import "fmt"
105105
var _ = fmt.Sprintf("%d", "123")
106+
-- c/c.go --
107+
package c
108+
var C int
109+
-- c/c2.go --
110+
package c
111+
var C int
106112
`)
107113

108114
// no files
@@ -128,6 +134,14 @@ var _ = fmt.Sprintf("%d", "123")
128134
res.checkStdout(`a.go:.* fmt.Sprintf format %s has arg 123 of wrong type int`)
129135
res.checkStdout(`b.go:.* fmt.Sprintf format %d has arg "123" of wrong type string`)
130136
}
137+
138+
// diagnostic with related information spanning files
139+
{
140+
res := gopls(t, tree, "check", "./c/c2.go")
141+
res.checkExit(true)
142+
res.checkStdout(`c2.go:2:5-6: C redeclared in this block`)
143+
res.checkStdout(`c.go:2:5-6: - other declaration of C`)
144+
}
131145
}
132146

133147
// TestCallHierarchy tests the 'call_hierarchy' subcommand (../call_hierarchy.go).

0 commit comments

Comments
 (0)