The current Span type is stored as a single point plus a byte length:
type Span = {
offset: number
length: number
line: number
column: number
}
This is fine for simple single-line errors, but it starts to break down once we want:
- Multi-line spans (e.g. an unclosed string that runs for several lines)
- Related spans ("unclosed
( opened here")
- Clean conversion to LSP / JSON / SARIF output formats
- Span unions and precise end positions
I'd like to move to a start/end position model:
type Position = {
byteOffset: number
charOffset: number
line: number
column: number
}
type Span = {
start: Position
end: Position
}
byteOffset stays for fast source.slice(...), and charOffset/column become user-facing. This is a breaking change to the public Span shape, so it should be done before a 1.0 release if possible.
Open questions:
- Should we keep the old
Span(state, length) factory for backwards compatibility?
- Should
Span carry a cached source slice, or keep slicing on demand in the formatter?
- How does this affect
Parser.spanned() and the internal Span() helper in errors.ts?
The current
Spantype is stored as a single point plus a byte length:This is fine for simple single-line errors, but it starts to break down once we want:
(opened here")I'd like to move to a start/end position model:
byteOffsetstays for fastsource.slice(...), andcharOffset/columnbecome user-facing. This is a breaking change to the publicSpanshape, so it should be done before a 1.0 release if possible.Open questions:
Span(state, length)factory for backwards compatibility?Spancarry a cachedsourceslice, or keep slicing on demand in the formatter?Parser.spanned()and the internalSpan()helper inerrors.ts?