Documentation
¶
Overview ¶
Package diagnostic provides Rust-style annotated error rendering for ELPS CLI output. It is intentionally independent of the lisp/ package so that it can be used by any CLI command without creating import cycles.
Index ¶
- type ColorMode
- type Diagnostic
- type Renderer
- type Session
- func (s *Session) Finish() (int, error)
- func (s *Session) Header(message func())
- func (s *Session) Note(note func())
- func (s *Session) Remaining() int
- func (s *Session) Span(span Span)
- func (s *Session) Step() bool
- func (s *Session) Stop()
- func (s *Session) Text(parts ...string)
- func (s *Session) Write(p []byte) (int, error)
- type Severity
- type Span
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Diagnostic ¶
type Diagnostic struct {
Severity Severity
Message string
Spans []Span
Notes []string // "= note:" lines (stack trace frames, etc.)
}
Diagnostic represents a single error, warning, or note with optional source annotations and trailing notes.
type Renderer ¶
type Renderer struct {
// Color controls ANSI color output. Default is ColorAuto.
Color ColorMode
// SourceReader reads source file contents. If nil, os.ReadFile is used.
SourceReader func(string) ([]byte, error)
}
Renderer formats diagnostics as Rust-style annotated source snippets.
func (*Renderer) NewSession ¶ added in v1.62.0
NewSession reserves space for a truncation marker within limit bytes. The request context and work budget cover construction, source reads and writing.
type Session ¶ added in v1.62.0
type Session struct {
// contains filtered or unexported fields
}
Session streams one complete diagnostic under a shared byte/work budget. Callers must check Step before constructing fields and use Remaining before allocating variable-sized text. Text writes existing fields in bounded chunks. Finish emits a fitting marker on exhaustion, including cancellation by a writer. Like io.Writer, a session cannot interrupt a Write already in progress.
func (*Session) Finish ¶ added in v1.62.0
Finish completes the report, returning the actual bytes written and I/O error.
func (*Session) Header ¶ added in v1.62.0
func (s *Session) Header(message func())
Header writes an error header, invoking message only while work remains.
func (*Session) Note ¶ added in v1.62.0
func (s *Session) Note(note func())
Note streams a note without building an intermediate concatenated string.
func (*Session) Remaining ¶ added in v1.62.0
Remaining is the space available for content, excluding the reserved marker.
func (*Session) Span ¶ added in v1.62.0
Span displays a source location and snippet under this session's budget.
func (*Session) Step ¶ added in v1.62.0
Step charges one unit of work and checks cancellation. All producers share it.
func (*Session) Stop ¶ added in v1.62.0
func (s *Session) Stop()
Stop records that the complete diagnostic could not be produced.
type Span ¶
type Span struct {
File string // path for reading source; display name if unreadable
Line int // 1-based line number
Col int // 1-based start byte column
EndCol int // 1-based end byte column, INCLUSIVE (0 = auto-detect from source)
Label string // text shown under the underline
}
Span identifies a region of source code to highlight in the diagnostic.
UNITS AND CONVENTION. Col and EndCol are 1-based BYTE columns, and EndCol is INCLUSIVE -- it names the column of the span's last byte, not the one after it. A span covering "false" at columns 7 through 11 is Col: 7, EndCol: 11.
That is the OPPOSITE of parser/token.Location.EndCol, which is documented (as of the #463 fix) as an EXCLUSIVE byte column. The two types have same-named fields with opposite conventions, and nothing in the tree bridges one into the other today: cmd/diagnostic.go and repl/diagnostic.go both set Col and leave EndCol zero for auto-detection. The first caller to wire an analyser's end position straight into a Span would get an underline one caret too long, which is why the convention is written down here rather than left to be inferred (issue #469). Converting is `EndCol: loc.EndCol - 1`.
The RENDERER measures the underline in terminal CELLS rather than in bytes, so the carets line up with what a terminal draws even when the span holds multi-byte, East Asian wide, or combining characters -- see displayWidth in renderer.go. The byte convention here is about how a caller ADDRESSES the source; it is not the unit the carets are counted in.