x/tools: assume go1.22 and simplify

This CL does not include simplifications to gopls.

Updates golang/go#65917
Updates golang/go#69095

Change-Id: I2b54992681e2c671324e22668d8401962a1d2363
Reviewed-on: https://go-review.googlesource.com/c/tools/+/593683
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Alan Donovan 2024-06-21 14:31:30 -04:00
Родитель 1d5e334177
Коммит 3bb0ed7baa
45 изменённых файлов: 135 добавлений и 467 удалений

Просмотреть файл

@ -1,13 +0,0 @@
// Copyright 2023 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.20
package main
import "os/exec"
func cmdInterrupt(cmd *exec.Cmd) {
// cmd.Cancel and cmd.WaitDelay not available before Go 1.20.
}

Просмотреть файл

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.20
package main
import (

Просмотреть файл

@ -1,20 +0,0 @@
// Copyright 2023 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.
// Starting in Go 1.20, the global rand is auto-seeded,
// with a better value than the current Unix nanoseconds.
// Only seed if we're using older versions of Go.
//go:build !go1.20
package main
import (
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}

Просмотреть файл

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.20
package main
import (

Просмотреть файл

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.20
package main_test
import (

Просмотреть файл

@ -223,10 +223,6 @@ func NewT1() *T1 { return &T1{T} }
// duplicate list errors with findings (issue #67790)
{name: "list-error-findings", pattern: []string{cperrFile}, analyzers: []*analysis.Analyzer{renameAnalyzer}, code: 3},
} {
if test.name == "despite-error" && testenv.Go1Point() < 20 {
// The behavior in the comment on the despite-error test only occurs for Go 1.20+.
continue
}
if got := checker.Run(test.pattern, test.analyzers); got != test.code {
t.Errorf("got incorrect exit code %d for test %s; want %d", got, test.name, test.code)
}

Просмотреть файл

@ -10,11 +10,9 @@ import (
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/go/analysis/passes/directive"
"golang.org/x/tools/internal/testenv"
)
func Test(t *testing.T) {
testenv.NeedsGo1Point(t, 16)
analyzer := *directive.Analyzer
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
defer func() {

Просмотреть файл

@ -10,29 +10,10 @@ import (
"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/go/analysis/passes/loopclosure"
"golang.org/x/tools/internal/testenv"
"golang.org/x/tools/internal/testfiles"
)
func Test(t *testing.T) {
// legacy loopclosure test expectations are incorrect > 1.21.
testenv.SkipAfterGo1Point(t, 21)
testdata := analysistest.TestData()
analysistest.Run(t, testdata, loopclosure.Analyzer,
"a", "golang.org/...", "subtests", "typeparams")
}
func TestVersions22(t *testing.T) {
t.Skip("Disabled for golang.org/cl/603895. Fix and re-enable.")
testenv.NeedsGo1Point(t, 22)
func TestVersions(t *testing.T) {
dir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), "src", "versions", "go22.txtar"))
analysistest.Run(t, dir, loopclosure.Analyzer, "golang.org/fake/versions")
}
func TestVersions18(t *testing.T) {
t.Skip("Disabled for golang.org/cl/603895. Fix and re-enable.")
dir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), "src", "versions", "go18.txtar"))
analysistest.Run(t, dir, loopclosure.Analyzer, "golang.org/fake/versions")
}

Просмотреть файл

@ -1,13 +1,13 @@
Test loopclosure at go version go1.22.
The go1.19 build tag is necessary to force the file version.
The go1.21 build tag is necessary to force the file version.
-- go.mod --
module golang.org/fake/versions
go 1.22
-- pre.go --
//go:build go1.19
//go:build go1.21
package versions

Просмотреть файл

@ -8,11 +8,9 @@ import (
"testing"
"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/internal/testenv"
)
func Test(t *testing.T) {
testenv.NeedsGo1Point(t, 21)
testdata := analysistest.TestData()
analysistest.Run(t, testdata, Analyzer, "a", "b")
}

Просмотреть файл

@ -10,7 +10,6 @@ import (
"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/go/analysis/passes/stdversion"
"golang.org/x/tools/internal/testenv"
"golang.org/x/tools/internal/testfiles"
)
@ -18,8 +17,6 @@ func Test(t *testing.T) {
t.Skip("Disabled for golang.org/cl/603895. Fix and re-enable.")
// The test relies on go1.21 std symbols, but the analyzer
// itself requires the go1.22 implementation of versions.FileVersions.
testenv.NeedsGo1Point(t, 22)
dir := testfiles.ExtractTxtarFileToTmp(t, filepath.Join(analysistest.TestData(), "test.txtar"))
analysistest.Run(t, dir, stdversion.Analyzer,
"example.com/a",

Просмотреть файл

@ -1,12 +0,0 @@
// 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.20
// +build go1.20
package interp_test
func init() {
testdataTests = append(testdataTests, "slice2array.go")
}

Просмотреть файл

@ -1,12 +0,0 @@
// Copyright 2023 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.21
// +build go1.21
package interp_test
func init() {
testdataTests = append(testdataTests, "minmax.go")
}

Просмотреть файл

@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.22
// +build go1.22
package interp_test
import (
@ -19,13 +16,6 @@ import (
"golang.org/x/tools/internal/testenv"
)
func init() {
testdataTests = append(testdataTests,
"rangevarlifetime_go122.go",
"forvarlifetime_go122.go",
)
}
// TestExperimentRange tests files in testdata with GOEXPERIMENT=range set.
func TestExperimentRange(t *testing.T) {
testenv.NeedsGoExperiment(t, "range")

Просмотреть файл

@ -137,6 +137,10 @@ var testdataTests = []string{
"fixedbugs/issue66783.go",
"typeassert.go",
"zeros.go",
"slice2array.go",
"minmax.go",
"rangevarlifetime_go122.go",
"forvarlifetime_go122.go",
}
func init() {

Просмотреть файл

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.22
package main
import (

Просмотреть файл

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.19
//go:build go1.21
// goversion can be pinned to anything strictly before 1.22.

Просмотреть файл

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.19
//go:build go1.21
// goversion can be pinned to anything strictly before 1.22.

Просмотреть файл

@ -67,7 +67,7 @@ func TestNewAlias(t *testing.T) {
t.Errorf("Expected Unalias(A)==%q. got %q", want, got)
}
if testenv.Go1Point() >= 22 && godebug != "gotypesalias=0" {
if godebug != "gotypesalias=0" {
if _, ok := A.Type().(*types.Alias); !ok {
t.Errorf("Expected A.Type() to be a types.Alias(). got %q", A.Type())
}

Просмотреть файл

@ -415,8 +415,7 @@ func CheckReadable(pass *analysis.Pass, filename string) error {
return nil
}
for _, f := range pass.Files {
// TODO(adonovan): use go1.20 f.FileStart
if pass.Fset.File(f.Pos()).Name() == filename {
if pass.Fset.File(f.FileStart).Name() == filename {
return nil
}
}

Просмотреть файл

@ -138,8 +138,13 @@ func predeclared() []types.Type {
// used internally by gc; never used by this package or in .a files
anyType{},
// comparable
types.Universe.Lookup("comparable").Type(),
// any
types.Universe.Lookup("any").Type(),
}
predecl = append(predecl, additionalPredeclared()...)
})
return predecl
}

Просмотреть файл

@ -232,14 +232,19 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
// Select appropriate importer.
if len(data) > 0 {
switch data[0] {
case 'v', 'c', 'd': // binary, till go1.10
case 'v', 'c', 'd':
// binary: emitted by cmd/compile till go1.10; obsolete.
return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0])
case 'i': // indexed, till go1.19
case 'i':
// indexed: emitted by cmd/compile till go1.19;
// now used only for serializing go/types.
// See https://github.com/golang/go/issues/69491.
_, pkg, err := IImportData(fset, packages, data[1:], id)
return pkg, err
case 'u': // unified, from go1.20
case 'u':
// unified: emitted by cmd/compile since go1.20.
_, pkg, err := UImportData(fset, packages, data[1:size], id)
return pkg, err

Просмотреть файл

@ -242,7 +242,6 @@ import (
"golang.org/x/tools/go/types/objectpath"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/tokeninternal"
)
// IExportShallow encodes "shallow" export data for the specified package.
@ -441,7 +440,7 @@ func (p *iexporter) encodeFile(w *intWriter, file *token.File, needed []uint64)
// Sort the set of needed offsets. Duplicates are harmless.
sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] })
lines := tokeninternal.GetLines(file) // byte offset of each line start
lines := file.Lines() // byte offset of each line start
w.uint64(uint64(len(lines)))
// Rather than record the entire array of line start offsets,

Просмотреть файл

@ -9,8 +9,4 @@ package gcimporter
var IExportCommon = iexportCommon
const (
IExportVersion = iexportVersion
IExportVersionGenerics = iexportVersionGenerics
IExportVersionGo1_18 = iexportVersionGo1_18
)
const IExportVersion = iexportVersionGenerics

Просмотреть файл

@ -4,9 +4,6 @@
// This is a copy of bexport_test.go for iexport.go.
//go:build go1.11
// +build go1.11
package gcimporter_test
import (

Просмотреть файл

@ -53,6 +53,7 @@ const (
iexportVersionPosCol = 1
iexportVersionGo1_18 = 2
iexportVersionGenerics = 2
iexportVersion = iexportVersionGenerics
iexportVersionCurrent = 2
)

Просмотреть файл

@ -1,34 +0,0 @@
// 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.
package gcimporter
import "go/types"
const iexportVersion = iexportVersionGenerics
// additionalPredeclared returns additional predeclared types in go.1.18.
func additionalPredeclared() []types.Type {
return []types.Type{
// comparable
types.Universe.Lookup("comparable").Type(),
// any
types.Universe.Lookup("any").Type(),
}
}
// See cmd/compile/internal/types.SplitVargenSuffix.
func splitVargenSuffix(name string) (base, suffix string) {
i := len(name)
for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {
i--
}
const dot = "·"
if i >= len(dot) && name[i-len(dot):i] == dot {
i -= len(dot)
return name[:i], name[i:]
}
return name, ""
}

Просмотреть файл

@ -738,3 +738,17 @@ func pkgScope(pkg *types.Package) *types.Scope {
}
return types.Universe
}
// See cmd/compile/internal/types.SplitVargenSuffix.
func splitVargenSuffix(name string) (base, suffix string) {
i := len(name)
for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {
i--
}
const dot = "·"
if i >= len(dot) && name[i-len(dot):i] == dot {
i -= len(dot)
return name[:i], name[i:]
}
return name, ""
}

Просмотреть файл

@ -16,7 +16,6 @@ import (
"os"
"os/exec"
"path/filepath"
"reflect"
"regexp"
"runtime"
"strconv"
@ -250,16 +249,13 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
cmd.Stdout = stdout
cmd.Stderr = stderr
// cmd.WaitDelay was added only in go1.20 (see #50436).
if waitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); waitDelay.IsValid() {
// https://go.dev/issue/59541: don't wait forever copying stderr
// after the command has exited.
// After CL 484741 we copy stdout manually, so we we'll stop reading that as
// soon as ctx is done. However, we also don't want to wait around forever
// for stderr. Give a much-longer-than-reasonable delay and then assume that
// something has wedged in the kernel or runtime.
waitDelay.Set(reflect.ValueOf(30 * time.Second))
}
// https://go.dev/issue/59541: don't wait forever copying stderr
// after the command has exited.
// After CL 484741 we copy stdout manually, so we we'll stop reading that as
// soon as ctx is done. However, we also don't want to wait around forever
// for stderr. Give a much-longer-than-reasonable delay and then assume that
// something has wedged in the kernel or runtime.
cmd.WaitDelay = 30 * time.Second
// The cwd gets resolved to the real path. On Darwin, where
// /tmp is a symlink, this breaks anything that expects the

Просмотреть файл

@ -1,58 +0,0 @@
// Copyright 2019 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.22
// +build go1.22
package imports
import (
"context"
"testing"
)
// Tests that go.work files and vendor directory are respected.
func TestModWorkspaceVendoring(t *testing.T) {
mt := setup(t, nil, `
-- go.work --
go 1.22
use (
./a
./b
)
-- a/go.mod --
module example.com/a
go 1.22
require rsc.io/sampler v1.3.1
-- a/a.go --
package a
import _ "rsc.io/sampler"
-- b/go.mod --
module example.com/b
go 1.22
-- b/b.go --
package b
`, "")
defer mt.cleanup()
// generate vendor directory
if _, err := mt.env.invokeGo(context.Background(), "work", "vendor"); err != nil {
t.Fatal(err)
}
// update module resolver
mt.env.ClearModuleInfo()
mt.env.UpdateResolver(mt.env.resolver.ClearForNewScan())
mt.assertModuleFoundInDir("example.com/a", "a", `main/a$`)
mt.assertScanFinds("example.com/a", "a")
mt.assertModuleFoundInDir("example.com/b", "b", `main/b$`)
mt.assertScanFinds("example.com/b", "b")
mt.assertModuleFoundInDir("rsc.io/sampler", "sampler", `/vendor/`)
}

Просмотреть файл

@ -267,10 +267,7 @@ import _ "rsc.io/sampler"
t.Fatal(err)
}
wantDir := `pkg.*mod.*/sampler@.*$`
if testenv.Go1Point() >= 14 {
wantDir = `/vendor/`
}
wantDir := `/vendor/`
// Clear out the resolver's module info, since we've changed the environment.
// (the presence of a /vendor directory affects `go list -m`).
@ -1323,3 +1320,48 @@ func BenchmarkModuleResolver_InitialScan(b *testing.B) {
scanToSlice(resolver, exclude)
}
}
// Tests that go.work files and vendor directory are respected.
func TestModWorkspaceVendoring(t *testing.T) {
mt := setup(t, nil, `
-- go.work --
go 1.22
use (
./a
./b
)
-- a/go.mod --
module example.com/a
go 1.22
require rsc.io/sampler v1.3.1
-- a/a.go --
package a
import _ "rsc.io/sampler"
-- b/go.mod --
module example.com/b
go 1.22
-- b/b.go --
package b
`, "")
defer mt.cleanup()
// generate vendor directory
if _, err := mt.env.invokeGo(context.Background(), "work", "vendor"); err != nil {
t.Fatal(err)
}
// update module resolver
mt.env.ClearModuleInfo()
mt.env.UpdateResolver(mt.env.resolver.ClearForNewScan())
mt.assertModuleFoundInDir("example.com/a", "a", `main/a$`)
mt.assertScanFinds("example.com/a", "a")
mt.assertModuleFoundInDir("example.com/b", "b", `main/b$`)
mt.assertScanFinds("example.com/b", "b")
mt.assertModuleFoundInDir("rsc.io/sampler", "sampler", `/vendor/`)
}

Просмотреть файл

@ -14,8 +14,6 @@ import (
"os"
"path/filepath"
"strings"
"golang.org/x/tools/internal/testenv"
)
// WriteModuleVersion creates a directory in the proxy dir for a module.
@ -82,18 +80,10 @@ func checkClose(name string, closer io.Closer, err *error) {
// ToURL returns the file uri for a proxy directory.
func ToURL(dir string) string {
if testenv.Go1Point() >= 13 {
// file URLs on Windows must start with file:///. See golang.org/issue/6027.
path := filepath.ToSlash(dir)
if !strings.HasPrefix(path, "/") {
path = "/" + path
}
return "file://" + path
} else {
// Prior to go1.13, the Go command on Windows only accepted GOPROXY file URLs
// of the form file://C:/path/to/proxy. This was incorrect: when parsed, "C:"
// is interpreted as the host. See golang.org/issue/6027. This has been
// fixed in go1.13, but we emit the old format for old releases.
return "file://" + filepath.ToSlash(dir)
// file URLs on Windows must start with file:///. See golang.org/issue/6027.
path := filepath.ToSlash(dir)
if !strings.HasPrefix(path, "/") {
path = "/" + path
}
return "file://" + path
}

Просмотреть файл

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.20
package analyzer
import (

Просмотреть файл

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.20
package analyzer_test
import (

Просмотреть файл

@ -15,6 +15,7 @@ import (
"go/types"
pathpkg "path"
"reflect"
"slices"
"strconv"
"strings"
@ -151,7 +152,7 @@ func (st *state) inline() (*Result, error) {
elideBraces := res.elideBraces
if !elideBraces {
if newBlock, ok := res.new.(*ast.BlockStmt); ok {
i := nodeIndex(caller.path, res.old)
i := slices.Index(caller.path, res.old)
parent := caller.path[i+1]
var body []ast.Stmt
switch parent := parent.(type) {
@ -2465,7 +2466,7 @@ func callStmt(callPath []ast.Node, unrestricted bool) *ast.ExprStmt {
parent, _ := callContext(callPath)
stmt, ok := parent.(*ast.ExprStmt)
if ok && unrestricted {
switch callPath[nodeIndex(callPath, stmt)+1].(type) {
switch callPath[slices.Index(callPath, ast.Node(stmt))+1].(type) {
case *ast.LabeledStmt,
*ast.BlockStmt,
*ast.CaseClause,
@ -2775,7 +2776,7 @@ func consistentOffsets(caller *Caller) bool {
// ancestor of the CallExpr identified by its PathEnclosingInterval).
func needsParens(callPath []ast.Node, old, new ast.Node) bool {
// Find enclosing old node and its parent.
i := nodeIndex(callPath, old)
i := slices.Index(callPath, old)
if i == -1 {
panic("not found")
}
@ -2837,16 +2838,6 @@ func needsParens(callPath []ast.Node, old, new ast.Node) bool {
return false
}
func nodeIndex(nodes []ast.Node, n ast.Node) int {
// TODO(adonovan): Use index[ast.Node]() in go1.20.
for i, node := range nodes {
if node == n {
return i
}
}
return -1
}
// declares returns the set of lexical names declared by a
// sequence of statements from the same block, excluding sub-blocks.
// (Lexical names do not include control labels.)

Просмотреть файл

@ -11,41 +11,10 @@ import (
"go/token"
"sort"
"sync"
"sync/atomic"
"unsafe"
)
// GetLines returns the table of line-start offsets from a token.File.
func GetLines(file *token.File) []int {
// token.File has a Lines method on Go 1.21 and later.
if file, ok := (interface{})(file).(interface{ Lines() []int }); ok {
return file.Lines()
}
// This declaration must match that of token.File.
// This creates a risk of dependency skew.
// For now we check that the size of the two
// declarations is the same, on the (fragile) assumption
// that future changes would add fields.
type tokenFile119 struct {
_ string
_ int
_ int
mu sync.Mutex // we're not complete monsters
lines []int
_ []struct{}
}
if unsafe.Sizeof(*file) != unsafe.Sizeof(tokenFile119{}) {
panic("unexpected token.File size")
}
var ptr *tokenFile119
type uP = unsafe.Pointer
*(*uP)(uP(&ptr)) = uP(file)
ptr.mu.Lock()
defer ptr.mu.Unlock()
return ptr.lines
}
// AddExistingFiles adds the specified files to the FileSet if they
// are not already present. It panics if any pair of files in the
// resulting FileSet would overlap.
@ -56,7 +25,7 @@ func AddExistingFiles(fset *token.FileSet, files []*token.File) {
mutex sync.RWMutex
base int
files []*token.File
_ *token.File // changed to atomic.Pointer[token.File] in go1.19
_ atomic.Pointer[token.File]
}
// If the size of token.FileSet changes, this will fail to compile.
@ -116,8 +85,7 @@ func FileSetFor(files ...*token.File) *token.FileSet {
fset := token.NewFileSet()
for _, f := range files {
f2 := fset.AddFile(f.Name(), f.Base(), f.Size())
lines := GetLines(f)
f2.SetLines(lines)
f2.SetLines(f.Lines())
}
return fset
}

Просмотреть файл

@ -1,14 +0,0 @@
// Copyright 2024 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.
package versions
// toolchain is maximum version (<1.22) that the go toolchain used
// to build the current tool is known to support.
//
// When a tool is built with >=1.22, the value of toolchain is unused.
//
// x/tools does not support building with go <1.18. So we take this
// as the minimum possible maximum.
var toolchain string = Go1_18

Просмотреть файл

@ -1,14 +0,0 @@
// Copyright 2024 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.19
// +build go1.19
package versions
func init() {
if Compare(toolchain, Go1_19) < 0 {
toolchain = Go1_19
}
}

Просмотреть файл

@ -1,14 +0,0 @@
// Copyright 2024 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.20
// +build go1.20
package versions
func init() {
if Compare(toolchain, Go1_20) < 0 {
toolchain = Go1_20
}
}

Просмотреть файл

@ -1,14 +0,0 @@
// Copyright 2024 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.21
// +build go1.21
package versions
func init() {
if Compare(toolchain, Go1_21) < 0 {
toolchain = Go1_21
}
}

Просмотреть файл

@ -5,15 +5,34 @@
package versions
import (
"go/ast"
"go/types"
)
// GoVersion returns the Go version of the type package.
// It returns zero if no version can be determined.
func GoVersion(pkg *types.Package) string {
// TODO(taking): x/tools can call GoVersion() [from 1.21] after 1.25.
if pkg, ok := any(pkg).(interface{ GoVersion() string }); ok {
return pkg.GoVersion()
// FileVersion returns a file's Go version.
// The reported version is an unknown Future version if a
// version cannot be determined.
func FileVersion(info *types.Info, file *ast.File) string {
// In tools built with Go >= 1.22, the Go version of a file
// follow a cascades of sources:
// 1) types.Info.FileVersion, which follows the cascade:
// 1.a) file version (ast.File.GoVersion),
// 1.b) the package version (types.Config.GoVersion), or
// 2) is some unknown Future version.
//
// File versions require a valid package version to be provided to types
// in Config.GoVersion. Config.GoVersion is either from the package's module
// or the toolchain (go run). This value should be provided by go/packages
// or unitchecker.Config.GoVersion.
if v := info.FileVersions[file]; IsValid(v) {
return v
}
return ""
// Note: we could instead return runtime.Version() [if valid].
// This would act as a max version on what a tool can support.
return Future
}
// InitFileVersions initializes info to record Go versions for Go files.
func InitFileVersions(info *types.Info) {
info.FileVersions = make(map[*ast.File]string)
}

Просмотреть файл

@ -1,30 +0,0 @@
// Copyright 2023 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.22
// +build !go1.22
package versions
import (
"go/ast"
"go/types"
)
// FileVersion returns a language version (<=1.21) derived from runtime.Version()
// or an unknown future version.
func FileVersion(info *types.Info, file *ast.File) string {
// In x/tools built with Go <= 1.21, we do not have Info.FileVersions
// available. We use a go version derived from the toolchain used to
// compile the tool by default.
// This will be <= go1.21. We take this as the maximum version that
// this tool can support.
//
// There are no features currently in x/tools that need to tell fine grained
// differences for versions <1.22.
return toolchain
}
// InitFileVersions is a noop when compiled with this Go version.
func InitFileVersions(*types.Info) {}

Просмотреть файл

@ -1,41 +0,0 @@
// Copyright 2023 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.22
// +build go1.22
package versions
import (
"go/ast"
"go/types"
)
// FileVersion returns a file's Go version.
// The reported version is an unknown Future version if a
// version cannot be determined.
func FileVersion(info *types.Info, file *ast.File) string {
// In tools built with Go >= 1.22, the Go version of a file
// follow a cascades of sources:
// 1) types.Info.FileVersion, which follows the cascade:
// 1.a) file version (ast.File.GoVersion),
// 1.b) the package version (types.Config.GoVersion), or
// 2) is some unknown Future version.
//
// File versions require a valid package version to be provided to types
// in Config.GoVersion. Config.GoVersion is either from the package's module
// or the toolchain (go run). This value should be provided by go/packages
// or unitchecker.Config.GoVersion.
if v := info.FileVersions[file]; IsValid(v) {
return v
}
// Note: we could instead return runtime.Version() [if valid].
// This would act as a max version on what a tool can support.
return Future
}
// InitFileVersions initializes info to record Go versions for Go files.
func InitFileVersions(info *types.Info) {
info.FileVersions = make(map[*ast.File]string)
}

Просмотреть файл

@ -13,13 +13,10 @@ import (
"go/types"
"testing"
"golang.org/x/tools/internal/testenv"
"golang.org/x/tools/internal/versions"
)
func Test(t *testing.T) {
testenv.NeedsGo1Point(t, 22)
var contents = map[string]string{
"gobuild.go": `
//go:build go1.23
@ -49,7 +46,7 @@ func Test(t *testing.T) {
files[i] = parse(t, fset, test.fname, contents[test.fname])
}
pkg, info := typeCheck(t, fset, files, item.goversion)
if got, want := versions.GoVersion(pkg), item.pversion; versions.Compare(got, want) != 0 {
if got, want := pkg.GoVersion(), item.pversion; versions.Compare(got, want) != 0 {
t.Errorf("GoVersion()=%q. expected %q", got, want)
}
if got := versions.FileVersion(info, nil); got != "" {

Просмотреть файл

@ -11,7 +11,6 @@ import (
"go/types"
"testing"
"golang.org/x/tools/internal/testenv"
"golang.org/x/tools/internal/versions"
)
@ -192,9 +191,7 @@ func TestBefore(t *testing.T) {
}
}
func TestFileVersions122(t *testing.T) {
testenv.NeedsGo1Point(t, 22)
func TestFileVersions(t *testing.T) {
const source = `
package P
`
@ -230,27 +227,3 @@ func TestFileVersions122(t *testing.T) {
}
}
}
func TestFileVersions121(t *testing.T) {
testenv.SkipAfterGo1Point(t, 21)
// If <1.22, info and file are ignored.
v := versions.FileVersion(nil, nil)
oneof := map[string]bool{
versions.Go1_18: true,
versions.Go1_19: true,
versions.Go1_20: true,
versions.Go1_21: true,
}
if !oneof[v] {
t.Errorf("FileVersion(...)=%q expected to be a known go version <1.22", v)
}
if versions.AtLeast(v, versions.Go1_22) {
t.Errorf("versions.AtLeast(%q, %q) expected to be false", v, versions.Go1_22)
}
if !versions.Before(v, versions.Go1_22) {
t.Errorf("versions.Before(%q, %q) expected to hold", v, versions.Go1_22)
}
}