master
 1//! Utilities shared between compiler sub-commands
 2const std = @import("std");
 3const aro = @import("aro");
 4const ErrorBundle = std.zig.ErrorBundle;
 5
 6pub 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}