2020-10-29 15:11:52 +02:00
|
|
|
package config
|
2018-01-28 02:22:17 +02:00
|
|
|
|
|
|
|
import (
|
2020-10-29 15:11:52 +02:00
|
|
|
"errors"
|
2018-01-28 02:22:17 +02:00
|
|
|
"fmt"
|
2023-05-16 08:06:52 +02:00
|
|
|
"os"
|
2018-02-04 04:56:45 +02:00
|
|
|
|
2018-01-28 02:22:17 +02:00
|
|
|
"github.com/mgechev/revive/formatter"
|
|
|
|
|
2020-10-29 15:11:52 +02:00
|
|
|
"github.com/BurntSushi/toml"
|
2018-01-28 02:22:17 +02:00
|
|
|
"github.com/mgechev/revive/lint"
|
|
|
|
"github.com/mgechev/revive/rule"
|
|
|
|
)
|
|
|
|
|
|
|
|
var defaultRules = []lint.Rule{
|
|
|
|
&rule.VarDeclarationsRule{},
|
|
|
|
&rule.PackageCommentsRule{},
|
|
|
|
&rule.DotImportsRule{},
|
|
|
|
&rule.BlankImportsRule{},
|
|
|
|
&rule.ExportedRule{},
|
2018-05-27 06:28:31 +02:00
|
|
|
&rule.VarNamingRule{},
|
2018-05-27 01:14:36 +02:00
|
|
|
&rule.IndentErrorFlowRule{},
|
2018-01-28 02:22:17 +02:00
|
|
|
&rule.RangeRule{},
|
|
|
|
&rule.ErrorfRule{},
|
2018-05-27 06:28:31 +02:00
|
|
|
&rule.ErrorNamingRule{},
|
2018-01-28 02:22:17 +02:00
|
|
|
&rule.ErrorStringsRule{},
|
2018-05-27 06:28:31 +02:00
|
|
|
&rule.ReceiverNamingRule{},
|
2018-01-28 02:22:17 +02:00
|
|
|
&rule.IncrementDecrementRule{},
|
|
|
|
&rule.ErrorReturnRule{},
|
|
|
|
&rule.UnexportedReturnRule{},
|
2018-05-27 06:28:31 +02:00
|
|
|
&rule.TimeNamingRule{},
|
|
|
|
&rule.ContextKeysType{},
|
|
|
|
&rule.ContextAsArgumentRule{},
|
2023-03-15 01:17:36 +02:00
|
|
|
&rule.EmptyBlockRule{},
|
|
|
|
&rule.SuperfluousElseRule{},
|
|
|
|
&rule.UnusedParamRule{},
|
|
|
|
&rule.UnreachableCodeRule{},
|
|
|
|
&rule.RedefinesBuiltinIDRule{},
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var allRules = append([]lint.Rule{
|
|
|
|
&rule.ArgumentsLimitRule{},
|
|
|
|
&rule.CyclomaticRule{},
|
2018-05-27 06:28:31 +02:00
|
|
|
&rule.FileHeaderRule{},
|
2018-07-02 04:05:20 +02:00
|
|
|
&rule.ConfusingNamingRule{},
|
2018-06-22 13:21:09 +02:00
|
|
|
&rule.GetReturnRule{},
|
2018-06-24 09:26:21 +02:00
|
|
|
&rule.ModifiesParamRule{},
|
2018-07-02 04:09:58 +02:00
|
|
|
&rule.ConfusingResultsRule{},
|
2018-06-26 22:21:03 +02:00
|
|
|
&rule.DeepExitRule{},
|
2018-07-17 21:21:27 +02:00
|
|
|
&rule.AddConstantRule{},
|
2018-07-22 07:58:48 +02:00
|
|
|
&rule.FlagParamRule{},
|
2018-07-28 07:38:39 +02:00
|
|
|
&rule.UnnecessaryStmtRule{},
|
2018-07-28 18:07:31 +02:00
|
|
|
&rule.StructTagRule{},
|
2018-08-14 00:18:28 +02:00
|
|
|
&rule.ModifiesValRecRule{},
|
2018-08-23 20:45:10 +02:00
|
|
|
&rule.ConstantLogicalExprRule{},
|
2018-08-23 20:10:17 +02:00
|
|
|
&rule.BoolLiteralRule{},
|
2018-09-17 22:06:42 +02:00
|
|
|
&rule.ImportsBlacklistRule{},
|
2018-09-17 11:06:53 +02:00
|
|
|
&rule.FunctionResultsLimitRule{},
|
2018-09-18 17:19:25 +02:00
|
|
|
&rule.MaxPublicStructsRule{},
|
2018-09-29 05:32:32 +02:00
|
|
|
&rule.RangeValInClosureRule{},
|
2020-02-26 22:33:00 +02:00
|
|
|
&rule.RangeValAddress{},
|
2018-10-03 10:01:41 +02:00
|
|
|
&rule.WaitGroupByValueRule{},
|
2018-10-03 08:12:19 +02:00
|
|
|
&rule.AtomicRule{},
|
2018-10-11 23:52:46 +02:00
|
|
|
&rule.EmptyLinesRule{},
|
2018-10-19 14:18:33 +02:00
|
|
|
&rule.LineLengthLimitRule{},
|
2018-10-31 16:32:23 +02:00
|
|
|
&rule.CallToGCRule{},
|
2019-03-20 20:54:03 +02:00
|
|
|
&rule.DuplicatedImportsRule{},
|
2019-03-27 20:46:20 +02:00
|
|
|
&rule.ImportShadowingRule{},
|
2019-04-17 22:55:52 +02:00
|
|
|
&rule.BareReturnRule{},
|
2019-04-18 19:35:51 +02:00
|
|
|
&rule.UnusedReceiverRule{},
|
2019-04-28 04:23:17 +02:00
|
|
|
&rule.UnhandledErrorRule{},
|
2019-12-14 09:27:06 +02:00
|
|
|
&rule.CognitiveComplexityRule{},
|
2020-02-18 19:38:01 +02:00
|
|
|
&rule.StringOfIntRule{},
|
2021-04-18 18:35:30 +02:00
|
|
|
&rule.StringFormatRule{},
|
2020-05-08 20:14:21 +02:00
|
|
|
&rule.EarlyReturnRule{},
|
2020-05-09 17:10:34 +02:00
|
|
|
&rule.UnconditionalRecursionRule{},
|
2020-05-08 22:20:59 +02:00
|
|
|
&rule.IdenticalBranchesRule{},
|
2020-05-24 20:49:49 +02:00
|
|
|
&rule.DeferRule{},
|
2020-07-23 01:17:20 +02:00
|
|
|
&rule.UnexportedNamingRule{},
|
2021-03-21 00:45:30 +02:00
|
|
|
&rule.FunctionLength{},
|
2021-06-15 11:36:41 +02:00
|
|
|
&rule.NestedStructs{},
|
2021-08-16 00:30:08 +02:00
|
|
|
&rule.UselessBreak{},
|
2023-09-17 10:58:45 +02:00
|
|
|
&rule.UncheckedTypeAssertionRule{},
|
2021-10-03 15:35:13 +02:00
|
|
|
&rule.TimeEqualRule{},
|
2021-10-14 20:56:29 +02:00
|
|
|
&rule.BannedCharsRule{},
|
2021-10-23 09:29:14 +02:00
|
|
|
&rule.OptimizeOperandsOrderRule{},
|
2022-03-29 20:25:38 +02:00
|
|
|
&rule.UseAnyRule{},
|
2022-04-18 18:45:42 +02:00
|
|
|
&rule.DataRaceRule{},
|
2022-10-29 19:32:42 +02:00
|
|
|
&rule.CommentSpacingsRule{},
|
Drop if-return from default ruleset (#843)
The `if-return` rule was originally a golint rule which was removed
from their ruleset for being out of scope. Similarly, it was dropped
from revive intentionally as a result of #537. More recently, it was
reintroduced into the default ruleset as a result of #799 due to a
discrepancy in documentation without a discussion of whether this rule
in particular belonged as a part of that default rule set.
While it is no longer a goal of this project to align 100% with the
golint defaults, I believe that this rule gives bad advice often enough
that it should not be enabled by default.
For example, consider the following code:
```go
if err := func1(); err != nil {
return err
}
if err := func2(); err != nil {
return err
}
if err := func3(); err != nil {
return err
}
return nil
```
The `if-return` rule considers this a violation of style, and instead
suggests the following:
```go
if err := func1(); err != nil {
return err
}
if err := func2(); err != nil {
return err
}
return func3()
```
While this is more terse, it has a few shortcomings compared to the
original. In particular, it means extending the size of the diff if
changing the order of checks, adding logic after the call that currently
happens to be last, or choosing to wrap the error. And in that last
case, it can make it less obvious that there is an unwrapped error being
propagated up the call stack.
This in practice has a very similar effect to disabling trailing commas;
while it is not necessarily wrong as a style choice, I don't believe it
warrants a position as part of the default ruleset here.
See-also: https://github.com/golang/lint/issues/363
2023-06-26 18:43:19 +02:00
|
|
|
&rule.IfReturnRule{},
|
2023-07-31 08:22:40 +02:00
|
|
|
&rule.RedundantImportAlias{},
|
2023-08-28 15:26:00 +02:00
|
|
|
&rule.ImportAliasNamingRule{},
|
2023-09-17 11:22:11 +02:00
|
|
|
&rule.EnforceMapStyleRule{},
|
2018-01-28 02:22:17 +02:00
|
|
|
}, defaultRules...)
|
|
|
|
|
|
|
|
var allFormatters = []lint.Formatter{
|
2018-05-26 21:08:02 +02:00
|
|
|
&formatter.Stylish{},
|
2018-05-26 22:47:13 +02:00
|
|
|
&formatter.Friendly{},
|
2018-01-28 03:01:18 +02:00
|
|
|
&formatter.JSON{},
|
2018-07-14 00:01:27 +02:00
|
|
|
&formatter.NDJSON{},
|
2018-01-28 03:01:18 +02:00
|
|
|
&formatter.Default{},
|
2018-09-17 20:57:56 +02:00
|
|
|
&formatter.Unix{},
|
2018-07-15 21:45:15 +02:00
|
|
|
&formatter.Checkstyle{},
|
2018-10-31 01:07:32 +02:00
|
|
|
&formatter.Plain{},
|
2021-04-05 20:54:33 +02:00
|
|
|
&formatter.Sarif{},
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func getFormatters() map[string]lint.Formatter {
|
|
|
|
result := map[string]lint.Formatter{}
|
|
|
|
for _, f := range allFormatters {
|
|
|
|
result[f.Name()] = f
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-05-21 09:53:10 +02:00
|
|
|
// GetLintingRules yields the linting rules that must be applied by the linter
|
2022-03-20 10:12:51 +02:00
|
|
|
func GetLintingRules(config *lint.Config, extraRules []lint.Rule) ([]lint.Rule, error) {
|
2018-01-28 02:22:17 +02:00
|
|
|
rulesMap := map[string]lint.Rule{}
|
|
|
|
for _, r := range allRules {
|
|
|
|
rulesMap[r.Name()] = r
|
|
|
|
}
|
2022-03-20 10:12:51 +02:00
|
|
|
for _, r := range extraRules {
|
|
|
|
if _, ok := rulesMap[r.Name()]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
rulesMap[r.Name()] = r
|
|
|
|
}
|
2018-01-28 02:22:17 +02:00
|
|
|
|
2021-10-14 20:56:29 +02:00
|
|
|
var lintingRules []lint.Rule
|
2021-05-21 09:53:10 +02:00
|
|
|
for name, ruleConfig := range config.Rules {
|
2022-04-10 11:55:13 +02:00
|
|
|
r, ok := rulesMap[name]
|
2018-01-28 02:22:17 +02:00
|
|
|
if !ok {
|
2020-10-29 15:11:52 +02:00
|
|
|
return nil, fmt.Errorf("cannot find rule: %s", name)
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
2021-05-21 09:53:10 +02:00
|
|
|
|
|
|
|
if ruleConfig.Disabled {
|
|
|
|
continue // skip disabled rules
|
|
|
|
}
|
|
|
|
|
2022-04-10 11:55:13 +02:00
|
|
|
lintingRules = append(lintingRules, r)
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
|
|
|
|
2020-10-29 15:11:52 +02:00
|
|
|
return lintingRules, nil
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
|
|
|
|
2021-10-03 15:32:16 +02:00
|
|
|
func parseConfig(path string, config *lint.Config) error {
|
2023-05-16 08:06:52 +02:00
|
|
|
file, err := os.ReadFile(path)
|
2018-01-28 02:22:17 +02:00
|
|
|
if err != nil {
|
2021-10-03 15:32:16 +02:00
|
|
|
return errors.New("cannot read the config file")
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
2020-10-29 15:11:52 +02:00
|
|
|
_, err = toml.Decode(string(file), config)
|
2018-01-28 02:22:17 +02:00
|
|
|
if err != nil {
|
2021-10-03 15:32:16 +02:00
|
|
|
return fmt.Errorf("cannot parse the config file: %v", err)
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
2023-08-12 08:21:11 +02:00
|
|
|
for k, r := range config.Rules {
|
|
|
|
err := r.Initialize()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error in config of rule [%s] : [%v]", k, err)
|
|
|
|
}
|
|
|
|
config.Rules[k] = r
|
|
|
|
}
|
|
|
|
|
2021-10-03 15:32:16 +02:00
|
|
|
return nil
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func normalizeConfig(config *lint.Config) {
|
2021-09-30 22:37:44 +02:00
|
|
|
if len(config.Rules) == 0 {
|
|
|
|
config.Rules = map[string]lint.RuleConfig{}
|
2018-01-28 03:01:18 +02:00
|
|
|
}
|
2021-09-30 22:37:44 +02:00
|
|
|
if config.EnableAllRules {
|
|
|
|
// Add to the configuration all rules not yet present in it
|
2022-04-10 11:55:13 +02:00
|
|
|
for _, r := range allRules {
|
|
|
|
ruleName := r.Name()
|
2021-09-30 22:37:44 +02:00
|
|
|
_, alreadyInConf := config.Rules[ruleName]
|
|
|
|
if alreadyInConf {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// Add the rule with an empty conf for
|
|
|
|
config.Rules[ruleName] = lint.RuleConfig{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-28 02:22:17 +02:00
|
|
|
severity := config.Severity
|
|
|
|
if severity != "" {
|
|
|
|
for k, v := range config.Rules {
|
|
|
|
if v.Severity == "" {
|
|
|
|
v.Severity = severity
|
|
|
|
}
|
|
|
|
config.Rules[k] = v
|
|
|
|
}
|
2019-08-02 17:21:33 +02:00
|
|
|
for k, v := range config.Directives {
|
|
|
|
if v.Severity == "" {
|
|
|
|
v.Severity = severity
|
|
|
|
}
|
|
|
|
config.Directives[k] = v
|
|
|
|
}
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-03 15:32:16 +02:00
|
|
|
const defaultConfidence = 0.8
|
|
|
|
|
2020-10-29 15:11:52 +02:00
|
|
|
// GetConfig yields the configuration
|
|
|
|
func GetConfig(configPath string) (*lint.Config, error) {
|
2022-03-02 09:24:55 +02:00
|
|
|
config := &lint.Config{}
|
2021-10-03 15:32:16 +02:00
|
|
|
switch {
|
|
|
|
case configPath != "":
|
|
|
|
config.Confidence = defaultConfidence
|
|
|
|
err := parseConfig(configPath, config)
|
2020-10-29 15:11:52 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-10-03 15:32:16 +02:00
|
|
|
|
|
|
|
default: // no configuration provided
|
|
|
|
config = defaultConfig()
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
2021-10-03 15:32:16 +02:00
|
|
|
|
2018-01-28 02:22:17 +02:00
|
|
|
normalizeConfig(config)
|
2020-10-29 15:11:52 +02:00
|
|
|
return config, nil
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
|
|
|
|
2020-10-29 15:11:52 +02:00
|
|
|
// GetFormatter yields the formatter for lint failures
|
|
|
|
func GetFormatter(formatterName string) (lint.Formatter, error) {
|
2018-01-28 02:22:17 +02:00
|
|
|
formatters := getFormatters()
|
2022-04-10 11:55:13 +02:00
|
|
|
fmtr := formatters["default"]
|
2018-01-28 02:22:17 +02:00
|
|
|
if formatterName != "" {
|
|
|
|
f, ok := formatters[formatterName]
|
|
|
|
if !ok {
|
2020-10-29 15:11:52 +02:00
|
|
|
return nil, fmt.Errorf("unknown formatter %v", formatterName)
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
2022-04-10 11:55:13 +02:00
|
|
|
fmtr = f
|
2018-01-28 02:22:17 +02:00
|
|
|
}
|
2022-04-10 11:55:13 +02:00
|
|
|
return fmtr, nil
|
2019-09-17 17:38:25 +02:00
|
|
|
}
|
|
|
|
|
2018-01-28 02:22:17 +02:00
|
|
|
func defaultConfig() *lint.Config {
|
|
|
|
defaultConfig := lint.Config{
|
2021-10-03 15:32:16 +02:00
|
|
|
Confidence: defaultConfidence,
|
2018-01-28 02:22:17 +02:00
|
|
|
Severity: lint.SeverityWarning,
|
|
|
|
Rules: map[string]lint.RuleConfig{},
|
|
|
|
}
|
|
|
|
for _, r := range defaultRules {
|
|
|
|
defaultConfig.Rules[r.Name()] = lint.RuleConfig{}
|
|
|
|
}
|
|
|
|
return &defaultConfig
|
|
|
|
}
|