3939 enableSpawner bool
4040 enableSpawnerlabel bool
4141 enableGotask bool
42+
43+ // File filtering flags.
44+ analyzeTests bool
4245)
4346
4447func init () {
@@ -56,6 +59,9 @@ func init() {
5659 Analyzer .Flags .BoolVar (& enableSpawner , "spawner" , true , "enable spawner checker" )
5760 Analyzer .Flags .BoolVar (& enableSpawnerlabel , "spawnerlabel" , false , "enable spawnerlabel checker" )
5861 Analyzer .Flags .BoolVar (& enableGotask , "gotask" , true , "enable gotask checker (requires -goroutine-deriver)" )
62+
63+ // File filtering flags
64+ Analyzer .Flags .BoolVar (& analyzeTests , "test" , true , "analyze test files (*_test.go)" )
5965}
6066
6167// Analyzer is the main analyzer for goroutinectx.
@@ -75,11 +81,14 @@ func run(pass *analysis.Pass) (any, error) {
7581 return nil , ErrNoInspector
7682 }
7783
84+ // Build set of files to skip
85+ skipFiles := buildSkipFiles (pass )
86+
7887 // Parse configuration
7988 carriers := carrier .Parse (contextCarriers )
8089
81- // Build ignore maps for each file
82- ignoreMaps := buildIgnoreMaps (pass )
90+ // Build ignore maps for each file (excluding skipped files)
91+ ignoreMaps := buildIgnoreMaps (pass , skipFiles )
8392
8493 // Build spawner map from //goroutinectx:spawner directives and -external-spawner flag
8594 spawners := spawnerdir .Build (pass , externalSpawner )
@@ -88,12 +97,12 @@ func run(pass *analysis.Pass) (any, error) {
8897 enabled := buildEnabledCheckers (spawners )
8998
9099 // Run AST-based checks (goroutine, errgroup, waitgroup)
91- runASTChecks (pass , insp , ignoreMaps , carriers , spawners )
100+ runASTChecks (pass , insp , ignoreMaps , carriers , spawners , skipFiles )
92101
93102 // Run spawnerlabel checker if enabled
94103 if enableSpawnerlabel {
95104 spawnerlabelChecker := spawnerlabel .New (spawners )
96- spawnerlabelChecker .Check (pass , ignoreMaps )
105+ spawnerlabelChecker .Check (pass , ignoreMaps , skipFiles )
97106 }
98107
99108 // Report unused ignore directives
@@ -102,12 +111,39 @@ func run(pass *analysis.Pass) (any, error) {
102111 return nil , nil
103112}
104113
114+ // buildSkipFiles creates a set of filenames to skip based on flags.
115+ // Generated files are always skipped.
116+ // Test files are skipped when analyzeTests is false.
117+ func buildSkipFiles (pass * analysis.Pass ) map [string ]bool {
118+ skipFiles := make (map [string ]bool )
119+
120+ for _ , file := range pass .Files {
121+ filename := pass .Fset .Position (file .Pos ()).Filename
122+
123+ // Always skip generated files
124+ if ast .IsGenerated (file ) {
125+ skipFiles [filename ] = true
126+ continue
127+ }
128+
129+ // Skip test files if -test=false
130+ if ! analyzeTests && strings .HasSuffix (filename , "_test.go" ) {
131+ skipFiles [filename ] = true
132+ }
133+ }
134+
135+ return skipFiles
136+ }
137+
105138// buildIgnoreMaps creates ignore maps for each file in the pass.
106- func buildIgnoreMaps (pass * analysis.Pass ) map [string ]ignore.Map {
139+ func buildIgnoreMaps (pass * analysis.Pass , skipFiles map [ string ] bool ) map [string ]ignore.Map {
107140 ignoreMaps := make (map [string ]ignore.Map )
108141
109142 for _ , file := range pass .Files {
110143 filename := pass .Fset .Position (file .Pos ()).Filename
144+ if skipFiles [filename ] {
145+ continue
146+ }
111147 ignoreMaps [filename ] = ignore .Build (pass .Fset , file )
112148 }
113149
@@ -121,6 +157,7 @@ func runASTChecks(
121157 ignoreMaps map [string ]ignore.Map ,
122158 carriers []carrier.Carrier ,
123159 spawners * spawnerdir.Map ,
160+ skipFiles map [string ]bool ,
124161) {
125162 // Build context scopes for functions with context parameters
126163 funcScopes := buildFuncScopes (pass , insp , carriers )
@@ -171,12 +208,16 @@ func runASTChecks(
171208 return true
172209 }
173210
211+ filename := pass .Fset .Position (n .Pos ()).Filename
212+ if skipFiles [filename ] {
213+ return true
214+ }
215+
174216 scope := findEnclosingScope (funcScopes , stack )
175217 if scope == nil {
176218 return true // No context in scope
177219 }
178220
179- filename := pass .Fset .Position (n .Pos ()).Filename
180221 cctx := & context.CheckContext {
181222 Pass : pass ,
182223 Scope : scope ,
0 commit comments