...
1
16
17 package utils
18
19 import (
20 "encoding/json"
21 "fmt"
22 "github.com/bazelbuild/buildtools/build"
23 "github.com/bazelbuild/buildtools/warn"
24 "strings"
25 )
26
27
28 type Diagnostics struct {
29 Success bool `json:"success"`
30 Files []*FileDiagnostics `json:"files"`
31 }
32
33
34 func (d *Diagnostics) Format(format string, verbose bool) string {
35 switch format {
36 case "text", "":
37 var output strings.Builder
38 for _, f := range d.Files {
39 for _, w := range f.Warnings {
40 formatString := "%s:%d: %s: %s (%s)\n"
41 if !w.Actionable {
42 formatString = "%s:%d: %s: %s [%s]\n"
43 }
44 output.WriteString(fmt.Sprintf(formatString,
45 f.Filename,
46 w.Start.Line,
47 w.Category,
48 w.Message,
49 w.URL))
50 }
51 if !f.Formatted {
52 output.WriteString(fmt.Sprintf("%s # reformat\n", f.Filename))
53 }
54 }
55 return output.String()
56 case "json":
57 var result []byte
58 if verbose {
59 result, _ = json.MarshalIndent(*d, "", " ")
60 } else {
61 result, _ = json.Marshal(*d)
62 }
63 return string(result) + "\n"
64 }
65 return ""
66 }
67
68
69 type FileDiagnostics struct {
70 Filename string `json:"filename"`
71 Formatted bool `json:"formatted"`
72 Valid bool `json:"valid"`
73 Warnings []*warning `json:"warnings"`
74 }
75
76 type warning struct {
77 Start position `json:"start"`
78 End position `json:"end"`
79 Category string `json:"category"`
80 Actionable bool `json:"actionable"`
81 AutoFixable bool `json:"autoFixable"`
82 Message string `json:"message"`
83 URL string `json:"url"`
84 }
85
86 type position struct {
87 Line int `json:"line"`
88 Column int `json:"column"`
89 }
90
91
92 func NewDiagnostics(fileDiagnostics ...*FileDiagnostics) *Diagnostics {
93 diagnostics := &Diagnostics{
94 Success: true,
95 Files: fileDiagnostics,
96 }
97 for _, file := range diagnostics.Files {
98 if !file.Formatted || len(file.Warnings) > 0 {
99 diagnostics.Success = false
100 break
101 }
102 }
103 return diagnostics
104 }
105
106
107 func NewFileDiagnostics(filename string, warnings []*warn.Finding) *FileDiagnostics {
108 fileDiagnostics := FileDiagnostics{
109 Filename: filename,
110 Formatted: true,
111 Valid: true,
112 Warnings: []*warning{},
113 }
114
115 for _, w := range warnings {
116 fileDiagnostics.Warnings = append(fileDiagnostics.Warnings, &warning{
117 Start: makePosition(w.Start),
118 End: makePosition(w.End),
119 Category: w.Category,
120 Actionable: w.Actionable,
121 AutoFixable: w.AutoFixable,
122 Message: w.Message,
123 URL: w.URL,
124 })
125 }
126
127 return &fileDiagnostics
128 }
129
130
131 func InvalidFileDiagnostics(filename string) *FileDiagnostics {
132 fileDiagnostics := &FileDiagnostics{
133 Filename: filename,
134 Formatted: false,
135 Valid: false,
136 Warnings: []*warning{},
137 }
138 if filename == "" {
139 fileDiagnostics.Filename = "<stdin>"
140 }
141 return fileDiagnostics
142 }
143
144 func makePosition(p build.Position) position {
145 return position{
146 Line: p.Line,
147 Column: p.LineRune,
148 }
149 }
150
View as plain text