5
5
"fmt"
6
6
"go/ast"
7
7
"go/types"
8
- "maps"
9
- "reflect"
10
8
"runtime"
11
9
"slices"
12
10
"strings"
@@ -19,7 +17,6 @@ import (
19
17
20
18
"github.com/golangci/golangci-lint/v2/pkg/config"
21
19
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
22
- "github.com/golangci/golangci-lint/v2/pkg/golinters/internal"
23
20
"github.com/golangci/golangci-lint/v2/pkg/lint/linter"
24
21
"github.com/golangci/golangci-lint/v2/pkg/logutils"
25
22
)
31
28
isDebug = logutils .HaveDebugTag (logutils .DebugKeyGoCritic )
32
29
)
33
30
34
- func New (settings * config.GoCriticSettings ) * goanalysis.Linter {
31
+ func New (settings * config.GoCriticSettings , replacer * strings. Replacer ) * goanalysis.Linter {
35
32
wrapper := & goCriticWrapper {
36
33
sizes : types .SizesFor ("gc" , runtime .GOARCH ),
37
34
}
@@ -58,23 +55,18 @@ Dynamic rules are written declaratively with AST patterns, filters, report messa
58
55
nil ,
59
56
).
60
57
WithContextSetter (func (context * linter.Context ) {
61
- wrapper .replacer = strings .NewReplacer (
62
- internal .PlaceholderBasePath , context .Cfg .GetBasePath (),
63
- )
64
-
65
- wrapper .init (context .Log , settings )
58
+ wrapper .init (context .Log , settings , replacer )
66
59
}).
67
60
WithLoadMode (goanalysis .LoadModeTypesInfo )
68
61
}
69
62
70
63
type goCriticWrapper struct {
71
64
settingsWrapper * settingsWrapper
72
- replacer * strings.Replacer
73
65
sizes types.Sizes
74
66
once sync.Once
75
67
}
76
68
77
- func (w * goCriticWrapper ) init (logger logutils.Log , settings * config.GoCriticSettings ) {
69
+ func (w * goCriticWrapper ) init (logger logutils.Log , settings * config.GoCriticSettings , replacer * strings. Replacer ) {
78
70
if settings == nil {
79
71
return
80
72
}
@@ -86,12 +78,9 @@ func (w *goCriticWrapper) init(logger logutils.Log, settings *config.GoCriticSet
86
78
}
87
79
})
88
80
89
- settingsWrapper := newSettingsWrapper (settings , logger )
90
- settingsWrapper .InferEnabledChecks ()
81
+ settingsWrapper := newSettingsWrapper (logger , settings , replacer )
91
82
92
- // Validate must be after InferEnabledChecks, not before.
93
- // Because it uses gathered information about tags set and finally enabled checks.
94
- if err := settingsWrapper .Validate (); err != nil {
83
+ if err := settingsWrapper .Load (); err != nil {
95
84
logger .Fatalf ("%s: invalid settings: %s" , linterName , err )
96
85
}
97
86
@@ -140,7 +129,8 @@ func (w *goCriticWrapper) buildEnabledCheckers(linterCtx *gocriticlinter.Context
140
129
continue
141
130
}
142
131
143
- if err := w .configureCheckerInfo (info , allLowerCasedParams ); err != nil {
132
+ err := w .settingsWrapper .setCheckerParams (info , allLowerCasedParams )
133
+ if err != nil {
144
134
return nil , err
145
135
}
146
136
@@ -155,59 +145,6 @@ func (w *goCriticWrapper) buildEnabledCheckers(linterCtx *gocriticlinter.Context
155
145
return enabledCheckers , nil
156
146
}
157
147
158
- func (w * goCriticWrapper ) configureCheckerInfo (
159
- info * gocriticlinter.CheckerInfo ,
160
- allLowerCasedParams map [string ]config.GoCriticCheckSettings ,
161
- ) error {
162
- params := allLowerCasedParams [strings .ToLower (info .Name )]
163
- if params == nil { // no config for this checker
164
- return nil
165
- }
166
-
167
- // To lowercase info param keys here because golangci-lint's config parser lowercases all strings.
168
- infoParams := normalizeMap (info .Params )
169
- for k , p := range params {
170
- v , ok := infoParams [k ]
171
- if ok {
172
- v .Value = w .normalizeCheckerParamsValue (p )
173
- continue
174
- }
175
-
176
- // param `k` isn't supported
177
- if len (info .Params ) == 0 {
178
- return fmt .Errorf ("checker %s config param %s doesn't exist: checker doesn't have params" ,
179
- info .Name , k )
180
- }
181
-
182
- supportedKeys := slices .Sorted (maps .Keys (info .Params ))
183
-
184
- return fmt .Errorf ("checker %s config param %s doesn't exist, all existing: %s" ,
185
- info .Name , k , supportedKeys )
186
- }
187
-
188
- return nil
189
- }
190
-
191
- // normalizeCheckerParamsValue normalizes value types.
192
- // go-critic asserts that CheckerParam.Value has some specific types,
193
- // but the file parsers (TOML, YAML, JSON) don't create the same representation for raw type.
194
- // then we have to convert value types into the expected value types.
195
- // Maybe in the future, this kind of conversion will be done in go-critic itself.
196
- func (w * goCriticWrapper ) normalizeCheckerParamsValue (p any ) any {
197
- rv := reflect .ValueOf (p )
198
- switch rv .Type ().Kind () {
199
- case reflect .Int64 , reflect .Int32 , reflect .Int16 , reflect .Int8 , reflect .Int :
200
- return int (rv .Int ())
201
- case reflect .Bool :
202
- return rv .Bool ()
203
- case reflect .String :
204
- // Perform variable substitution.
205
- return w .replacer .Replace (rv .String ())
206
- default :
207
- return p
208
- }
209
- }
210
-
211
148
func runOnFile (pass * analysis.Pass , f * ast.File , checks []* gocriticlinter.Checker ) {
212
149
for _ , c := range checks {
213
150
// All checkers are expected to use *lint.Context
@@ -233,19 +170,3 @@ func runOnFile(pass *analysis.Pass, f *ast.File, checks []*gocriticlinter.Checke
233
170
}
234
171
}
235
172
}
236
-
237
- func normalizeMap [ValueT any ](in map [string ]ValueT ) map [string ]ValueT {
238
- ret := make (map [string ]ValueT , len (in ))
239
- for k , v := range in {
240
- ret [strings .ToLower (k )] = v
241
- }
242
- return ret
243
- }
244
-
245
- func isEnabledByDefaultGoCriticChecker (info * gocriticlinter.CheckerInfo ) bool {
246
- // https://github.com/go-critic/go-critic/blob/5b67cfd487ae9fe058b4b19321901b3131810f65/cmd/gocritic/check.go#L342-L345
247
- return ! info .HasTag (gocriticlinter .ExperimentalTag ) &&
248
- ! info .HasTag (gocriticlinter .OpinionatedTag ) &&
249
- ! info .HasTag (gocriticlinter .PerformanceTag ) &&
250
- ! info .HasTag (gocriticlinter .SecurityTag )
251
- }
0 commit comments