github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io/ioutil"
     7  
     8  	"github.com/mgechev/revive/formatter"
     9  
    10  	"github.com/BurntSushi/toml"
    11  	"github.com/mgechev/revive/lint"
    12  	"github.com/mgechev/revive/rule"
    13  )
    14  
    15  var defaultRules = []lint.Rule{
    16  	&rule.VarDeclarationsRule{},
    17  	&rule.PackageCommentsRule{},
    18  	&rule.DotImportsRule{},
    19  	&rule.BlankImportsRule{},
    20  	&rule.ExportedRule{},
    21  	&rule.VarNamingRule{},
    22  	&rule.IndentErrorFlowRule{},
    23  	&rule.IfReturnRule{},
    24  	&rule.RangeRule{},
    25  	&rule.ErrorfRule{},
    26  	&rule.ErrorNamingRule{},
    27  	&rule.ErrorStringsRule{},
    28  	&rule.ReceiverNamingRule{},
    29  	&rule.IncrementDecrementRule{},
    30  	&rule.ErrorReturnRule{},
    31  	&rule.UnexportedReturnRule{},
    32  	&rule.TimeNamingRule{},
    33  	&rule.ContextKeysType{},
    34  	&rule.ContextAsArgumentRule{},
    35  }
    36  
    37  var allRules = append([]lint.Rule{
    38  	&rule.ArgumentsLimitRule{},
    39  	&rule.CyclomaticRule{},
    40  	&rule.FileHeaderRule{},
    41  	&rule.EmptyBlockRule{},
    42  	&rule.SuperfluousElseRule{},
    43  	&rule.ConfusingNamingRule{},
    44  	&rule.GetReturnRule{},
    45  	&rule.ModifiesParamRule{},
    46  	&rule.ConfusingResultsRule{},
    47  	&rule.DeepExitRule{},
    48  	&rule.UnusedParamRule{},
    49  	&rule.UnreachableCodeRule{},
    50  	&rule.AddConstantRule{},
    51  	&rule.FlagParamRule{},
    52  	&rule.UnnecessaryStmtRule{},
    53  	&rule.StructTagRule{},
    54  	&rule.ModifiesValRecRule{},
    55  	&rule.ConstantLogicalExprRule{},
    56  	&rule.BoolLiteralRule{},
    57  	&rule.RedefinesBuiltinIDRule{},
    58  	&rule.ImportsBlacklistRule{},
    59  	&rule.FunctionResultsLimitRule{},
    60  	&rule.MaxPublicStructsRule{},
    61  	&rule.RangeValInClosureRule{},
    62  	&rule.RangeValAddress{},
    63  	&rule.WaitGroupByValueRule{},
    64  	&rule.AtomicRule{},
    65  	&rule.EmptyLinesRule{},
    66  	&rule.LineLengthLimitRule{},
    67  	&rule.CallToGCRule{},
    68  	&rule.DuplicatedImportsRule{},
    69  	&rule.ImportShadowingRule{},
    70  	&rule.BareReturnRule{},
    71  	&rule.UnusedReceiverRule{},
    72  	&rule.UnhandledErrorRule{},
    73  	&rule.CognitiveComplexityRule{},
    74  	&rule.StringOfIntRule{},
    75  	&rule.StringFormatRule{},
    76  	&rule.EarlyReturnRule{},
    77  	&rule.UnconditionalRecursionRule{},
    78  	&rule.IdenticalBranchesRule{},
    79  	&rule.DeferRule{},
    80  	&rule.UnexportedNamingRule{},
    81  	&rule.FunctionLength{},
    82  	&rule.NestedStructs{},
    83  	&rule.ForbidImportsRule{},
    84  }, defaultRules...)
    85  
    86  var allFormatters = []lint.Formatter{
    87  	&formatter.Stylish{},
    88  	&formatter.Friendly{},
    89  	&formatter.JSON{},
    90  	&formatter.NDJSON{},
    91  	&formatter.Default{},
    92  	&formatter.Unix{},
    93  	&formatter.Checkstyle{},
    94  	&formatter.Plain{},
    95  	&formatter.Sarif{},
    96  }
    97  
    98  func getFormatters() map[string]lint.Formatter {
    99  	result := map[string]lint.Formatter{}
   100  	for _, f := range allFormatters {
   101  		result[f.Name()] = f
   102  	}
   103  	return result
   104  }
   105  
   106  // GetLintingRules yields the linting rules that must be applied by the linter
   107  func GetLintingRules(config *lint.Config) ([]lint.Rule, error) {
   108  	if config.EnableAllRules {
   109  		return getAllRules(config)
   110  	}
   111  
   112  	return getEnabledRules(config)
   113  }
   114  
   115  // getAllRules yields the list of all available rules except those disabled by configuration
   116  func getAllRules(config *lint.Config) ([]lint.Rule, error) {
   117  	lintingRules := []lint.Rule{}
   118  	for _, r := range allRules {
   119  		ruleConf := config.Rules[r.Name()]
   120  		if ruleConf.Disabled {
   121  			continue // skip disabled rules
   122  		}
   123  
   124  		lintingRules = append(lintingRules, r)
   125  	}
   126  
   127  	return lintingRules, nil
   128  }
   129  
   130  // getEnabledRules yields the list of rules that are enabled by configuration
   131  func getEnabledRules(config *lint.Config) ([]lint.Rule, error) {
   132  	rulesMap := map[string]lint.Rule{}
   133  	for _, r := range allRules {
   134  		rulesMap[r.Name()] = r
   135  	}
   136  
   137  	lintingRules := []lint.Rule{}
   138  	for name, ruleConfig := range config.Rules {
   139  		rule, ok := rulesMap[name]
   140  		if !ok {
   141  			return nil, fmt.Errorf("cannot find rule: %s", name)
   142  		}
   143  
   144  		if ruleConfig.Disabled {
   145  			continue // skip disabled rules
   146  		}
   147  
   148  		lintingRules = append(lintingRules, rule)
   149  	}
   150  
   151  	return lintingRules, nil
   152  }
   153  
   154  func parseConfig(path string) (*lint.Config, error) {
   155  	config := &lint.Config{}
   156  	file, err := ioutil.ReadFile(path)
   157  	if err != nil {
   158  		return nil, errors.New("cannot read the config file")
   159  	}
   160  	_, err = toml.Decode(string(file), config)
   161  	if err != nil {
   162  		return nil, fmt.Errorf("cannot parse the config file: %v", err)
   163  	}
   164  	return config, nil
   165  }
   166  
   167  func normalizeConfig(config *lint.Config) {
   168  	if config.Confidence == 0 {
   169  		config.Confidence = 0.8
   170  	}
   171  	severity := config.Severity
   172  	if severity != "" {
   173  		for k, v := range config.Rules {
   174  			if v.Severity == "" {
   175  				v.Severity = severity
   176  			}
   177  			config.Rules[k] = v
   178  		}
   179  		for k, v := range config.Directives {
   180  			if v.Severity == "" {
   181  				v.Severity = severity
   182  			}
   183  			config.Directives[k] = v
   184  		}
   185  	}
   186  }
   187  
   188  // GetConfig yields the configuration
   189  func GetConfig(configPath string) (*lint.Config, error) {
   190  	config := defaultConfig()
   191  	if configPath != "" {
   192  		var err error
   193  		config, err = parseConfig(configPath)
   194  		if err != nil {
   195  			return nil, err
   196  		}
   197  	}
   198  	normalizeConfig(config)
   199  	return config, nil
   200  }
   201  
   202  // GetFormatter yields the formatter for lint failures
   203  func GetFormatter(formatterName string) (lint.Formatter, error) {
   204  	formatters := getFormatters()
   205  	formatter := formatters["default"]
   206  	if formatterName != "" {
   207  		f, ok := formatters[formatterName]
   208  		if !ok {
   209  			return nil, fmt.Errorf("unknown formatter %v", formatterName)
   210  		}
   211  		formatter = f
   212  	}
   213  	return formatter, nil
   214  }
   215  
   216  func defaultConfig() *lint.Config {
   217  	defaultConfig := lint.Config{
   218  		Confidence: 0.0,
   219  		Severity:   lint.SeverityWarning,
   220  		Rules:      map[string]lint.RuleConfig{},
   221  	}
   222  	for _, r := range defaultRules {
   223  		defaultConfig.Rules[r.Name()] = lint.RuleConfig{}
   224  	}
   225  	return &defaultConfig
   226  }