diff --git a/internal/lsp/cmd/check.go b/internal/lsp/cmd/check.go index e42f976aee..1a8961e6c3 100644 --- a/internal/lsp/cmd/check.go +++ b/internal/lsp/cmd/check.go @@ -57,15 +57,15 @@ func (c *check) Run(ctx context.Context, args ...string) error { } // now wait for results // TODO: maybe conn.ExecuteCommand(ctx, &protocol.ExecuteCommandParams{Command: "gopls-wait-idle"}) + ctx, cancel := context.WithTimeout(ctx, time.Second*30) + defer cancel() + for _, file := range checking { - select { - case <-file.hasDiagnostics: - case <-time.After(30 * time.Second): - return errors.Errorf("timed out waiting for results from %v", file.uri) + diagnostics, err := file.waitForDiagnostics(ctx) + if err != nil { + return err } - file.diagnosticsMu.Lock() - defer file.diagnosticsMu.Unlock() - for _, d := range file.diagnostics { + for _, d := range diagnostics { spn, err := file.mapper.RangeSpan(d.Range) if err != nil { return errors.Errorf("Could not convert position %v for %q", d.Range, d.Message) diff --git a/internal/lsp/cmd/cmd.go b/internal/lsp/cmd/cmd.go index e7c9d8681e..e1346e3e2e 100644 --- a/internal/lsp/cmd/cmd.go +++ b/internal/lsp/cmd/cmd.go @@ -406,6 +406,18 @@ func (c *cmdClient) getFile(ctx context.Context, uri span.URI) *cmdFile { return file } +func (file *cmdFile) waitForDiagnostics(ctx context.Context) ([]protocol.Diagnostic, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-file.hasDiagnostics: + } + + file.diagnosticsMu.Lock() + defer file.diagnosticsMu.Unlock() + return file.diagnostics, nil +} + func (c *connection) AddFile(ctx context.Context, uri span.URI) *cmdFile { c.Client.filesMu.Lock() defer c.Client.filesMu.Unlock() diff --git a/internal/lsp/cmd/references.go b/internal/lsp/cmd/references.go index 8b91356b9c..49905d950c 100644 --- a/internal/lsp/cmd/references.go +++ b/internal/lsp/cmd/references.go @@ -54,12 +54,10 @@ func (r *references) Run(ctx context.Context, args ...string) error { if file.err != nil { return file.err } - loc, err := file.mapper.Location(from) if err != nil { return err } - p := protocol.ReferenceParams{ Context: protocol.ReferenceContext{ IncludeDeclaration: r.IncludeDeclaration, @@ -73,7 +71,6 @@ func (r *references) Run(ctx context.Context, args ...string) error { if err != nil { return err } - if len(locations) == 0 { return tool.CommandLineErrorf("%v: not an identifier", from) } @@ -94,6 +91,5 @@ func (r *references) Run(ctx context.Context, args ...string) error { for _, s := range spans { fmt.Println(s) } - return nil } diff --git a/internal/lsp/cmd/test/check.go b/internal/lsp/cmd/test/check.go index 65e96889b9..db277fac9b 100644 --- a/internal/lsp/cmd/test/check.go +++ b/internal/lsp/cmd/test/check.go @@ -18,6 +18,9 @@ func (r *runner) Diagnostics(t *testing.T, uri span.URI, want []source.Diagnosti if len(want) == 1 && want[0].Message == "" { return } + if strings.Contains(uri.Filename(), "circular") { + t.Skip("skipping circular diagnostics tests due to golang/go#36265") + } fname := uri.Filename() out, _ := r.RunGoplsCmd(t, "check", fname) // parse got into a collection of reports diff --git a/internal/lsp/source/implementation.go b/internal/lsp/source/implementation.go index cab9e61f2d..b9c39ef295 100644 --- a/internal/lsp/source/implementation.go +++ b/internal/lsp/source/implementation.go @@ -106,15 +106,19 @@ func implementations(ctx context.Context, s Snapshot, f FileHandle, pp protocol. info := pkg.GetTypesInfo() for _, obj := range info.Defs { + obj, ok := obj.(*types.TypeName) // We ignore aliases 'type M = N' to avoid duplicate reporting // of the Named type N. - if obj, ok := obj.(*types.TypeName); ok && !obj.IsAlias() { - // We skip interface types since we only want concrete - // implementations. - if named, ok := obj.Type().(*types.Named); ok && !isInterface(named) { - allNamed = append(allNamed, named) - } + if !ok || obj.IsAlias() { + continue } + named, ok := obj.Type().(*types.Named) + // We skip interface types since we only want concrete + // implementations. + if !ok || isInterface(named) { + continue + } + allNamed = append(allNamed, named) } }