diff --git a/formatter/cli_formatter.go b/formatter/cli_formatter.go index a355b18..e346f52 100644 --- a/formatter/cli_formatter.go +++ b/formatter/cli_formatter.go @@ -20,30 +20,32 @@ type CLIFormatter struct { Metadata linter.FormatterMetadata } -func formatFailure(failure linter.Failure) []string { +func formatFailure(failure linter.Failure, severity linter.Severity) []string { fString := color.BlueString(failure.Failure) - fTypeStr := string(failure.Type) + fTypeStr := string(severity) fType := color.RedString(fTypeStr) lineColumn := failure.Position pos := fmt.Sprintf("(%d, %d)", lineColumn.Start.Line, lineColumn.Start.Column) - if failure.Type == linter.FailureTypeWarning { + if severity == linter.SeverityWarning { fType = color.YellowString(fTypeStr) } return []string{failure.GetFilename(), pos, fType, fString} } // Format formats the failures gotten from the linter. -func (f *CLIFormatter) Format(failures <-chan linter.Failure) (string, error) { +func (f *CLIFormatter) Format(failures <-chan linter.Failure, config linter.RulesConfig) (string, error) { var result [][]string var totalErrors = 0 var total = 0 for f := range failures { - result = append(result, formatFailure(f)) total++ - if f.Type == linter.FailureTypeError { + currentType := linter.SeverityWarning + if config, ok := config[f.RuleName]; ok && config.Severity == linter.SeverityError { + currentType = linter.SeverityError totalErrors++ } + result = append(result, formatFailure(f, linter.Severity(currentType))) } ps := "problems" if total == 1 { diff --git a/formatter/json_formatter.go b/formatter/json_formatter.go index 3ddb1ab..32b7a39 100644 --- a/formatter/json_formatter.go +++ b/formatter/json_formatter.go @@ -13,7 +13,7 @@ type JSONFormatter struct { } // Format formats the failures gotten from the linter. -func (f *JSONFormatter) Format(failures <-chan linter.Failure) (string, error) { +func (f *JSONFormatter) Format(failures <-chan linter.Failure, config linter.RulesConfig) (string, error) { var slice []linter.Failure for failure := range failures { slice = append(slice, failure) diff --git a/linter/file.go b/linter/file.go index 63a8c63..29c52a5 100644 --- a/linter/file.go +++ b/linter/file.go @@ -91,7 +91,7 @@ func (f *File) lint(rules []Rule, rulesConfig RulesConfig, failures chan Failure disabledIntervals := f.disabledIntervals(rules) for _, currentRule := range rules { config := rulesConfig[currentRule.Name()] - currentFailures := currentRule.Apply(f, config) + currentFailures := currentRule.Apply(f, config.Arguments) for idx, failure := range currentFailures { if failure.RuleName == "" { failure.RuleName = currentRule.Name() diff --git a/linter/formatter.go b/linter/formatter.go index c249c5f..3344e97 100644 --- a/linter/formatter.go +++ b/linter/formatter.go @@ -9,5 +9,5 @@ type FormatterMetadata struct { // Formatter defines an interface for failure formatters type Formatter interface { - Format(<-chan Failure, <-chan string, int) string + Format(<-chan Failure, RulesConfig) string } diff --git a/linter/rule.go b/linter/rule.go index a4a233d..f282737 100644 --- a/linter/rule.go +++ b/linter/rule.go @@ -6,14 +6,14 @@ import ( ) const ( - // FailureTypeWarning declares failures of type warning - FailureTypeWarning = "warning" - // FailureTypeError declares failures of type error. - FailureTypeError = "error" + // SeverityWarning declares failures of type warning + SeverityWarning = "warning" + // SeverityError declares failures of type error. + SeverityError = "error" ) -// FailureType is the type for the failure types. -type FailureType string +// Severity is the type for the failure types. +type Severity string // FailurePosition returns the failure position type FailurePosition struct { @@ -26,7 +26,6 @@ type Failure struct { Failure string RuleName string Category string - Type FailureType Position FailurePosition Node ast.Node `json:"-"` Confidence float64 @@ -48,16 +47,16 @@ type DisabledInterval struct { } // Arguments is type used for the arguments of a rule. -type Arguments []string +type Arguments = []string -// Config contains the rule configuration. -type Config struct { - Name string +// RuleConfig is type used for the rule configuration. +type RuleConfig struct { Arguments Arguments + Severity Severity } // RulesConfig defiles the config for all rules. -type RulesConfig = map[string]Arguments +type RulesConfig = map[string]RuleConfig // Rule defines an abstract rule interaface type Rule interface { diff --git a/main.go b/main.go index 7ae7c22..c37c0ec 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "os" "github.com/mgechev/revive/formatter" "github.com/mgechev/revive/linter" @@ -20,7 +21,7 @@ func main() { } } - func foobar(a int, b int, c int, d int) { + func foo_bar(a int, b int, c int, d int) { return a + b + c; } ` @@ -29,10 +30,13 @@ func main() { return []byte(src), nil }) var result []linter.Rule - result = append(result, &rule.LintElseRule{}, &rule.ArgumentsLimitRule{}) + result = append(result, &rule.LintElseRule{}, &rule.ArgumentsLimitRule{}, &rule.NamesRule{}) var config = linter.RulesConfig{ - "argument-limit": []string{"3"}, + "argument-limit": linter.RuleConfig{ + Arguments: []string{"3"}, + Severity: linter.SeverityWarning, + }, } failures, err := revive.Lint([]string{"foo.go", "bar.go", "baz.go"}, result, config) @@ -40,11 +44,29 @@ func main() { panic(err) } - var formatter formatter.CLIFormatter - output, err := formatter.Format(failures) - if err != nil { - panic(err) - } + formatChan := make(chan linter.Failure) + exitChan := make(chan bool) + var output string + go (func() { + var formatter formatter.CLIFormatter + output, err = formatter.Format(formatChan, config) + if err != nil { + panic(err) + } + exitChan <- true + })() + + exitCode := 0 + for f := range failures { + if c, ok := config[f.RuleName]; ok && c.Severity == linter.SeverityError { + exitCode = 1 + } + formatChan <- f + } + close(formatChan) + <-exitChan fmt.Println(output) + + os.Exit(exitCode) } diff --git a/rule/argument-limit.go b/rule/argument-limit.go index 1ec2252..ee71762 100644 --- a/rule/argument-limit.go +++ b/rule/argument-limit.go @@ -52,7 +52,6 @@ func (w lintArgsNum) Visit(n ast.Node) ast.Visitor { if num > w.total { w.onFailure(linter.Failure{ Failure: fmt.Sprintf("maximum number of arguments per function exceeded; max %d but got %d", w.total, num), - Type: linter.FailureTypeWarning, Node: node.Type, }) return w diff --git a/rule/no-else-return.go b/rule/no-else-return.go index 8fa2a11..f23748e 100644 --- a/rule/no-else-return.go +++ b/rule/no-else-return.go @@ -66,7 +66,6 @@ func (w lintElse) Visit(node ast.Node) ast.Visitor { } w.onFailure(linter.Failure{ Failure: "if block ends with a return statement, so drop this else and outdent its block" + extra, - Type: linter.FailureTypeWarning, Node: ifStmt.Else, }) }