mirror of
https://github.com/golang/go.git
synced 2025-05-06 08:03:03 +00:00
internal/lsp: handle undelivered diagnostics
This change adds a cache of undelivered diagnostics on the server-side. If we fail to send a diagnostic once, we will retry the next time that the server sends diagnostics. Change-Id: I161dfad8ea1d2cfdcee933baed2d6872dc03b0c0 Reviewed-on: https://go-review.googlesource.com/c/tools/+/167737 Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
parent
e2f00d1e07
commit
cf22ef0385
@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) cacheAndDiagnose(ctx context.Context, uri span.URI, content string) error {
|
func (s *Server) cacheAndDiagnose(ctx context.Context, uri span.URI, content string) error {
|
||||||
if err := s.setContent(ctx, uri, []byte(content)); err != nil {
|
if err := s.view.SetContent(ctx, uri, []byte(content)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
@ -26,22 +26,40 @@ func (s *Server) cacheAndDiagnose(ctx context.Context, uri span.URI, content str
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return // handle error?
|
return // handle error?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.undeliveredMu.Lock()
|
||||||
|
defer s.undeliveredMu.Unlock()
|
||||||
|
|
||||||
for uri, diagnostics := range reports {
|
for uri, diagnostics := range reports {
|
||||||
protocolDiagnostics, err := toProtocolDiagnostics(ctx, s.view, diagnostics)
|
if err := s.publishDiagnostics(ctx, uri, diagnostics); err != nil {
|
||||||
if err != nil {
|
s.undelivered[uri] = diagnostics
|
||||||
continue // handle errors?
|
continue
|
||||||
}
|
}
|
||||||
s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
|
// In case we had old, undelivered diagnostics.
|
||||||
Diagnostics: protocolDiagnostics,
|
delete(s.undelivered, uri)
|
||||||
URI: protocol.NewURI(uri),
|
}
|
||||||
})
|
// Anytime we compute diagnostics, make sure to also send along any
|
||||||
|
// undelivered ones (only for remaining URIs).
|
||||||
|
for uri, diagnostics := range s.undelivered {
|
||||||
|
s.publishDiagnostics(ctx, uri, diagnostics)
|
||||||
|
|
||||||
|
// If we fail to deliver the same diagnostics twice, just give up.
|
||||||
|
delete(s.undelivered, uri)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) setContent(ctx context.Context, uri span.URI, content []byte) error {
|
func (s *Server) publishDiagnostics(ctx context.Context, uri span.URI, diagnostics []source.Diagnostic) error {
|
||||||
return s.view.SetContent(ctx, uri, content)
|
protocolDiagnostics, err := toProtocolDiagnostics(ctx, s.view, diagnostics)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
|
||||||
|
Diagnostics: protocolDiagnostics,
|
||||||
|
URI: protocol.NewURI(uri),
|
||||||
|
})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toProtocolDiagnostics(ctx context.Context, v source.View, diagnostics []source.Diagnostic) ([]protocol.Diagnostic, error) {
|
func toProtocolDiagnostics(ctx context.Context, v source.View, diagnostics []source.Diagnostic) ([]protocol.Diagnostic, error) {
|
||||||
|
@ -80,7 +80,13 @@ type Server struct {
|
|||||||
|
|
||||||
textDocumentSyncKind protocol.TextDocumentSyncKind
|
textDocumentSyncKind protocol.TextDocumentSyncKind
|
||||||
|
|
||||||
|
viewMu sync.Mutex
|
||||||
view *cache.View
|
view *cache.View
|
||||||
|
|
||||||
|
// undelivered is a cache of any diagnostics that the server
|
||||||
|
// failed to deliver for some reason.
|
||||||
|
undeliveredMu sync.Mutex
|
||||||
|
undelivered map[span.URI][]source.Diagnostic
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Run(ctx context.Context) error {
|
func (s *Server) Run(ctx context.Context) error {
|
||||||
@ -302,7 +308,9 @@ func (s *Server) DidSave(context.Context, *protocol.DidSaveTextDocumentParams) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) DidClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error {
|
func (s *Server) DidClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error {
|
||||||
s.setContent(ctx, span.NewURI(params.TextDocument.URI), nil)
|
if err := s.view.SetContent(ctx, span.NewURI(params.TextDocument.URI), nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@ import (
|
|||||||
// package does not directly access the file system.
|
// package does not directly access the file system.
|
||||||
type View interface {
|
type View interface {
|
||||||
Logger() xlog.Logger
|
Logger() xlog.Logger
|
||||||
|
FileSet() *token.FileSet
|
||||||
GetFile(ctx context.Context, uri span.URI) (File, error)
|
GetFile(ctx context.Context, uri span.URI) (File, error)
|
||||||
SetContent(ctx context.Context, uri span.URI, content []byte) error
|
SetContent(ctx context.Context, uri span.URI, content []byte) error
|
||||||
FileSet() *token.FileSet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// File represents a Go source file that has been type-checked. It is the input
|
// File represents a Go source file that has been type-checked. It is the input
|
||||||
|
Loading…
x
Reference in New Issue
Block a user