| ... | @@ -37,7 +37,11 @@ const ErrorMsg = union(enum) { | ... | @@ -37,7 +37,11 @@ const ErrorMsg = union(enum) { |
| 37 | src: struct { | 37 | src: struct { |
| 38 | src_path: []const u8, | 38 | src_path: []const u8, |
| 39 | msg: []const u8, | 39 | msg: []const u8, |
| | 40 | // maxint means match anything |
| | 41 | // this is a workaround for stage1 compiler bug I ran into when making it ?u32 |
| 40 | line: u32, | 42 | line: u32, |
| | 43 | // maxint means match anything |
| | 44 | // this is a workaround for stage1 compiler bug I ran into when making it ?u32 |
| 41 | column: u32, | 45 | column: u32, |
| 42 | kind: Kind, | 46 | kind: Kind, |
| 43 | }, | 47 | }, |
| ... | @@ -81,13 +85,23 @@ const ErrorMsg = union(enum) { | ... | @@ -81,13 +85,23 @@ const ErrorMsg = union(enum) { |
| 81 | _ = options; | 85 | _ = options; |
| 82 | switch (self) { | 86 | switch (self) { |
| 83 | .src => |src| { | 87 | .src => |src| { |
| 84 | return writer.print("{s}:{d}:{d}: {s}: {s}", .{ | 88 | if (!std.mem.eql(u8, src.src_path, "?") or |
| 85 | src.src_path, | 89 | src.line != std.math.maxInt(u32) or |
| 86 | src.line + 1, | 90 | src.column != std.math.maxInt(u32)) |
| 87 | src.column + 1, | 91 | { |
| 88 | @tagName(src.kind), | 92 | try writer.print("{s}:", .{src.src_path}); |
| 89 | src.msg, | 93 | if (src.line != std.math.maxInt(u32)) { |
| 90 | }); | 94 | try writer.print("{d}:", .{src.line + 1}); |
| | 95 | } else { |
| | 96 | try writer.writeAll("?:"); |
| | 97 | } |
| | 98 | if (src.column != std.math.maxInt(u32)) { |
| | 99 | try writer.print("{d}: ", .{src.column + 1}); |
| | 100 | } else { |
| | 101 | try writer.writeAll("?: "); |
| | 102 | } |
| | 103 | } |
| | 104 | return writer.print("{s}: {s}", .{ @tagName(src.kind), src.msg }); |
| 91 | }, | 105 | }, |
| 92 | .plain => |plain| { | 106 | .plain => |plain| { |
| 93 | return writer.print("{s}: {s}", .{ @tagName(plain.kind), plain.msg }); | 107 | return writer.print("{s}: {s}", .{ @tagName(plain.kind), plain.msg }); |
| ... | @@ -220,8 +234,14 @@ pub const TestContext = struct { | ... | @@ -220,8 +234,14 @@ pub const TestContext = struct { |
| 220 | const kind_text = it.next() orelse @panic("missing 'error'/'note'"); | 234 | const kind_text = it.next() orelse @panic("missing 'error'/'note'"); |
| 221 | const msg = it.rest()[1..]; // skip over the space at end of "error: " | 235 | const msg = it.rest()[1..]; // skip over the space at end of "error: " |
| 222 | | 236 | |
| 223 | const line = std.fmt.parseInt(u32, line_text, 10) catch @panic("bad line number"); | 237 | const line: ?u32 = if (std.mem.eql(u8, line_text, "?")) |
| 224 | const column = std.fmt.parseInt(u32, col_text, 10) catch @panic("bad column number"); | 238 | null |
| | 239 | else |
| | 240 | std.fmt.parseInt(u32, line_text, 10) catch @panic("bad line number"); |
| | 241 | const column: ?u32 = if (std.mem.eql(u8, line_text, "?")) |
| | 242 | null |
| | 243 | else |
| | 244 | std.fmt.parseInt(u32, col_text, 10) catch @panic("bad column number"); |
| 225 | const kind: ErrorMsg.Kind = if (std.mem.eql(u8, kind_text, " error")) | 245 | const kind: ErrorMsg.Kind = if (std.mem.eql(u8, kind_text, " error")) |
| 226 | .@"error" | 246 | .@"error" |
| 227 | else if (std.mem.eql(u8, kind_text, " note")) | 247 | else if (std.mem.eql(u8, kind_text, " note")) |
| ... | @@ -229,16 +249,28 @@ pub const TestContext = struct { | ... | @@ -229,16 +249,28 @@ pub const TestContext = struct { |
| 229 | else | 249 | else |
| 230 | @panic("expected 'error'/'note'"); | 250 | @panic("expected 'error'/'note'"); |
| 231 | | 251 | |
| 232 | if (line == 0 or column == 0) { | 252 | const line_0based: u32 = if (line) |n| blk: { |
| 233 | @panic("line and column must be specified starting at one"); | 253 | if (n == 0) { |
| 234 | } | 254 | print("{s}: line must be specified starting at one\n", .{self.name}); |
| | 255 | return; |
| | 256 | } |
| | 257 | break :blk n - 1; |
| | 258 | } else std.math.maxInt(u32); |
| | 259 | |
| | 260 | const column_0based: u32 = if (column) |n| blk: { |
| | 261 | if (n == 0) { |
| | 262 | print("{s}: line must be specified starting at one\n", .{self.name}); |
| | 263 | return; |
| | 264 | } |
| | 265 | break :blk n - 1; |
| | 266 | } else std.math.maxInt(u32); |
| 235 | | 267 | |
| 236 | array[i] = .{ | 268 | array[i] = .{ |
| 237 | .src = .{ | 269 | .src = .{ |
| 238 | .src_path = src_path, | 270 | .src_path = src_path, |
| 239 | .msg = msg, | 271 | .msg = msg, |
| 240 | .line = line - 1, | 272 | .line = line_0based, |
| 241 | .column = column - 1, | 273 | .column = column_0based, |
| 242 | .kind = kind, | 274 | .kind = kind, |
| 243 | }, | 275 | }, |
| 244 | }; | 276 | }; |
| ... | @@ -737,7 +769,7 @@ pub const TestContext = struct { | ... | @@ -737,7 +769,7 @@ pub const TestContext = struct { |
| 737 | } | 769 | } |
| 738 | var ok = true; | 770 | var ok = true; |
| 739 | if (case.expect_exact) { | 771 | if (case.expect_exact) { |
| 740 | var err_iter = ErrLineIter.init(result.stderr); | 772 | var err_iter = std.mem.split(result.stderr, "\n"); |
| 741 | var i: usize = 0; | 773 | var i: usize = 0; |
| 742 | ok = while (err_iter.next()) |line| : (i += 1) { | 774 | ok = while (err_iter.next()) |line| : (i += 1) { |
| 743 | if (i >= case_error_list.len) break false; | 775 | if (i >= case_error_list.len) break false; |
| ... | @@ -940,8 +972,10 @@ pub const TestContext = struct { | ... | @@ -940,8 +972,10 @@ pub const TestContext = struct { |
| 940 | std.mem.eql(u8, case_msg.src.src_path, actual_msg.src_path); | 972 | std.mem.eql(u8, case_msg.src.src_path, actual_msg.src_path); |
| 941 | | 973 | |
| 942 | if (src_path_ok and | 974 | if (src_path_ok and |
| 943 | actual_msg.line == case_msg.src.line and | 975 | (case_msg.src.line == std.math.maxInt(u32) or |
| 944 | actual_msg.column == case_msg.src.column and | 976 | actual_msg.line == case_msg.src.line) and |
| | 977 | (case_msg.src.column == std.math.maxInt(u32) or |
| | 978 | actual_msg.column == case_msg.src.column) and |
| 945 | std.mem.eql(u8, case_msg.src.msg, actual_msg.msg) and | 979 | std.mem.eql(u8, case_msg.src.msg, actual_msg.msg) and |
| 946 | case_msg.src.kind == .@"error") | 980 | case_msg.src.kind == .@"error") |
| 947 | { | 981 | { |
| ... | @@ -978,8 +1012,10 @@ pub const TestContext = struct { | ... | @@ -978,8 +1012,10 @@ pub const TestContext = struct { |
| 978 | } | 1012 | } |
| 979 | if (ex_tag != .src) continue; | 1013 | if (ex_tag != .src) continue; |
| 980 | | 1014 | |
| 981 | if (actual_msg.line == case_msg.src.line and | 1015 | if ((case_msg.src.line == std.math.maxInt(u32) or |
| 982 | actual_msg.column == case_msg.src.column and | 1016 | actual_msg.line == case_msg.src.line) and |
| | 1017 | (case_msg.src.column == std.math.maxInt(u32) or |
| | 1018 | actual_msg.column == case_msg.src.column) and |
| 983 | std.mem.eql(u8, case_msg.src.msg, actual_msg.msg) and | 1019 | std.mem.eql(u8, case_msg.src.msg, actual_msg.msg) and |
| 984 | case_msg.src.kind == .note) | 1020 | case_msg.src.kind == .note) |
| 985 | { | 1021 | { |
| ... | @@ -1162,19 +1198,3 @@ fn dumpArgs(argv: []const []const u8) void { | ... | @@ -1162,19 +1198,3 @@ fn dumpArgs(argv: []const []const u8) void { |
| 1162 | } | 1198 | } |
| 1163 | | 1199 | |
| 1164 | const tmp_src_path = "tmp.zig"; | 1200 | const tmp_src_path = "tmp.zig"; |
| 1165 | | | |
| 1166 | const ErrLineIter = struct { | | |
| 1167 | lines: std.mem.SplitIterator, | | |
| 1168 | | | |
| 1169 | fn init(input: []const u8) ErrLineIter { | | |
| 1170 | return ErrLineIter{ .lines = std.mem.split(input, "\n") }; | | |
| 1171 | } | | |
| 1172 | | | |
| 1173 | fn next(self: *ErrLineIter) ?[]const u8 { | | |
| 1174 | while (self.lines.next()) |line| { | | |
| 1175 | if (std.mem.indexOf(u8, line, tmp_src_path) != null) | | |
| 1176 | return line; | | |
| 1177 | } | | |
| 1178 | return null; | | |
| 1179 | } | | |
| 1180 | }; | | |