mirror of
https://github.com/mgechev/revive.git
synced 2025-03-17 20:57:58 +02:00
Add new formatter
This commit is contained in:
parent
b8e1c67e9c
commit
87860f3d8a
@ -50,6 +50,7 @@ var allRules = append([]lint.Rule{
|
||||
|
||||
var allFormatters = []lint.Formatter{
|
||||
&formatter.Stylish{},
|
||||
&formatter.Friendly{},
|
||||
&formatter.JSON{},
|
||||
&formatter.Default{},
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ confidence = 0.8
|
||||
[rule.package-comments]
|
||||
[rule.else]
|
||||
[rule.names]
|
||||
severity = "error"
|
||||
[rule.var-declaration]
|
||||
[rule.unexported-return]
|
||||
[rule.time-names]
|
||||
|
111
formatter/friendly.go
Normal file
111
formatter/friendly.go
Normal file
@ -0,0 +1,111 @@
|
||||
package formatter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/mgechev/revive/lint"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
)
|
||||
|
||||
var (
|
||||
errorEmoji = color.RedString("✘")
|
||||
warningEmoji = color.YellowString("⚠")
|
||||
)
|
||||
|
||||
var newLines = map[rune]bool{
|
||||
0x000A: true,
|
||||
0x000B: true,
|
||||
0x000C: true,
|
||||
0x000D: true,
|
||||
0x0085: true,
|
||||
0x2028: true,
|
||||
0x2029: true,
|
||||
}
|
||||
|
||||
// Friendly is an implementation of the Formatter interface
|
||||
// which formats the errors to JSON.
|
||||
type Friendly struct {
|
||||
Metadata lint.FormatterMetadata
|
||||
}
|
||||
|
||||
// Name returns the name of the formatter
|
||||
func (f *Friendly) Name() string {
|
||||
return "friendly"
|
||||
}
|
||||
|
||||
// Format formats the failures gotten from the lint.
|
||||
func (f *Friendly) Format(failures <-chan lint.Failure, config lint.RulesConfig) (string, error) {
|
||||
errorMap := map[string]int{}
|
||||
warningMap := map[string]int{}
|
||||
for failure := range failures {
|
||||
sev := severity(config, failure)
|
||||
f.printFriendlyFailure(failure, sev)
|
||||
if sev == lint.SeverityWarning {
|
||||
warningMap[failure.RuleName] = warningMap[failure.RuleName] + 1
|
||||
}
|
||||
if sev == lint.SeverityError {
|
||||
errorMap[failure.RuleName] = errorMap[failure.RuleName] + 1
|
||||
}
|
||||
}
|
||||
f.printStatistics(color.RedString("Errors:"), errorMap)
|
||||
f.printStatistics(color.YellowString("Warnings:"), warningMap)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (f *Friendly) printFriendlyFailure(failure lint.Failure, severity lint.Severity) {
|
||||
f.printHeaderRow(failure, severity)
|
||||
f.printFilePosition(failure)
|
||||
fmt.Println()
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func (f *Friendly) printHeaderRow(failure lint.Failure, severity lint.Severity) {
|
||||
emoji := warningEmoji
|
||||
if severity == lint.SeverityError {
|
||||
emoji = errorEmoji
|
||||
}
|
||||
fmt.Print(f.table([][]string{{emoji, failure.RuleName, color.GreenString(failure.Failure)}}))
|
||||
}
|
||||
|
||||
func (f *Friendly) printFilePosition(failure lint.Failure) {
|
||||
fmt.Printf(" %s:%d:%d", failure.GetFilename(), failure.Position.Start.Offset, failure.Position.End.Offset)
|
||||
}
|
||||
|
||||
type statEntry struct {
|
||||
name string
|
||||
failures int
|
||||
}
|
||||
|
||||
func (f *Friendly) printStatistics(header string, stats map[string]int) {
|
||||
if len(stats) == 0 {
|
||||
return
|
||||
}
|
||||
var data []statEntry
|
||||
for name, total := range stats {
|
||||
data = append(data, statEntry{name, total})
|
||||
}
|
||||
sort.Slice(data, func(i, j int) bool {
|
||||
return data[i].failures > data[j].failures
|
||||
})
|
||||
formatted := [][]string{}
|
||||
for _, entry := range data {
|
||||
formatted = append(formatted, []string{color.GreenString(fmt.Sprintf("%d", entry.failures)), entry.name})
|
||||
}
|
||||
fmt.Println(header)
|
||||
fmt.Println(f.table(formatted))
|
||||
}
|
||||
|
||||
func (f *Friendly) table(rows [][]string) string {
|
||||
buf := new(bytes.Buffer)
|
||||
table := tablewriter.NewWriter(buf)
|
||||
table.SetBorder(false)
|
||||
table.SetColumnSeparator("")
|
||||
table.SetRowSeparator("")
|
||||
table.SetAutoWrapText(false)
|
||||
table.AppendBulk(rows)
|
||||
table.Render()
|
||||
return buf.String()
|
||||
}
|
10
formatter/severity.go
Normal file
10
formatter/severity.go
Normal file
@ -0,0 +1,10 @@
|
||||
package formatter
|
||||
|
||||
import "github.com/mgechev/revive/lint"
|
||||
|
||||
func severity(config lint.RulesConfig, failure lint.Failure) lint.Severity {
|
||||
if config, ok := config[failure.RuleName]; ok && config.Severity == lint.SeverityError {
|
||||
return lint.SeverityError
|
||||
}
|
||||
return lint.SeverityWarning
|
||||
}
|
@ -9,11 +9,6 @@ import (
|
||||
"github.com/olekukonko/tablewriter"
|
||||
)
|
||||
|
||||
const (
|
||||
errorEmoji = ""
|
||||
warningEmoji = ""
|
||||
)
|
||||
|
||||
// Stylish is an implementation of the Formatter interface
|
||||
// which formats the errors to JSON.
|
||||
type Stylish struct {
|
||||
@ -44,9 +39,8 @@ func (f *Stylish) Format(failures <-chan lint.Failure, config lint.RulesConfig)
|
||||
|
||||
for f := range failures {
|
||||
total++
|
||||
currentType := lint.SeverityWarning
|
||||
if config, ok := config[f.RuleName]; ok && config.Severity == lint.SeverityError {
|
||||
currentType = lint.SeverityError
|
||||
currentType := severity(config, f)
|
||||
if currentType == lint.SeverityError {
|
||||
totalErrors++
|
||||
}
|
||||
result = append(result, formatFailure(f, lint.Severity(currentType)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user