Skip to content

Commit 4b3fb4c

Browse files
authored
revive: fix types and default configuration. (#1747)
1 parent 32e8517 commit 4b3fb4c

File tree

3 files changed

+123
-24
lines changed

3 files changed

+123
-24
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.13
44

55
require (
66
4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a
7+
github.com/BurntSushi/toml v0.3.1
78
github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5
89
github.com/OpenPeeDeeP/depguard v1.0.1
910
github.com/alexkohler/prealloc v0.0.0-20210204145425-77a5b5dd9799

pkg/golinters/revive.go

Lines changed: 110 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package golinters
22

33
import (
4+
"bytes"
45
"encoding/json"
56
"fmt"
67
"go/token"
78
"io/ioutil"
89

10+
"github.com/BurntSushi/toml"
911
"github.com/mgechev/dots"
1012
reviveConfig "github.com/mgechev/revive/config"
1113
"github.com/mgechev/revive/lint"
14+
"github.com/mgechev/revive/rule"
1215
"golang.org/x/tools/go/analysis"
1316

1417
"github.com/golangci/golangci-lint/pkg/config"
@@ -47,7 +50,7 @@ func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter {
4750
files = append(files, pass.Fset.PositionFor(file.Pos(), false).Filename)
4851
}
4952

50-
conf, err := setReviveConfig(cfg)
53+
conf, err := getReviveConfig(cfg)
5154
if err != nil {
5255
return nil, err
5356
}
@@ -128,46 +131,129 @@ func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter {
128131
}).WithLoadMode(goanalysis.LoadModeSyntax)
129132
}
130133

131-
func setReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) {
132-
// Get revive default configuration
133-
conf, err := reviveConfig.GetConfig("")
134+
// This function mimics the GetConfig function of revive.
135+
// This allow to get default values and right types.
136+
// https://github.com/golangci/golangci-lint/issues/1745
137+
// https://github.com/mgechev/revive/blob/389ba853b0b3587f0c3b71b5f0c61ea4e23928ec/config/config.go#L155
138+
func getReviveConfig(cfg *config.ReviveSettings) (*lint.Config, error) {
139+
rawRoot := createConfigMap(cfg)
140+
141+
buf := bytes.NewBuffer(nil)
142+
143+
err := toml.NewEncoder(buf).Encode(rawRoot)
134144
if err != nil {
135145
return nil, err
136146
}
137147

138-
// Default is false
139-
conf.IgnoreGeneratedHeader = cfg.IgnoreGeneratedHeader
148+
conf := defaultConfig()
140149

141-
if cfg.Severity != "" {
142-
conf.Severity = lint.Severity(cfg.Severity)
150+
_, err = toml.DecodeReader(buf, conf)
151+
if err != nil {
152+
return nil, err
143153
}
144154

145-
if cfg.Confidence != 0 {
146-
conf.Confidence = cfg.Confidence
147-
}
155+
normalizeConfig(conf)
148156

149157
// By default golangci-lint ignores missing doc comments, follow same convention by removing this default rule
150158
// Relevant issue: https://github.com/golangci/golangci-lint/issues/456
159+
delete(conf.Rules, "package-comments")
151160
delete(conf.Rules, "exported")
152161

153-
if len(cfg.Rules) != 0 {
154-
// Clear default rules, only use rules defined in config
155-
conf.Rules = make(map[string]lint.RuleConfig, len(cfg.Rules))
162+
return conf, nil
163+
}
164+
165+
func createConfigMap(cfg *config.ReviveSettings) map[string]interface{} {
166+
rawRoot := map[string]interface{}{
167+
"ignoreGeneratedHeader": cfg.IgnoreGeneratedHeader,
168+
"confidence": cfg.Confidence,
169+
"severity": cfg.Severity,
170+
"errorCode": cfg.ErrorCode,
171+
"warningCode": cfg.WarningCode,
156172
}
157-
for _, r := range cfg.Rules {
158-
conf.Rules[r.Name] = lint.RuleConfig{Arguments: r.Arguments, Severity: lint.Severity(r.Severity)}
173+
174+
rawDirectives := map[string]map[string]interface{}{}
175+
for _, directive := range cfg.Directives {
176+
rawDirectives[directive.Name] = map[string]interface{}{
177+
"severity": directive.Severity,
178+
}
159179
}
160180

161-
conf.ErrorCode = cfg.ErrorCode
162-
conf.WarningCode = cfg.WarningCode
181+
if len(rawDirectives) > 0 {
182+
rawRoot["directive"] = rawDirectives
183+
}
163184

164-
if len(cfg.Directives) != 0 {
165-
// Clear default Directives, only use Directives defined in config
166-
conf.Directives = make(map[string]lint.DirectiveConfig, len(cfg.Directives))
185+
rawRules := map[string]map[string]interface{}{}
186+
for _, s := range cfg.Rules {
187+
rawRules[s.Name] = map[string]interface{}{
188+
"severity": s.Severity,
189+
"arguments": s.Arguments,
190+
}
167191
}
168-
for _, d := range cfg.Directives {
169-
conf.Directives[d.Name] = lint.DirectiveConfig{Severity: lint.Severity(d.Severity)}
192+
193+
if len(rawRules) > 0 {
194+
rawRoot["rule"] = rawRules
170195
}
171196

172-
return conf, nil
197+
return rawRoot
198+
}
199+
200+
// This element is not exported by revive, so we need copy the code.
201+
// Extracted from https://github.com/mgechev/revive/blob/389ba853b0b3587f0c3b71b5f0c61ea4e23928ec/config/config.go#L15
202+
var defaultRules = []lint.Rule{
203+
&rule.VarDeclarationsRule{},
204+
&rule.PackageCommentsRule{},
205+
&rule.DotImportsRule{},
206+
&rule.BlankImportsRule{},
207+
&rule.ExportedRule{},
208+
&rule.VarNamingRule{},
209+
&rule.IndentErrorFlowRule{},
210+
&rule.IfReturnRule{},
211+
&rule.RangeRule{},
212+
&rule.ErrorfRule{},
213+
&rule.ErrorNamingRule{},
214+
&rule.ErrorStringsRule{},
215+
&rule.ReceiverNamingRule{},
216+
&rule.IncrementDecrementRule{},
217+
&rule.ErrorReturnRule{},
218+
&rule.UnexportedReturnRule{},
219+
&rule.TimeNamingRule{},
220+
&rule.ContextKeysType{},
221+
&rule.ContextAsArgumentRule{},
222+
}
223+
224+
// This element is not exported by revive, so we need copy the code.
225+
// Extracted from https://github.com/mgechev/revive/blob/389ba853b0b3587f0c3b71b5f0c61ea4e23928ec/config/config.go#L133
226+
func normalizeConfig(cfg *lint.Config) {
227+
if cfg.Confidence == 0 {
228+
cfg.Confidence = 0.8
229+
}
230+
severity := cfg.Severity
231+
if severity != "" {
232+
for k, v := range cfg.Rules {
233+
if v.Severity == "" {
234+
v.Severity = severity
235+
}
236+
cfg.Rules[k] = v
237+
}
238+
for k, v := range cfg.Directives {
239+
if v.Severity == "" {
240+
v.Severity = severity
241+
}
242+
cfg.Directives[k] = v
243+
}
244+
}
245+
}
246+
247+
// This element is not exported by revive, so we need copy the code.
248+
// Extracted from https://github.com/mgechev/revive/blob/389ba853b0b3587f0c3b71b5f0c61ea4e23928ec/config/config.go#L182
249+
func defaultConfig() *lint.Config {
250+
defaultConfig := lint.Config{
251+
Confidence: 0.0,
252+
Severity: lint.SeverityWarning,
253+
Rules: map[string]lint.RuleConfig{},
254+
}
255+
for _, r := range defaultRules {
256+
defaultConfig.Rules[r.Name()] = lint.RuleConfig{}
257+
}
258+
return &defaultConfig
173259
}

test/testdata/configs/revive.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,15 @@ linters-settings:
55
rules:
66
- name: indent-error-flow
77
severity: warning
8+
- name: cognitive-complexity
9+
arguments: [ 7 ]
10+
- name: line-length-limit
11+
arguments: [ 110 ]
12+
- name: function-result-limit
13+
arguments: [ 3 ]
14+
- name: argument-limit
15+
arguments: [ 4 ]
16+
- name: cyclomatic
17+
arguments: [ 10 ]
18+
- name: max-public-structs
19+
arguments: [ 3 ]

0 commit comments

Comments
 (0)