| 1 | //! Utilities shared between compiler sub-commands |
| 2 | const std = @import("std"); |
| 3 | const aro = @import("aro"); |
| 4 | const ErrorBundle = std.zig.ErrorBundle; |
| 5 | |
| 6 | pub fn aroDiagnosticsToErrorBundle( |
| 7 | d: *const aro.Diagnostics, |
| 8 | gpa: std.mem.Allocator, |
| 9 | fail_msg: ?[]const u8, |
| 10 | ) !ErrorBundle { |
| 11 | @branchHint(.cold); |
| 12 | |
| 13 | var bundle: ErrorBundle.Wip = undefined; |
| 14 | try bundle.init(gpa); |
| 15 | errdefer bundle.deinit(); |
| 16 | |
| 17 | if (fail_msg) |msg| { |
| 18 | try bundle.addRootErrorMessage(.{ |
| 19 | .msg = try bundle.addString(msg), |
| 20 | }); |
| 21 | } |
| 22 | |
| 23 | var cur_err: ?ErrorBundle.ErrorMessage = null; |
| 24 | var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; |
| 25 | defer cur_notes.deinit(gpa); |
| 26 | for (d.output.to_list.messages.items) |msg| { |
| 27 | switch (msg.kind) { |
| 28 | .off, .warning => { |
| 29 | // Emit any pending error and clear everything so that notes don't bleed into unassociated errors |
| 30 | if (cur_err) |err| { |
| 31 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); |
| 32 | cur_err = null; |
| 33 | } |
| 34 | cur_notes.clearRetainingCapacity(); |
| 35 | continue; |
| 36 | }, |
| 37 | .note => if (cur_err == null) continue, |
| 38 | .@"fatal error", .@"error" => {}, |
| 39 | } |
| 40 | |
| 41 | const src_loc = src_loc: { |
| 42 | if (msg.location) |location| { |
| 43 | break :src_loc try bundle.addSourceLocation(.{ |
| 44 | .src_path = try bundle.addString(location.path), |
| 45 | .line = location.line_no - 1, // 1-based -> 0-based |
| 46 | .column = location.col - 1, // 1-based -> 0-based |
| 47 | .span_start = location.width, |
| 48 | .span_main = location.width, |
| 49 | .span_end = location.width, |
| 50 | .source_line = try bundle.addString(location.line), |
| 51 | }); |
| 52 | } |
| 53 | break :src_loc ErrorBundle.SourceLocationIndex.none; |
| 54 | }; |
| 55 | |
| 56 | switch (msg.kind) { |
| 57 | .@"fatal error", .@"error" => { |
| 58 | if (cur_err) |err| { |
| 59 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); |
| 60 | } |
| 61 | cur_err = .{ |
| 62 | .msg = try bundle.addString(msg.text), |
| 63 | .src_loc = src_loc, |
| 64 | }; |
| 65 | cur_notes.clearRetainingCapacity(); |
| 66 | }, |
| 67 | .note => { |
| 68 | cur_err.?.notes_len += 1; |
| 69 | try cur_notes.append(gpa, .{ |
| 70 | .msg = try bundle.addString(msg.text), |
| 71 | .src_loc = src_loc, |
| 72 | }); |
| 73 | }, |
| 74 | .off, .warning => unreachable, |
| 75 | } |
| 76 | } |
| 77 | if (cur_err) |err| { |
| 78 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); |
| 79 | } |
| 80 | |
| 81 | return try bundle.toOwnedBundle(""); |
| 82 | } |