Skip to content

Commit 4fb020b

Browse files
committed
Merge branch 'refactor/opus-cleanup-v2'
2 parents 1449ce2 + fb06698 commit 4fb020b

File tree

16 files changed

+903
-45
lines changed

16 files changed

+903
-45
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ go run github.com/mpyw/goroutinectx/cmd/goroutinectx@latest ./...
4040
```
4141

4242
> [!CAUTION]
43-
> To prevent supply chain attacks, pin to a specific version tag instead of `@latest` in CI/CD pipelines (e.g., `@v0.7.3`).
43+
> To prevent supply chain attacks, pin to a specific version tag instead of `@latest` in CI/CD pipelines (e.g., `@v0.7.4`).
4444
4545
### As a Library
4646

analyzer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,11 @@ func buildCheckers(derivers *deriver.Matcher, spawners *spawner.Map) ([]internal
169169

170170
// Goroutine checkers
171171
if enableGoroutine {
172-
goStmtCheckers = append(goStmtCheckers, &checkers.Goroutine{Derivers: derivers})
172+
goStmtCheckers = append(goStmtCheckers, &checkers.Goroutine{})
173173
}
174174

175175
if derivers != nil {
176-
goStmtCheckers = append(goStmtCheckers, &checkers.GoroutineDerive{Derivers: derivers})
176+
goStmtCheckers = append(goStmtCheckers, checkers.NewGoroutineDerive(derivers))
177177
}
178178

179179
// Call checkers

analyzer_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@ func TestErrgroup(t *testing.T) {
1818
analysistest.Run(t, testdata, goroutinectx.Analyzer, "errgroup")
1919
}
2020

21+
func TestErrgroupDerive(t *testing.T) {
22+
testdata := analysistest.TestData()
23+
24+
deriveFunc := "github.com/my-example-app/telemetry/apm.NewGoroutineContext"
25+
if err := goroutinectx.Analyzer.Flags.Set("goroutine-deriver", deriveFunc); err != nil {
26+
t.Fatal(err)
27+
}
28+
29+
defer func() {
30+
_ = goroutinectx.Analyzer.Flags.Set("goroutine-deriver", "")
31+
}()
32+
33+
analysistest.Run(t, testdata, goroutinectx.Analyzer, "errgroupderive")
34+
}
35+
2136
func TestConc(t *testing.T) {
2237
testdata := analysistest.TestData()
2338
analysistest.Run(t, testdata, goroutinectx.Analyzer, "conc")
@@ -107,6 +122,21 @@ func TestCarrierDerive(t *testing.T) {
107122
analysistest.Run(t, testdata, goroutinectx.Analyzer, "carrierderive")
108123
}
109124

125+
func TestSpawnerDerive(t *testing.T) {
126+
testdata := analysistest.TestData()
127+
128+
deriveFunc := "github.com/my-example-app/telemetry/apm.NewGoroutineContext"
129+
if err := goroutinectx.Analyzer.Flags.Set("goroutine-deriver", deriveFunc); err != nil {
130+
t.Fatal(err)
131+
}
132+
133+
defer func() {
134+
_ = goroutinectx.Analyzer.Flags.Set("goroutine-deriver", "")
135+
}()
136+
137+
analysistest.Run(t, testdata, goroutinectx.Analyzer, "spawnerderive")
138+
}
139+
110140
func TestSpawner(t *testing.T) {
111141
testdata := analysistest.TestData()
112142
analysistest.Run(t, testdata, goroutinectx.Analyzer, "spawner")

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ go 1.24.0
77
// - v0.1.0-v0.4.0: -test flag conflicted with singlechecker's built-in flag
88
retract [v0.1.0, v0.4.0]
99

10+
// Retract v0.7.2-v0.7.3 due to:
11+
// - -goroutine-deriver flag didn't work with errgroup/waitgroup/conc/spawner checkers
12+
// (deriver checking logic was lost during refactoring)
13+
retract [v0.7.2, v0.7.3]
14+
1015
require golang.org/x/tools v0.40.0
1116

1217
require (

internal/checkers/goroutine.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ import (
1010
)
1111

1212
// Goroutine checks that go statements propagate context.
13-
type Goroutine struct {
14-
Derivers *deriver.Matcher
15-
}
13+
type Goroutine struct{}
1614

1715
// Name returns the checker name for ignore directive matching.
1816
func (*Goroutine) Name() ignore.CheckerName {
@@ -83,7 +81,12 @@ func (*Goroutine) checkFromAST(cctx *probe.Context, stmt *ast.GoStmt) bool {
8381

8482
// GoroutineDerive checks that go statements call a deriver function.
8583
type GoroutineDerive struct {
86-
Derivers *deriver.Matcher
84+
derivers *deriver.Matcher
85+
}
86+
87+
// NewGoroutineDerive creates a new GoroutineDerive checker.
88+
func NewGoroutineDerive(derivers *deriver.Matcher) *GoroutineDerive {
89+
return &GoroutineDerive{derivers: derivers}
8790
}
8891

8992
// Name returns the checker name for ignore directive matching.
@@ -93,7 +96,7 @@ func (*GoroutineDerive) Name() ignore.CheckerName {
9396

9497
// CheckGoStmt checks a go statement for deriver function calls.
9598
func (c *GoroutineDerive) CheckGoStmt(cctx *probe.Context, stmt *ast.GoStmt) *internal.Result {
96-
if c.Derivers == nil || c.Derivers.IsEmpty() {
99+
if c.derivers == nil || c.derivers.IsEmpty() {
97100
return internal.OK()
98101
}
99102

@@ -108,7 +111,7 @@ func (c *GoroutineDerive) CheckGoStmt(cctx *probe.Context, stmt *ast.GoStmt) *in
108111
return result
109112
}
110113

111-
if c.Derivers.SatisfiesAnyGroup(cctx.Pass, lit.Body) {
114+
if c.derivers.SatisfiesAnyGroup(cctx.Pass, lit.Body) {
112115
return internal.OK()
113116
}
114117
return internal.Fail(c.message())
@@ -132,11 +135,11 @@ func (c *GoroutineDerive) CheckGoStmt(cctx *probe.Context, stmt *ast.GoStmt) *in
132135
}
133136

134137
func (c *GoroutineDerive) message() string {
135-
return "goroutine should call " + c.Derivers.Original + " to derive context"
138+
return "goroutine should call " + c.derivers.Original + " to derive context"
136139
}
137140

138141
func (c *GoroutineDerive) deferMessage() string {
139-
return "goroutine calls " + c.Derivers.Original + " in defer, but it should be called at goroutine start"
142+
return "goroutine calls " + c.derivers.Original + " in defer, but it should be called at goroutine start"
140143
}
141144

142145
func (c *GoroutineDerive) checkFromSSA(cctx *probe.Context, lit *ast.FuncLit) (*internal.Result, bool) {
@@ -149,7 +152,7 @@ func (c *GoroutineDerive) checkFromSSA(cctx *probe.Context, lit *ast.FuncLit) (*
149152
return nil, false
150153
}
151154

152-
result := cctx.Tracer.ClosureCallsDeriver(ssaFn, c.Derivers)
155+
result := cctx.Tracer.ClosureCallsDeriver(ssaFn, c.derivers)
153156

154157
if result.FoundAtStart {
155158
return internal.OK(), true
@@ -172,7 +175,7 @@ func (c *GoroutineDerive) checkIdent(cctx *probe.Context, ident *ast.Ident) bool
172175
return true
173176
}
174177

175-
return c.Derivers.SatisfiesAnyGroup(cctx.Pass, funcLit.Body)
178+
return c.derivers.SatisfiesAnyGroup(cctx.Pass, funcLit.Body)
176179
}
177180

178181
func (c *GoroutineDerive) checkHigherOrder(cctx *probe.Context, innerCall *ast.CallExpr) bool {
@@ -214,7 +217,7 @@ func (c *GoroutineDerive) factoryReturnsCallingFunc(cctx *probe.Context, factory
214217
callsDeriver = true
215218
return false
216219
}
217-
if c.Derivers.SatisfiesAnyGroup(cctx.Pass, fl.Body) {
220+
if c.derivers.SatisfiesAnyGroup(cctx.Pass, fl.Body) {
218221
callsDeriver = true
219222
return false
220223
}
@@ -243,7 +246,7 @@ func (c *GoroutineDerive) returnedValueCalls(cctx *probe.Context, result ast.Exp
243246
if cctx.FuncLitHasContextParam(innerFuncLit) {
244247
return true
245248
}
246-
return c.Derivers.SatisfiesAnyGroup(cctx.Pass, innerFuncLit.Body)
249+
return c.derivers.SatisfiesAnyGroup(cctx.Pass, innerFuncLit.Body)
247250
}
248251

249252
ident, ok := result.(*ast.Ident)
@@ -259,5 +262,5 @@ func (c *GoroutineDerive) returnedValueCalls(cctx *probe.Context, result ast.Exp
259262
if cctx.FuncLitHasContextParam(innerFuncLit) {
260263
return true
261264
}
262-
return c.Derivers.SatisfiesAnyGroup(cctx.Pass, innerFuncLit.Body)
265+
return c.derivers.SatisfiesAnyGroup(cctx.Pass, innerFuncLit.Body)
263266
}

0 commit comments

Comments
 (0)