cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.26.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/reporter/console.go

129lines · modecode

1package reporter
2
3import (
4 "fmt"
5 "io"
6 "os"
7 "sort"
8 "strconv"
9 "strings"
10
11 "github.com/fatih/color"
12 "github.com/rs/zerolog/log"
13
14 "github.com/cloudflare/pint/internal/checks"
15 "github.com/cloudflare/pint/internal/output"
16)
17
18func NewConsoleReporter(output io.Writer) ConsoleReporter {
19 return ConsoleReporter{output: output}
20}
21
22type ConsoleReporter struct {
23 output io.Writer
24}
25
26func (cr ConsoleReporter) Submit(summary Summary) error {
27 reports := summary.Reports
28 sort.Slice(reports, func(i, j int) bool {
29 if reports[i].Path < reports[j].Path {
30 return true
31 }
32 if reports[i].Path > reports[j].Path {
33 return false
34 }
35 if reports[i].Problem.Lines[0] < reports[j].Problem.Lines[0] {
36 return true
37 }
38 if reports[i].Problem.Lines[0] > reports[j].Problem.Lines[0] {
39 return false
40 }
41 if reports[i].Problem.Reporter < reports[j].Problem.Reporter {
42 return true
43 }
44 if reports[i].Problem.Reporter > reports[j].Problem.Reporter {
45 return false
46 }
47 return reports[i].Problem.Text < reports[j].Problem.Text
48 })
49
50 perFile := map[string][]string{}
51 for _, report := range reports {
52 if !shouldReport(report) {
53 log.Debug().
54 Str("path", report.Path).
55 Str("lines", output.FormatLineRangeString(report.Problem.Lines)).
56 Msg("Problem reported on unmodified line, skipping")
57 continue
58 }
59
60 if _, ok := perFile[report.Path]; !ok {
61 perFile[report.Path] = []string{}
62 }
63
64 content, err := readFile(report.Path)
65 if err != nil {
66 return err
67 }
68
69 msg := []string{}
70 firstLine, lastLine := report.Problem.LineRange()
71 msg = append(msg, color.CyanString("%s:%s: ", report.Path, printLineRange(firstLine, lastLine)))
72 switch report.Problem.Severity {
73 case checks.Bug, checks.Fatal:
74 msg = append(msg, color.RedString(report.Problem.Text))
75 case checks.Warning:
76 msg = append(msg, color.YellowString(report.Problem.Text))
77 case checks.Information:
78 msg = append(msg, color.HiBlackString(report.Problem.Text))
79 }
80 msg = append(msg, color.MagentaString(" (%s)\n", report.Problem.Reporter))
81
82 lines := strings.Split(content, "\n")
83 if lastLine > len(lines)-1 {
84 lastLine = len(lines) - 1
85 log.Warn().Str("path", report.Path).Msgf("Tried to read more lines than present in the source file, this is likely due to '\n' usage in some rules, see https://github.com/cloudflare/pint/issues/20 for details")
86 }
87 for _, c := range lines[firstLine-1 : lastLine] {
88 msg = append(msg, color.WhiteString("%s\n", c))
89 }
90 perFile[report.Path] = append(perFile[report.Path], strings.Join(msg, ""))
91 }
92
93 paths := []string{}
94 for path := range perFile {
95 paths = append(paths, path)
96 }
97 sort.Strings(paths)
98
99 for _, path := range paths {
100 msgs := perFile[path]
101 for _, msg := range msgs {
102 fmt.Fprintln(cr.output, msg)
103 }
104 }
105
106 return nil
107}
108
109func readFile(path string) (string, error) {
110 f, err := os.Open(path)
111 if err != nil {
112 return "", err
113 }
114 defer f.Close()
115
116 content, err := io.ReadAll(f)
117 if err != nil {
118 return "", err
119 }
120
121 return string(content), nil
122}
123
124func printLineRange(s, e int) string {
125 if s == e {
126 return strconv.Itoa(s)
127 }
128 return fmt.Sprintf("%d-%d", s, e)
129}
130