fix(diagnostics): locate import parse errors in the imported file
A parse error raised while resolving an `#import` was rendered against the ROOT file's source — the caret landed on an unrelated line (often a comment) even though the message named the correct imported file. Two compounding causes: - core.zig wired `diagnostics.import_sources` only AFTER import resolution returned, but a parse error aborts mid-resolution (before that wiring), so the renderer had no imported sources and fell back to the root file. Wire it (and seed the main-file source) BEFORE resolving. - imports.zig emitted the diagnostic at the importer's `#import` span instead of the parser's actual error offset inside the imported file, and didn't pin the diagnostic's source_file to that file. parser.zig now records `err_end` alongside `err_offset` for a proper caret width. New `DiagnosticList.addFmtInFile` renders against an explicit source file; imports.zig uses it with `importErrSpan(&p)`. Regression test: examples/1176-diagnostics-import-parse-error-location (importer + deliberately-broken companion; caret must land in the companion).
This commit is contained in:
@@ -179,6 +179,18 @@ pub const DiagnosticList = struct {
|
||||
_ = self.addFmtId(level, span, fmt, args);
|
||||
}
|
||||
|
||||
/// Like `addFmt`, but renders against an EXPLICIT source file (resolved via
|
||||
/// `import_sources`) instead of the ambient `current_source_file`. Used to
|
||||
/// pin a diagnostic whose `span` is an offset into a NON-current file — e.g.
|
||||
/// a parse error raised while resolving an `#import`, where the span belongs
|
||||
/// to the imported file, not the importer.
|
||||
pub fn addFmtInFile(self: *DiagnosticList, level: Level, source_file: []const u8, span: ?Span, comptime fmt: []const u8, args: anytype) void {
|
||||
const saved = self.current_source_file;
|
||||
self.current_source_file = source_file;
|
||||
defer self.current_source_file = saved;
|
||||
_ = self.addFmtId(level, span, fmt, args);
|
||||
}
|
||||
|
||||
pub fn addFmtId(self: *DiagnosticList, level: Level, span: ?Span, comptime fmt: []const u8, args: anytype) usize {
|
||||
const message = std.fmt.allocPrint(self.allocator, fmt, args) catch "diagnostic format error";
|
||||
return self.addId(level, message, span);
|
||||
|
||||
Reference in New Issue
Block a user