2 files changed,
35 insertions(+),
24 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-09-26 18:20:01 +0300
Authored at:
2026-09-26 17:36:58 +0300
Change ID:
pxytruqywoxupqrnqqnursynmzxmxpuy
Parent:
e0319e5
jump to
| M | internal/linter/report.go |
| M | journal/ast/ast.go |
M
internal/linter/report.go
··· 1 1 package linter 2 2 3 3 import ( 4 + "bufio" 4 5 "encoding/json" 5 6 "errors" 6 - "fmt" 7 7 "io" 8 8 "os" 9 9 "path/filepath" 10 - "sort" 10 + "slices" 11 + "strconv" 12 + "strings" 11 13 ) 12 14 13 15 // PathStyle controls how file paths are shown in output. ··· 21 23 22 24 // Reporter collects lint findings across files and flushes them in the desired format. 23 25 type Reporter struct { 24 - w io.Writer 26 + w *bufio.Writer 25 27 finds []Find 26 28 style PathStyle 27 29 cfg Config 28 30 } 29 31 30 32 func NewReporter(w io.Writer, style PathStyle, cfg Config) *Reporter { 31 - return &Reporter{w: w, style: style, cfg: cfg} 33 + return &Reporter{w: bufio.NewWriter(w), style: style, cfg: cfg} 32 34 } 33 35 34 36 func (r *Reporter) Collect(finds []Find) { ··· 48 50 } 49 51 50 52 func (r *Reporter) Flush(format string) error { 53 + defer r.w.Flush() 51 54 switch format { 52 55 case "json": 53 56 return fprintJSON(r.w, r.style, r.finds) ··· 62 65 // fprint writes finds in text format: file:line:col code: message. 63 66 func fprint(w io.Writer, style PathStyle, finds []Find) { 64 67 sortFinds(finds) 68 + wd, _ := os.Getwd() 65 69 for _, find := range finds { 66 - _, _ = fmt.Fprintf(w, "%s:%d:%d: %s: %s\n", 67 - formatPath(style, find.Span.File), 68 - find.Span.Start.Line, find.Span.Start.Col, 69 - find.Code, find.Message) 70 + io.WriteString(w, formatPath(style, find.Span.File, wd)) 71 + io.WriteString(w, ":") 72 + io.WriteString(w, strconv.Itoa(find.Span.Start.Line)) 73 + io.WriteString(w, ":") 74 + io.WriteString(w, strconv.Itoa(find.Span.Start.Col)) 75 + io.WriteString(w, ": ") 76 + io.WriteString(w, string(find.Code)) 77 + io.WriteString(w, ": ") 78 + io.WriteString(w, find.Message) 79 + io.WriteString(w, "\n") 70 80 } 71 81 } 72 82 ··· 82 92 // fprintJSON writes finds as [findJSON] array. 83 93 func fprintJSON(w io.Writer, style PathStyle, finds []Find) error { 84 94 sortFinds(finds) 95 + wd, _ := os.Getwd() 85 96 jsonFinds := make([]findJSON, len(finds)) 86 97 for i, find := range finds { 87 98 jsonFinds[i] = findJSON{ 88 99 Message: find.Message, 89 100 Severity: find.Severity.String(), // TODO: it's unset 90 101 Code: string(find.Code), 91 - File: formatPath(style, find.Span.File), 102 + File: formatPath(style, find.Span.File, wd), 92 103 Line: find.Span.Start.Line, 93 104 Column: find.Span.Start.Col, 94 105 } ··· 96 107 return json.NewEncoder(w).Encode(jsonFinds) 97 108 } 98 109 99 -func formatPath(style PathStyle, p string) string { 110 +func formatPath(style PathStyle, path, wdir string) string { 100 111 switch style { 101 112 case PathBasename: 102 - return filepath.Base(p) 113 + return filepath.Base(path) 103 114 case PathAbsolute: 104 - return p 115 + return path 105 116 case PathRelative: 106 - wd, err := os.Getwd() 107 - if err == nil { 108 - if rel, err := filepath.Rel(wd, p); err == nil { 117 + if wdir != "" { 118 + if rel, err := filepath.Rel(wdir, path); err == nil { 109 119 return rel 110 120 } 111 121 } 112 - return p 122 + return path 113 123 default: 114 124 panic("impossible PathStyle value") 115 125 } 116 126 } 117 127 118 128 func sortFinds(finds []Find) { 119 - sort.Slice(finds, func(i, j int) bool { 120 - if finds[i].Span.Start.Line != finds[j].Span.Start.Line { 121 - return finds[i].Span.Start.Line < finds[j].Span.Start.Line 129 + slices.SortFunc(finds, func(a, b Find) int { 130 + if a.Span.Start.Line != b.Span.Start.Line { 131 + return a.Span.Start.Line - b.Span.Start.Line 122 132 } 123 - if finds[i].Span.Start.Col != finds[j].Span.Start.Col { 124 - return finds[i].Span.Start.Col < finds[j].Span.Start.Col 133 + if a.Span.Start.Col != b.Span.Start.Col { 134 + return a.Span.Start.Col - b.Span.Start.Col 125 135 } 126 - if finds[i].Code != finds[j].Code { 127 - return finds[i].Code < finds[j].Code 136 + if a.Code != b.Code { 137 + return strings.Compare(string(a.Code), string(b.Code)) 128 138 } 129 - return finds[i].Message < finds[j].Message 139 + return strings.Compare(a.Message, b.Message) 130 140 }) 131 141 }