Skip to content

Commit 598a95a

Browse files
authored
handle dot import (#44)
Signed-off-by: sivchari <[email protected]>
1 parent 3e70ac2 commit 598a95a

File tree

3 files changed

+161
-52
lines changed

3 files changed

+161
-52
lines changed

tenv.go

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package tenv
33
import (
44
"fmt"
55
"go/ast"
6+
"go/token"
7+
"go/types"
68
"strings"
79

810
"golang.org/x/tools/go/analysis"
@@ -94,19 +96,17 @@ func checkExprStmt(pass *analysis.Pass, stmt *ast.ExprStmt, funcName, argName st
9496
return false
9597
}
9698
checkArgs(pass, callExpr.Args, funcName, argName)
97-
fun, ok := callExpr.Fun.(*ast.SelectorExpr)
98-
if !ok {
99-
return false
99+
ident, ok := callExpr.Fun.(*ast.Ident)
100+
if ok {
101+
obj := pass.TypesInfo.ObjectOf(ident)
102+
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
100103
}
101-
obj := pass.TypesInfo.ObjectOf(fun.Sel)
102-
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
103-
if targetName == "os.Setenv" {
104-
if argName == "" {
105-
argName = "testing"
106-
}
107-
pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
104+
fun, ok := callExpr.Fun.(*ast.SelectorExpr)
105+
if ok {
106+
obj := pass.TypesInfo.ObjectOf(fun.Sel)
107+
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
108108
}
109-
return true
109+
return false
110110
}
111111

112112
func checkArgs(pass *analysis.Pass, args []ast.Expr, funcName, argName string) {
@@ -115,17 +115,15 @@ func checkArgs(pass *analysis.Pass, args []ast.Expr, funcName, argName string) {
115115
if !ok {
116116
continue
117117
}
118-
fun, ok := callExpr.Fun.(*ast.SelectorExpr)
119-
if !ok {
120-
continue
118+
ident, ok := callExpr.Fun.(*ast.Ident)
119+
if ok {
120+
obj := pass.TypesInfo.ObjectOf(ident)
121+
checkObj(pass, obj, arg.Pos(), funcName, argName)
121122
}
122-
obj := pass.TypesInfo.ObjectOf(fun.Sel)
123-
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
124-
if targetName == "os.Setenv" {
125-
if argName == "" {
126-
argName = "testing"
127-
}
128-
pass.Reportf(arg.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
123+
fun, ok := callExpr.Fun.(*ast.SelectorExpr)
124+
if ok {
125+
obj := pass.TypesInfo.ObjectOf(fun.Sel)
126+
checkObj(pass, obj, arg.Pos(), funcName, argName)
129127
}
130128
}
131129
}
@@ -139,37 +137,45 @@ func checkIfStmt(pass *analysis.Pass, stmt *ast.IfStmt, funcName, argName string
139137
if !ok {
140138
return false
141139
}
142-
fun, ok := rhs.Fun.(*ast.SelectorExpr)
143-
if !ok {
144-
return false
140+
ident, ok := rhs.Fun.(*ast.Ident)
141+
if ok {
142+
obj := pass.TypesInfo.ObjectOf(ident)
143+
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
145144
}
146-
obj := pass.TypesInfo.ObjectOf(fun.Sel)
147-
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
148-
if targetName == "os.Setenv" {
149-
if argName == "" {
150-
argName = "testing"
151-
}
152-
pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
145+
fun, ok := rhs.Fun.(*ast.SelectorExpr)
146+
if ok {
147+
obj := pass.TypesInfo.ObjectOf(fun.Sel)
148+
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
153149
}
154-
return true
150+
return false
155151
}
156152

157153
func checkAssignStmt(pass *analysis.Pass, stmt *ast.AssignStmt, funcName, argName string) bool {
158154
rhs, ok := stmt.Rhs[0].(*ast.CallExpr)
159155
if !ok {
160156
return false
161157
}
158+
ident, ok := rhs.Fun.(*ast.Ident)
159+
if ok {
160+
obj := pass.TypesInfo.ObjectOf(ident)
161+
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
162+
}
162163
fun, ok := rhs.Fun.(*ast.SelectorExpr)
163-
if !ok {
164-
return false
164+
if ok {
165+
obj := pass.TypesInfo.ObjectOf(fun.Sel)
166+
return checkObj(pass, obj, stmt.Pos(), funcName, argName)
165167
}
166-
obj := pass.TypesInfo.ObjectOf(fun.Sel)
168+
return false
169+
}
170+
171+
func checkObj(pass *analysis.Pass, obj types.Object, pos token.Pos, funcName, argName string) bool {
167172
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
168173
if targetName == "os.Setenv" {
169174
if argName == "" {
170175
argName = "testing"
171176
}
172-
pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
177+
fmt.Println(argName, funcName)
178+
pass.Reportf(pos, "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, funcName)
173179
}
174180
return true
175181
}

testdata/src/a/a_custom_test.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,39 @@ var (
1414
)
1515

1616
func testsetup2() {
17-
os.Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup"
18-
err := os.Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup"
17+
os.Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup2"
18+
err := os.Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup2"
1919
if err != nil {
2020
_ = err
2121
}
2222
os.Setenv("a", "b") // if -all = true, "func setup is not using testing.Setenv"
2323
}
2424

2525
func TestF2(t *mytest.T) {
26-
testsetup()
27-
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF"
28-
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF"
26+
testsetup2()
27+
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF2"
28+
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF2"
2929
_ = err
30-
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF"
30+
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF2"
3131
_ = err
3232
}
3333
}
3434

3535
func BenchmarkF2(b *mytest.B) {
3636
TB(b)
37-
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF"
38-
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF"
37+
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF2"
38+
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF2"
3939
_ = err
40-
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF"
40+
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF2"
4141
_ = err
4242
}
4343
}
4444

4545
func TB2(tb mytest.TB) {
46-
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB"
47-
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB"
46+
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB2"
47+
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB2"
4848
_ = err
49-
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB"
49+
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB2"
5050
_ = err
5151
}
5252
}
@@ -90,15 +90,15 @@ func TestTDD2(t *mytest.T) {
9090

9191
func TestLoop2(t *mytest.T) {
9292
for i := 0; i < 3; i++ {
93-
os.Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop"
94-
err := os.Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop"
93+
os.Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop2"
94+
err := os.Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop2"
9595
_ = err
96-
if err := os.Setenv(fmt.Sprintf("a%d", i), "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop"
96+
if err := os.Setenv(fmt.Sprintf("a%d", i), "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop2"
9797
_ = err
9898
}
9999
}
100100
}
101101

102102
func TestUsingArg2(t *mytest.T) {
103-
require.NoError(t, os.Setenv("a", "b")) // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestUsingArg"
103+
require.NoError(t, os.Setenv("a", "b")) // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestUsingArg2"
104104
}

testdata/src/a/dot_import_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package a
2+
3+
import (
4+
"fmt"
5+
. "os"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
var (
12+
e3 = Setenv("a", "b") // never seen
13+
)
14+
15+
func testsetup3() {
16+
Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup3"
17+
err := Setenv("a", "b") // if -all = true, want "os\\.Setenv\\(\\) can be replaced by `testing\\.Setenv\\(\\)` in testsetup3"
18+
if err != nil {
19+
_ = err
20+
}
21+
Setenv("a", "b") // if -all = true, "func setup is not using testing.Setenv"
22+
}
23+
24+
func TestF3(t *testing.T) {
25+
testsetup3()
26+
Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF3"
27+
err := Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF3"
28+
_ = err
29+
if err := Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF3"
30+
_ = err
31+
}
32+
}
33+
34+
func BenchmarkF3(b *testing.B) {
35+
TB(b)
36+
Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF3"
37+
err := Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF3"
38+
_ = err
39+
if err := Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF3"
40+
_ = err
41+
}
42+
}
43+
44+
func TB3(tb testing.TB) {
45+
Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB3"
46+
err := Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB3"
47+
_ = err
48+
if err := Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB3"
49+
_ = err
50+
}
51+
}
52+
53+
func TestFunctionLiteral3(t *testing.T) {
54+
testsetup3()
55+
t.Run("test", func(t *testing.T) {
56+
Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
57+
err := Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
58+
_ = err
59+
if err := Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
60+
_ = err
61+
}
62+
})
63+
}
64+
65+
func TestEmpty3(t *testing.T) {
66+
t.Run("test", func(*testing.T) {})
67+
}
68+
69+
func TestEmptyTB3(t *testing.T) {
70+
func(testing.TB) {}(t)
71+
}
72+
73+
func TestTDD3(t *testing.T) {
74+
for _, tt := range []struct {
75+
name string
76+
}{
77+
{"test"},
78+
} {
79+
t.Run(tt.name, func(t *testing.T) {
80+
Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
81+
err := Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
82+
_ = err
83+
if err := Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
84+
_ = err
85+
}
86+
})
87+
}
88+
}
89+
90+
func TestLoop3(t *testing.T) {
91+
for i := 0; i < 3; i++ {
92+
Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop3"
93+
err := Setenv(fmt.Sprintf("a%d", i), "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop3"
94+
_ = err
95+
if err := Setenv(fmt.Sprintf("a%d", i), "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestLoop3"
96+
_ = err
97+
}
98+
}
99+
}
100+
101+
func TestUsingArg3(t *testing.T) {
102+
require.NoError(t, Setenv("a", "b")) // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestUsingArg3"
103+
}

0 commit comments

Comments
 (0)