| ... | ... | @@ -6,6 +6,7 @@ const Allocator = std.mem.Allocator; |
| 6 | 6 | const assert = std.debug.assert; |
| 7 | 7 | const log = std.log.scoped(.compilation); |
| 8 | 8 | const Target = std.Target; |
| 9 | const debug = std.debug; |
| 9 | 10 | |
| 10 | 11 | const Value = @import("value.zig").Value; |
| 11 | 12 | const Type = @import("type.zig").Type; |
| ... | ... | @@ -266,9 +267,30 @@ pub const AllErrors = struct { |
| 266 | 267 | list: []const Message, |
| 267 | 268 | |
| 268 | 269 | pub const Message = union(enum) { |
| 270 | const MessageType = enum { |
| 271 | pub fn render(self: @This(), stderr: anytype, ttyconf: std.debug.TTY.Config) !void { |
| 272 | switch (self) { |
| 273 | .err => { |
| 274 | ttyconf.setColor(stderr, .Red); |
| 275 | try stderr.writeAll("error:"); |
| 276 | }, |
| 277 | .note => { |
| 278 | ttyconf.setColor(stderr, .Green); |
| 279 | try stderr.writeAll("note:"); |
| 280 | }, |
| 281 | } |
| 282 | ttyconf.setColor(stderr, .Reset); |
| 283 | } |
| 284 | err, |
| 285 | note |
| 286 | }; |
| 287 | |
| 269 | 288 | src: struct { |
| 270 | 289 | msg: []const u8, |
| 271 | | src_path: []const u8, |
| 290 | src_path: union(enum) { |
| 291 | path: []const u8, |
| 292 | scope: *Module.Scope.File, |
| 293 | }, |
| 272 | 294 | line: u32, |
| 273 | 295 | column: u32, |
| 274 | 296 | byte_offset: u32, |
| ... | ... | @@ -278,26 +300,70 @@ pub const AllErrors = struct { |
| 278 | 300 | msg: []const u8, |
| 279 | 301 | }, |
| 280 | 302 | |
| 281 | | pub fn renderToStdErr(msg: Message) void { |
| 282 | | return msg.renderToStdErrInner("error"); |
| 303 | pub fn renderToStdErr(msg: Message, mod: ?*Module) !void { |
| 304 | return msg.renderToStdErrInner(.err, mod); |
| 283 | 305 | } |
| 284 | 306 | |
| 285 | | fn renderToStdErrInner(msg: Message, kind: []const u8) void { |
| 307 | fn renderToStdErrInner(msg: Message, kind: MessageType, mod: ?*Module) (std.fs.File.WriteError || @typeInfo(@typeInfo(@TypeOf(Module.Scope.File.getSource)).Fn.return_type.?).ErrorUnion.error_set)!void { |
| 308 | const ttyconf = debug.detectTTYConfig(); |
| 309 | const stderr = std.io.getStdErr().writer(); |
| 286 | 310 | switch (msg) { |
| 287 | 311 | .src => |src| { |
| 288 | | std.debug.print("{s}:{d}:{d}: {s}: {s}\n", .{ |
| 289 | | src.src_path, |
| 290 | | src.line + 1, |
| 291 | | src.column + 1, |
| 292 | | kind, |
| 293 | | src.msg, |
| 294 | | }); |
| 312 | switch (src.src_path) { |
| 313 | .path => |p| { |
| 314 | // TODO read the file and do pretty printing for c objects? |
| 315 | try stderr.print("{s}:{d}:{d}: ", .{ |
| 316 | p, |
| 317 | src.line + 1, |
| 318 | src.column + 1, |
| 319 | }); |
| 320 | try kind.render(stderr, ttyconf); |
| 321 | try stderr.print(" {s}\n", .{ |
| 322 | src.msg, |
| 323 | }); |
| 324 | }, |
| 325 | .scope => |s| { |
| 326 | const module = mod.?; |
| 327 | try stderr.print("{s}:{d}:{d}: ", .{ |
| 328 | s.sub_file_path, |
| 329 | src.line + 1, |
| 330 | src.column + 1, |
| 331 | }); |
| 332 | try kind.render(stderr, ttyconf); |
| 333 | try stderr.print(" {s}\n", .{ |
| 334 | src.msg, |
| 335 | }); |
| 336 | const fsource = try s.getSource(module); |
| 337 | const end_pos = blk: for (fsource[src.byte_offset..]) |c, i| { |
| 338 | if (c == '\n') |
| 339 | break :blk src.byte_offset + i + 1; |
| 340 | if (c == 0) |
| 341 | break :blk fsource.len - 1; |
| 342 | } else unreachable; |
| 343 | const start_pos = blk: { |
| 344 | var i = src.byte_offset; |
| 345 | var c: u8 = fsource[i]; |
| 346 | while (i > 0) : ({ |
| 347 | i -= 1; |
| 348 | c = fsource[i]; |
| 349 | }) { |
| 350 | if (c == '\n') break :blk i + 1; |
| 351 | } |
| 352 | break :blk 0; |
| 353 | }; |
| 354 | try stderr.writeAll(fsource[start_pos..end_pos]); |
| 355 | try stderr.writeByteNTimes(' ', src.column); |
| 356 | ttyconf.setColor(stderr, .Cyan); |
| 357 | try stderr.writeAll("^\n"); |
| 358 | ttyconf.setColor(stderr, .Reset); |
| 359 | }, |
| 360 | } |
| 295 | 361 | for (src.notes) |note| { |
| 296 | | note.renderToStdErrInner("note"); |
| 362 | try note.renderToStdErrInner(.note, mod); |
| 297 | 363 | } |
| 298 | 364 | }, |
| 299 | 365 | .plain => |plain| { |
| 300 | | std.debug.print("{s}: {s}\n", .{ kind, plain.msg }); |
| 366 | debug.print("{s}: {s}\n", .{ kind, plain.msg }); |
| 301 | 367 | }, |
| 302 | 368 | } |
| 303 | 369 | } |
| ... | ... | @@ -319,10 +385,11 @@ pub const AllErrors = struct { |
| 319 | 385 | const source = try module_note.src_loc.fileScope().getSource(module); |
| 320 | 386 | const byte_offset = try module_note.src_loc.byteOffset(); |
| 321 | 387 | const loc = std.zig.findLineColumn(source, byte_offset); |
| 322 | | const sub_file_path = module_note.src_loc.fileScope().sub_file_path; |
| 388 | const fscope = module_note.src_loc.fileScope(); |
| 323 | 389 | note.* = .{ |
| 324 | 390 | .src = .{ |
| 325 | | .src_path = try arena.allocator.dupe(u8, sub_file_path), |
| 391 | // TODO this might be freed, might need to dupe the source |
| 392 | .src_path = .{ .scope = fscope }, |
| 326 | 393 | .msg = try arena.allocator.dupe(u8, module_note.msg), |
| 327 | 394 | .byte_offset = byte_offset, |
| 328 | 395 | .line = @intCast(u32, loc.line), |
| ... | ... | @@ -333,10 +400,10 @@ pub const AllErrors = struct { |
| 333 | 400 | const source = try module_err_msg.src_loc.fileScope().getSource(module); |
| 334 | 401 | const byte_offset = try module_err_msg.src_loc.byteOffset(); |
| 335 | 402 | const loc = std.zig.findLineColumn(source, byte_offset); |
| 336 | | const sub_file_path = module_err_msg.src_loc.fileScope().sub_file_path; |
| 403 | const fscope = module_err_msg.src_loc.fileScope(); |
| 337 | 404 | try errors.append(.{ |
| 338 | 405 | .src = .{ |
| 339 | | .src_path = try arena.allocator.dupe(u8, sub_file_path), |
| 406 | .src_path = .{ .scope = fscope }, |
| 340 | 407 | .msg = try arena.allocator.dupe(u8, module_err_msg.msg), |
| 341 | 408 | .byte_offset = byte_offset, |
| 342 | 409 | .line = @intCast(u32, loc.line), |
| ... | ... | @@ -1482,7 +1549,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 1482 | 1549 | // C error reporting bubbling up. |
| 1483 | 1550 | try errors.append(.{ |
| 1484 | 1551 | .src = .{ |
| 1485 | | .src_path = try arena.allocator.dupe(u8, c_object.src.src_path), |
| 1552 | .src_path = .{ .path = try arena.allocator.dupe(u8, c_object.src.src_path) }, |
| 1486 | 1553 | .msg = try std.fmt.allocPrint(&arena.allocator, "unable to build C object: {s}", .{ |
| 1487 | 1554 | err_msg.msg, |
| 1488 | 1555 | }), |