DoxigAlpha

renderErrorMessageToWriter

Function parameters

Parameters

#
w:*Writer
kind:[]const u8
color:std.io.tty.Color
indent:usize

Type definitions in this namespace

Types

#
ErrorMessageList
There will be a MessageIndex for each len at start.
SourceLocation
Trailing:
ErrorMessage
Trailing:

Functions in this namespace

Functions

#
nullTerminatedString
Given an index into `string_bytes` returns the null-terminated string found there.

Special encoding when there are no errors.

Values

#
empty
Special encoding when there are no errors.

Source

Implementation

#
fn renderErrorMessageToWriter(
    eb: ErrorBundle,
    options: RenderOptions,
    err_msg_index: MessageIndex,
    w: *Writer,
    kind: []const u8,
    color: std.io.tty.Color,
    indent: usize,
) (Writer.Error || std.posix.UnexpectedError)!void {
    const ttyconf = options.ttyconf;
    const err_msg = eb.getErrorMessage(err_msg_index);
    if (err_msg.src_loc != .none) {
        const src = eb.extraData(SourceLocation, @intFromEnum(err_msg.src_loc));
        var prefix: std.io.Writer.Discarding = .init(&.{});
        try w.splatByteAll(' ', indent);
        prefix.count += indent;
        try ttyconf.setColor(w, .bold);
        try w.print("{s}:{d}:{d}: ", .{
            eb.nullTerminatedString(src.data.src_path),
            src.data.line + 1,
            src.data.column + 1,
        });
        try prefix.writer.print("{s}:{d}:{d}: ", .{
            eb.nullTerminatedString(src.data.src_path),
            src.data.line + 1,
            src.data.column + 1,
        });
        try ttyconf.setColor(w, color);
        try w.writeAll(kind);
        prefix.count += kind.len;
        try w.writeAll(": ");
        prefix.count += 2;
        // This is the length of the part before the error message:
        // e.g. "file.zig:4:5: error: "
        const prefix_len: usize = @intCast(prefix.count);
        try ttyconf.setColor(w, .reset);
        try ttyconf.setColor(w, .bold);
        if (err_msg.count == 1) {
            try writeMsg(eb, err_msg, w, prefix_len);
            try w.writeByte('\n');
        } else {
            try writeMsg(eb, err_msg, w, prefix_len);
            try ttyconf.setColor(w, .dim);
            try w.print(" ({d} times)\n", .{err_msg.count});
        }
        try ttyconf.setColor(w, .reset);
        if (src.data.source_line != 0 and options.include_source_line) {
            const line = eb.nullTerminatedString(src.data.source_line);
            for (line) |b| switch (b) {
                '\t' => try w.writeByte(' '),
                else => try w.writeByte(b),
            };
            try w.writeByte('\n');
            // TODO basic unicode code point monospace width
            const before_caret = src.data.span_main - src.data.span_start;
            // -1 since span.main includes the caret
            const after_caret = src.data.span_end -| src.data.span_main -| 1;
            try w.splatByteAll(' ', src.data.column - before_caret);
            try ttyconf.setColor(w, .green);
            try w.splatByteAll('~', before_caret);
            try w.writeByte('^');
            try w.splatByteAll('~', after_caret);
            try w.writeByte('\n');
            try ttyconf.setColor(w, .reset);
        }
        for (eb.getNotes(err_msg_index)) |note| {
            try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent);
        }
        if (src.data.reference_trace_len > 0 and options.include_reference_trace) {
            try ttyconf.setColor(w, .reset);
            try ttyconf.setColor(w, .dim);
            try w.print("referenced by:\n", .{});
            var ref_index = src.end;
            for (0..src.data.reference_trace_len) |_| {
                const ref_trace = eb.extraData(ReferenceTrace, ref_index);
                ref_index = ref_trace.end;
                if (ref_trace.data.src_loc != .none) {
                    const ref_src = eb.getSourceLocation(ref_trace.data.src_loc);
                    try w.print("    {s}: {s}:{d}:{d}\n", .{
                        eb.nullTerminatedString(ref_trace.data.decl_name),
                        eb.nullTerminatedString(ref_src.src_path),
                        ref_src.line + 1,
                        ref_src.column + 1,
                    });
                } else if (ref_trace.data.decl_name != 0) {
                    const count = ref_trace.data.decl_name;
                    try w.print(
                        "    {d} reference(s) hidden; use '-freference-trace={d}' to see all references\n",
                        .{ count, count + src.data.reference_trace_len - 1 },
                    );
                } else {
                    try w.print(
                        "    remaining reference traces hidden; use '-freference-trace' to see all reference traces\n",
                        .{},
                    );
                }
            }
            try ttyconf.setColor(w, .reset);
        }
    } else {
        try ttyconf.setColor(w, color);
        try w.splatByteAll(' ', indent);
        try w.writeAll(kind);
        try w.writeAll(": ");
        try ttyconf.setColor(w, .reset);
        const msg = eb.nullTerminatedString(err_msg.msg);
        if (err_msg.count == 1) {
            try w.print("{s}\n", .{msg});
        } else {
            try w.print("{s}", .{msg});
            try ttyconf.setColor(w, .dim);
            try w.print(" ({d} times)\n", .{err_msg.count});
        }
        try ttyconf.setColor(w, .reset);
        for (eb.getNotes(err_msg_index)) |note| {
            try renderErrorMessageToWriter(eb, options, note, w, "note", .cyan, indent + 4);
        }
    }
}