mirror of
https://github.com/mgechev/revive.git
synced 2025-03-05 15:05:47 +02:00
Implement command line arguments
This commit is contained in:
parent
a227153bc2
commit
8746067321
196
config.go
Normal file
196
config.go
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
zglob "github.com/mattn/go-zglob"
|
||||||
|
"github.com/mgechev/revive/formatter"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/mgechev/revive/lint"
|
||||||
|
"github.com/mgechev/revive/rule"
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultRules = []lint.Rule{
|
||||||
|
&rule.VarDeclarationsRule{},
|
||||||
|
&rule.PackageCommentsRule{},
|
||||||
|
&rule.DotImportsRule{},
|
||||||
|
&rule.BlankImportsRule{},
|
||||||
|
&rule.ExportedRule{},
|
||||||
|
&rule.NamesRule{},
|
||||||
|
&rule.ElseRule{},
|
||||||
|
&rule.IfReturnRule{},
|
||||||
|
&rule.RangeRule{},
|
||||||
|
&rule.ErrorfRule{},
|
||||||
|
&rule.ErrorsRule{},
|
||||||
|
&rule.ErrorStringsRule{},
|
||||||
|
&rule.ReceiverNameRule{},
|
||||||
|
&rule.IncrementDecrementRule{},
|
||||||
|
&rule.ErrorReturnRule{},
|
||||||
|
&rule.UnexportedReturnRule{},
|
||||||
|
&rule.TimeNamesRule{},
|
||||||
|
&rule.ContextKeyTypeRule{},
|
||||||
|
&rule.ContextArgumentsRule{},
|
||||||
|
}
|
||||||
|
|
||||||
|
var allRules = append([]lint.Rule{
|
||||||
|
&rule.ArgumentsLimitRule{},
|
||||||
|
&rule.CyclomaticRule{},
|
||||||
|
}, defaultRules...)
|
||||||
|
|
||||||
|
var allFormatters = []lint.Formatter{
|
||||||
|
&formatter.CLIFormatter{},
|
||||||
|
&formatter.JSONFormatter{},
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFormatters() map[string]lint.Formatter {
|
||||||
|
result := map[string]lint.Formatter{}
|
||||||
|
for _, f := range allFormatters {
|
||||||
|
result[f.Name()] = f
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLintingRules(config *lint.Config) []lint.Rule {
|
||||||
|
rulesMap := map[string]lint.Rule{}
|
||||||
|
for _, r := range allRules {
|
||||||
|
rulesMap[r.Name()] = r
|
||||||
|
}
|
||||||
|
|
||||||
|
lintingRules := []lint.Rule{}
|
||||||
|
for name := range config.Rules {
|
||||||
|
rule, ok := rulesMap[name]
|
||||||
|
if !ok {
|
||||||
|
panic("cannot find rule: " + name)
|
||||||
|
}
|
||||||
|
lintingRules = append(lintingRules, rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lintingRules
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConfig(path string) *lint.Config {
|
||||||
|
config := &lint.Config{}
|
||||||
|
file, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
panic("cannot read the config file")
|
||||||
|
}
|
||||||
|
_, err = toml.Decode(string(file), config)
|
||||||
|
if err != nil {
|
||||||
|
panic("cannot parse the config file: " + err.Error())
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizeConfig(config *lint.Config) {
|
||||||
|
severity := config.Severity
|
||||||
|
if severity != "" {
|
||||||
|
for k, v := range config.Rules {
|
||||||
|
if v.Severity == "" {
|
||||||
|
v.Severity = severity
|
||||||
|
}
|
||||||
|
config.Rules[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConfig() *lint.Config {
|
||||||
|
config := defaultConfig()
|
||||||
|
if configPath != "" {
|
||||||
|
config = parseConfig(configPath)
|
||||||
|
}
|
||||||
|
normalizeConfig(config)
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFormatter() lint.Formatter {
|
||||||
|
formatters := getFormatters()
|
||||||
|
formatter := formatters["cli"]
|
||||||
|
if formatterName != "" {
|
||||||
|
f, ok := formatters[formatterName]
|
||||||
|
if !ok {
|
||||||
|
panic("unknown formatter " + formatterName)
|
||||||
|
}
|
||||||
|
formatter = f
|
||||||
|
}
|
||||||
|
return formatter
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultConfig() *lint.Config {
|
||||||
|
defaultConfig := lint.Config{
|
||||||
|
Confidence: 0.0,
|
||||||
|
Severity: lint.SeverityWarning,
|
||||||
|
Rules: map[string]lint.RuleConfig{},
|
||||||
|
}
|
||||||
|
for _, r := range defaultRules {
|
||||||
|
defaultConfig.Rules[r.Name()] = lint.RuleConfig{}
|
||||||
|
}
|
||||||
|
return &defaultConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFiles() []string {
|
||||||
|
globs := flag.Args()
|
||||||
|
if len(globs) == 0 {
|
||||||
|
panic("files not specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
var matches []string
|
||||||
|
for _, g := range globs {
|
||||||
|
m, err := zglob.Glob(g)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
matches = append(matches, m...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if excludeGlobs == "" {
|
||||||
|
return matches
|
||||||
|
}
|
||||||
|
|
||||||
|
excluded := map[string]bool{}
|
||||||
|
excludeGlobSlice := strings.Split(excludeGlobs, " ")
|
||||||
|
for _, g := range excludeGlobSlice {
|
||||||
|
m, err := zglob.Glob(g)
|
||||||
|
if err != nil {
|
||||||
|
panic("error while parsing glob from exclude " + err.Error())
|
||||||
|
}
|
||||||
|
for _, match := range m {
|
||||||
|
excluded[match] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var finalMatches []string
|
||||||
|
for _, m := range matches {
|
||||||
|
if _, ok := excluded[m]; !ok {
|
||||||
|
finalMatches = append(finalMatches, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalMatches
|
||||||
|
}
|
||||||
|
|
||||||
|
var configPath string
|
||||||
|
var excludeGlobs string
|
||||||
|
var formatterName string
|
||||||
|
var help bool
|
||||||
|
|
||||||
|
var originalUsage = flag.Usage
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.Usage = func() {
|
||||||
|
fmt.Println(banner)
|
||||||
|
originalUsage()
|
||||||
|
}
|
||||||
|
const (
|
||||||
|
configUsage = "path to the configuration TOML file"
|
||||||
|
excludeUsage = "glob which specifies files to be excluded"
|
||||||
|
formatterUsage = "formatter to be used for the output"
|
||||||
|
)
|
||||||
|
flag.StringVar(&configPath, "config", "", configUsage)
|
||||||
|
flag.StringVar(&excludeGlobs, "exclude", "", excludeUsage)
|
||||||
|
flag.StringVar(&formatterName, "formatter", "", formatterUsage)
|
||||||
|
flag.Parse()
|
||||||
|
}
|
@ -2,9 +2,9 @@ severity = "warning"
|
|||||||
confidence = 0.8
|
confidence = 0.8
|
||||||
|
|
||||||
[rule.else]
|
[rule.else]
|
||||||
severity = "error"
|
|
||||||
[rule.names]
|
[rule.names]
|
||||||
[rule.argument-limit]
|
[rule.argument-limit]
|
||||||
arguments = [2]
|
arguments = [2]
|
||||||
[rule.cyclomatic]
|
[rule.cyclomatic]
|
||||||
|
severity = "error"
|
||||||
arguments = [3]
|
arguments = [3]
|
@ -1,7 +1,7 @@
|
|||||||
// Test for returning errors.
|
// Test for returning errors.
|
||||||
|
|
||||||
// Package foo ...
|
// Package foo ...
|
||||||
package foo
|
package pkg
|
||||||
|
|
||||||
// Returns nothing
|
// Returns nothing
|
||||||
func f() { // ok
|
func f() { // ok
|
||||||
|
@ -20,6 +20,11 @@ type CLIFormatter struct {
|
|||||||
Metadata lint.FormatterMetadata
|
Metadata lint.FormatterMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the formatter
|
||||||
|
func (f *CLIFormatter) Name() string {
|
||||||
|
return "cli"
|
||||||
|
}
|
||||||
|
|
||||||
func formatFailure(failure lint.Failure, severity lint.Severity) []string {
|
func formatFailure(failure lint.Failure, severity lint.Severity) []string {
|
||||||
fString := color.BlueString(failure.Failure)
|
fString := color.BlueString(failure.Failure)
|
||||||
fName := color.RedString(failure.RuleName)
|
fName := color.RedString(failure.RuleName)
|
||||||
|
@ -12,6 +12,11 @@ type JSONFormatter struct {
|
|||||||
Metadata lint.FormatterMetadata
|
Metadata lint.FormatterMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the formatter
|
||||||
|
func (f *JSONFormatter) Name() string {
|
||||||
|
return "json"
|
||||||
|
}
|
||||||
|
|
||||||
// Format formats the failures gotten from the lint.
|
// Format formats the failures gotten from the lint.
|
||||||
func (f *JSONFormatter) Format(failures <-chan lint.Failure, config lint.RulesConfig) (string, error) {
|
func (f *JSONFormatter) Format(failures <-chan lint.Failure, config lint.RulesConfig) (string, error) {
|
||||||
var slice []lint.Failure
|
var slice []lint.Failure
|
||||||
|
@ -9,5 +9,6 @@ type FormatterMetadata struct {
|
|||||||
|
|
||||||
// Formatter defines an interface for failure formatters
|
// Formatter defines an interface for failure formatters
|
||||||
type Formatter interface {
|
type Formatter interface {
|
||||||
Format(<-chan Failure, RulesConfig) string
|
Format(<-chan Failure, RulesConfig) (string, error)
|
||||||
|
Name() string
|
||||||
}
|
}
|
||||||
|
110
main.go
110
main.go
@ -5,122 +5,29 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
"github.com/mgechev/revive/formatter"
|
|
||||||
"github.com/mgechev/revive/lint"
|
"github.com/mgechev/revive/lint"
|
||||||
"github.com/mgechev/revive/rule"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var allRules = []lint.Rule{
|
const banner = `
|
||||||
&rule.ArgumentsLimitRule{},
|
Welcome to:
|
||||||
&rule.VarDeclarationsRule{},
|
_ __ _____ _(_)__ _____
|
||||||
&rule.PackageCommentsRule{},
|
|
||||||
&rule.DotImportsRule{},
|
|
||||||
&rule.BlankImportsRule{},
|
|
||||||
&rule.ExportedRule{},
|
|
||||||
&rule.NamesRule{},
|
|
||||||
&rule.ElseRule{},
|
|
||||||
&rule.IfReturnRule{},
|
|
||||||
&rule.RangeRule{},
|
|
||||||
&rule.ErrorfRule{},
|
|
||||||
&rule.ErrorsRule{},
|
|
||||||
&rule.ErrorStringsRule{},
|
|
||||||
&rule.ReceiverNameRule{},
|
|
||||||
&rule.IncrementDecrementRule{},
|
|
||||||
&rule.ErrorReturnRule{},
|
|
||||||
&rule.UnexportedReturnRule{},
|
|
||||||
&rule.TimeNamesRule{},
|
|
||||||
&rule.ContextKeyTypeRule{},
|
|
||||||
&rule.ContextArgumentsRule{},
|
|
||||||
&rule.CyclomaticRule{},
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLintingRules(config *lint.Config) []lint.Rule {
|
|
||||||
rulesMap := map[string]lint.Rule{}
|
|
||||||
for _, r := range allRules {
|
|
||||||
rulesMap[r.Name()] = r
|
|
||||||
}
|
|
||||||
|
|
||||||
lintingRules := []lint.Rule{}
|
|
||||||
for name := range config.Rules {
|
|
||||||
rule, ok := rulesMap[name]
|
|
||||||
if !ok {
|
|
||||||
panic("cannot find rule: " + name)
|
|
||||||
}
|
|
||||||
lintingRules = append(lintingRules, rule)
|
|
||||||
}
|
|
||||||
|
|
||||||
return lintingRules
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseConfig(path string) *lint.Config {
|
|
||||||
config := &lint.Config{}
|
|
||||||
file, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
panic("cannot read the config file")
|
|
||||||
}
|
|
||||||
_, err = toml.Decode(string(file), config)
|
|
||||||
if err != nil {
|
|
||||||
panic("cannot parse the config file: " + err.Error())
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
func normalizeConfig(config *lint.Config) {
|
|
||||||
severity := config.Severity
|
|
||||||
if severity != "" {
|
|
||||||
for k, v := range config.Rules {
|
|
||||||
if v.Severity == "" {
|
|
||||||
v.Severity = severity
|
|
||||||
}
|
|
||||||
config.Rules[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const usage = `
|
|
||||||
Welcome to:
|
|
||||||
_ __ _____ _(_)__ _____
|
|
||||||
| '__/ _ \ \ / / \ \ / / _ \
|
| '__/ _ \ \ / / \ \ / / _ \
|
||||||
| | | __/\ V /| |\ V / __/
|
| | | __/\ V /| |\ V / __/
|
||||||
|_| \___| \_/ |_| \_/ \___|
|
|_| \___| \_/ |_| \_/ \___|
|
||||||
|
|
||||||
Usage:
|
|
||||||
revive [flags] <Go file or directory> ...
|
|
||||||
Flags:
|
|
||||||
-c string path to the configuration TOML file.
|
|
||||||
-e string glob which specifies files to be excluded.
|
|
||||||
-f string formatter to be used for the output.
|
|
||||||
-h output this screen.
|
|
||||||
`
|
`
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
src := `
|
config := getConfig()
|
||||||
package p
|
formatter := getFormatter()
|
||||||
|
files := getFiles()
|
||||||
// revive:disable:cyclomatic
|
|
||||||
func Test() {
|
|
||||||
if true || bar && baz {
|
|
||||||
return 42;
|
|
||||||
} else {
|
|
||||||
return 23;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// revive:enable:cyclomatic
|
|
||||||
|
|
||||||
func foo_bar(a int, b int, c int, d int) {
|
|
||||||
return a + b + c;
|
|
||||||
}`
|
|
||||||
|
|
||||||
revive := lint.New(func(file string) ([]byte, error) {
|
revive := lint.New(func(file string) ([]byte, error) {
|
||||||
return []byte(src), nil
|
return ioutil.ReadFile(file)
|
||||||
})
|
})
|
||||||
|
|
||||||
config := parseConfig("config.toml")
|
|
||||||
normalizeConfig(config)
|
|
||||||
lintingRules := getLintingRules(config)
|
lintingRules := getLintingRules(config)
|
||||||
|
|
||||||
failures, err := revive.Lint([]string{"foo.go", "bar.go", "baz.go"}, lintingRules, config.Rules)
|
failures, err := revive.Lint(files, lintingRules, config.Rules)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -130,7 +37,6 @@ func main() {
|
|||||||
|
|
||||||
var output string
|
var output string
|
||||||
go (func() {
|
go (func() {
|
||||||
var formatter formatter.CLIFormatter
|
|
||||||
output, err = formatter.Format(formatChan, config.Rules)
|
output, err = formatter.Format(formatChan, config.Rules)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -143,7 +143,6 @@ func assertFailures(t *testing.T, baseDir string, fi os.FileInfo, src []byte, ru
|
|||||||
|
|
||||||
ps, err := l.Lint([]string{fi.Name()}, rules, config)
|
ps, err := l.Lint([]string{fi.Name()}, rules, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user