diff options
author | 2021-04-18 20:43:04 -0700 | |
---|---|---|
committer | 2021-04-18 20:43:04 -0700 | |
commit | 97c6c4b036d61ad5a42dff52340a6eb44dd8c855 (patch) | |
tree | de4fdd31827f9423db2566c9b62792ab9cb2d2c6 /src/logger.zig | |
parent | 41367499de215d8125310118ef82737c9aca8a57 (diff) | |
download | bun-97c6c4b036d61ad5a42dff52340a6eb44dd8c855.tar.gz bun-97c6c4b036d61ad5a42dff52340a6eb44dd8c855.tar.zst bun-97c6c4b036d61ad5a42dff52340a6eb44dd8c855.zip |
wip
Diffstat (limited to 'src/logger.zig')
-rw-r--r-- | src/logger.zig | 195 |
1 files changed, 176 insertions, 19 deletions
diff --git a/src/logger.zig b/src/logger.zig index 617eb4434..8180fd04b 100644 --- a/src/logger.zig +++ b/src/logger.zig @@ -1,5 +1,7 @@ const std = @import("std"); const strings = @import("strings.zig"); +const fs = @import("fs.zig"); +const unicode = std.unicode; const expect = std.testing.expect; const assert = std.debug.assert; @@ -24,13 +26,13 @@ pub const Kind = enum { pub const Loc = i32; pub const Location = struct { - file: []u8, - namespace: []u8 = "file", + file: []const u8, + namespace: []const u8 = "file", line: i32 = 1, // 1-based column: i32 = 0, // 0-based, in bytes - length: u32 = 0, // in bytes - line_text: ?[]u8, - suggestion: ?[]u8, + length: usize = 0, // in bytes + line_text: ?[]const u8 = null, + suggestion: ?[]const u8 = null, pub fn init(file: []u8, namespace: []u8, line: i32, column: i32, length: u32, line_text: ?[]u8, suggestion: ?[]u8) Location { return Location{ @@ -44,7 +46,23 @@ pub const Location = struct { }; } - pub fn init_file(file: []u8, line: i32, column: i32, length: u32, line_text: ?[]u8, suggestion: ?[]u8) Location { + pub fn init_or_nil(_source: ?Source, r: Range) ?Location { + if (_source) |source| { + var data = source.initErrorPosition(r.loc); + return Location{ + .file = source.path.pretty_path, + .namespace = source.path.namespace, + .line = usize2Loc(data.line_count), + .column = usize2Loc(data.column_count), + .length = source.contents.len, + .line_text = source.contents[data.line_start..data.line_end], + }; + } else { + return null; + } + } + + pub fn init_file(file: []const u8, line: i32, column: i32, length: u32, line_text: ?[]u8, suggestion: ?[]u8) Location { var namespace = "file".*; return Location{ @@ -59,14 +77,14 @@ pub const Location = struct { } }; -pub const Data = struct { text: []u8, location: *Location }; +pub const Data = struct { text: []u8, location: ?Location = null }; pub const Msg = struct { kind: Kind = Kind.err, data: Data, }; -pub const Range = struct { start: u32 = 0, len: i32 = 0 }; +pub const Range = struct { loc: Loc = 0, len: i32 = 0 }; pub const Log = struct { debug: bool = false, @@ -74,30 +92,169 @@ pub const Log = struct { errors: u8 = 0, msgs: ArrayList(Msg), + pub fn addVerbose(log: *Log, source: ?Source, loc: Loc, text: []u8) void { + log.addMsg(Msg{ + .kind = .verbose, + .data = rangeData(source, Range{ .Loc = loc }, text), + }); + } + + pub fn addVerboseWithNotes(source: ?Source, loc: Loc, text: []u8, notes: []Data) void { + log.addMsg(Msg{ + .kind = .verbose, + .data = rangeData(source, Range{ .loc = loc }, text), + .notes = notes, + }); + } + + pub fn addRangeError(log: *Log, source: ?Source, r: Range, text: []u8) void { + log.addMsg(Msg{ + .kind = .Error, + .data = rangeData(source, r, text), + }); + } + + pub fn addRangeWarning(log: *Log, source: ?Source, r: Range, text: []u8) void { + log.addMsg(Msg{ + .kind = .warning, + .data = rangeData(source, r, text), + }); + } + + pub fn addRangeDebug(log: *Log, source: ?Source, r: Range, text: []u8) void { + log.addMsg(Msg{ + .kind = .debug, + .data = rangeData(source, r, text), + }); + } + + pub fn addRangeErrorWithNotes(log: *Log, source: ?Source, r: Range, text: []u8, notes: []Data) void { + log.addMsg(Msg{ + .kind = Kind.err, + .data = rangeData(source, r, text), + .notes = notes, + }); + } + + pub fn addRangeWarningWithNotes(log: *Log, source: ?Source, r: Range, text: []u8, notes: []Data) void { + log.addMsg(Msg{ + .kind = .warning, + .data = rangeData(source, r, text), + .notes = notes, + }); + } + // TODO: - pub fn add_msg(self: *Log, msg: Msg) !void { + pub fn addMsg(self: *Log, msg: Msg) !void { try self.msgs.append(msg); } // TODO: - pub fn add_err(self: *Log, msg: Msg) !void { - // try self.msgs.append(msg); + pub fn addError(self: *Log, _source: ?Source, loc: Loc, text: []u8) !void { + try self.addMsg(Msg{ .kind = .err, .data = rangeData(_source, Range{ .loc = loc }, text) }); + self.errors += 1; } // TODO: pub fn print(self: *Log, to: anytype) !void { for (self.msgs.items) |msg| { - try std.fmt.format(to, "\n\n{s}: {s}\n{s}\n{s}:{}:{}", .{ msg.kind.string(), msg.data.text, msg.data.location.line_text, msg.data.location.file, msg.data.location.line, msg.data.location.column }); + try std.fmt.format(to, "\n\n{s}: {s}\n{s}\n{s}:{}:{}", .{ msg.kind.string(), msg.data.text, msg.data.location.?.line_text, msg.data.location.?.file, msg.data.location.?.line, msg.data.location.?.column }); } } }; -pub const Source = struct { index: u32 = 0, contents: []u8, +pub fn usize2Loc(loc: usize) Loc { + if (loc > std.math.maxInt(Loc)) { + return 9999; + } else { + return @intCast(Loc, loc); + } +} + +pub const Source = struct { + path: fs.Path, + index: u32 = 0, + contents: []const u8, + + // An identifier that is mixed in to automatically-generated symbol names to + // improve readability. For example, if the identifier is "util" then the + // symbol for an "export default" statement will be called "util_default". + identifier_name: []u8, + + pub const ErrorPosition = struct { line_start: usize, line_end: usize, column_count: usize, line_count: usize }; -// An identifier that is mixed in to automatically-generated symbol names to -// improve readability. For example, if the identifier is "util" then the -// symbol for an "export default" statement will be called "util_default". -identifier_name: []u8 }; + pub fn initPathString(pathString: []const u8, contents: []const u8, allocator: *std.mem.Allocator) Source { + const path = fs.Path.init(pathString, allocator); + return Source{ .path = path, .identifier_name = path.name.base, .contents = contents }; + } + + pub fn initErrorPosition(self: *const Source, _offset: Loc) ErrorPosition { + var prev_code_point: u21 = 0; + var offset: usize = if (_offset < 0) 0 else @intCast(usize, _offset); + + const contents = self.contents; + + var iter = unicode.Utf8Iterator{ + .bytes = self.contents[0..offset], + .i = std.math.min(offset, self.contents.len), + }; + + var line_start: usize = 0; + var line_count: usize = 0; + + while (iter.nextCodepoint()) |code_point| { + switch (code_point) { + '\n' => { + line_start = iter.i + 1; + if (prev_code_point != '\r') { + line_count += 1; + } + }, + + '\r' => { + line_start = iter.i + 1; + line_count += 1; + }, + + 0x2028, 0x2029 => { + line_start = iter.i + 3; // These take three bytes to encode in UTF-8 + line_count += 1; + }, + else => {}, + } + + prev_code_point = code_point; + } + + iter = unicode.Utf8Iterator{ + .bytes = self.contents[offset..], + .i = std.math.min(offset, self.contents.len), + }; + + // Scan to the end of the line (or end of file if this is the last line) + var line_end: usize = contents.len; + + loop: while (iter.nextCodepoint()) |code_point| { + switch (code_point) { + '\r', '\n', 0x2028, 0x2029 => { + line_end = offset + iter.i; + break :loop; + }, + else => {}, + } + } + return ErrorPosition{ + .line_start = line_start, + .line_end = line_end, + .line_count = line_count, + .column_count = offset - line_start, + }; + } +}; + +pub fn rangeData(source: ?Source, r: Range, text: []u8) Data { + return Data{ .text = text, .location = Location.init_or_nil(source, r) }; +} test "print msg" { var log = Log{ .msgs = ArrayList(Msg).init(std.testing.allocator) }; @@ -107,9 +264,9 @@ test "print msg" { var err = "invalid syntax".*; var namespace = "file".*; - try log.add_msg(Msg{ + try log.addMsg(Msg{ .kind = .err, - .data = Data{ .location = &Location.init_file(&filename, 1, 3, 0, &syntax, ""), .text = &err }, + .data = Data{ .location = Location.init_file(&filename, 1, 3, 0, &syntax, ""), .text = &err }, }); const stdout = std.io.getStdOut().writer(); |