zig/src-self-hosted/errmsg.zig

101 lines
2.6 KiB
Zig
Raw Normal View History

const std = @import("std");
const mem = std.mem;
const os = std.os;
const Token = std.zig.Token;
const ast = std.zig.ast;
const TokenIndex = std.zig.ast.TokenIndex;
pub const Color = enum {
Auto,
Off,
On,
};
pub const Span = struct {
first: ast.TokenIndex,
last: ast.TokenIndex,
2018-07-13 18:56:38 -07:00
pub fn token(i: TokenIndex) Span {
return Span {
.first = i,
.last = i,
};
}
};
pub const Msg = struct {
path: []const u8,
text: []u8,
span: Span,
tree: *ast.Tree,
};
/// `path` must outlive the returned Msg
/// `tree` must outlive the returned Msg
/// Caller owns returned Msg and must free with `allocator`
pub fn createFromParseError(
allocator: *mem.Allocator,
parse_error: *const ast.Error,
tree: *ast.Tree,
path: []const u8,
) !*Msg {
const loc_token = parse_error.loc();
var text_buf = try std.Buffer.initSize(allocator, 0);
defer text_buf.deinit();
var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
try parse_error.render(&tree.tokens, out_stream);
const msg = try allocator.create(Msg{
.tree = tree,
.path = path,
.text = text_buf.toOwnedSlice(),
.span = Span{
.first = loc_token,
.last = loc_token,
},
});
errdefer allocator.destroy(msg);
return msg;
}
pub fn printToStream(stream: var, msg: *const Msg, color_on: bool) !void {
const first_token = msg.tree.tokens.at(msg.span.first);
const last_token = msg.tree.tokens.at(msg.span.last);
const start_loc = msg.tree.tokenLocationPtr(0, first_token);
const end_loc = msg.tree.tokenLocationPtr(first_token.end, last_token);
if (!color_on) {
try stream.print(
"{}:{}:{}: error: {}\n",
msg.path,
start_loc.line + 1,
start_loc.column + 1,
msg.text,
);
return;
}
try stream.print(
"{}:{}:{}: error: {}\n{}\n",
msg.path,
start_loc.line + 1,
start_loc.column + 1,
msg.text,
msg.tree.source[start_loc.line_start..start_loc.line_end],
);
try stream.writeByteNTimes(' ', start_loc.column);
try stream.writeByteNTimes('~', last_token.end - first_token.start);
try stream.write("\n");
}
pub fn printToFile(file: *os.File, msg: *const Msg, color: Color) !void {
const color_on = switch (color) {
Color.Auto => file.isTty(),
Color.On => true,
Color.Off => false,
};
var stream = &std.io.FileOutStream.init(file).stream;
return printToStream(stream, msg, color_on);
}