diff --git a/internal/lsp/debug/serve.go b/internal/lsp/debug/serve.go
index aec976ad6f..473518e433 100644
--- a/internal/lsp/debug/serve.go
+++ b/internal/lsp/debug/serve.go
@@ -181,6 +181,7 @@ type Client struct {
Logfile string
GoplsPath string
ServerID string
+ Service protocol.Server
}
// A Server is an outgoing connection to a remote LSP server.
@@ -314,6 +315,16 @@ func (i *Instance) getInfo(r *http.Request) interface{} {
return template.HTML(buf.String())
}
+func (i *Instance) AddService(s protocol.Server, session *cache.Session) {
+ for _, c := range i.State.clients {
+ if c.Session == session {
+ c.Service = s
+ return
+ }
+ }
+ stdlog.Printf("unable to find a Client to add the protocol.Server to")
+}
+
func getMemory(r *http.Request) interface{} {
var m runtime.MemStats
runtime.ReadMemStats(&m)
@@ -785,6 +796,29 @@ Using session: {{template "sessionlink" .Session.ID}}
{{if .DebugAddress}}Debug this client at: {{localAddress .DebugAddress}}
{{end}}
Logfile: {{.Logfile}}
Gopls Path: {{.GoplsPath}}
+
Diagnostics
+{{/*Service: []protocol.Server; each server has map[uri]fileReports;
+ each fileReport: map[diagnosticSoure]diagnosticReport
+ diagnosticSource is one of 5 source
+ diagnosticReport: snapshotID and map[hash]*source.Diagnostic
+ sourceDiagnostic: struct {
+ Range protocol.Range
+ Message string
+ Source string
+ Code string
+ CodeHref string
+ Severity protocol.DiagnosticSeverity
+ Tags []protocol.DiagnosticTag
+
+ Related []RelatedInformation
+ }
+ RelatedInformation: struct {
+ URI span.URI
+ Range protocol.Range
+ Message string
+ }
+ */}}
+{{range $k, $v := .Service.Diagnostics}}- {{$k}}:
{{range $v}}- {{.}}
{{end}}
{{end}}
{{end}}
`))
diff --git a/internal/lsp/diagnostics.go b/internal/lsp/diagnostics.go
index 4941f007ea..adf19ad86d 100644
--- a/internal/lsp/diagnostics.go
+++ b/internal/lsp/diagnostics.go
@@ -50,6 +50,23 @@ type fileReports struct {
reports map[diagnosticSource]diagnosticReport
}
+func (d diagnosticSource) String() string {
+ switch d {
+ case modSource:
+ return "FromSource"
+ case gcDetailsSource:
+ return "FromGCDetails"
+ case analysisSource:
+ return "FromAnalysis"
+ case typeCheckSource:
+ return "FromTypeChecking"
+ case orphanedSource:
+ return "FromOrphans"
+ default:
+ return fmt.Sprintf("From?%d?", d)
+ }
+}
+
// hashDiagnostics computes a hash to identify diags.
func hashDiagnostics(diags ...*source.Diagnostic) string {
source.SortDiagnostics(diags)
@@ -546,3 +563,34 @@ func (s *Server) shouldIgnoreError(ctx context.Context, snapshot source.Snapshot
})
return !hasGo
}
+
+// Diagnostics formattedfor the debug server
+// (all the relevant fields of Server are private)
+// (The alternative is to export them)
+func (s *Server) Diagnostics() map[string][]string {
+ ans := make(map[string][]string)
+ s.diagnosticsMu.Lock()
+ defer s.diagnosticsMu.Unlock()
+ for k, v := range s.diagnostics {
+ fn := k.Filename()
+ for typ, d := range v.reports {
+ if len(d.diags) == 0 {
+ continue
+ }
+ for _, dx := range d.diags {
+ ans[fn] = append(ans[fn], auxStr(dx, d, typ))
+ }
+ }
+ }
+ return ans
+}
+
+func auxStr(v *source.Diagnostic, d diagnosticReport, typ diagnosticSource) string {
+ // Tags? RelatedInformation?
+ msg := fmt.Sprintf("(%s)%q(source:%q,code:%q,severity:%s,snapshot:%d,type:%s)",
+ v.Range, v.Message, v.Source, v.Code, v.Severity, d.snapshotID, typ)
+ for _, r := range v.Related {
+ msg += fmt.Sprintf(" [%s:%s,%q]", r.URI.Filename(), r.Range, r.Message)
+ }
+ return msg
+}
diff --git a/internal/lsp/lsprpc/lsprpc.go b/internal/lsp/lsprpc/lsprpc.go
index 623533f22a..51267910cf 100644
--- a/internal/lsp/lsprpc/lsprpc.go
+++ b/internal/lsp/lsprpc/lsprpc.go
@@ -61,6 +61,7 @@ func (s *StreamServer) ServeStream(ctx context.Context, conn jsonrpc2.Conn) erro
server := s.serverForTest
if server == nil {
server = lsp.NewServer(session, client)
+ debug.GetInstance(ctx).AddService(server, session)
}
// Clients may or may not send a shutdown message. Make sure the server is
// shut down.