@@ -28,7 +28,7 @@ The execution starts here:
2828
2929``` go title=cmd/golangci-lint/main.go
3030func main () {
31- e := commands.NewExecutor (version, commit, date )
31+ e := commands.NewExecutor (info )
3232
3333 if err := e.Execute (); err != nil {
3434 fmt.Fprintf (os.Stderr , " failed executing command with error %v \n " , err)
@@ -45,7 +45,8 @@ type Executor struct {
4545 runCmd *cobra.Command
4646 lintersCmd *cobra.Command
4747
48- exitCode int
48+ exitCode int
49+ buildInfo BuildInfo
4950
5051 cfg *config.Config
5152 log logutils.Log
@@ -69,9 +70,9 @@ We use dependency injection and all root dependencies are stored in this executo
6970
7071In the function ` NewExecutor ` we do the following:
7172
72- 1 . init dependencies
73- 2 . init [ cobra] ( https://github.com/spf13/cobra ) commands
74- 3 . parse config file using [ viper] ( https://github.com/spf13/viper ) and merge it with command line args .
73+ 1 . Initialize dependencies.
74+ 2 . Initialize [ cobra] ( https://github.com/spf13/cobra ) commands.
75+ 3 . Parse the config file using [ viper] ( https://github.com/spf13/viper ) and merge it with command line arguments .
7576
7677The following execution is controlled by ` cobra ` . If a user executes ` golangci-lint run `
7778then ` cobra ` executes ` e.runCmd ` .
@@ -82,19 +83,23 @@ Different `cobra` commands have different runners, e.g. a `run` command is confi
8283func (e *Executor ) initRun () {
8384 e.runCmd = &cobra.Command {
8485 Use: " run" ,
85- Short: welcomeMessage ,
86+ Short: " Run the linters " ,
8687 Run: e.executeRun ,
87- PreRun : func (_ *cobra.Command , _ []string ) {
88+ PreRunE : func (_ *cobra.Command , _ []string ) error {
8889 if ok := e.acquireFileLock (); !ok {
89- e. log . Fatalf ( " Parallel golangci-lint is running" )
90+ return errors. New ( " parallel golangci-lint is running" )
9091 }
92+ return nil
9193 },
9294 PostRun: func (_ *cobra.Command , _ []string ) {
9395 e.releaseFileLock ()
9496 },
9597 }
9698 e.rootCmd .AddCommand (e.runCmd )
97- e.runCmd .SetOutput (logutils.StdOut ) // use custom output to properly color it in Windows terminals
99+
100+ e.runCmd .SetOut (logutils.StdOut ) // use custom output to properly color it in Windows terminals
101+ e.runCmd .SetErr (logutils.StdErr )
102+
98103 e.initRunConfiguration (e.runCmd )
99104}
100105```
@@ -114,13 +119,13 @@ func (cl *ContextLoader) Load(ctx context.Context, linters []*linter.Config) (*l
114119 loadMode := cl.findLoadMode (linters)
115120 pkgs , err := cl.loadPackages (ctx, loadMode)
116121 if err != nil {
117- return nil , err
122+ return nil , fmt. Errorf ( " failed to load packages: % w " , err)
118123 }
119124
120- // ...
121- ret := &linter.Context {
122- // ...
123- }
125+ // ...
126+ ret := &linter.Context {
127+ // ...
128+ }
124129 return ret, nil
125130}
126131```
@@ -142,10 +147,11 @@ func (lc *Config) WithLoadFiles() *Config {
142147
143148If a linter uses ` go/analysis ` and needs type information, we need to extract more data by ` go/packages ` :
144149
145- ``` go title=/ pkg/lint/linter/config.go
150+ ``` go title=pkg/lint/linter/config.go
146151func (lc *Config ) WithLoadForGoAnalysis () *Config {
147152 lc = lc.WithLoadFiles ()
148- lc.LoadMode |= packages.NeedImports | packages.NeedDeps | packages.NeedExportsFile | packages.NeedTypesSizes
153+ lc.LoadMode |= packages.NeedImports | packages.NeedDeps | packages.NeedExportFile | packages.NeedTypesSizes
154+ lc.IsSlow = true
149155 return lc
150156}
151157```
@@ -159,20 +165,24 @@ First, we need to find all enabled linters. All linters are registered here:
159165
160166``` go title=pkg/lint/lintersdb/manager.go
161167func (m Manager ) GetAllSupportedLinterConfigs () []*linter .Config {
162- // ...
163- lcs := []*linter.Config {
168+ // ...
169+ linters = append (linters,
170+ // ...
171+ linter.NewConfig (golinters.NewBodyclose ()).
172+ WithSince (" v1.18.0" ).
173+ WithLoadForGoAnalysis ().
174+ WithPresets (linter.PresetPerformance , linter.PresetBugs ).
175+ WithURL (" https://github.com/timakin/bodyclose" ),
176+ // ...
164177 linter.NewConfig (golinters.NewGovet (govetCfg)).
178+ WithEnabledByDefault ().
179+ WithSince (" v1.0.0" ).
165180 WithLoadForGoAnalysis ().
166- WithPresets (linter.PresetBugs ).
181+ WithPresets (linter.PresetBugs , linter. PresetMetaLinter ).
167182 WithAlternativeNames (" vet" , " vetshadow" ).
168183 WithURL (" https://pkg.go.dev/cmd/vet" ),
169- linter.NewConfig (golinters.NewBodyclose ()).
170- WithLoadForGoAnalysis ().
171- WithPresets (linter.PresetPerformance , linter.PresetBugs ).
172- WithURL (" https://github.com/timakin/bodyclose" ),
173- // ...
174- }
175- // ...
184+ }
185+ // ...
176186}
177187```
178188
@@ -189,9 +199,9 @@ We merge enabled linters into one `MetaLinter` to improve execution time if we c
189199// into a fewer number of linters. E.g. some go/analysis linters can be optimized into
190200// one metalinter for data reuse and speed up.
191201func (es EnabledSet) GetOptimizedLinters() ([]*linter.Config, error) {
192- // ...
193- es.combineGoAnalysisLinters (resultLintersSet)
194- // ...
202+ // ...
203+ es.combineGoAnalysisLinters (resultLintersSet)
204+ // ...
195205}
196206```
197207
@@ -221,6 +231,8 @@ type Issue struct {
221231 FromLinter string
222232 Text string
223233
234+ Severity string
235+
224236 // Source lines of a code with the issue to show
225237 SourceLines []string
226238
@@ -250,8 +262,10 @@ We have an abstraction of `result.Processor` to postprocess found issues:
250262``` sh
251263$ tree -L 1 ./pkg/result/processors/
252264./pkg/result/processors/
265+ ./pkg/result/processors/
253266├── autogenerated_exclude.go
254267├── autogenerated_exclude_test.go
268+ ├── base_rule.go
255269├── cgo.go
256270├── diff.go
257271├── exclude.go
@@ -262,6 +276,7 @@ $ tree -L 1 ./pkg/result/processors/
262276├── fixer.go
263277├── identifier_marker.go
264278├── identifier_marker_test.go
279+ ├── issues.go
265280├── max_from_linter.go
266281├── max_from_linter_test.go
267282├── max_per_file_from_linter.go
@@ -270,17 +285,23 @@ $ tree -L 1 ./pkg/result/processors/
270285├── max_same_issues_test.go
271286├── nolint.go
272287├── nolint_test.go
288+ ├── path_prefixer.go
289+ ├── path_prefixer_test.go
273290├── path_prettifier.go
274291├── path_shortener.go
275292├── processor.go
293+ ├── processor_test.go
294+ ├── severity_rules.go
295+ ├── severity_rules_test.go
276296├── skip_dirs.go
277297├── skip_files.go
278298├── skip_files_test.go
299+ ├── sort_results.go
300+ ├── sort_results_test.go
279301├── source_code.go
280302├── testdata
281303├── uniq_by_line.go
282- ├── uniq_by_line_test.go
283- └── utils.go
304+ └── uniq_by_line_test.go
284305```
285306
286307The abstraction is simple:
@@ -303,14 +324,24 @@ We have an abstraction for printing found issues.
303324$ tree -L 1 ./pkg/printers/
304325./pkg/printers/
305326├── checkstyle.go
327+ ├── checkstyle_test.go
306328├── codeclimate.go
329+ ├── codeclimate_test.go
307330├── github.go
308331├── github_test.go
332+ ├── html.go
333+ ├── html_test.go
309334├── json.go
335+ ├── json_test.go
310336├── junitxml.go
337+ ├── junitxml_test.go
311338├── printer.go
312339├── tab.go
313- └── text.go
340+ ├── tab_test.go
341+ ├── teamcity.go
342+ ├── teamcity_test.go
343+ ├── text.go
344+ └── text_test.go
314345```
315346
316347Needed printer is selected by command line option ` --out-format ` .
0 commit comments