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 }