Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handle dot import #44

Merged
merged 1 commit into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 42 additions & 36 deletions tenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package tenv
import (
"fmt"
"go/ast"
"go/token"
"go/types"
"strings"

"golang.org/x/tools/go/analysis"
Expand Down Expand Up @@ -94,19 +96,17 @@ func checkExprStmt(pass *analysis.Pass, stmt *ast.ExprStmt, funcName, argName st
return false
}
checkArgs(pass, callExpr.Args, funcName, argName)
fun, ok := callExpr.Fun.(*ast.SelectorExpr)
if !ok {
return false
ident, ok := callExpr.Fun.(*ast.Ident)
if ok {
obj := pass.TypesInfo.ObjectOf(ident)
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
}
obj := pass.TypesInfo.ObjectOf(fun.Sel)
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
if targetName == "os.Setenv" {
if argName == "" {
argName = "testing"
}
pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
fun, ok := callExpr.Fun.(*ast.SelectorExpr)
if ok {
obj := pass.TypesInfo.ObjectOf(fun.Sel)
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
}
return true
return false
}

func checkArgs(pass *analysis.Pass, args []ast.Expr, funcName, argName string) {
Expand All @@ -115,17 +115,15 @@ func checkArgs(pass *analysis.Pass, args []ast.Expr, funcName, argName string) {
if !ok {
continue
}
fun, ok := callExpr.Fun.(*ast.SelectorExpr)
if !ok {
continue
ident, ok := callExpr.Fun.(*ast.Ident)
if ok {
obj := pass.TypesInfo.ObjectOf(ident)
checkObj(pass, obj, arg.Pos(), funcName, argName)
}
obj := pass.TypesInfo.ObjectOf(fun.Sel)
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
if targetName == "os.Setenv" {
if argName == "" {
argName = "testing"
}
pass.Reportf(arg.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
fun, ok := callExpr.Fun.(*ast.SelectorExpr)
if ok {
obj := pass.TypesInfo.ObjectOf(fun.Sel)
checkObj(pass, obj, arg.Pos(), funcName, argName)
}
}
}
Expand All @@ -139,37 +137,45 @@ func checkIfStmt(pass *analysis.Pass, stmt *ast.IfStmt, funcName, argName string
if !ok {
return false
}
fun, ok := rhs.Fun.(*ast.SelectorExpr)
if !ok {
return false
ident, ok := rhs.Fun.(*ast.Ident)
if ok {
obj := pass.TypesInfo.ObjectOf(ident)
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
}
obj := pass.TypesInfo.ObjectOf(fun.Sel)
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
if targetName == "os.Setenv" {
if argName == "" {
argName = "testing"
}
pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
fun, ok := rhs.Fun.(*ast.SelectorExpr)
if ok {
obj := pass.TypesInfo.ObjectOf(fun.Sel)
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
}
return true
return false
}

func checkAssignStmt(pass *analysis.Pass, stmt *ast.AssignStmt, funcName, argName string) bool {
rhs, ok := stmt.Rhs[0].(*ast.CallExpr)
if !ok {
return false
}
ident, ok := rhs.Fun.(*ast.Ident)
if ok {
obj := pass.TypesInfo.ObjectOf(ident)
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
}
fun, ok := rhs.Fun.(*ast.SelectorExpr)
if !ok {
return false
if ok {
obj := pass.TypesInfo.ObjectOf(fun.Sel)
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
}
obj := pass.TypesInfo.ObjectOf(fun.Sel)
return false
}

func checkObj(pass *analysis.Pass, obj types.Object, pos token.Pos, funcName, argName string) bool {
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
if targetName == "os.Setenv" {
if argName == "" {
argName = "testing"
}
pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
fmt.Println(argName, funcName)
pass.Reportf(pos, "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
}
return true
}
Expand Down
32 changes: 16 additions & 16 deletions testdata/src/a/a_custom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,39 @@ var (
)

func testsetup2() {
os.Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup"
err := os.Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup"
os.Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup2"
err := os.Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup2"
if err != nil {
_ = err
}
os.Setenv("a", "b") // if -all = true, "func setup is not using testing.Setenv"
}

func TestF2(t *mytest.T) {
testsetup()
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF"
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF"
testsetup2()
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF2"
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF2"
_ = err
if err := os.Setenv("a", "b"); err != nil { // 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 TestF2"
_ = err
}
}

func BenchmarkF2(b *mytest.B) {
TB(b)
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF"
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF"
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF2"
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF2"
_ = err
if err := os.Setenv("a", "b"); err != nil { // 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 BenchmarkF2"
_ = err
}
}

func TB2(tb mytest.TB) {
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB"
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB"
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB2"
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB2"
_ = err
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB"
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB2"
_ = err
}
}
Expand Down Expand Up @@ -90,15 +90,15 @@ func TestTDD2(t *mytest.T) {

func TestLoop2(t *mytest.T) {
for i := 0; i < 3; i++ {
os.Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop"
err := os.Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop"
os.Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop2"
err := os.Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop2"
_ = err
if err := os.Setenv(fmt.Sprintf("a%d", i), "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop"
if err := os.Setenv(fmt.Sprintf("a%d", i), "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop2"
_ = err
}
}
}

func TestUsingArg2(t *mytest.T) {
require.NoError(t, os.Setenv("a", "b")) // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestUsingArg"
require.NoError(t, os.Setenv("a", "b")) // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestUsingArg2"
}
103 changes: 103 additions & 0 deletions testdata/src/a/dot_import_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package a

import (
"fmt"
. "os"
"testing"

"github.com/stretchr/testify/require"
)

var (
e3 = Setenv("a", "b") // never seen
)

func testsetup3() {
Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup3"
err := Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup3"
if err != nil {
_ = err
}
Setenv("a", "b") // if -all = true, "func setup is not using testing.Setenv"
}

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

func BenchmarkF3(b *testing.B) {
TB(b)
Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF3"
err := Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF3"
_ = err
if err := Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF3"
_ = err
}
}

func TB3(tb testing.TB) {
Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB3"
err := Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB3"
_ = err
if err := Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB3"
_ = err
}
}

func TestFunctionLiteral3(t *testing.T) {
testsetup3()
t.Run("test", func(t *testing.T) {
Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
err := Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
_ = err
if err := Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
_ = err
}
})
}

func TestEmpty3(t *testing.T) {
t.Run("test", func(*testing.T) {})
}

func TestEmptyTB3(t *testing.T) {
func(testing.TB) {}(t)
}

func TestTDD3(t *testing.T) {
for _, tt := range []struct {
name string
}{
{"test"},
} {
t.Run(tt.name, func(t *testing.T) {
Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
err := Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
_ = err
if err := Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
_ = err
}
})
}
}

func TestLoop3(t *testing.T) {
for i := 0; i < 3; i++ {
Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop3"
err := Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop3"
_ = err
if err := Setenv(fmt.Sprintf("a%d", i), "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop3"
_ = err
}
}
}

func TestUsingArg3(t *testing.T) {
require.NoError(t, Setenv("a", "b")) // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestUsingArg3"
}
Loading