Render source-annotated error reports in the docs - #165
Open
vito wants to merge 7 commits into
Open
Conversation
Add ErrorReport/ErrorReporter: a renderer-neutral extraction of everything the terminal boundary printer shows — the primary message, public data fields, the cause chain, parallel sibling failures, and a ±2-line source window per site. Non-terminal frontends (the docs build, the wasm playground) can render annotated errors from this instead of scraping or discarding ANSI output. The extraction reuses the uncaught-report helpers (writeErrorFields refactored to share a new errorFields) so wording stays in lockstep with the terminal, which is unchanged. Nested InferenceErrors groups are flattened so interface-implementation checks surface every missing member, and ErrorReporter.Sources resolves locations pointing into earlier separately-parsed units (REPL entries, literate blocks). Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
CreateSourceError attached the current EvalContext's source to whatever node location the error carried, and WarnAtSource quoted that source under any warning site. When separately-parsed units evaluate against accumulated state — REPL entries, docs literate blocks — a location from an earlier unit would get the current unit's text quoted under its line numbers. Only attach the context's source when the location's filename matches the context's (or carries none at all). Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
Without cgo the tree-sitter enhancement is unavailable and ParseWithRecovery returned pigeon's raw error, whose message embeds a "filename:line:col (offset):" prefix — the wasm playground dumped that verbatim, synthetic filename and all. Convert the first pigeon error into a SourceError carrying the location and source, so every frontend annotates parse failures the same way; the cgo path now falls back to the same conversion when tree-sitter finds nothing to improve. The enhanced and fallback messages still word the failure differently, but both carry a location and the source text. Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
Union provenance notes printed origin.Loc.Filename unconditionally, which rendered a dangling "at :1:14" for locations without a filename (docs snippets, the playground) and would spell out synthetic unit names now that those parse under per-block filenames. The note sits beneath an error whose own annotation already names the file, so print line:col only. Golden files regenerated. Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
Expected-failure blocks used to bake a bare "stage: message" line, deliberately stripping SourceError's terminal rendering. Bake the structured report instead: a labeled header, the "--> line:col" arrow, a line-numbered gutter with syntax-highlighted source and a caret underline, plus data fields, "caused by:" chains, and "also failed:" siblings — the same shape formatSourceAnnotation prints, minus ANSI and the synthetic filename. Blocks parse under per-block filenames (snippet-N) and the session records each block's source, so a failure raised in a function defined fences earlier quotes that fence instead of dangling a bare arrow. Eval runs under an EvalContext like RunFile so non-raise faults carry locations, and captured output is stripped of ANSI (warnings color themselves for a terminal). playground.js rebuilds the identical DOM on replay (see the playground commit); this also evicts the raw escape bytes that sibling failures used to leak into mutation.html. Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
Return a structured "report" field from every wasm eval path and render it in playground.js as the same annotated DOM the build bakes — renderError, errorReportHtml, and highlightLinesHtml mirror docs/go/errorreport.go, with the bare label+message line kept as the fallback. Sessions number entries snippet-N exactly like the build and record each entry's source, so cross-entry locations quote the defining entry on replay. classify() ports the build's interface-wrapper retry, so fragments that don't parse bare (error-snippet windows, stdlib signatures) highlight identically in both places. REPL and playground errors previously dumped ANSI-laden SourceError.Error() text into the page; they now render annotated too. Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
The propagation section showed the uncaught error report as a hand-written caret drawing in a static fence, because the build could not generate one. Replace it with a live dang-failure fence raising DeployError from a rescue arm: the baked report now shows the real implicit cause chain, data fields, and raise sites, and the build verifies it like every other failure block. Signed-off-by: Alex Suraci <suraci.alex@gmail.com>
Deploying dang with
|
| Latest commit: |
9cbb990
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://66ddddc0.dang-3kk.pages.dev |
| Branch Preview URL: | https://docs-error-reports.dang-3kk.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Docs errors used to bake as a single pink line —
Runtime error: something went wrong— with the annotated rendering deliberately stripped (failureMessageunwrapped to the bare message in both the build and the wasm playground). Expected-failure blocks now bake the same source-annotated report the CLI prints: labeled header,--> line:colarrow, line-numbered gutter with syntax-highlighted source,^^^underline, plus the full uncaught treatment — public data fields, stackedcaused by:sections, andalso failed:siblings from a concurrent{{ }}.The core is a new renderer-neutral extraction in
pkg/dang(ErrorReport/ErrorReporter) that mirrors the boundary printer using its own helpers, so wording matches the terminal and terminal output itself is byte-for-byte unchanged (goldens pass untouched except one deliberate change, below). The docs build renders it to HTML (docs/go/errorreport.go), the wasm module returns it as a structuredreportfield, andplayground.jsrebuilds the identical DOM on replay — verified by a headless-browser harness that clicked Run on errors.html and diffed all 12 replayed error blocks byte-for-byte against the baked HTML.Along the way this fixes several latent issues:
snippet-N, same scheme in build and replay) with session-recorded sources, so a failure raised in a function defined fences earlier quotes that fence — the propagation section'slookup(404)block now shows the actualraise NotFoundError(...)site instead of a dangling location.CreateSourceError/WarnAtSourcegained a matching guard so a cross-unit location never gets the wrong unit's source quoted under its line numbers.InferenceErrorsgroups (interface-implementation checks) are flattened so every missing member surfaces, not just the first.playground.js'sclassify()ports the build'sinterface _ { }wrap-retry, so fragments that don't parse bare highlight identically client-side.SourceErrors instead of dumpingsnippet-N:1:22 (21): no match found…verbatim.at 1:14instead ofat :1:14(filename dropped — the error's own annotation already names the file); six goldens regenerated.DeployErrorfrom a rescue arm, so the uncaught-report example is generated and verified by the build like every other block.Built HTML, the search index, and
dang.wasmare gitignored build artifacts; rebuild withcd docs && ./build.sh. Verified: full test suite (new extraction/renderer tests included), cgo/no-cgo/wasm builds, a clean docs build, the browser replay diff above, and a Node harness driving the real wasm to confirm cross-entry quoting and the parse-error fallback.🤖 Generated with Claude Code