Skip to content

Commit d993d3a

Browse files
committed
group of fixes after running on golang source code
1 parent 6f38492 commit d993d3a

31 files changed

+332
-104
lines changed

Gopkg.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
test:
2-
go test -v ./...
2+
go test -v -race ./...

internal/commands/linters.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package commands
33
import (
44
"fmt"
55
"os"
6+
"strings"
67

78
"github.com/fatih/color"
89
"github.com/golangci/golangci-lint/pkg"
@@ -20,7 +21,7 @@ func (e *Executor) initLinters() {
2021

2122
func printLinterConfigs(lcs []pkg.LinterConfig) {
2223
for _, lc := range lcs {
23-
fmt.Printf("%s: %s\n", color.YellowString(lc.Linter.Name()), lc.Desc)
24+
fmt.Printf("%s: %s\n", color.YellowString(lc.Linter.Name()), lc.Linter.Desc())
2425
}
2526
}
2627

@@ -39,5 +40,15 @@ func (e Executor) executeLinters(cmd *cobra.Command, args []string) {
3940
color.Red("\nDisabled by default linters:\n")
4041
printLinterConfigs(disabledLCs)
4142

43+
color.Green("\nLinters presets:")
44+
for _, p := range pkg.AllPresets() {
45+
linters := pkg.GetAllLintersForPreset(p)
46+
linterNames := []string{}
47+
for _, linter := range linters {
48+
linterNames = append(linterNames, linter.Name())
49+
}
50+
fmt.Printf("%s: %s\n", color.YellowString(p), strings.Join(linterNames, ", "))
51+
}
52+
4253
os.Exit(0)
4354
}

internal/commands/run.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"go/build"
7+
"go/token"
78
"log"
89
"strings"
910
"time"
@@ -38,16 +39,16 @@ func (e *Executor) initRun() {
3839
fmt.Sprintf("Format of output: %s", strings.Join(config.OutFormats, "|")))
3940
runCmd.Flags().BoolVar(&rc.PrintIssuedLine, "print-issued-lines", true, "Print lines of code with issue")
4041
runCmd.Flags().BoolVar(&rc.PrintLinterName, "print-linter-name", true, "Print linter name in issue line")
42+
runCmd.Flags().BoolVar(&rc.PrintWelcomeMessage, "print-welcome", true, "Print welcome message")
4143

4244
runCmd.Flags().IntVar(&rc.ExitCodeIfIssuesFound, "issues-exit-code",
4345
1, "Exit code when issues were found")
4446
runCmd.Flags().StringSliceVar(&rc.BuildTags, "build-tags", []string{}, "Build tags (not all linters support them)")
4547

46-
runCmd.Flags().BoolVar(&rc.Errcheck.CheckClose, "errcheck.check-close", false, "Errcheck: check missed error checks on .Close() calls")
4748
runCmd.Flags().BoolVar(&rc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", false, "Errcheck: check for ignored type assertion results")
4849
runCmd.Flags().BoolVar(&rc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, "Errcheck: check for errors assigned to blank identifier: _ = errFunc()")
4950

50-
runCmd.Flags().BoolVar(&rc.Govet.CheckShadowing, "govet.check-shadowing", true, "Govet: check for shadowed variables")
51+
runCmd.Flags().BoolVar(&rc.Govet.CheckShadowing, "govet.check-shadowing", false, "Govet: check for shadowed variables")
5152

5253
runCmd.Flags().Float64Var(&rc.Golint.MinConfidence, "golint.min-confidence", 0.8, "Golint: minimum confidence of a problem to print it")
5354

@@ -90,6 +91,9 @@ func (e *Executor) initRun() {
9091
runCmd.Flags().StringVar(&rc.DiffFromRevision, "new-from-rev", "", "Show only new issues created after git revision `REV`")
9192
runCmd.Flags().StringVar(&rc.DiffPatchFilePath, "new-from-patch", "", "Show only new issues created in git patch with file path `PATH`")
9293
runCmd.Flags().BoolVar(&rc.AnalyzeTests, "tests", false, "Analyze tests (*_test.go)")
94+
95+
runCmd.Flags().StringSliceVarP(&rc.Presets, "presets", "p", []string{},
96+
fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see them. This option implies option --disable-all", strings.Join(pkg.AllPresets(), "|")))
9397
}
9498

9599
func isFullImportNeeded(linters []pkg.Linter) bool {
@@ -208,10 +212,15 @@ func (e *Executor) runAnalysis(ctx context.Context, args []string) (chan result.
208212
if len(excludePatterns) != 0 {
209213
excludeTotalPattern = fmt.Sprintf("(%s)", strings.Join(excludePatterns, "|"))
210214
}
215+
fset := token.NewFileSet()
216+
if lintCtx.Program != nil {
217+
fset = lintCtx.Program.Fset
218+
}
211219
runner := pkg.SimpleRunner{
212220
Processors: []processors.Processor{
213221
processors.NewExclude(excludeTotalPattern),
214-
processors.NewNolint(lintCtx.Program.Fset),
222+
processors.NewCgo(),
223+
processors.NewNolint(fset),
215224
processors.NewUniqByLine(),
216225
processors.NewDiff(e.cfg.Run.Diff, e.cfg.Run.DiffFromRevision, e.cfg.Run.DiffPatchFilePath),
217226
processors.NewMaxPerFileFromLinter(),
@@ -231,6 +240,10 @@ func (e *Executor) executeRun(cmd *cobra.Command, args []string) {
231240
logrus.Infof("Run took %s", time.Since(startedAt))
232241
}(time.Now())
233242

243+
if e.cfg.Run.PrintWelcomeMessage {
244+
fmt.Println("Run this tool in cloud on every github pull request in https://golangci.com for free (public repos)")
245+
}
246+
234247
f := func() error {
235248
issues, err := e.runAnalysis(ctx, args)
236249
if err != nil {

pkg/config/config.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const (
1515
var OutFormats = []string{OutFormatColoredLineNumber, OutFormatLineNumber, OutFormatJSON}
1616

1717
var DefaultExcludePatterns = []string{
18+
"Error return value of `(os\\.Std(out|err)\\.Write|.*\\.Close)` is not checked",
1819
"should have comment",
1920
"comment on exported method",
2021
"G104", // disable what errcheck does: it reports on Close etc
@@ -33,14 +34,14 @@ type Run struct { // nolint:maligned
3334

3435
BuildTags []string
3536

36-
OutFormat string
37-
PrintIssuedLine bool
38-
PrintLinterName bool
37+
OutFormat string
38+
PrintIssuedLine bool
39+
PrintLinterName bool
40+
PrintWelcomeMessage bool
3941

4042
ExitCodeIfIssuesFound int
4143

4244
Errcheck struct {
43-
CheckClose bool
4445
CheckTypeAssertions bool
4546
CheckAssignToBlank bool
4647
}
@@ -83,6 +84,8 @@ type Run struct { // nolint:maligned
8384
EnableAllLinters bool
8485
DisableAllLinters bool
8586

87+
Presets []string
88+
8689
ExcludePatterns []string
8790
UseDefaultExcludes bool
8891

pkg/enabled_linters.go

Lines changed: 127 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,69 @@ package pkg
33
import (
44
"context"
55
"fmt"
6+
"strings"
67
"sync"
78

89
"github.com/golangci/golangci-lint/pkg/config"
910
"github.com/golangci/golangci-lint/pkg/golinters"
1011
"github.com/sirupsen/logrus"
1112
)
1213

14+
const (
15+
PresetFormatting = "format"
16+
PresetComplexity = "complexity"
17+
PresetStyle = "style"
18+
PresetBugs = "bugs"
19+
PresetUnused = "unused"
20+
PresetPerformance = "performance"
21+
)
22+
23+
func AllPresets() []string {
24+
return []string{PresetBugs, PresetUnused, PresetFormatting, PresetStyle, PresetComplexity, PresetPerformance}
25+
}
26+
27+
func allPresetsSet() map[string]bool {
28+
ret := map[string]bool{}
29+
for _, p := range AllPresets() {
30+
ret[p] = true
31+
}
32+
return ret
33+
}
34+
1335
type LinterConfig struct {
14-
Desc string
1536
Linter Linter
1637
EnabledByDefault bool
1738
DoesFullImport bool
1839
NeedsSSARepr bool
40+
InPresets []string
41+
}
42+
43+
func (lc LinterConfig) WithFullImport() LinterConfig {
44+
lc.DoesFullImport = true
45+
return lc
46+
}
47+
48+
func (lc LinterConfig) WithSSA() LinterConfig {
49+
lc.DoesFullImport = true
50+
lc.NeedsSSARepr = true
51+
return lc
52+
}
53+
54+
func (lc LinterConfig) WithPresets(presets ...string) LinterConfig {
55+
lc.InPresets = presets
56+
return lc
57+
}
58+
59+
func (lc LinterConfig) WithDisabledByDefault() LinterConfig {
60+
lc.EnabledByDefault = false
61+
return lc
62+
}
63+
64+
func newLinterConfig(linter Linter) LinterConfig {
65+
return LinterConfig{
66+
Linter: linter,
67+
EnabledByDefault: true,
68+
}
1969
}
2070

2171
var nameToLC map[string]LinterConfig
@@ -37,46 +87,26 @@ func GetLinterConfig(name string) *LinterConfig {
3787
return &lc
3888
}
3989

40-
func enabledByDefault(linter Linter, desc string, doesFullImport, needsSSARepr bool) LinterConfig {
41-
return LinterConfig{
42-
EnabledByDefault: true,
43-
Linter: linter,
44-
Desc: desc,
45-
DoesFullImport: doesFullImport,
46-
NeedsSSARepr: needsSSARepr,
47-
}
48-
}
49-
50-
func disabledByDefault(linter Linter, desc string, doesFullImport, needsSSARepr bool) LinterConfig {
51-
return LinterConfig{
52-
EnabledByDefault: false,
53-
Linter: linter,
54-
Desc: desc,
55-
DoesFullImport: doesFullImport,
56-
NeedsSSARepr: needsSSARepr,
57-
}
58-
}
59-
6090
func GetAllSupportedLinterConfigs() []LinterConfig {
6191
return []LinterConfig{
62-
enabledByDefault(golinters.Govet{}, "Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string", false, false),
63-
enabledByDefault(golinters.Errcheck{}, "Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases", true, false),
64-
enabledByDefault(golinters.Golint{}, "Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes", false, false),
65-
enabledByDefault(golinters.Megacheck{}, "Megacheck: 3 sub-linters in one: staticcheck, gosimple and unused", true, true),
66-
enabledByDefault(golinters.Gas{}, "Inspects source code for security problems", true, false),
67-
enabledByDefault(golinters.Structcheck{}, "Finds unused struct fields", true, false),
68-
enabledByDefault(golinters.Varcheck{}, "Finds unused global variables and constants", true, false),
69-
enabledByDefault(golinters.Interfacer{}, "Linter that suggests narrower interface types", true, true),
70-
enabledByDefault(golinters.Unconvert{}, "Remove unnecessary type conversions", true, false),
71-
enabledByDefault(golinters.Ineffassign{}, "Detects when assignments to existing variables are not used", false, false),
72-
enabledByDefault(golinters.Dupl{}, "Tool for code clone detection", false, false),
73-
enabledByDefault(golinters.Goconst{}, "Finds repeated strings that could be replaced by a constant", false, false),
74-
enabledByDefault(golinters.Deadcode{}, "Finds unused code", true, false),
75-
enabledByDefault(golinters.Gocyclo{}, "Computes and checks the cyclomatic complexity of functions", false, false),
76-
77-
disabledByDefault(golinters.Gofmt{}, "Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification", false, false),
78-
disabledByDefault(golinters.Gofmt{UseGoimports: true}, "Goimports does everything that gofmt does. Additionally it checks unused imports", false, false),
79-
disabledByDefault(golinters.Maligned{}, "Tool to detect Go structs that would take less memory if their fields were sorted", true, false),
92+
newLinterConfig(golinters.Govet{}).WithPresets(PresetBugs),
93+
newLinterConfig(golinters.Errcheck{}).WithFullImport().WithPresets(PresetBugs),
94+
newLinterConfig(golinters.Golint{}).WithDisabledByDefault().WithPresets(PresetStyle),
95+
newLinterConfig(golinters.Megacheck{}).WithSSA().WithPresets(PresetBugs, PresetUnused, PresetStyle),
96+
newLinterConfig(golinters.Gas{}).WithFullImport().WithPresets(PresetBugs),
97+
newLinterConfig(golinters.Structcheck{}).WithFullImport().WithPresets(PresetUnused),
98+
newLinterConfig(golinters.Varcheck{}).WithFullImport().WithPresets(PresetUnused),
99+
newLinterConfig(golinters.Interfacer{}).WithDisabledByDefault().WithSSA().WithPresets(PresetStyle),
100+
newLinterConfig(golinters.Unconvert{}).WithDisabledByDefault().WithFullImport().WithPresets(PresetStyle),
101+
newLinterConfig(golinters.Ineffassign{}).WithPresets(PresetUnused),
102+
newLinterConfig(golinters.Dupl{}).WithDisabledByDefault().WithPresets(PresetStyle),
103+
newLinterConfig(golinters.Goconst{}).WithDisabledByDefault().WithPresets(PresetStyle),
104+
newLinterConfig(golinters.Deadcode{}).WithFullImport().WithPresets(PresetUnused),
105+
newLinterConfig(golinters.Gocyclo{}).WithDisabledByDefault().WithPresets(PresetComplexity),
106+
107+
newLinterConfig(golinters.Gofmt{}).WithDisabledByDefault().WithPresets(PresetFormatting),
108+
newLinterConfig(golinters.Gofmt{UseGoimports: true}).WithDisabledByDefault().WithPresets(PresetFormatting),
109+
newLinterConfig(golinters.Maligned{}).WithFullImport().WithDisabledByDefault().WithPresets(PresetPerformance),
80110
}
81111
}
82112

@@ -132,6 +162,17 @@ func validateEnabledDisabledLintersConfig(cfg *config.Run) error {
132162
}
133163
}
134164

165+
allPresets := allPresetsSet()
166+
for _, p := range cfg.Presets {
167+
if !allPresets[p] {
168+
return fmt.Errorf("no such preset %q: only next presets exist: (%s)", p, strings.Join(AllPresets(), "|"))
169+
}
170+
}
171+
172+
if len(cfg.Presets) != 0 && cfg.EnableAllLinters {
173+
return fmt.Errorf("--presets is incompatible with --enable-all")
174+
}
175+
135176
if cfg.EnableAllLinters && cfg.DisableAllLinters {
136177
return fmt.Errorf("--enable-all and --disable-all options must not be combined")
137178
}
@@ -164,12 +205,29 @@ func validateEnabledDisabledLintersConfig(cfg *config.Run) error {
164205
return nil
165206
}
166207

208+
func GetAllLintersForPreset(p string) []Linter {
209+
ret := []Linter{}
210+
for _, lc := range GetAllSupportedLinterConfigs() {
211+
for _, ip := range lc.InPresets {
212+
if p == ip {
213+
ret = append(ret, lc.Linter)
214+
break
215+
}
216+
}
217+
}
218+
219+
return ret
220+
}
221+
167222
func GetEnabledLinters(ctx context.Context, cfg *config.Run) ([]Linter, error) {
168223
if err := validateEnabledDisabledLintersConfig(cfg); err != nil {
169224
return nil, err
170225
}
226+
171227
resultLintersSet := map[string]Linter{}
172228
switch {
229+
case len(cfg.Presets) != 0:
230+
break // imply --disable-all
173231
case cfg.EnableAllLinters:
174232
resultLintersSet = lintersToMap(getAllSupportedLinters())
175233
case cfg.DisableAllLinters:
@@ -182,6 +240,32 @@ func GetEnabledLinters(ctx context.Context, cfg *config.Run) ([]Linter, error) {
182240
resultLintersSet[name] = getLinterByName(name)
183241
}
184242

243+
// XXX: hacks because of sub-linters in megacheck
244+
megacheckWasEnabledByUser := resultLintersSet["megacheck"] != nil
245+
if !megacheckWasEnabledByUser {
246+
cfg.Megacheck.EnableGosimple = false
247+
cfg.Megacheck.EnableStaticcheck = false
248+
cfg.Megacheck.EnableUnused = false
249+
}
250+
251+
for _, p := range cfg.Presets {
252+
for _, linter := range GetAllLintersForPreset(p) {
253+
resultLintersSet[linter.Name()] = linter
254+
}
255+
256+
if !megacheckWasEnabledByUser {
257+
if p == PresetBugs {
258+
cfg.Megacheck.EnableStaticcheck = true
259+
}
260+
if p == PresetStyle {
261+
cfg.Megacheck.EnableGosimple = true
262+
}
263+
if p == PresetUnused {
264+
cfg.Megacheck.EnableUnused = true
265+
}
266+
}
267+
}
268+
185269
for _, name := range cfg.DisabledLinters {
186270
delete(resultLintersSet, name)
187271
}
@@ -192,7 +276,10 @@ func GetEnabledLinters(ctx context.Context, cfg *config.Run) ([]Linter, error) {
192276
resultLinters = append(resultLinters, linter)
193277
resultLinterNames = append(resultLinterNames, name)
194278
}
195-
logrus.Infof("Enabled linters: %s", resultLinterNames)
279+
logrus.Infof("Active linters: %s", resultLinterNames)
280+
if len(cfg.Presets) != 0 {
281+
logrus.Infof("Active presets: %s", cfg.Presets)
282+
}
196283

197284
return resultLinters, nil
198285
}

pkg/enabled_linters_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ func testOneSource(t *testing.T, sourcePath string) {
5656
"--print-issued-lines=false",
5757
"--print-linter-name=false",
5858
"--out-format=line-number",
59+
"--print-welcome=false",
60+
"--govet.check-shadowing=true",
5961
sourcePath)
6062
runGoErrchk(cmd, t)
6163
}

0 commit comments

Comments
 (0)