aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/fix
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2020-06-29 14:29:09 -0400
committerRuss Cox <rsc@golang.org>2021-10-28 17:52:59 +0000
commit31249688487ca3a60f856ad082d4e84c4d5f79fb (patch)
tree69b3eb3308e882329c2d780e784ee4f01888f65a /src/cmd/fix
parent6bd0e7fa8a2cb5c8de9d4566c900233715d8cf0e (diff)
downloadgo-31249688487ca3a60f856ad082d4e84c4d5f79fb.tar.gz
go-31249688487ca3a60f856ad082d4e84c4d5f79fb.zip
cmd/fix: add buildtag fix
Now that Go 1.17 is out and Go 1.15 is unsupported, removing // +build lines can be done safely: in the worst case, if code is compiled using Go 1.16 the toolchain will detect the presence of a //go:build without // +build and fail the build. (It will not silently choose the wrong files.) Note that +build lines will continue to work in Go sources forever. This just provides a mechanism for users who are done with Go 1.16 to remove them easily, by running "go fix". Also update for new generics AST. For #41184. Fixes #48978. Change-Id: I11a432c319e5abd05ad68dda9ccd7a7fdcc8bbb8 Reviewed-on: https://go-review.googlesource.com/c/go/+/240611 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
Diffstat (limited to 'src/cmd/fix')
-rw-r--r--src/cmd/fix/buildtag.go51
-rw-r--r--src/cmd/fix/buildtag_test.go34
-rw-r--r--src/cmd/fix/fix.go9
-rw-r--r--src/cmd/fix/main.go28
-rw-r--r--src/cmd/fix/main_test.go23
5 files changed, 139 insertions, 6 deletions
diff --git a/src/cmd/fix/buildtag.go b/src/cmd/fix/buildtag.go
new file mode 100644
index 0000000000..5f4fbfef16
--- /dev/null
+++ b/src/cmd/fix/buildtag.go
@@ -0,0 +1,51 @@
+// Copyright 2020 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 main
+
+import (
+ "go/ast"
+ "strings"
+)
+
+func init() {
+ register(buildtagFix)
+}
+
+const buildtagGoVersionCutoff = 1_18
+
+var buildtagFix = fix{
+ name: "buildtag",
+ date: "2021-08-25",
+ f: buildtag,
+ desc: `Remove +build comments from modules using Go 1.18 or later`,
+}
+
+func buildtag(f *ast.File) bool {
+ if goVersion < buildtagGoVersionCutoff {
+ return false
+ }
+
+ // File is already gofmt-ed, so we know that if there are +build lines,
+ // they are in a comment group that starts with a //go:build line followed
+ // by a blank line. While we cannot delete comments from an AST and
+ // expect consistent output in general, this specific case - deleting only
+ // some lines from a comment block - does format correctly.
+ fixed := false
+ for _, g := range f.Comments {
+ sawGoBuild := false
+ for i, c := range g.List {
+ if strings.HasPrefix(c.Text, "//go:build ") {
+ sawGoBuild = true
+ }
+ if sawGoBuild && strings.HasPrefix(c.Text, "// +build ") {
+ g.List = g.List[:i]
+ fixed = true
+ break
+ }
+ }
+ }
+
+ return fixed
+}
diff --git a/src/cmd/fix/buildtag_test.go b/src/cmd/fix/buildtag_test.go
new file mode 100644
index 0000000000..1c6efbe9e0
--- /dev/null
+++ b/src/cmd/fix/buildtag_test.go
@@ -0,0 +1,34 @@
+// Copyright 2020 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 main
+
+func init() {
+ addTestCases(buildtagTests, buildtag)
+}
+
+var buildtagTests = []testCase{
+ {
+ Name: "buildtag.oldGo",
+ Version: 1_10,
+ In: `//go:build yes
+// +build yes
+
+package main
+`,
+ },
+ {
+ Name: "buildtag.new",
+ Version: 1_99,
+ In: `//go:build yes
+// +build yes
+
+package main
+`,
+ Out: `//go:build yes
+
+package main
+`,
+ },
+}
diff --git a/src/cmd/fix/fix.go b/src/cmd/fix/fix.go
index b49db37571..b9980c17b9 100644
--- a/src/cmd/fix/fix.go
+++ b/src/cmd/fix/fix.go
@@ -125,6 +125,9 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) {
case *ast.IndexExpr:
walkBeforeAfter(&n.X, before, after)
walkBeforeAfter(&n.Index, before, after)
+ case *ast.IndexListExpr:
+ walkBeforeAfter(&n.X, before, after)
+ walkBeforeAfter(&n.Indices, before, after)
case *ast.SliceExpr:
walkBeforeAfter(&n.X, before, after)
if n.Low != nil {
@@ -156,6 +159,9 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) {
case *ast.StructType:
walkBeforeAfter(&n.Fields, before, after)
case *ast.FuncType:
+ if n.TypeParams != nil {
+ walkBeforeAfter(&n.TypeParams, before, after)
+ }
walkBeforeAfter(&n.Params, before, after)
if n.Results != nil {
walkBeforeAfter(&n.Results, before, after)
@@ -231,6 +237,9 @@ func walkBeforeAfter(x interface{}, before, after func(interface{})) {
walkBeforeAfter(&n.Values, before, after)
walkBeforeAfter(&n.Names, before, after)
case *ast.TypeSpec:
+ if n.TypeParams != nil {
+ walkBeforeAfter(&n.TypeParams, before, after)
+ }
walkBeforeAfter(&n.Type, before, after)
case *ast.BadDecl:
diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go
index d055929aac..b5f7b901d6 100644
--- a/src/cmd/fix/main.go
+++ b/src/cmd/fix/main.go
@@ -18,6 +18,7 @@ import (
"os"
"path/filepath"
"sort"
+ "strconv"
"strings"
"cmd/internal/diff"
@@ -36,7 +37,12 @@ var forceRewrites = flag.String("force", "",
var allowed, force map[string]bool
-var doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files")
+var (
+ doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files")
+ goVersionStr = flag.String("go", "", "go language version for files")
+
+ goVersion int // 115 for go1.15
+)
// enable for debugging fix failures
const debug = false // display incorrectly reformatted source and exit
@@ -63,6 +69,26 @@ func main() {
flag.Usage = usage
flag.Parse()
+ if *goVersionStr != "" {
+ if !strings.HasPrefix(*goVersionStr, "go") {
+ report(fmt.Errorf("invalid -go=%s", *goVersionStr))
+ os.Exit(exitCode)
+ }
+ majorStr := (*goVersionStr)[len("go"):]
+ minorStr := "0"
+ if i := strings.Index(majorStr, "."); i >= 0 {
+ majorStr, minorStr = majorStr[:i], majorStr[i+len("."):]
+ }
+ major, err1 := strconv.Atoi(majorStr)
+ minor, err2 := strconv.Atoi(minorStr)
+ if err1 != nil || err2 != nil || major < 0 || major >= 100 || minor < 0 || minor >= 100 {
+ report(fmt.Errorf("invalid -go=%s", *goVersionStr))
+ os.Exit(exitCode)
+ }
+
+ goVersion = major*100 + minor
+ }
+
sort.Sort(byDate(fixes))
if *allowedRewrites != "" {
diff --git a/src/cmd/fix/main_test.go b/src/cmd/fix/main_test.go
index af16bcaa31..1baa95c545 100644
--- a/src/cmd/fix/main_test.go
+++ b/src/cmd/fix/main_test.go
@@ -14,10 +14,11 @@ import (
)
type testCase struct {
- Name string
- Fn func(*ast.File) bool
- In string
- Out string
+ Name string
+ Fn func(*ast.File) bool
+ Version int
+ In string
+ Out string
}
var testCases []testCase
@@ -78,7 +79,16 @@ func TestRewrite(t *testing.T) {
for _, tt := range testCases {
tt := tt
t.Run(tt.Name, func(t *testing.T) {
- t.Parallel()
+ if tt.Version == 0 {
+ t.Parallel()
+ } else {
+ old := goVersion
+ goVersion = tt.Version
+ defer func() {
+ goVersion = old
+ }()
+ }
+
// Apply fix: should get tt.Out.
out, fixed, ok := parseFixPrint(t, tt.Fn, tt.Name, tt.In, true)
if !ok {
@@ -91,6 +101,9 @@ func TestRewrite(t *testing.T) {
return
}
+ if tt.Out == "" {
+ tt.Out = tt.In
+ }
if out != tt.Out {
t.Errorf("incorrect output.\n")
if !strings.HasPrefix(tt.Name, "testdata/") {