@@ -12,22 +12,16 @@ import (
12
12
13
13
"github.com/fatih/color"
14
14
"github.com/golangci/golangci-lint/pkg/config"
15
+ "github.com/golangci/golangci-lint/pkg/exitcodes"
15
16
"github.com/golangci/golangci-lint/pkg/lint"
16
17
"github.com/golangci/golangci-lint/pkg/lint/lintersdb"
17
18
"github.com/golangci/golangci-lint/pkg/logutils"
18
19
"github.com/golangci/golangci-lint/pkg/printers"
19
20
"github.com/golangci/golangci-lint/pkg/result"
20
- "github.com/golangci/golangci-lint/pkg/result/processors"
21
- "github.com/sirupsen/logrus"
22
21
"github.com/spf13/cobra"
23
22
"github.com/spf13/pflag"
24
23
)
25
24
26
- const (
27
- exitCodeIfFailure = 3
28
- exitCodeIfTimeout = 4
29
- )
30
-
31
25
func getDefaultExcludeHelp () string {
32
26
parts := []string {"Use or not use default excludes:" }
33
27
for _ , ep := range config .DefaultExcludePatterns {
@@ -64,7 +58,7 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
64
58
// Run config
65
59
rc := & cfg .Run
66
60
fs .IntVar (& rc .ExitCodeIfIssuesFound , "issues-exit-code" ,
67
- 1 , wh ("Exit code when issues were found" ))
61
+ exitcodes . IssuesFound , wh ("Exit code when issues were found" ))
68
62
fs .StringSliceVar (& rc .BuildTags , "build-tags" , nil , wh ("Build tags" ))
69
63
fs .DurationVar (& rc .Deadline , "deadline" , time .Minute , wh ("Deadline for total work" ))
70
64
fs .BoolVar (& rc .AnalyzeTests , "tests" , true , wh ("Analyze tests (*_test.go)" ))
@@ -165,65 +159,76 @@ func (e *Executor) initRun() {
165
159
// init e.cfg by values from config: flags parse will see these values
166
160
// like the default ones. It will overwrite them only if the same option
167
161
// is found in command-line: it's ok, command-line has higher priority.
168
- e .parseConfig ()
169
162
170
- // Slice options must be explicitly set for properly merging.
163
+ r := config .NewFileReader (e .cfg , e .log .Child ("config_reader" ), func (fs * pflag.FlagSet , cfg * config.Config ) {
164
+ // Don't do `fs.AddFlagSet(cmd.Flags())` because it shares flags representations:
165
+ // `changed` variable inside string slice vars will be shared.
166
+ // Use another config variable here, not e.cfg, to not
167
+ // affect main parsing by this parsing of only config option.
168
+ initFlagSet (fs , cfg )
169
+
170
+ // Parse max options, even force version option: don't want
171
+ // to get access to Executor here: it's error-prone to use
172
+ // cfg vs e.cfg.
173
+ initRootFlagSet (fs , cfg , true )
174
+ })
175
+ if err := r .Read (); err != nil {
176
+ e .log .Fatalf ("Can't read config: %s" , err )
177
+ }
178
+
179
+ // Slice options must be explicitly set for proper merging of config and command-line options.
171
180
fixSlicesFlags (fs )
172
181
}
173
182
183
+ func fixSlicesFlags (fs * pflag.FlagSet ) {
184
+ // It's a dirty hack to set flag.Changed to true for every string slice flag.
185
+ // It's necessary to merge config and command-line slices: otherwise command-line
186
+ // flags will always overwrite ones from the config.
187
+ fs .VisitAll (func (f * pflag.Flag ) {
188
+ if f .Value .Type () != "stringSlice" {
189
+ return
190
+ }
191
+
192
+ s , err := fs .GetStringSlice (f .Name )
193
+ if err != nil {
194
+ return
195
+ }
196
+
197
+ if s == nil { // assume that every string slice flag has nil as the default
198
+ return
199
+ }
200
+
201
+ // calling Set sets Changed to true: next Set calls will append, not overwrite
202
+ _ = f .Value .Set (strings .Join (s , "," ))
203
+ })
204
+ }
205
+
174
206
func (e * Executor ) runAnalysis (ctx context.Context , args []string ) (<- chan result.Issue , error ) {
175
207
e .cfg .Run .Args = args
176
208
177
- linters , err := lintersdb .GetEnabledLinters (e .cfg )
209
+ linters , err := lintersdb .GetEnabledLinters (e .cfg , e . log . Child ( "lintersdb" ) )
178
210
if err != nil {
179
211
return nil , err
180
212
}
181
213
182
- lintCtx , err := lint .LoadContext (ctx , linters , e .cfg )
214
+ lintCtx , err := lint .LoadContext (ctx , linters , e .cfg , e . log . Child ( "load" ) )
183
215
if err != nil {
184
216
return nil , err
185
217
}
186
218
187
- excludePatterns := e .cfg .Issues .ExcludePatterns
188
- if e .cfg .Issues .UseDefaultExcludes {
189
- excludePatterns = append (excludePatterns , config .GetDefaultExcludePatternsStrings ()... )
190
- }
191
- var excludeTotalPattern string
192
- if len (excludePatterns ) != 0 {
193
- excludeTotalPattern = fmt .Sprintf ("(%s)" , strings .Join (excludePatterns , "|" ))
194
- }
195
-
196
- skipFilesProcessor , err := processors .NewSkipFiles (e .cfg .Run .SkipFiles )
219
+ runner , err := lint .NewRunner (lintCtx .ASTCache , e .cfg , e .log .Child ("runner" ))
197
220
if err != nil {
198
221
return nil , err
199
222
}
200
223
201
- runner := lint.SimpleRunner {
202
- Processors : []processors.Processor {
203
- processors .NewPathPrettifier (), // must be before diff, nolint and exclude autogenerated processor at least
204
- processors .NewCgo (),
205
- skipFilesProcessor ,
206
-
207
- processors .NewAutogeneratedExclude (lintCtx .ASTCache ),
208
- processors .NewExclude (excludeTotalPattern ),
209
- processors .NewNolint (lintCtx .ASTCache ),
210
-
211
- processors .NewUniqByLine (),
212
- processors .NewDiff (e .cfg .Issues .Diff , e .cfg .Issues .DiffFromRevision , e .cfg .Issues .DiffPatchFilePath ),
213
- processors .NewMaxPerFileFromLinter (),
214
- processors .NewMaxSameIssues (e .cfg .Issues .MaxSameIssues ),
215
- processors .NewMaxFromLinter (e .cfg .Issues .MaxIssuesPerLinter ),
216
- },
217
- }
218
-
219
224
return runner .Run (ctx , linters , lintCtx ), nil
220
225
}
221
226
222
- func setOutputToDevNull () (savedStdout , savedStderr * os.File ) {
227
+ func ( e * Executor ) setOutputToDevNull () (savedStdout , savedStderr * os.File ) {
223
228
savedStdout , savedStderr = os .Stdout , os .Stderr
224
229
devNull , err := os .Open (os .DevNull )
225
230
if err != nil {
226
- logrus . Warnf ("can 't open null device %q: %s" , os .DevNull , err )
231
+ e . log . Warnf ("Can 't open null device %q: %s" , os .DevNull , err )
227
232
return
228
233
}
229
234
@@ -235,7 +240,7 @@ func (e *Executor) runAndPrint(ctx context.Context, args []string) error {
235
240
if ! logutils .HaveDebugTag ("linters_output" ) {
236
241
// Don't allow linters and loader to print anything
237
242
log .SetOutput (ioutil .Discard )
238
- savedStdout , savedStderr := setOutputToDevNull ()
243
+ savedStdout , savedStderr := e . setOutputToDevNull ()
239
244
defer func () {
240
245
os .Stdout , os .Stderr = savedStdout , savedStderr
241
246
}()
@@ -253,9 +258,11 @@ func (e *Executor) runAndPrint(ctx context.Context, args []string) error {
253
258
p = printers .NewJSON ()
254
259
case config .OutFormatColoredLineNumber , config .OutFormatLineNumber :
255
260
p = printers .NewText (e .cfg .Output .PrintIssuedLine ,
256
- format == config .OutFormatColoredLineNumber , e .cfg .Output .PrintLinterName )
261
+ format == config .OutFormatColoredLineNumber , e .cfg .Output .PrintLinterName ,
262
+ e .log .Child ("text_printer" ))
257
263
case config .OutFormatTab :
258
- p = printers .NewTab (e .cfg .Output .PrintLinterName )
264
+ p = printers .NewTab (e .cfg .Output .PrintLinterName ,
265
+ e .log .Child ("tab_printer" ))
259
266
case config .OutFormatCheckstyle :
260
267
p = printers .NewCheckstyle ()
261
268
default :
@@ -288,22 +295,22 @@ func (e *Executor) executeRun(cmd *cobra.Command, args []string) {
288
295
defer cancel ()
289
296
290
297
if needTrackResources {
291
- go watchResources (ctx , trackResourcesEndCh )
298
+ go watchResources (ctx , trackResourcesEndCh , e . log )
292
299
}
293
300
294
301
if err := e .runAndPrint (ctx , args ); err != nil {
295
- logrus . Warnf ( "running error: %s" , err )
296
- if e .exitCode == 0 {
297
- e .exitCode = exitCodeIfFailure
302
+ e . log . Errorf ( "Running error: %s" , err )
303
+ if e .exitCode == exitcodes . Success {
304
+ e .exitCode = exitcodes . Failure
298
305
}
299
306
}
300
307
301
- if e .exitCode == 0 && ctx .Err () != nil {
302
- e .exitCode = exitCodeIfTimeout
308
+ if e .exitCode == exitcodes . Success && ctx .Err () != nil {
309
+ e .exitCode = exitcodes . Timeout
303
310
}
304
311
}
305
312
306
- func watchResources (ctx context.Context , done chan struct {}) {
313
+ func watchResources (ctx context.Context , done chan struct {}, log logutils. Log ) {
307
314
startedAt := time .Now ()
308
315
309
316
rssValues := []uint64 {}
@@ -339,8 +346,8 @@ func watchResources(ctx context.Context, done chan struct{}) {
339
346
340
347
const MB = 1024 * 1024
341
348
maxMB := float64 (max ) / MB
342
- logrus .Infof ("Memory: %d samples, avg is %.1fMB, max is %.1fMB" ,
349
+ log .Infof ("Memory: %d samples, avg is %.1fMB, max is %.1fMB" ,
343
350
len (rssValues ), float64 (avg )/ MB , maxMB )
344
- logrus .Infof ("Execution took %s" , time .Since (startedAt ))
351
+ log .Infof ("Execution took %s" , time .Since (startedAt ))
345
352
close (done )
346
353
}
0 commit comments