diff --git a/README.md b/README.md index c5d0047..30921d5 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,9 @@ go vet -vettool=(which tenv) ./... ### option -The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. +The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures. + +The option `go` allows to specify Go version. If the version is not empty and lower than Go 1.17 the analysis will be skipped. By default, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked. diff --git a/tenv.go b/tenv.go index fcff98d..000a7e9 100644 --- a/tenv.go +++ b/tenv.go @@ -2,6 +2,7 @@ package tenv import ( "go/ast" + "strconv" "strings" "golang.org/x/tools/go/analysis" @@ -24,13 +25,22 @@ var Analyzer = &analysis.Analyzer{ var ( A = "all" aflag bool + + Go = "go" + goflag string ) func init() { Analyzer.Flags.BoolVar(&aflag, A, false, "the all option will run against all method in test file") + Analyzer.Flags.StringVar(&goflag, Go, "1.17", "Go version") } func run(pass *analysis.Pass) (interface{}, error) { + if goVersionLower117(goflag) { + // Do nothing because T.Setenv added in go1.17 + return nil, nil + } + inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) nodeFilter := []ast.Node{ @@ -44,7 +54,6 @@ func run(pass *analysis.Pass) (interface{}, error) { checkFuncDecl(pass, n, pass.Fset.File(n.Pos()).Name()) case *ast.FuncLit: checkFuncLit(pass, n, pass.Fset.File(n.Pos()).Name()) - } }) return nil, nil @@ -211,3 +220,35 @@ func checkSelectorExprTarget(typ *ast.SelectorExpr) bool { targetName := x.Name + "." + typ.Sel.Name return targetName == "testing.TB" } + +// goVersionLower117 returns true if version is lower than go1.17. +// In case of any parse errors it returns false. +func goVersionLower117(version string) bool { + version = strings.TrimPrefix(version, "go") + if version == "" { + return false + } + + parts := strings.Split(version, ".") + if len(parts) != 2 { + return false + } + + major, err := strconv.Atoi(parts[0]) + if err != nil { + return false + } + if major < 1 { + return true + } + + minor, err := strconv.Atoi(parts[1]) + if err != nil { + return false + } + if minor < 17 { + return true + } + + return false +} diff --git a/tenv_test.go b/tenv_test.go index c4789c0..cd958e4 100644 --- a/tenv_test.go +++ b/tenv_test.go @@ -14,3 +14,10 @@ func TestAnalyzer(t *testing.T) { testdata := testutil.WithModules(t, analysistest.TestData(), nil) analysistest.Run(t, testdata, tenv.Analyzer, "a") } + +func TestAnalyzerGo116(t *testing.T) { + testdata := testutil.WithModules(t, analysistest.TestData(), nil) + a := tenv.Analyzer + a.Flags.Parse([]string{"-go", "1.16"}) + analysistest.Run(t, testdata, a, "go116") +} diff --git a/testdata/src/go116/go.mod b/testdata/src/go116/go.mod new file mode 100644 index 0000000..f78d17a --- /dev/null +++ b/testdata/src/go116/go.mod @@ -0,0 +1,3 @@ +module go116 + +go 1.16 diff --git a/testdata/src/go116/go116_test.go b/testdata/src/go116/go116_test.go new file mode 100644 index 0000000..dc6554c --- /dev/null +++ b/testdata/src/go116/go116_test.go @@ -0,0 +1,12 @@ +package go116 + +import ( + "os" + "testing" +) + +func TestF(t *testing.T) { + os.Setenv("a", "b") // if -go = 1.16, "" + err := os.Setenv("a", "b") // if -go = 1.16, "" + _ = err +}