1
0
mirror of https://github.com/mgechev/revive.git synced 2025-05-21 22:13:14 +02:00

Implement severity

This commit is contained in:
mgechev 2018-01-24 15:41:40 -08:00
parent b2e276ddf8
commit 4f31c1639f
8 changed files with 52 additions and 31 deletions

@ -20,30 +20,32 @@ type CLIFormatter struct {
Metadata linter.FormatterMetadata Metadata linter.FormatterMetadata
} }
func formatFailure(failure linter.Failure) []string { func formatFailure(failure linter.Failure, severity linter.Severity) []string {
fString := color.BlueString(failure.Failure) fString := color.BlueString(failure.Failure)
fTypeStr := string(failure.Type) fTypeStr := string(severity)
fType := color.RedString(fTypeStr) fType := color.RedString(fTypeStr)
lineColumn := failure.Position lineColumn := failure.Position
pos := fmt.Sprintf("(%d, %d)", lineColumn.Start.Line, lineColumn.Start.Column) pos := fmt.Sprintf("(%d, %d)", lineColumn.Start.Line, lineColumn.Start.Column)
if failure.Type == linter.FailureTypeWarning { if severity == linter.SeverityWarning {
fType = color.YellowString(fTypeStr) fType = color.YellowString(fTypeStr)
} }
return []string{failure.GetFilename(), pos, fType, fString} return []string{failure.GetFilename(), pos, fType, fString}
} }
// Format formats the failures gotten from the linter. // 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 result [][]string
var totalErrors = 0 var totalErrors = 0
var total = 0 var total = 0
for f := range failures { for f := range failures {
result = append(result, formatFailure(f))
total++ total++
if f.Type == linter.FailureTypeError { currentType := linter.SeverityWarning
if config, ok := config[f.RuleName]; ok && config.Severity == linter.SeverityError {
currentType = linter.SeverityError
totalErrors++ totalErrors++
} }
result = append(result, formatFailure(f, linter.Severity(currentType)))
} }
ps := "problems" ps := "problems"
if total == 1 { if total == 1 {

@ -13,7 +13,7 @@ type JSONFormatter struct {
} }
// Format formats the failures gotten from the linter. // 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 var slice []linter.Failure
for failure := range failures { for failure := range failures {
slice = append(slice, failure) slice = append(slice, failure)

@ -91,7 +91,7 @@ func (f *File) lint(rules []Rule, rulesConfig RulesConfig, failures chan Failure
disabledIntervals := f.disabledIntervals(rules) disabledIntervals := f.disabledIntervals(rules)
for _, currentRule := range rules { for _, currentRule := range rules {
config := rulesConfig[currentRule.Name()] config := rulesConfig[currentRule.Name()]
currentFailures := currentRule.Apply(f, config) currentFailures := currentRule.Apply(f, config.Arguments)
for idx, failure := range currentFailures { for idx, failure := range currentFailures {
if failure.RuleName == "" { if failure.RuleName == "" {
failure.RuleName = currentRule.Name() failure.RuleName = currentRule.Name()

@ -9,5 +9,5 @@ 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, <-chan string, int) string Format(<-chan Failure, RulesConfig) string
} }

@ -6,14 +6,14 @@ import (
) )
const ( const (
// FailureTypeWarning declares failures of type warning // SeverityWarning declares failures of type warning
FailureTypeWarning = "warning" SeverityWarning = "warning"
// FailureTypeError declares failures of type error. // SeverityError declares failures of type error.
FailureTypeError = "error" SeverityError = "error"
) )
// FailureType is the type for the failure types. // Severity is the type for the failure types.
type FailureType string type Severity string
// FailurePosition returns the failure position // FailurePosition returns the failure position
type FailurePosition struct { type FailurePosition struct {
@ -26,7 +26,6 @@ type Failure struct {
Failure string Failure string
RuleName string RuleName string
Category string Category string
Type FailureType
Position FailurePosition Position FailurePosition
Node ast.Node `json:"-"` Node ast.Node `json:"-"`
Confidence float64 Confidence float64
@ -48,16 +47,16 @@ type DisabledInterval struct {
} }
// Arguments is type used for the arguments of a rule. // Arguments is type used for the arguments of a rule.
type Arguments []string type Arguments = []string
// Config contains the rule configuration. // RuleConfig is type used for the rule configuration.
type Config struct { type RuleConfig struct {
Name string
Arguments Arguments Arguments Arguments
Severity Severity
} }
// RulesConfig defiles the config for all rules. // RulesConfig defiles the config for all rules.
type RulesConfig = map[string]Arguments type RulesConfig = map[string]RuleConfig
// Rule defines an abstract rule interaface // Rule defines an abstract rule interaface
type Rule interface { type Rule interface {

38
main.go

@ -2,6 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"os"
"github.com/mgechev/revive/formatter" "github.com/mgechev/revive/formatter"
"github.com/mgechev/revive/linter" "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; return a + b + c;
} }
` `
@ -29,10 +30,13 @@ func main() {
return []byte(src), nil return []byte(src), nil
}) })
var result []linter.Rule var result []linter.Rule
result = append(result, &rule.LintElseRule{}, &rule.ArgumentsLimitRule{}) result = append(result, &rule.LintElseRule{}, &rule.ArgumentsLimitRule{}, &rule.NamesRule{})
var config = linter.RulesConfig{ 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) failures, err := revive.Lint([]string{"foo.go", "bar.go", "baz.go"}, result, config)
@ -40,11 +44,29 @@ func main() {
panic(err) panic(err)
} }
var formatter formatter.CLIFormatter formatChan := make(chan linter.Failure)
output, err := formatter.Format(failures) exitChan := make(chan bool)
if err != nil { var output string
panic(err)
}
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) fmt.Println(output)
os.Exit(exitCode)
} }

@ -52,7 +52,6 @@ func (w lintArgsNum) Visit(n ast.Node) ast.Visitor {
if num > w.total { if num > w.total {
w.onFailure(linter.Failure{ w.onFailure(linter.Failure{
Failure: fmt.Sprintf("maximum number of arguments per function exceeded; max %d but got %d", w.total, num), Failure: fmt.Sprintf("maximum number of arguments per function exceeded; max %d but got %d", w.total, num),
Type: linter.FailureTypeWarning,
Node: node.Type, Node: node.Type,
}) })
return w return w

@ -66,7 +66,6 @@ func (w lintElse) Visit(node ast.Node) ast.Visitor {
} }
w.onFailure(linter.Failure{ w.onFailure(linter.Failure{
Failure: "if block ends with a return statement, so drop this else and outdent its block" + extra, Failure: "if block ends with a return statement, so drop this else and outdent its block" + extra,
Type: linter.FailureTypeWarning,
Node: ifStmt.Else, Node: ifStmt.Else,
}) })
} }