123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- 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.Config) (string, error) {
- errorMap := map[string]int{}
- warningMap := map[string]int{}
- totalErrors := 0
- totalWarnings := 0
- for failure := range failures {
- sev := severity(config, failure)
- f.printFriendlyFailure(failure, sev)
- if sev == lint.SeverityWarning {
- warningMap[failure.RuleName] = warningMap[failure.RuleName] + 1
- totalWarnings++
- }
- if sev == lint.SeverityError {
- errorMap[failure.RuleName] = errorMap[failure.RuleName] + 1
- totalErrors++
- }
- }
- f.printSummary(totalErrors, totalWarnings)
- 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, "https://revive.run/r#" + failure.RuleName, color.GreenString(failure.Failure)}}))
- }
-
- func (f *Friendly) printFilePosition(failure lint.Failure) {
- fmt.Printf(" %s:%d:%d", failure.GetFilename(), failure.Position.Start.Line, failure.Position.Start.Column)
- }
-
- type statEntry struct {
- name string
- failures int
- }
-
- func (f *Friendly) printSummary(errors, warnings int) {
- emoji := warningEmoji
- if errors > 0 {
- emoji = errorEmoji
- }
- problemsLabel := "problems"
- if errors+warnings == 1 {
- problemsLabel = "problem"
- }
- warningsLabel := "warnings"
- if warnings == 1 {
- warningsLabel = "warning"
- }
- errorsLabel := "errors"
- if errors == 1 {
- errorsLabel = "error"
- }
- str := fmt.Sprintf("%d %s (%d %s, %d %s)", errors+warnings, problemsLabel, errors, errorsLabel, warnings, warningsLabel)
- if errors > 0 {
- fmt.Printf("%s %s\n", emoji, color.RedString(str))
- fmt.Println()
- return
- }
- if warnings > 0 {
- fmt.Printf("%s %s\n", emoji, color.YellowString(str))
- fmt.Println()
- return
- }
- }
-
- 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()
- }
|