Skip to content

Commit 3e9b681

Browse files
committed
fix #370: fix go-critic configuration broken in v1.13
1 parent af080e7 commit 3e9b681

File tree

4 files changed

+106
-4
lines changed

4 files changed

+106
-4
lines changed

pkg/config/config_gocritic.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,11 @@ func (s *GocriticSettings) validateCheckerNames() error {
295295

296296
return nil
297297
}
298+
299+
func (s *GocriticSettings) GetLowercasedParams() map[string]GocriticCheckSettings {
300+
ret := map[string]GocriticCheckSettings{}
301+
for checker, params := range s.SettingsPerCheck {
302+
ret[strings.ToLower(checker)] = params
303+
}
304+
return ret
305+
}

pkg/golinters/gocritic.go

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ import (
88
"path/filepath"
99
"runtime"
1010
"runtime/debug"
11+
"sort"
12+
"strings"
1113
"sync"
1214

15+
"github.com/golangci/golangci-lint/pkg/config"
16+
1317
"github.com/go-lintpack/lintpack"
1418
"golang.org/x/tools/go/loader"
1519

@@ -27,22 +31,79 @@ func (Gocritic) Desc() string {
2731
return "The most opinionated Go source code linter"
2832
}
2933

30-
func (lint Gocritic) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
31-
sizes := types.SizesFor("gc", runtime.GOARCH)
32-
lintpackCtx := lintpack.NewContext(lintCtx.Program.Fset, sizes)
34+
func (Gocritic) normalizeCheckerInfoParams(info *lintpack.CheckerInfo) lintpack.CheckerParams {
35+
// lowercase info param keys here because golangci-lint's config parser lowercases all strings
36+
ret := lintpack.CheckerParams{}
37+
for k, v := range info.Params {
38+
ret[strings.ToLower(k)] = v
39+
}
40+
41+
return ret
42+
}
43+
44+
func (lint Gocritic) configureCheckerInfo(info *lintpack.CheckerInfo, allParams map[string]config.GocriticCheckSettings) error {
45+
params := allParams[strings.ToLower(info.Name)]
46+
if params == nil { // no config for this checker
47+
return nil
48+
}
49+
50+
infoParams := lint.normalizeCheckerInfoParams(info)
51+
for k, p := range params {
52+
v, ok := infoParams[k]
53+
if ok {
54+
v.Value = p
55+
continue
56+
}
57+
58+
// param `k` isn't supported
59+
if len(info.Params) == 0 {
60+
return fmt.Errorf("checker %s config param %s doesn't exist: checker doesn't have params",
61+
info.Name, k)
62+
}
63+
64+
var supportedKeys []string
65+
for sk := range info.Params {
66+
supportedKeys = append(supportedKeys, sk)
67+
}
68+
sort.Strings(supportedKeys)
69+
70+
return fmt.Errorf("checker %s config param %s doesn't exist, all existing: %s",
71+
info.Name, k, supportedKeys)
72+
}
73+
74+
return nil
75+
}
3376

77+
func (lint Gocritic) buildEnabledCheckers(lintCtx *linter.Context, lintpackCtx *lintpack.Context) ([]*lintpack.Checker, error) {
3478
s := lintCtx.Settings().Gocritic
79+
allParams := s.GetLowercasedParams()
3580

3681
var enabledCheckers []*lintpack.Checker
3782
for _, info := range lintpack.GetCheckersInfo() {
3883
if !s.IsCheckEnabled(info.Name) {
3984
continue
4085
}
4186

87+
if err := lint.configureCheckerInfo(info, allParams); err != nil {
88+
return nil, err
89+
}
90+
4291
c := lintpack.NewChecker(lintpackCtx, info)
4392
enabledCheckers = append(enabledCheckers, c)
4493
}
4594

95+
return enabledCheckers, nil
96+
}
97+
98+
func (lint Gocritic) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
99+
sizes := types.SizesFor("gc", runtime.GOARCH)
100+
lintpackCtx := lintpack.NewContext(lintCtx.Program.Fset, sizes)
101+
102+
enabledCheckers, err := lint.buildEnabledCheckers(lintCtx, lintpackCtx)
103+
if err != nil {
104+
return nil, err
105+
}
106+
46107
issuesCh := make(chan result.Issue, 1024)
47108
var panicErr error
48109
go func() {

test/testdata/configs/gocritic.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
linters-settings:
2+
gocritic:
3+
enabled-checks:
4+
- rangeValCopy
5+
- flagDeref
6+
settings:
7+
rangevalcopy:
8+
sizethreshold: 2

test/testdata/gocritic.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
11
//args: -Egocritic
2+
//config_path: testdata/configs/gocritic.yml
23
package testdata
34

4-
import "flag"
5+
import (
6+
"flag"
7+
"log"
8+
)
59

610
var _ = *flag.Bool("global1", false, "") // ERROR "flagDeref: immediate deref in \*flag.Bool\(.global1., false, ..\) is most likely an error; consider using flag\.BoolVar"
11+
12+
type size1 struct {
13+
a bool
14+
}
15+
16+
type size2 struct {
17+
size1
18+
b bool
19+
}
20+
21+
func gocriticRangeValCopySize1(ss []size1) {
22+
for _, s := range ss {
23+
log.Print(s)
24+
}
25+
}
26+
27+
func gocriticRangeValCopySize2(ss []size2) {
28+
for _, s := range ss { // ERROR "rangeValCopy: each iteration copies 2 bytes.*"
29+
log.Print(s)
30+
}
31+
}

0 commit comments

Comments
 (0)