lang F0.3: multi-message diagnostic bundling + help-blocks
Feature 0 complete. addNote/addHelp bundle notes and help-blocks under a primary diagnostic (handle from new addId/addFmtId); help blocks carry an optional fix-it line that substitutes the suggested source. renderExtended now renders primary -> notes -> helps with blank-line separators. Wire the CLI to the extended renderer (renderErrors -> renderStderr) and flip render_style default to .extended; the previous renderErrors -> renderDebug path bypassed render() entirely, so flipping the field alone was a no-op. 13 diagnostic snapshots re-rendered to the extended format.
This commit is contained in:
@@ -237,12 +237,116 @@ test "renderExtended: multi-line span renders each line with carets" {
|
||||
try testing.expectEqualStrings(expected, output);
|
||||
}
|
||||
|
||||
test "render: default compact style still works" {
|
||||
test "renderExtended: primary bundled with one note" {
|
||||
var dl = errors.DiagnosticList.init(testing.allocator, "let x = y\nlet y = z\n", "b.sx");
|
||||
defer dl.deinit();
|
||||
const p = dl.addId(.err, "undefined name", Span{ .start = 8, .end = 9 });
|
||||
dl.addNote(p, Span{ .start = 14, .end = 15 }, "declared here");
|
||||
|
||||
const output = try renderToString(&dl, testing.allocator);
|
||||
defer testing.allocator.free(output);
|
||||
|
||||
const expected =
|
||||
\\error: undefined name
|
||||
\\ --> b.sx:1:9
|
||||
\\ |
|
||||
\\ 1 | let x = y
|
||||
\\ | ^
|
||||
\\
|
||||
\\note: declared here
|
||||
\\ --> b.sx:2:5
|
||||
\\ |
|
||||
\\ 2 | let y = z
|
||||
\\ | ^
|
||||
\\
|
||||
;
|
||||
try testing.expectEqualStrings(expected, output);
|
||||
}
|
||||
|
||||
test "renderExtended: primary bundled with help (no fix code)" {
|
||||
var dl = errors.DiagnosticList.init(testing.allocator, "foo bar\n", "h.sx");
|
||||
defer dl.deinit();
|
||||
const p = dl.addId(.err, "bad thing", Span{ .start = 0, .end = 3 });
|
||||
dl.addHelp(p, null, "try something else", null);
|
||||
|
||||
const output = try renderToString(&dl, testing.allocator);
|
||||
defer testing.allocator.free(output);
|
||||
|
||||
const expected =
|
||||
\\error: bad thing
|
||||
\\ --> h.sx:1:1
|
||||
\\ |
|
||||
\\ 1 | foo bar
|
||||
\\ | ^^^
|
||||
\\
|
||||
\\help: try something else
|
||||
\\
|
||||
;
|
||||
try testing.expectEqualStrings(expected, output);
|
||||
}
|
||||
|
||||
test "renderExtended: help with fix-it code substitutes the line and omits arrow" {
|
||||
var dl = errors.DiagnosticList.init(testing.allocator, " x := foo.value\n", "f.sx");
|
||||
defer dl.deinit();
|
||||
// primary span covers "value" at columns 12..17.
|
||||
const p = dl.addId(.err, "no such field", Span{ .start = 11, .end = 16 });
|
||||
dl.addHelp(p, Span{ .start = 11, .end = 16 }, "did you mean `val`?", " x := foo.val");
|
||||
|
||||
const output = try renderToString(&dl, testing.allocator);
|
||||
defer testing.allocator.free(output);
|
||||
|
||||
const expected =
|
||||
\\error: no such field
|
||||
\\ --> f.sx:1:12
|
||||
\\ |
|
||||
\\ 1 | x := foo.value
|
||||
\\ | ^^^^^
|
||||
\\
|
||||
\\help: did you mean `val`?
|
||||
\\ |
|
||||
\\ 1 | x := foo.val
|
||||
\\ | ^^^^^
|
||||
\\
|
||||
;
|
||||
try testing.expectEqualStrings(expected, output);
|
||||
}
|
||||
|
||||
test "renderExtended: note and help bundle in note-then-help order" {
|
||||
var dl = errors.DiagnosticList.init(testing.allocator, "aaa\n", "o.sx");
|
||||
defer dl.deinit();
|
||||
const p = dl.addId(.err, "primary", Span{ .start = 0, .end = 3 });
|
||||
// Add help first, then note: rendering must still emit note before help.
|
||||
dl.addHelp(p, null, "the help", null);
|
||||
dl.addNote(p, Span{ .start = 0, .end = 3 }, "the note");
|
||||
|
||||
const output = try renderToString(&dl, testing.allocator);
|
||||
defer testing.allocator.free(output);
|
||||
|
||||
const expected =
|
||||
\\error: primary
|
||||
\\ --> o.sx:1:1
|
||||
\\ |
|
||||
\\ 1 | aaa
|
||||
\\ | ^^^
|
||||
\\
|
||||
\\note: the note
|
||||
\\ --> o.sx:1:1
|
||||
\\ |
|
||||
\\ 1 | aaa
|
||||
\\ | ^^^
|
||||
\\
|
||||
\\help: the help
|
||||
\\
|
||||
;
|
||||
try testing.expectEqualStrings(expected, output);
|
||||
}
|
||||
|
||||
test "render: compact style still available behind the flag" {
|
||||
var dl = errors.DiagnosticList.init(testing.allocator, "abc\n", "c.sx");
|
||||
defer dl.deinit();
|
||||
dl.render_style = .compact;
|
||||
dl.add(.err, "compact error", Span{ .start = 0, .end = 3 });
|
||||
|
||||
// Default render_style is .compact — preserves the existing gcc-style.
|
||||
var aw = std.Io.Writer.Allocating.init(testing.allocator);
|
||||
defer {
|
||||
var r = aw.writer.toArrayList();
|
||||
|
||||
Reference in New Issue
Block a user