Skip to content

Commit

Permalink
internal/lsp/cache: set types.Config.GoVersion
Browse files Browse the repository at this point in the history
Set the language version from the controlling go.mod file's go version,
if any. Also verify that we properly surface a diagnostic if the version
is invalid.

I didn't add any quick fixes.

Fixes golang/go#50688.

Change-Id: Ic472502d1224a1decb5b989d51110b837020e998
Reviewed-on: https://go-review.googlesource.com/c/tools/+/383394
Trust: Heschi Kreinick <heschi@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
  • Loading branch information
heschi committed Feb 7, 2022
1 parent 6aaba77 commit 164402d
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 0 deletions.
19 changes: 19 additions & 0 deletions gopls/internal/regtest/diagnostics/diagnostics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2138,3 +2138,22 @@ func main() {
)
})
}

func TestLangVersion(t *testing.T) {
testenv.NeedsGo1Point(t, 18) // Requires types.Config.GoVersion, new in 1.18.
const files = `
-- go.mod --
module mod.com
go 1.12
-- main.go --
package main
const C = 0b10
`
Run(t, files, func(t *testing.T, env *Env) {
env.Await(env.DiagnosticAtRegexpWithMessage("main.go", `0b10`, "go1.13 or later"))
env.WriteWorkspaceFile("go.mod", "module mod.com \n\ngo 1.13\n")
env.Await(EmptyDiagnostics("main.go"))
})
}
17 changes: 17 additions & 0 deletions gopls/internal/regtest/modfile/modfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1120,3 +1120,20 @@ func main() {
)
})
}

func TestInvalidGoVersion(t *testing.T) {
testenv.NeedsGo1Point(t, 14) // Times out on 1.13 for reasons unclear. Not worth worrying about.
const files = `
-- go.mod --
module mod.com
go foo
-- main.go --
package main
`
Run(t, files, func(t *testing.T, env *Env) {
env.Await(env.DiagnosticAtRegexpWithMessage("go.mod", `go foo`, "invalid go version"))
env.WriteWorkspaceFile("go.mod", "module mod.com \n\ngo 1.12\n")
env.Await(EmptyDiagnostics("go.mod"))
})
}
12 changes: 12 additions & 0 deletions internal/lsp/cache/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"go/types"
"path"
"path/filepath"
"regexp"
"sort"
"strings"
"sync"
Expand Down Expand Up @@ -420,6 +421,8 @@ func typeCheck(ctx context.Context, snapshot *snapshot, m *Metadata, mode source
return pkg, nil
}

var goVersionRx = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)

func doTypeCheck(ctx context.Context, snapshot *snapshot, m *Metadata, mode source.ParseMode, deps map[PackagePath]*packageHandle, astFilter *unexportedFilter) (*pkg, error) {
ctx, done := event.Start(ctx, "cache.typeCheck", tag.Package.Of(string(m.ID)))
defer done()
Expand Down Expand Up @@ -515,6 +518,15 @@ func doTypeCheck(ctx context.Context, snapshot *snapshot, m *Metadata, mode sour
return depPkg.types, nil
}),
}
if pkg.m.Module != nil && pkg.m.Module.GoVersion != "" {
goVersion := "go" + pkg.m.Module.GoVersion
// types.NewChecker panics if GoVersion is invalid. An unparsable mod
// file should probably stop us before we get here, but double check
// just in case.
if goVersionRx.MatchString(goVersion) {
typesinternal.SetGoVersion(cfg, goVersion)
}
}

if mode != source.ParseFull {
cfg.DisableUnusedImportCheck = true
Expand Down
2 changes: 2 additions & 0 deletions internal/typesinternal/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ func ReadGo116ErrorData(err types.Error) (code ErrorCode, start, end token.Pos,
}
return ErrorCode(data[0]), token.Pos(data[1]), token.Pos(data[2]), true
}

var SetGoVersion = func(conf *types.Config, version string) bool { return false }
19 changes: 19 additions & 0 deletions internal/typesinternal/types_118.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build go1.18
// +build go1.18

package typesinternal

import (
"go/types"
)

func init() {
SetGoVersion = func(conf *types.Config, version string) bool {
conf.GoVersion = version
return true
}
}

0 comments on commit 164402d

Please sign in to comment.