Skip to content

Commit 6d11a09

Browse files
findleyrgopherbot
authored andcommitted
[gopls-release-branch.0.10] gopls/internal/lsp: improve the Go version deprecation message
Improve the Go version deprecation message to be a warning at 1.13-15, and provide better instructions for making it go away. Clarify support in the gopls README. Change-Id: I6b08e0bd698f5c085eee7a851a130c53affb8ab5 Reviewed-on: https://go-review.googlesource.com/c/tools/+/445581 Run-TryBot: Robert Findley <[email protected]> Reviewed-by: Hyang-Ah Hana Kim <[email protected]> Auto-Submit: Robert Findley <[email protected]> Reviewed-by: Alan Donovan <[email protected]> TryBot-Result: Gopher Robot <[email protected]> gopls-CI: kokoro <[email protected]> (cherry picked from commit 42cb7be) Reviewed-on: https://go-review.googlesource.com/c/tools/+/445817
1 parent 72c3df8 commit 6d11a09

File tree

5 files changed

+112
-20
lines changed

5 files changed

+112
-20
lines changed

gopls/README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,22 @@ If you are having issues with `gopls`, please follow the steps described in the
7272
`gopls` follows the
7373
[Go Release Policy](https://golang.org/doc/devel/release.html#policy),
7474
meaning that it officially supports the last 2 major Go releases. Per
75-
[issue #39146](golang.org/issues/39146), we attempt to maintain best-effort
75+
[issue #39146](https://go.dev/issues/39146), we attempt to maintain best-effort
7676
support for the last 4 major Go releases, but this support extends only to not
7777
breaking the build and avoiding easily fixable regressions.
7878

79-
The following table shows the final gopls version that supports being built
80-
with a given Go version. Go releases more recent than any in the table can
81-
build any version of gopls.
79+
In the context of this discussion, gopls "supports" a Go version if it supports
80+
being built with that Go version as well as integrating with the `go` command
81+
of that Go version.
8282

83-
| Go Version | Final gopls Version With Support |
84-
| ----------- | -------------------------------- |
83+
The following table shows the final gopls version that supports a given Go
84+
version. Go releases more recent than any in the table can be used with any
85+
version of gopls.
86+
87+
| Go Version | Final gopls version with support (without warnings) |
88+
| ----------- | --------------------------------------------------- |
8589
| Go 1.12 | [[email protected]](https://github.com/golang/tools/releases/tag/gopls%2Fv0.7.5) |
90+
| Go 1.15 | [[email protected]](https://github.com/golang/tools/releases/tag/gopls%2Fv0.9.5) |
8691

8792
Our extended support is enforced via [continuous integration with older Go
8893
versions](doc/contributing.md#ci). This legacy Go CI may not block releases:

gopls/internal/lsp/general.go

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,54 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
226226
return nil
227227
}
228228

229-
// OldestSupportedGoVersion is the last X in Go 1.X that we support.
229+
// GoVersionTable maps Go versions to the gopls version in which support will
230+
// be deprecated, and the final gopls version supporting them without warnings.
231+
// Keep this in sync with gopls/README.md
230232
//
231-
// Mutable for testing, since we won't otherwise run CI on unsupported Go
232-
// versions.
233-
var OldestSupportedGoVersion = 16
233+
// Must be sorted in ascending order of Go version.
234+
//
235+
// Mutable for testing.
236+
var GoVersionTable = []GoVersionSupport{
237+
{12, "", "v0.7.5"},
238+
{15, "v0.11.0", "v0.9.5"},
239+
}
240+
241+
// GoVersionSupport holds information about end-of-life Go version support.
242+
type GoVersionSupport struct {
243+
GoVersion int
244+
DeprecatedVersion string // if unset, the version is already deprecated
245+
InstallGoplsVersion string
246+
}
247+
248+
// OldestSupportedGoVersion is the last X in Go 1.X that this version of gopls
249+
// supports.
250+
func OldestSupportedGoVersion() int {
251+
return GoVersionTable[len(GoVersionTable)-1].GoVersion + 1
252+
}
253+
254+
func versionMessage(oldestVersion int) (string, protocol.MessageType) {
255+
for _, v := range GoVersionTable {
256+
if oldestVersion <= v.GoVersion {
257+
var msgBuilder strings.Builder
258+
259+
mType := protocol.Error
260+
fmt.Fprintf(&msgBuilder, "Found Go version 1.%d", oldestVersion)
261+
if v.DeprecatedVersion != "" {
262+
// not deprecated yet, just a warning
263+
fmt.Fprintf(&msgBuilder, ", which will be unsupported by gopls %s. ", v.DeprecatedVersion)
264+
mType = protocol.Warning
265+
} else {
266+
fmt.Fprint(&msgBuilder, ", which is not supported by this version of gopls. ")
267+
}
268+
fmt.Fprintf(&msgBuilder, "Please upgrade to Go 1.%d or later and reinstall gopls. ", OldestSupportedGoVersion())
269+
fmt.Fprintf(&msgBuilder, "If you can't upgrade and want this message to go away, please install gopls %s. ", v.InstallGoplsVersion)
270+
fmt.Fprint(&msgBuilder, "See https://go.dev/s/gopls-support-policy for more details.")
271+
272+
return msgBuilder.String(), mType
273+
}
274+
}
275+
return "", 0
276+
}
234277

235278
// checkViewGoVersions checks whether any Go version used by a view is too old,
236279
// raising a showMessage notification if so.
@@ -245,10 +288,9 @@ func (s *Server) checkViewGoVersions() {
245288
}
246289
}
247290

248-
if oldestVersion >= 0 && oldestVersion < OldestSupportedGoVersion {
249-
msg := fmt.Sprintf("Found Go version 1.%d, which is unsupported. Please upgrade to Go 1.%d or later.", oldestVersion, OldestSupportedGoVersion)
291+
if msg, mType := versionMessage(oldestVersion); msg != "" {
250292
s.eventuallyShowMessage(context.Background(), &protocol.ShowMessageParams{
251-
Type: protocol.Error,
293+
Type: mType,
252294
Message: msg,
253295
})
254296
}

gopls/internal/lsp/general_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2022 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package lsp
6+
7+
import (
8+
"strings"
9+
"testing"
10+
11+
"golang.org/x/tools/gopls/internal/lsp/protocol"
12+
)
13+
14+
func TestVersionMessage(t *testing.T) {
15+
tests := []struct {
16+
goVer int
17+
wantContains []string // string fragments that we expect to see
18+
wantType protocol.MessageType
19+
}{
20+
{12, []string{"1.12", "not supported", "upgrade to Go 1.16", "install gopls v0.7.5"}, protocol.Error},
21+
{13, []string{"1.13", "will be unsupported by gopls v0.11.0", "upgrade to Go 1.16", "install gopls v0.9.5"}, protocol.Warning},
22+
{15, []string{"1.15", "will be unsupported by gopls v0.11.0", "upgrade to Go 1.16", "install gopls v0.9.5"}, protocol.Warning},
23+
{16, nil, 0},
24+
}
25+
26+
for _, test := range tests {
27+
gotMsg, gotType := versionMessage(test.goVer)
28+
29+
if len(test.wantContains) == 0 && gotMsg != "" {
30+
t.Errorf("versionMessage(%d) = %q, want \"\"", test.goVer, gotMsg)
31+
}
32+
33+
for _, want := range test.wantContains {
34+
if !strings.Contains(gotMsg, want) {
35+
t.Errorf("versionMessage(%d) = %q, want containing %q", test.goVer, gotMsg, want)
36+
}
37+
}
38+
39+
if gotType != test.wantType {
40+
t.Errorf("versionMessage(%d) = returned message type %d, want %d", test.goVer, gotType, test.wantType)
41+
}
42+
}
43+
}

gopls/internal/regtest/diagnostics/diagnostics_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,7 @@ func _() {
13581358
func TestEnableAllExperiments(t *testing.T) {
13591359
// Before the oldest supported Go version, gopls sends a warning to upgrade
13601360
// Go, which fails the expectation below.
1361-
testenv.NeedsGo1Point(t, lsp.OldestSupportedGoVersion)
1361+
testenv.NeedsGo1Point(t, lsp.OldestSupportedGoVersion())
13621362

13631363
const mod = `
13641364
-- go.mod --

gopls/internal/regtest/workspace/workspace_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,7 @@ import (
12421242
// supported.
12431243
func TestOldGoNotification_SupportedVersion(t *testing.T) {
12441244
v := goVersion(t)
1245-
if v < lsp.OldestSupportedGoVersion {
1245+
if v < lsp.OldestSupportedGoVersion() {
12461246
t.Skipf("go version 1.%d is unsupported", v)
12471247
}
12481248

@@ -1261,7 +1261,7 @@ func TestOldGoNotification_SupportedVersion(t *testing.T) {
12611261
// legacy Go versions (see also TestOldGoNotification_Fake)
12621262
func TestOldGoNotification_UnsupportedVersion(t *testing.T) {
12631263
v := goVersion(t)
1264-
if v >= lsp.OldestSupportedGoVersion {
1264+
if v >= lsp.OldestSupportedGoVersion() {
12651265
t.Skipf("go version 1.%d is supported", v)
12661266
}
12671267

@@ -1285,10 +1285,12 @@ func TestOldGoNotification_Fake(t *testing.T) {
12851285
if err != nil {
12861286
t.Fatal(err)
12871287
}
1288-
defer func(v int) {
1289-
lsp.OldestSupportedGoVersion = v
1290-
}(lsp.OldestSupportedGoVersion)
1291-
lsp.OldestSupportedGoVersion = goversion + 1
1288+
defer func(t []lsp.GoVersionSupport) {
1289+
lsp.GoVersionTable = t
1290+
}(lsp.GoVersionTable)
1291+
lsp.GoVersionTable = []lsp.GoVersionSupport{
1292+
{GoVersion: goversion, InstallGoplsVersion: "v1.0.0"},
1293+
}
12921294

12931295
Run(t, "", func(t *testing.T, env *Env) {
12941296
env.Await(

0 commit comments

Comments
 (0)