cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.3.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/reporter/console.go

120lines · modecode

1package reporter
2
3import (
4 "fmt"
5 "io"
6 "os"
7 "sort"
8 "strconv"
9 "strings"
10
11 "github.com/cloudflare/pint/internal/checks"
12 "github.com/cloudflare/pint/internal/output"
13 "github.com/rs/zerolog/log"
14)
15
16func NewConsoleReporter(output io.Writer) ConsoleReporter {
17 return ConsoleReporter{output: output}
18}
19
20type ConsoleReporter struct {
21 output io.Writer
22}
23
24func (cr ConsoleReporter) Submit(summary Summary) error {
25 reports := summary.Reports
26 reps := reports[:]
27 sort.Slice(reps, func(i, j int) bool {
28 if reports[i].Path < reports[j].Path {
29 return true
30 }
31 if reports[i].Path > reports[j].Path {
32 return false
33 }
34 if reports[i].Problem.Lines[0] < reports[j].Problem.Lines[0] {
35 return true
36 }
37 if reports[i].Problem.Lines[0] > reports[j].Problem.Lines[0] {
38 return false
39 }
40 if reports[i].Problem.Reporter < reports[j].Problem.Reporter {
41 return true
42 }
43 if reports[i].Problem.Reporter > reports[j].Problem.Reporter {
44 return false
45 }
46 return reports[i].Problem.Text < reports[j].Problem.Text
47 })
48
49 perFile := map[string][]string{}
50 for _, report := range reps {
51 if _, ok := perFile[report.Path]; !ok {
52 perFile[report.Path] = []string{}
53 }
54
55 content, err := readFile(report.Path)
56 if err != nil {
57 return err
58 }
59
60 msg := []string{}
61 firstLine, lastLine := report.Problem.LineRange()
62 msg = append(msg, output.MakeBlue("%s:%s: ", report.Path, printLineRange(firstLine, lastLine)))
63 switch report.Problem.Severity {
64 case checks.Bug, checks.Fatal:
65 msg = append(msg, output.MakeRed(report.Problem.Text))
66 case checks.Warning:
67 msg = append(msg, output.MakeYellow(report.Problem.Text))
68 default:
69 msg = append(msg, output.MakeGray(report.Problem.Text))
70 }
71 msg = append(msg, output.MakeMagneta(" (%s)\n", report.Problem.Reporter))
72
73 lines := strings.Split(content, "\n")
74 if lastLine > len(lines)-1 {
75 lastLine = len(lines) - 1
76 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")
77 }
78 for _, c := range lines[firstLine-1 : lastLine] {
79 msg = append(msg, output.MakeWhite("%s\n", c))
80 }
81 perFile[report.Path] = append(perFile[report.Path], strings.Join(msg, ""))
82 }
83
84 paths := []string{}
85 for path := range perFile {
86 paths = append(paths, path)
87 }
88 sort.Strings(paths)
89
90 for _, path := range paths {
91 msgs := perFile[path]
92 for _, msg := range msgs {
93 fmt.Fprintln(cr.output, msg)
94 }
95 }
96
97 return nil
98}
99
100func readFile(path string) (string, error) {
101 f, err := os.Open(path)
102 if err != nil {
103 return "", err
104 }
105 defer f.Close()
106
107 content, err := io.ReadAll(f)
108 if err != nil {
109 return "", err
110 }
111
112 return string(content), nil
113}
114
115func printLineRange(s, e int) string {
116 if s == e {
117 return strconv.Itoa(s)
118 }
119 return fmt.Sprintf("%d-%d", s, e)
120}
121