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:
@@ -796,6 +796,17 @@ fn reportDuplicateName(diagnostics: ?*errors.DiagnosticList, added: bool, name:
|
||||
diags.addFmt(.err, span, "duplicate top-level declaration '{s}'", .{name});
|
||||
}
|
||||
|
||||
/// Build the diagnostic span for a failed import parse, from the parser's
|
||||
/// ACTUAL error location INSIDE the imported file (`err_offset`/`err_end`) —
|
||||
/// not the importing file's `#import` span. Pair with `addFmtInFile` so the
|
||||
/// caret resolves against the imported file's own source (the source is already
|
||||
/// registered in `import_sources`); otherwise it falls back to the root file
|
||||
/// and the caret lands on an unrelated line.
|
||||
fn importErrSpan(p: *const parser.Parser) ast.Span {
|
||||
const start = p.err_offset orelse 0;
|
||||
return .{ .start = start, .end = p.err_end orelse start };
|
||||
}
|
||||
|
||||
/// Stamp the DEFINING module path onto a function body node, so a later
|
||||
/// pack/comptime monomorphization can pin `current_source_file` to the body's
|
||||
/// own module and resolve its bare names in that module's visibility context
|
||||
@@ -1062,7 +1073,7 @@ pub fn resolveImports(
|
||||
var p = parser.Parser.init(allocator, imp_source);
|
||||
const imp_root = p.parse() catch {
|
||||
if (diagnostics) |diags| {
|
||||
diags.addFmt(.err, decl.span, "parse error in '{s}': {s}", .{ resolved_path, p.err_msg orelse "unknown" });
|
||||
diags.addFmtInFile(.err, resolved_path, importErrSpan(&p), "parse error in '{s}': {s}", .{ resolved_path, p.err_msg orelse "unknown" });
|
||||
}
|
||||
return error.ImportError;
|
||||
};
|
||||
@@ -1207,7 +1218,7 @@ fn resolveDirectoryImport(
|
||||
var p = parser.Parser.init(allocator, imp_source);
|
||||
const imp_root = p.parse() catch {
|
||||
if (diagnostics) |diags| {
|
||||
diags.addFmt(.err, span, "parse error in '{s}': {s}", .{ file_path, p.err_msg orelse "unknown" });
|
||||
diags.addFmtInFile(.err, file_path, importErrSpan(&p), "parse error in '{s}': {s}", .{ file_path, p.err_msg orelse "unknown" });
|
||||
}
|
||||
return error.ImportError;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user