Skip to content

Commit 3db8fd2

Browse files
committed
internal/lsp: use a structured format for the server's version
The server reports its version to the client--add some structure to this report so that the client can parse and use it. Fixes golang/go#42171 Change-Id: I00bff3615391cbeede89e4be6b0d028fed67989e Reviewed-on: https://go-review.googlesource.com/c/tools/+/266198 Trust: Rebecca Stambler <[email protected]> Run-TryBot: Rebecca Stambler <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent 8694a4a commit 3db8fd2

File tree

4 files changed

+97
-60
lines changed

4 files changed

+97
-60
lines changed

internal/lsp/debug/info.1.11.go

Lines changed: 0 additions & 16 deletions
This file was deleted.

internal/lsp/debug/info.1.12.go

Lines changed: 0 additions & 38 deletions
This file was deleted.

internal/lsp/debug/info.go

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"context"
1010
"fmt"
1111
"io"
12+
"runtime/debug"
1213
"strings"
1314
)
1415

@@ -23,6 +24,71 @@ const (
2324
// Version is a manually-updated mechanism for tracking versions.
2425
var Version = "master"
2526

27+
// ServerVersion is the format used by gopls to report its version to the
28+
// client. This format is structured so that the client can parse it easily.
29+
type ServerVersion struct {
30+
Module
31+
Deps []*Module `json:"deps,omitempty"`
32+
}
33+
34+
type Module struct {
35+
ModuleVersion
36+
Replace *ModuleVersion `json:"replace,omitempty"`
37+
}
38+
39+
type ModuleVersion struct {
40+
Path string `json:"path,omitempty"`
41+
Version string `json:"version,omitempty"`
42+
Sum string `json:"sum,omitempty"`
43+
}
44+
45+
// VersionInfo returns the build info for the gopls process. If it was not
46+
// built in module mode, we return a GOPATH-specific message with the
47+
// hardcoded version.
48+
func VersionInfo() *ServerVersion {
49+
if info, ok := debug.ReadBuildInfo(); ok {
50+
return getVersion(info)
51+
}
52+
path := "gopls, built in GOPATH mode"
53+
return &ServerVersion{
54+
Module: Module{
55+
ModuleVersion: ModuleVersion{
56+
Path: path,
57+
Version: Version,
58+
},
59+
},
60+
}
61+
}
62+
63+
func getVersion(info *debug.BuildInfo) *ServerVersion {
64+
serverVersion := ServerVersion{
65+
Module: Module{
66+
ModuleVersion: ModuleVersion{
67+
Path: info.Main.Path,
68+
Version: info.Main.Version,
69+
Sum: info.Main.Sum,
70+
},
71+
},
72+
}
73+
for _, d := range info.Deps {
74+
m := &Module{
75+
ModuleVersion: ModuleVersion{
76+
Path: d.Path,
77+
Version: d.Version,
78+
Sum: d.Sum,
79+
},
80+
}
81+
if d.Replace != nil {
82+
m.Replace = &ModuleVersion{
83+
Path: d.Replace.Path,
84+
Version: d.Replace.Version,
85+
}
86+
}
87+
serverVersion.Deps = append(serverVersion.Deps, m)
88+
}
89+
return &serverVersion
90+
}
91+
2692
// PrintServerInfo writes HTML debug info to w for the Instance.
2793
func (i *Instance) PrintServerInfo(ctx context.Context, w io.Writer) {
2894
section(w, HTML, "Server Instance", func() {
@@ -39,12 +105,13 @@ func (i *Instance) PrintServerInfo(ctx context.Context, w io.Writer) {
39105
// specified by mode. verbose controls whether additional information is
40106
// written, including section headers.
41107
func PrintVersionInfo(ctx context.Context, w io.Writer, verbose bool, mode PrintMode) {
108+
info := VersionInfo()
42109
if !verbose {
43-
printBuildInfo(w, false, mode)
110+
printBuildInfo(w, info, false, mode)
44111
return
45112
}
46113
section(w, mode, "Build info", func() {
47-
printBuildInfo(w, true, mode)
114+
printBuildInfo(w, info, true, mode)
48115
})
49116
}
50117

@@ -64,3 +131,25 @@ func section(w io.Writer, mode PrintMode, title string, body func()) {
64131
fmt.Fprint(w, "</pre>\n")
65132
}
66133
}
134+
135+
func printBuildInfo(w io.Writer, info *ServerVersion, verbose bool, mode PrintMode) {
136+
fmt.Fprintf(w, "%v %v\n", info.Path, Version)
137+
printModuleInfo(w, &info.Module, mode)
138+
if !verbose {
139+
return
140+
}
141+
for _, dep := range info.Deps {
142+
printModuleInfo(w, dep, mode)
143+
}
144+
}
145+
146+
func printModuleInfo(w io.Writer, m *Module, mode PrintMode) {
147+
fmt.Fprintf(w, " %s@%s", m.Path, m.Version)
148+
if m.Sum != "" {
149+
fmt.Fprintf(w, " %s", m.Sum)
150+
}
151+
if m.Replace != nil {
152+
fmt.Fprintf(w, " => %v", m.Replace.Path)
153+
}
154+
fmt.Fprintf(w, "\n")
155+
}

internal/lsp/general.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package lsp
77
import (
88
"bytes"
99
"context"
10+
"encoding/json"
1011
"fmt"
1112
"io"
1213
"os"
@@ -83,8 +84,10 @@ func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitializ
8384
}
8485
}
8586

86-
goplsVer := &bytes.Buffer{}
87-
debug.PrintVersionInfo(ctx, goplsVer, true, debug.PlainText)
87+
goplsVersion, err := json.Marshal(debug.VersionInfo())
88+
if err != nil {
89+
return nil, err
90+
}
8891

8992
return &protocol.InitializeResult{
9093
Capabilities: protocol.ServerCapabilities{
@@ -130,10 +133,9 @@ func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitializ
130133
Version string `json:"version,omitempty"`
131134
}{
132135
Name: "gopls",
133-
Version: goplsVer.String(),
136+
Version: string(goplsVersion),
134137
},
135138
}, nil
136-
137139
}
138140

139141
func (s *Server) initialized(ctx context.Context, params *protocol.InitializedParams) error {

0 commit comments

Comments
 (0)