9
9
"context"
10
10
"fmt"
11
11
"io"
12
+ "runtime/debug"
12
13
"strings"
13
14
)
14
15
@@ -23,6 +24,71 @@ const (
23
24
// Version is a manually-updated mechanism for tracking versions.
24
25
var Version = "master"
25
26
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
+
26
92
// PrintServerInfo writes HTML debug info to w for the Instance.
27
93
func (i * Instance ) PrintServerInfo (ctx context.Context , w io.Writer ) {
28
94
section (w , HTML , "Server Instance" , func () {
@@ -39,12 +105,13 @@ func (i *Instance) PrintServerInfo(ctx context.Context, w io.Writer) {
39
105
// specified by mode. verbose controls whether additional information is
40
106
// written, including section headers.
41
107
func PrintVersionInfo (ctx context.Context , w io.Writer , verbose bool , mode PrintMode ) {
108
+ info := VersionInfo ()
42
109
if ! verbose {
43
- printBuildInfo (w , false , mode )
110
+ printBuildInfo (w , info , false , mode )
44
111
return
45
112
}
46
113
section (w , mode , "Build info" , func () {
47
- printBuildInfo (w , true , mode )
114
+ printBuildInfo (w , info , true , mode )
48
115
})
49
116
}
50
117
@@ -64,3 +131,25 @@ func section(w io.Writer, mode PrintMode, title string, body func()) {
64
131
fmt .Fprint (w , "</pre>\n " )
65
132
}
66
133
}
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
+ }
0 commit comments