Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
sivchari committed Sep 18, 2021
1 parent e75e242 commit 0da8554
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 69 deletions.
97 changes: 37 additions & 60 deletions tenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,11 @@ func run(pass *analysis.Pass) (interface{}, error) {
case *ast.File:
if strings.HasSuffix(pass.Fset.File(n.Pos()).Name(), "_test.go") {
for _, decl := range n.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl:
checkFunc(pass, decl)
case *ast.GenDecl:
if aflag {
checkGenDecl(pass, decl)
}
funcDecl, ok := decl.(*ast.FuncDecl)
if !ok {
continue
}
checkFunc(pass, funcDecl)
}
}
}
Expand All @@ -59,27 +56,28 @@ func run(pass *analysis.Pass) (interface{}, error) {
}

func checkFunc(pass *analysis.Pass, n *ast.FuncDecl) {
if targetRunner(n) {
argName, ok := targetRunner(n)
if ok {
for _, stmt := range n.Body.List {
switch stmt := stmt.(type) {
case *ast.ExprStmt:
if !checkExprStmt(pass, stmt, n) {
if !checkExprStmt(pass, stmt, n, argName) {
continue
}
case *ast.IfStmt:
if !checkIfStmt(pass, stmt, n) {
if !checkIfStmt(pass, stmt, n, argName) {
continue
}
case *ast.AssignStmt:
if !checkAssignStmt(pass, stmt, n) {
if !checkAssignStmt(pass, stmt, n, argName) {
continue
}
}
}
}
}

func checkExprStmt(pass *analysis.Pass, stmt *ast.ExprStmt, n *ast.FuncDecl) bool {
func checkExprStmt(pass *analysis.Pass, stmt *ast.ExprStmt, n *ast.FuncDecl, argName string) bool {
callExpr, ok := stmt.X.(*ast.CallExpr)
if !ok {
return false
Expand All @@ -92,14 +90,14 @@ func checkExprStmt(pass *analysis.Pass, stmt *ast.ExprStmt, n *ast.FuncDecl) boo
if !ok {
return false
}
funName := x.Name + "." + fun.Sel.Name
if funName == "os.Setenv" {
pass.Reportf(stmt.Pos(), "func %s is not using testing.Setenv", n.Name.Name)
targetName := x.Name + "." + fun.Sel.Name
if targetName == "os.Setenv" {
pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, n.Name.Name)
}
return true
}

func checkIfStmt(pass *analysis.Pass, stmt *ast.IfStmt, n *ast.FuncDecl) bool {
func checkIfStmt(pass *analysis.Pass, stmt *ast.IfStmt, n *ast.FuncDecl, argName string) bool {
assignStmt, ok := stmt.Init.(*ast.AssignStmt)
if !ok {
return false
Expand All @@ -116,14 +114,14 @@ func checkIfStmt(pass *analysis.Pass, stmt *ast.IfStmt, n *ast.FuncDecl) bool {
if !ok {
return false
}
funName := x.Name + "." + fun.Sel.Name
if funName == "os.Setenv" {
pass.Reportf(stmt.Pos(), "func %s is not using testing.Setenv", n.Name.Name)
targetName := x.Name + "." + fun.Sel.Name
if targetName == "os.Setenv" {
pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, n.Name.Name)
}
return true
}

func checkAssignStmt(pass *analysis.Pass, stmt *ast.AssignStmt, n *ast.FuncDecl) bool {
func checkAssignStmt(pass *analysis.Pass, stmt *ast.AssignStmt, n *ast.FuncDecl, argName string) bool {
rhs, ok := stmt.Rhs[0].(*ast.CallExpr)
if !ok {
return false
Expand All @@ -136,60 +134,30 @@ func checkAssignStmt(pass *analysis.Pass, stmt *ast.AssignStmt, n *ast.FuncDecl)
if !ok {
return false
}
funName := x.Name + "." + fun.Sel.Name
if funName == "os.Setenv" {
pass.Reportf(stmt.Pos(), "func %s is not using testing.Setenv", n.Name.Name)
targetName := x.Name + "." + fun.Sel.Name
if targetName == "os.Setenv" {
pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, n.Name.Name)
}
return true
}

func checkGenDecl(pass *analysis.Pass, decl *ast.GenDecl) {
for _, spec := range decl.Specs {
valueSpec, ok := spec.(*ast.ValueSpec)
if !ok {
continue
}
if len(valueSpec.Values) == 0 {
continue
}
callExpr, ok := valueSpec.Values[0].(*ast.CallExpr)
if !ok {
continue
}
selectorExpr, ok := callExpr.Fun.(*ast.SelectorExpr)
if !ok {
continue
}
x, ok := selectorExpr.X.(*ast.Ident)
if !ok {
continue
}
variable := valueSpec.Names[0].Name
funName := x.Name + "." + selectorExpr.Sel.Name
if funName == "os.Setenv" {
pass.Reportf(valueSpec.Pos(), "variable %s is not using testing.Setenv", variable)
}
}
}

func targetRunner(funcDecl *ast.FuncDecl) bool {
if aflag {
return true
}
func targetRunner(funcDecl *ast.FuncDecl) (string, bool) {
params := funcDecl.Type.Params.List
for _, p := range params {
switch typ := p.Type.(type) {
case *ast.StarExpr:
if checkStarExprTarget(typ) {
return true
argName := p.Names[0].Name
return argName, true
}
case *ast.SelectorExpr:
if checkSelectorExprTarget(typ) {
return true
argName := p.Names[0].Name
return argName, true
}
}
}
return false
return "", false
}

func checkStarExprTarget(typ *ast.StarExpr) bool {
Expand All @@ -206,6 +174,9 @@ func checkStarExprTarget(typ *ast.StarExpr) bool {
case "testing.T", "testing.B":
return true
default:
if aflag {
return true
}
return false
}
}
Expand All @@ -216,5 +187,11 @@ func checkSelectorExprTarget(typ *ast.SelectorExpr) bool {
return false
}
targetName := x.Name + "." + typ.Sel.Name
return targetName == "testing.TB"
if targetName == "testing.TB" {
return true
}
if aflag {
return true
}
return false
}
15 changes: 6 additions & 9 deletions testdata/src/a/a_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import (
)

var (
e = os.Setenv("a", "b") // if -all = true, want "variable e is not using testing.Setenv"
_ = e
env string
e = os.Setenv("a", "b") // never seen
)

func setup() {
Expand All @@ -17,26 +15,25 @@ func setup() {
if err != nil {
_ = err
}
env = os.Getenv("a")
os.Setenv("a", "b") // if -all = true, "func setup is not using testing.Setenv"
}

func TestF(t *testing.T) {
setup()
os.Setenv("a", "b") // want "func TestF is not using testing.Setenv"
if err := os.Setenv("a", "b"); err != nil { // want "func TestF is not using testing.Setenv"
os.Setenv("a", "b") // want "os.Setenv() can be replaced by `t.Setenv()` in TestF"
if err := os.Setenv("a", "b"); err != nil { // want "os.Setenv() can be replaced by `t.Setenv()` in TestF"
_ = err
}
}

func BenchmarkF(b *testing.B) {
testTB(b)
os.Setenv("a", "b") // want "func BenchmarkF is not using testing.Setenv"
if err := os.Setenv("a", "b"); err != nil { // want "func BenchmarkF is not using testing.Setenv"
os.Setenv("a", "b") // want "os.Setenv() can be replaced by `b.Setenv()` in BenchmarkF"
if err := os.Setenv("a", "b"); err != nil { // want "os.Setenv() can be replaced by `b.Setenv()` in BenchmarkF"
_ = err
}
}

func testTB(tb testing.TB) {
os.Setenv("a", "b") // want "func testTB is not using testing.Setenv"
os.Setenv("a", "b") // want "os.Setenv() can be replaced by `tb.Setenv()` in testTB"
}

0 comments on commit 0da8554

Please sign in to comment.