hcl: Simplify the text DiagnosticWriter using new Range functions
Now that we have helper methods for computing relationships between ranges, we can eliminate all of the tricky line-counting and byte-counting code here and instead use the higher-level operations. The result is a single loop using the RangeScanner.
This commit is contained in:
parent
368a3f81c0
commit
14cfe59a52
@ -2,7 +2,6 @@ package hcl
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -70,21 +69,15 @@ func (w *diagnosticTextWriter) WriteDiagnostic(diag *Diagnostic) error {
|
||||
if diag.Subject != nil {
|
||||
|
||||
file := w.files[diag.Subject.Filename]
|
||||
if file == nil || file.Bytes == nil {
|
||||
if file == nil || file.Bytes == nil || diag.Subject.Empty() {
|
||||
fmt.Fprintf(w.wr, " on %s line %d:\n (source code not available)\n\n", diag.Subject.Filename, diag.Subject.Start.Line)
|
||||
} else {
|
||||
src := file.Bytes
|
||||
r := bytes.NewReader(src)
|
||||
sc := bufio.NewScanner(r)
|
||||
sc.Split(bufio.ScanLines)
|
||||
|
||||
var startLine, endLine int
|
||||
snipRange := *diag.Subject
|
||||
if diag.Context != nil {
|
||||
startLine = diag.Context.Start.Line
|
||||
endLine = diag.Context.End.Line
|
||||
} else {
|
||||
startLine = diag.Subject.Start.Line
|
||||
endLine = diag.Subject.End.Line
|
||||
// Show enough of the source code to include both the subject
|
||||
// and context ranges, which overlap in all reasonable
|
||||
// situations.
|
||||
snipRange = RangeOver(snipRange, *diag.Context)
|
||||
}
|
||||
|
||||
var contextLine string
|
||||
@ -95,35 +88,18 @@ func (w *diagnosticTextWriter) WriteDiagnostic(diag *Diagnostic) error {
|
||||
}
|
||||
}
|
||||
|
||||
li := 1
|
||||
var ls string
|
||||
for sc.Scan() {
|
||||
ls = sc.Text()
|
||||
|
||||
if li == startLine {
|
||||
break
|
||||
}
|
||||
li++
|
||||
}
|
||||
|
||||
fmt.Fprintf(w.wr, " on %s line %d%s:\n", diag.Subject.Filename, diag.Subject.Start.Line, contextLine)
|
||||
|
||||
// TODO: Generate markers for the specific characters that are in the Context and Subject ranges.
|
||||
// For now, we just print out the lines.
|
||||
src := file.Bytes
|
||||
sc := NewRangeScanner(src, diag.Subject.Filename, bufio.ScanLines)
|
||||
|
||||
fmt.Fprintf(w.wr, "%4d: %s\n", li, ls)
|
||||
|
||||
if endLine > li {
|
||||
for sc.Scan() {
|
||||
ls = sc.Text()
|
||||
li++
|
||||
|
||||
fmt.Fprintf(w.wr, "%4d: %s\n", li, ls)
|
||||
|
||||
if li == endLine {
|
||||
break
|
||||
}
|
||||
for sc.Scan() {
|
||||
lineRange := sc.Range()
|
||||
if !lineRange.Overlaps(snipRange) {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintf(w.wr, "%4d: %s\n", lineRange.Start.Line, sc.Bytes())
|
||||
}
|
||||
|
||||
w.wr.Write([]byte{'\n'})
|
||||
|
@ -45,10 +45,12 @@ All splines must be pre-reticulated.
|
||||
Detail: `"baz" is not a supported top-level attribute. Did you mean "bam"?`,
|
||||
Subject: &Range{
|
||||
Start: Pos{
|
||||
Byte: 16,
|
||||
Column: 1,
|
||||
Line: 3,
|
||||
},
|
||||
End: Pos{
|
||||
Byte: 19,
|
||||
Column: 4,
|
||||
Line: 3,
|
||||
},
|
||||
@ -71,10 +73,12 @@ attribute. Did you mean "bam"?
|
||||
Detail: `"pizza" is not a supported attribute. Did you mean "pizzetta"?`,
|
||||
Subject: &Range{
|
||||
Start: Pos{
|
||||
Byte: 42,
|
||||
Column: 3,
|
||||
Line: 5,
|
||||
},
|
||||
End: Pos{
|
||||
Byte: 47,
|
||||
Column: 8,
|
||||
Line: 5,
|
||||
},
|
||||
@ -83,10 +87,12 @@ attribute. Did you mean "bam"?
|
||||
// whether we're able to show a multi-line context when needed.
|
||||
Context: &Range{
|
||||
Start: Pos{
|
||||
Byte: 24,
|
||||
Column: 1,
|
||||
Line: 4,
|
||||
},
|
||||
End: Pos{
|
||||
Byte: 60,
|
||||
Column: 2,
|
||||
Line: 6,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user