6743a2254b
By default we generate human-readable diagnostics on the assumption that the caller is a simple program that is capturing stdin via a pipe and letting stderr go to the terminal. More sophisticated callers may wish to analyze the diagnostics themselves and perhaps present them in a different way, such as via a GUI.
102 lines
2.2 KiB
Go
102 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
|
|
"github.com/hashicorp/hcl2/hcl"
|
|
)
|
|
|
|
type jsonDiagWriter struct {
|
|
w io.Writer
|
|
diags hcl.Diagnostics
|
|
}
|
|
|
|
var _ hcl.DiagnosticWriter = &jsonDiagWriter{}
|
|
|
|
func (wr *jsonDiagWriter) WriteDiagnostic(diag *hcl.Diagnostic) error {
|
|
wr.diags = append(wr.diags, diag)
|
|
return nil
|
|
}
|
|
|
|
func (wr *jsonDiagWriter) WriteDiagnostics(diags hcl.Diagnostics) error {
|
|
wr.diags = append(wr.diags, diags...)
|
|
return nil
|
|
}
|
|
|
|
func (wr *jsonDiagWriter) Flush() error {
|
|
if len(wr.diags) == 0 {
|
|
return nil
|
|
}
|
|
|
|
type PosJSON struct {
|
|
Line int `json:"line"`
|
|
Column int `json:"column"`
|
|
Byte int `json:"byte"`
|
|
}
|
|
type RangeJSON struct {
|
|
Filename string `json:"filename"`
|
|
Start PosJSON `json:"start"`
|
|
End PosJSON `json:"end"`
|
|
}
|
|
type DiagnosticJSON struct {
|
|
Severity string `json:"severity"`
|
|
Summary string `json:"summary"`
|
|
Detail string `json:"detail,omitempty"`
|
|
Subject *RangeJSON `json:"subject,omitempty"`
|
|
}
|
|
type DiagnosticsJSON struct {
|
|
Diagnostics []DiagnosticJSON `json:"diagnostics"`
|
|
}
|
|
|
|
diagsJSON := make([]DiagnosticJSON, 0, len(wr.diags))
|
|
for _, diag := range wr.diags {
|
|
var diagJSON DiagnosticJSON
|
|
|
|
switch diag.Severity {
|
|
case hcl.DiagError:
|
|
diagJSON.Severity = "error"
|
|
case hcl.DiagWarning:
|
|
diagJSON.Severity = "warning"
|
|
default:
|
|
diagJSON.Severity = "(unknown)" // should never happen
|
|
}
|
|
|
|
diagJSON.Summary = diag.Summary
|
|
diagJSON.Detail = diag.Detail
|
|
if diag.Subject != nil {
|
|
diagJSON.Subject = &RangeJSON{}
|
|
sJSON := diagJSON.Subject
|
|
rng := diag.Subject
|
|
sJSON.Filename = rng.Filename
|
|
sJSON.Start.Line = rng.Start.Line
|
|
sJSON.Start.Column = rng.Start.Column
|
|
sJSON.Start.Byte = rng.Start.Byte
|
|
sJSON.End.Line = rng.End.Line
|
|
sJSON.End.Column = rng.End.Column
|
|
sJSON.End.Byte = rng.End.Byte
|
|
}
|
|
|
|
diagsJSON = append(diagsJSON, diagJSON)
|
|
}
|
|
|
|
src, err := json.MarshalIndent(DiagnosticsJSON{diagsJSON}, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = wr.w.Write(src)
|
|
wr.w.Write([]byte{'\n'})
|
|
return err
|
|
}
|
|
|
|
type flusher interface {
|
|
Flush() error
|
|
}
|
|
|
|
func flush(maybeFlusher interface{}) error {
|
|
if f, ok := maybeFlusher.(flusher); ok {
|
|
return f.Flush()
|
|
}
|
|
return nil
|
|
}
|