Skip to content

Commit 7b68c50

Browse files
authored
use analysis.Pass (#42)
Signed-off-by: sivchari <[email protected]>
1 parent 5cae67a commit 7b68c50

File tree

4 files changed

+125
-42
lines changed

4 files changed

+125
-42
lines changed

.github/workflows/workflows.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
run: |
3333
go mod download
3434
- name: Test
35-
run: go test
35+
run: go test ./...
3636

3737
lint:
3838
name: Lint
@@ -42,4 +42,4 @@ jobs:
4242
- name: golangci-lint
4343
uses: golangci/golangci-lint-action@v2
4444
with:
45-
version: v1.59.0
45+
version: v1.61.0

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/sivchari/tenv
22

3-
go 1.21.0
3+
go 1.22.3
44

55
require (
66
github.com/gostaticanalysis/testutil v0.4.0

tenv.go

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package tenv
22

33
import (
4+
"fmt"
45
"go/ast"
56
"strings"
67

@@ -51,15 +52,15 @@ func run(pass *analysis.Pass) (interface{}, error) {
5152
}
5253

5354
func checkFuncDecl(pass *analysis.Pass, f *ast.FuncDecl, fileName string) {
54-
argName, ok := targetRunner(f.Type.Params.List, fileName)
55+
argName, ok := targetRunner(pass, f.Type.Params.List, fileName)
5556
if !ok {
5657
return
5758
}
5859
checkStmts(pass, f.Body.List, f.Name.Name, argName)
5960
}
6061

6162
func checkFuncLit(pass *analysis.Pass, f *ast.FuncLit, fileName string) {
62-
argName, ok := targetRunner(f.Type.Params.List, fileName)
63+
argName, ok := targetRunner(pass, f.Type.Params.List, fileName)
6364
if !ok {
6465
return
6566
}
@@ -97,11 +98,8 @@ func checkExprStmt(pass *analysis.Pass, stmt *ast.ExprStmt, funcName, argName st
9798
if !ok {
9899
return false
99100
}
100-
x, ok := fun.X.(*ast.Ident)
101-
if !ok {
102-
return false
103-
}
104-
targetName := x.Name + "." + fun.Sel.Name
101+
obj := pass.TypesInfo.ObjectOf(fun.Sel)
102+
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
105103
if targetName == "os.Setenv" {
106104
if argName == "" {
107105
argName = "testing"
@@ -121,11 +119,8 @@ func checkArgs(pass *analysis.Pass, args []ast.Expr, funcName, argName string) {
121119
if !ok {
122120
continue
123121
}
124-
x, ok := fun.X.(*ast.Ident)
125-
if !ok {
126-
continue
127-
}
128-
targetName := x.Name + "." + fun.Sel.Name
122+
obj := pass.TypesInfo.ObjectOf(fun.Sel)
123+
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
129124
if targetName == "os.Setenv" {
130125
if argName == "" {
131126
argName = "testing"
@@ -148,11 +143,8 @@ func checkIfStmt(pass *analysis.Pass, stmt *ast.IfStmt, funcName, argName string
148143
if !ok {
149144
return false
150145
}
151-
x, ok := fun.X.(*ast.Ident)
152-
if !ok {
153-
return false
154-
}
155-
targetName := x.Name + "." + fun.Sel.Name
146+
obj := pass.TypesInfo.ObjectOf(fun.Sel)
147+
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
156148
if targetName == "os.Setenv" {
157149
if argName == "" {
158150
argName = "testing"
@@ -171,11 +163,8 @@ func checkAssignStmt(pass *analysis.Pass, stmt *ast.AssignStmt, funcName, argNam
171163
if !ok {
172164
return false
173165
}
174-
x, ok := fun.X.(*ast.Ident)
175-
if !ok {
176-
return false
177-
}
178-
targetName := x.Name + "." + fun.Sel.Name
166+
obj := pass.TypesInfo.ObjectOf(fun.Sel)
167+
targetName := fmt.Sprintf("%s.%s", obj.Pkg().Name(), obj.Name())
179168
if targetName == "os.Setenv" {
180169
if argName == "" {
181170
argName = "testing"
@@ -189,19 +178,19 @@ func checkForStmt(pass *analysis.Pass, stmt *ast.ForStmt, funcName, argName stri
189178
checkStmts(pass, stmt.Body.List, funcName, argName)
190179
}
191180

192-
func targetRunner(params []*ast.Field, fileName string) (string, bool) {
181+
func targetRunner(pass *analysis.Pass, params []*ast.Field, fileName string) (string, bool) {
193182
for _, p := range params {
194183
switch typ := p.Type.(type) {
195184
case *ast.StarExpr:
196-
if checkStarExprTarget(typ) {
185+
if checkStarExprTarget(pass, typ) {
197186
if len(p.Names) == 0 {
198187
return "", false
199188
}
200189
argName := p.Names[0].Name
201190
return argName, true
202191
}
203192
case *ast.SelectorExpr:
204-
if checkSelectorExprTarget(typ) {
193+
if checkSelectorExprTarget(pass, typ) {
205194
if len(p.Names) == 0 {
206195
return "", false
207196
}
@@ -216,29 +205,19 @@ func targetRunner(params []*ast.Field, fileName string) (string, bool) {
216205
return "", false
217206
}
218207

219-
func checkStarExprTarget(typ *ast.StarExpr) bool {
208+
func checkStarExprTarget(pass *analysis.Pass, typ *ast.StarExpr) bool {
220209
selector, ok := typ.X.(*ast.SelectorExpr)
221210
if !ok {
222211
return false
223212
}
224-
x, ok := selector.X.(*ast.Ident)
225-
if !ok {
226-
return false
227-
}
228-
targetName := x.Name + "." + selector.Sel.Name
229-
switch targetName {
213+
switch pass.TypesInfo.TypeOf(selector).String() {
230214
case "testing.T", "testing.B":
231215
return true
232216
default:
233217
return false
234218
}
235219
}
236220

237-
func checkSelectorExprTarget(typ *ast.SelectorExpr) bool {
238-
x, ok := typ.X.(*ast.Ident)
239-
if !ok {
240-
return false
241-
}
242-
targetName := x.Name + "." + typ.Sel.Name
243-
return targetName == "testing.TB"
221+
func checkSelectorExprTarget(pass *analysis.Pass, typ *ast.SelectorExpr) bool {
222+
return pass.TypesInfo.TypeOf(typ).String() == "testing.TB"
244223
}

testdata/src/a/a_custom_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package a
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"testing"
7+
mytest "testing"
8+
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
var (
13+
e2 = os.Setenv("a", "b") // never seen
14+
)
15+
16+
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"
19+
if err != nil {
20+
_ = err
21+
}
22+
os.Setenv("a", "b") // if -all = true, "func setup is not using testing.Setenv"
23+
}
24+
25+
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"
29+
_ = err
30+
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestF"
31+
_ = err
32+
}
33+
}
34+
35+
func BenchmarkF2(b *mytest.B) {
36+
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"
39+
_ = err
40+
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `b\\.Setenv\\(\\)` in BenchmarkF"
41+
_ = err
42+
}
43+
}
44+
45+
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"
48+
_ = err
49+
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `tb\\.Setenv\\(\\)` in TB"
50+
_ = err
51+
}
52+
}
53+
54+
func TestFunctionLiteral2(t *mytest.T) {
55+
testsetup()
56+
t.Run("test", func(t *mytest.T) {
57+
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
58+
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
59+
_ = err
60+
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
61+
_ = err
62+
}
63+
})
64+
}
65+
66+
func TestEmpty2(t *mytest.T) {
67+
t.Run("test", func(*testing.T) {})
68+
}
69+
70+
func TestEmptyTB2(t *mytest.T) {
71+
func(testing.TB) {}(t)
72+
}
73+
74+
func TestTDD2(t *mytest.T) {
75+
for _, tt := range []struct {
76+
name string
77+
}{
78+
{"test"},
79+
} {
80+
t.Run(tt.name, func(t *testing.T) {
81+
os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
82+
err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
83+
_ = err
84+
if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in anonymous function"
85+
_ = err
86+
}
87+
})
88+
}
89+
}
90+
91+
func TestLoop2(t *mytest.T) {
92+
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"
95+
_ = 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"
97+
_ = err
98+
}
99+
}
100+
}
101+
102+
func TestUsingArg2(t *mytest.T) {
103+
require.NoError(t, os.Setenv("a", "b")) // want "os\\.Setenv\\(\\) can be replaced by `t\\.Setenv\\(\\)` in TestUsingArg"
104+
}

0 commit comments

Comments
 (0)