From 9a2fc6cf4c8b4434ae45170953b77b3239120fea Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Mar 2024 15:34:29 +0000 Subject: Serialize errors to make them sortable, deterministic, and generally more control --- src/error.cpp | 213 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 133 insertions(+), 80 deletions(-) (limited to 'src/error.cpp') diff --git a/src/error.cpp b/src/error.cpp index e63682829..e5803e5a2 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -1,3 +1,14 @@ +enum ErrorValueKind : u32 { + ErrorValue_Error, + ErrorValue_Warning, +}; + +struct ErrorValue { + ErrorValueKind kind; + TokenPos pos; + Array msgs; +}; + struct ErrorCollector { TokenPos prev; std::atomic count; @@ -8,21 +19,54 @@ struct ErrorCollector { BlockingMutex string_mutex; RecursiveMutex block_mutex; - RecursiveMutex error_buffer_mutex; - Array error_buffer; - Array errors; + Array error_values; + ErrorValue curr_error_value; + std::atomic curr_error_value_set; }; gb_global ErrorCollector global_error_collector; +gb_internal void push_error_value(TokenPos const &pos, ErrorValueKind kind = ErrorValue_Error) { + GB_ASSERT(global_error_collector.curr_error_value_set.load() == false); + ErrorValue ev = {kind, pos}; + ev.msgs.allocator = heap_allocator(); + + global_error_collector.curr_error_value = ev; + global_error_collector.curr_error_value_set.store(true); +} + +gb_internal void pop_error_value(void) { + if (global_error_collector.curr_error_value_set.load()) { + array_add(&global_error_collector.error_values, global_error_collector.curr_error_value); + + global_error_collector.curr_error_value = {}; + global_error_collector.curr_error_value_set.store(false); + } +} + + +gb_internal void try_pop_error_value(void) { + if (!global_error_collector.in_block.load()) { + pop_error_value(); + } +} + +gb_internal ErrorValue *get_error_value(void) { + GB_ASSERT(global_error_collector.curr_error_value_set.load() == true); + return &global_error_collector.curr_error_value; +} + + + gb_internal bool any_errors(void) { return global_error_collector.count.load() != 0; } + + gb_internal void init_global_error_collector(void) { - array_init(&global_error_collector.errors, heap_allocator()); - array_init(&global_error_collector.error_buffer, heap_allocator()); + array_init(&global_error_collector.error_values, heap_allocator()); array_init(&global_file_path_strings, heap_allocator(), 1, 4096); array_init(&global_files, heap_allocator(), 1, 4096); } @@ -102,6 +146,7 @@ gb_internal AstFile *thread_safe_get_ast_file_from_id(i32 index) { gb_internal bool global_warnings_as_errors(void); gb_internal bool global_ignore_warnings(void); gb_internal bool show_error_line(void); +gb_internal bool terse_errors(void); gb_internal bool has_ansi_terminal_colours(void); gb_internal gbString get_file_line_as_string(TokenPos const &pos, i32 *offset); @@ -113,55 +158,32 @@ gb_internal void syntax_error(Token const &token, char const *fmt, ...); gb_internal void syntax_error(TokenPos pos, char const *fmt, ...); gb_internal void syntax_warning(Token const &token, char const *fmt, ...); gb_internal void compiler_error(char const *fmt, ...); +gb_internal void print_all_errors(void); -gb_internal void begin_error_block(void) { - mutex_lock(&global_error_collector.block_mutex); - global_error_collector.in_block.store(true); -} -gb_internal void end_error_block(void) { - mutex_lock(&global_error_collector.error_buffer_mutex); - isize n = global_error_collector.error_buffer.count; - if (n > 0) { - u8 *text = global_error_collector.error_buffer.data; - - bool add_extra_newline = false; +#define ERROR_OUT_PROC(name) void name(char const *fmt, va_list va) +typedef ERROR_OUT_PROC(ErrorOutProc); - if (show_error_line()) { - if (n >= 2 && !(text[n-2] == '\n' && text[n-1] == '\n')) { - add_extra_newline = true; - } - } else { - isize newline_count = 0; - for (isize i = 0; i < n; i++) { - if (text[i] == '\n') { - newline_count += 1; - } - } - if (newline_count > 1) { - add_extra_newline = true; - } - } +gb_internal ERROR_OUT_PROC(default_error_out_va) { + char buf[4096] = {}; + isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va); + isize n = len-1; - if (add_extra_newline) { - // add an extra new line as padding when the error line is being shown - error_line("\n"); - } + String msg = {(u8 *)buf, n}; - n = global_error_collector.error_buffer.count; - text = gb_alloc_array(permanent_allocator(), u8, n+1); - gb_memmove(text, global_error_collector.error_buffer.data, n); - text[n] = 0; + ErrorValue *ev = get_error_value(); + array_add(&ev->msgs, copy_string(permanent_allocator(), msg)); +} +gb_global ErrorOutProc *error_out_va = default_error_out_va; - mutex_lock(&global_error_collector.error_out_mutex); - String s = {text, n}; - array_add(&global_error_collector.errors, s); - mutex_unlock(&global_error_collector.error_out_mutex); +gb_internal void begin_error_block(void) { + mutex_lock(&global_error_collector.block_mutex); + global_error_collector.in_block.store(true); +} - global_error_collector.error_buffer.count = 0; - } - mutex_unlock(&global_error_collector.error_buffer_mutex); +gb_internal void end_error_block(void) { + pop_error_value(); global_error_collector.in_block.store(false); mutex_unlock(&global_error_collector.block_mutex); } @@ -169,40 +191,6 @@ gb_internal void end_error_block(void) { #define ERROR_BLOCK() begin_error_block(); defer (end_error_block()) -#define ERROR_OUT_PROC(name) void name(char const *fmt, va_list va) -typedef ERROR_OUT_PROC(ErrorOutProc); - -gb_internal ERROR_OUT_PROC(default_error_out_va) { - gbFile *f = gb_file_get_standard(gbFileStandard_Error); - - char buf[4096] = {}; - isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va); - isize n = len-1; - if (global_error_collector.in_block) { - mutex_lock(&global_error_collector.error_buffer_mutex); - - isize cap = global_error_collector.error_buffer.count + n; - array_reserve(&global_error_collector.error_buffer, cap); - u8 *data = global_error_collector.error_buffer.data + global_error_collector.error_buffer.count; - gb_memmove(data, buf, n); - global_error_collector.error_buffer.count += n; - - mutex_unlock(&global_error_collector.error_buffer_mutex); - } else { - mutex_lock(&global_error_collector.error_out_mutex); - { - u8 *text = gb_alloc_array(permanent_allocator(), u8, n+1); - gb_memmove(text, buf, n); - text[n] = 0; - array_add(&global_error_collector.errors, make_string(text, n)); - } - mutex_unlock(&global_error_collector.error_out_mutex); - - } - gb_file_write(f, buf, n); -} - -gb_global ErrorOutProc *error_out_va = default_error_out_va; gb_internal void error_out(char const *fmt, ...) { va_list va; @@ -357,9 +345,12 @@ gb_internal void error_out_coloured(char const *str, TerminalStyle style, Termin gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) { global_error_collector.count.fetch_add(1); if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) { + print_all_errors(); gb_exit(1); } mutex_lock(&global_error_collector.mutex); + + push_error_value(pos, ErrorValue_Error); // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red); @@ -377,6 +368,7 @@ gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va } else { global_error_collector.count.fetch_sub(1); } + try_pop_error_value(); mutex_unlock(&global_error_collector.mutex); } @@ -387,6 +379,9 @@ gb_internal void warning_va(TokenPos const &pos, TokenPos end, char const *fmt, } global_error_collector.warning_count.fetch_add(1); mutex_lock(&global_error_collector.mutex); + + push_error_value(pos, ErrorValue_Warning); + if (!global_ignore_warnings()) { // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { @@ -402,6 +397,7 @@ gb_internal void warning_va(TokenPos const &pos, TokenPos end, char const *fmt, show_error_on_line(pos, end); } } + try_pop_error_value(); mutex_unlock(&global_error_collector.mutex); } @@ -413,9 +409,13 @@ gb_internal void error_line_va(char const *fmt, va_list va) { gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_list va) { global_error_collector.count.fetch_add(1); if (global_error_collector.count.load() > MAX_ERROR_COLLECTOR_COUNT()) { + print_all_errors(); gb_exit(1); } mutex_lock(&global_error_collector.mutex); + + push_error_value(pos, ErrorValue_Error); + // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red); @@ -428,6 +428,8 @@ gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_li } error_out_va(fmt, va); } + + try_pop_error_value(); mutex_unlock(&global_error_collector.mutex); } @@ -435,9 +437,13 @@ gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_li gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) { global_error_collector.count.fetch_add(1); if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) { + print_all_errors(); gb_exit(1); } mutex_lock(&global_error_collector.mutex); + + push_error_value(pos, ErrorValue_Warning); + // NOTE(bill): Duplicate error, skip it if (global_error_collector.prev != pos) { global_error_collector.prev = pos; @@ -451,15 +457,21 @@ gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const * error_out_va(fmt, va); error_out("\n"); } + + try_pop_error_value(); mutex_unlock(&global_error_collector.mutex); } gb_internal void syntax_error_with_verbose_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) { global_error_collector.count.fetch_add(1); if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT()) { + print_all_errors(); gb_exit(1); } mutex_lock(&global_error_collector.mutex); + + push_error_value(pos, ErrorValue_Warning); + // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { error_out_coloured("Syntax_Error: ", TerminalStyle_Normal, TerminalColour_Red); @@ -475,6 +487,8 @@ gb_internal void syntax_error_with_verbose_va(TokenPos const &pos, TokenPos end, error_out("\n"); show_error_on_line(pos, end); } + + try_pop_error_value(); mutex_unlock(&global_error_collector.mutex); } @@ -486,6 +500,10 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const } mutex_lock(&global_error_collector.mutex); global_error_collector.warning_count++; + + + push_error_value(pos, ErrorValue_Warning); + if (!global_ignore_warnings()) { // NOTE(bill): Duplicate error, skip it if (global_error_collector.prev != pos) { @@ -501,6 +519,8 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const error_out("\n"); } } + + try_pop_error_value(); mutex_unlock(&global_error_collector.mutex); } @@ -568,6 +588,8 @@ gb_internal void syntax_error_with_verbose(TokenPos pos, TokenPos end, char cons gb_internal void compiler_error(char const *fmt, ...) { + print_all_errors(); + va_list va; va_start(va, fmt); @@ -577,3 +599,34 @@ gb_internal void compiler_error(char const *fmt, ...) { GB_DEBUG_TRAP(); gb_exit(1); } + + + + + +gb_internal int error_value_cmp(void const *a, void const *b) { + ErrorValue *x = cast(ErrorValue *)a; + ErrorValue *y = cast(ErrorValue *)b; + return token_pos_cmp(x->pos, y->pos); +} + +gb_internal void print_all_errors(void) { + GB_ASSERT(any_errors()); + gbFile *f = gb_file_get_standard(gbFileStandard_Error); + + array_sort(global_error_collector.error_values, error_value_cmp); + + for_array(i, global_error_collector.error_values) { + ErrorValue ev = global_error_collector.error_values[i]; + for_array(j, ev.msgs) { + String msg = ev.msgs[j]; + gb_file_write(f, msg.text, msg.len); + if (terse_errors()) { + if (string_contains_char(msg, '\n')) { + break; + } + } + } + } + +} \ No newline at end of file -- cgit v1.2.3 From 17cc7a2c5ee8cbce8aeeff0e0952f54b681e14c7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Mar 2024 15:42:59 +0000 Subject: General clean-up for error.cpp --- src/error.cpp | 53 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'src/error.cpp') diff --git a/src/error.cpp b/src/error.cpp index e5803e5a2..d116781fb 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -14,10 +14,9 @@ struct ErrorCollector { std::atomic count; std::atomic warning_count; std::atomic in_block; - BlockingMutex mutex; - BlockingMutex error_out_mutex; - BlockingMutex string_mutex; - RecursiveMutex block_mutex; + + RecursiveMutex mutex; + BlockingMutex path_mutex; Array error_values; ErrorValue curr_error_value; @@ -81,7 +80,7 @@ gb_internal char *token_pos_to_string(TokenPos const &pos); gb_internal bool set_file_path_string(i32 index, String const &path) { bool ok = false; GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.string_mutex); + mutex_lock(&global_error_collector.path_mutex); if (index >= global_file_path_strings.count) { array_resize(&global_file_path_strings, index+1); @@ -92,14 +91,14 @@ gb_internal bool set_file_path_string(i32 index, String const &path) { ok = true; } - mutex_unlock(&global_error_collector.string_mutex); + mutex_unlock(&global_error_collector.path_mutex); return ok; } gb_internal bool thread_safe_set_ast_file_from_id(i32 index, AstFile *file) { bool ok = false; GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.string_mutex); + mutex_lock(&global_error_collector.path_mutex); if (index >= global_files.count) { array_resize(&global_files, index+1); @@ -110,33 +109,33 @@ gb_internal bool thread_safe_set_ast_file_from_id(i32 index, AstFile *file) { ok = true; } - mutex_unlock(&global_error_collector.string_mutex); + mutex_unlock(&global_error_collector.path_mutex); return ok; } gb_internal String get_file_path_string(i32 index) { GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.string_mutex); + mutex_lock(&global_error_collector.path_mutex); String path = {}; if (index < global_file_path_strings.count) { path = global_file_path_strings[index]; } - mutex_unlock(&global_error_collector.string_mutex); + mutex_unlock(&global_error_collector.path_mutex); return path; } gb_internal AstFile *thread_safe_get_ast_file_from_id(i32 index) { GB_ASSERT(index >= 0); - mutex_lock(&global_error_collector.string_mutex); + mutex_lock(&global_error_collector.path_mutex); AstFile *file = nullptr; if (index < global_files.count) { file = global_files[index]; } - mutex_unlock(&global_error_collector.string_mutex); + mutex_unlock(&global_error_collector.path_mutex); return file; } @@ -169,23 +168,26 @@ gb_internal ERROR_OUT_PROC(default_error_out_va) { isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va); isize n = len-1; - String msg = {(u8 *)buf, n}; + String msg = {}; + if (n) { + msg = copy_string(permanent_allocator(), {(u8 *)buf, n}); + } ErrorValue *ev = get_error_value(); - array_add(&ev->msgs, copy_string(permanent_allocator(), msg)); + array_add(&ev->msgs, msg); } gb_global ErrorOutProc *error_out_va = default_error_out_va; gb_internal void begin_error_block(void) { - mutex_lock(&global_error_collector.block_mutex); + mutex_lock(&global_error_collector.mutex); global_error_collector.in_block.store(true); } gb_internal void end_error_block(void) { pop_error_value(); global_error_collector.in_block.store(false); - mutex_unlock(&global_error_collector.block_mutex); + mutex_unlock(&global_error_collector.mutex); } #define ERROR_BLOCK() begin_error_block(); defer (end_error_block()) @@ -328,6 +330,9 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) { return false; } +gb_internal void error_out_empty(void) { + error_out(""); +} gb_internal void error_out_pos(TokenPos pos) { terminal_set_colours(TerminalStyle_Bold, TerminalColour_White); error_out("%s ", token_pos_to_string(pos)); @@ -353,6 +358,7 @@ gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va push_error_value(pos, ErrorValue_Error); // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { + error_out_empty(); error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red); error_out_va(fmt, va); error_out("\n"); @@ -385,6 +391,7 @@ gb_internal void warning_va(TokenPos const &pos, TokenPos end, char const *fmt, if (!global_ignore_warnings()) { // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { + error_out_empty(); error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow); error_out_va(fmt, va); error_out("\n"); @@ -418,6 +425,7 @@ gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_li // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { + error_out_empty(); error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red); error_out_va(fmt, va); } else if (global_error_collector.prev != pos) { @@ -453,6 +461,7 @@ gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const * error_out("\n"); // show_error_on_line(pos, end); } else if (pos.line == 0) { + error_out_empty(); error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red); error_out_va(fmt, va); error_out("\n"); @@ -474,6 +483,7 @@ gb_internal void syntax_error_with_verbose_va(TokenPos const &pos, TokenPos end, // NOTE(bill): Duplicate error, skip it if (pos.line == 0) { + error_out_empty(); error_out_coloured("Syntax_Error: ", TerminalStyle_Normal, TerminalColour_Red); error_out_va(fmt, va); error_out("\n"); @@ -514,6 +524,7 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const error_out("\n"); // show_error_on_line(pos, end); } else if (pos.line == 0) { + error_out_empty(); error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow); error_out_va(fmt, va); error_out("\n"); @@ -618,15 +629,13 @@ gb_internal void print_all_errors(void) { for_array(i, global_error_collector.error_values) { ErrorValue ev = global_error_collector.error_values[i]; - for_array(j, ev.msgs) { + for (isize j = 0; j < ev.msgs.count; j++) { String msg = ev.msgs[j]; gb_file_write(f, msg.text, msg.len); - if (terse_errors()) { - if (string_contains_char(msg, '\n')) { - break; - } + + if (terse_errors() && string_contains_char(msg, '\n')) { + break; } } } - } \ No newline at end of file -- cgit v1.2.3 From ba428fecdb309846b9a6dc8a6a3d738f2034f2ff Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Mar 2024 16:25:09 +0000 Subject: Add `-json-errors` --- src/build_settings.cpp | 8 +++- src/error.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++------ src/main.cpp | 10 +++++ 3 files changed, 110 insertions(+), 15 deletions(-) (limited to 'src/error.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c4073f329..58b5c9170 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -392,6 +392,7 @@ struct BuildContext { bool warnings_as_errors; bool hide_error_line; bool terse_errors; + bool json_errors; bool has_ansi_terminal_colours; bool ignore_lazy; @@ -1270,14 +1271,17 @@ gb_internal String get_fullpath_core_collection(gbAllocator a, String path, bool } gb_internal bool show_error_line(void) { - return !build_context.hide_error_line; + return !build_context.hide_error_line && !build_context.json_errors; } gb_internal bool terse_errors(void) { return build_context.terse_errors; } +gb_internal bool json_errors(void) { + return build_context.json_errors; +} gb_internal bool has_ansi_terminal_colours(void) { - return build_context.has_ansi_terminal_colours; + return build_context.has_ansi_terminal_colours && !json_errors(); } gb_internal bool has_asm_extension(String const &path) { diff --git a/src/error.cpp b/src/error.cpp index d116781fb..509470602 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -6,6 +6,7 @@ enum ErrorValueKind : u32 { struct ErrorValue { ErrorValueKind kind; TokenPos pos; + TokenPos end; Array msgs; }; @@ -146,6 +147,7 @@ gb_internal bool global_warnings_as_errors(void); gb_internal bool global_ignore_warnings(void); gb_internal bool show_error_line(void); gb_internal bool terse_errors(void); +gb_internal bool json_errors(void); gb_internal bool has_ansi_terminal_colours(void); gb_internal gbString get_file_line_as_string(TokenPos const &pos, i32 *offset); @@ -168,13 +170,11 @@ gb_internal ERROR_OUT_PROC(default_error_out_va) { isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va); isize n = len-1; - String msg = {}; - if (n) { - msg = copy_string(permanent_allocator(), {(u8 *)buf, n}); + if (n > 0) { + String msg = copy_string(permanent_allocator(), {(u8 *)buf, n}); + ErrorValue *ev = get_error_value(); + array_add(&ev->msgs, msg); } - - ErrorValue *ev = get_error_value(); - array_add(&ev->msgs, msg); } gb_global ErrorOutProc *error_out_va = default_error_out_va; @@ -246,6 +246,7 @@ gb_internal void terminal_reset_colours(void) { gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) { + get_error_value()->end = end; if (!show_error_line()) { return false; } @@ -622,19 +623,99 @@ gb_internal int error_value_cmp(void const *a, void const *b) { } gb_internal void print_all_errors(void) { + auto const &escape_char = [](gbFile *f, u8 c) { + switch (c) { + case '\n': gb_file_write(f, "\\n", 2); break; + case '"': gb_file_write(f, "\\\"", 2); break; + case '\\': gb_file_write(f, "\\\\", 2); break; + case '\b': gb_file_write(f, "\\b", 2); break; + case '\f': gb_file_write(f, "\\f", 2); break; + case '\r': gb_file_write(f, "\\r", 2); break; + case '\t': gb_file_write(f, "\\t", 2); break; + default: + if ('\x00' <= c && c <= '\x1f') { + gb_fprintf(f, "\\u%04x", c); + } else { + gb_file_write(f, &c, 1); + } + break; + } + }; + GB_ASSERT(any_errors()); gbFile *f = gb_file_get_standard(gbFileStandard_Error); array_sort(global_error_collector.error_values, error_value_cmp); - for_array(i, global_error_collector.error_values) { - ErrorValue ev = global_error_collector.error_values[i]; - for (isize j = 0; j < ev.msgs.count; j++) { - String msg = ev.msgs[j]; - gb_file_write(f, msg.text, msg.len); - if (terse_errors() && string_contains_char(msg, '\n')) { - break; + if (json_errors()) { + gb_fprintf(f, "{\n"); + gb_fprintf(f, "\t\"error_count\": %td,\n", global_error_collector.error_values.count); + gb_fprintf(f, "\t\"errors\": [\n"); + for_array(i, global_error_collector.error_values) { + ErrorValue ev = global_error_collector.error_values[i]; + + gb_fprintf(f, "\t\t{\n"); + + gb_fprintf(f, "\t\t\t\"pos\": {\n"); + + if (ev.pos.file_id) { + gb_fprintf(f, "\t\t\t\t\"file\": \""); + String file = get_file_path_string(ev.pos.file_id); + for (isize k = 0; k < file.len; k++) { + escape_char(f, file.text[k]); + } + gb_fprintf(f, "\",\n"); + gb_fprintf(f, "\t\t\t\t\"line\": %d,\n", ev.pos.line); + gb_fprintf(f, "\t\t\t\t\"column\": %d,\n", ev.pos.column); + i32 end_column = gb_max(ev.end.column, ev.pos.column); + gb_fprintf(f, "\t\t\t\t\"end_column\": %d\n", end_column); + gb_fprintf(f, "\t\t\t},\n"); + } + + gb_fprintf(f, "\t\t\t\"msgs\": [\n"); + + if (ev.msgs.count > 1) { + gb_fprintf(f, "\t\t\t\t\""); + + for (isize j = 1; j < ev.msgs.count; j++) { + String msg = ev.msgs[j]; + for (isize k = 0; k < msg.len; k++) { + u8 c = msg.text[k]; + if (c == '\n') { + if (k+1 == msg.len && j+1 == ev.msgs.count) { + // don't do the last one + } else { + gb_fprintf(f, "\",\n"); + gb_fprintf(f, "\t\t\t\t\""); + } + } else { + escape_char(f, c); + } + } + } + gb_fprintf(f, "\"\n"); + } + gb_fprintf(f, "\t\t\t]\n"); + gb_fprintf(f, "\t\t}"); + if (i+1 != global_error_collector.error_values.count) { + gb_fprintf(f, ","); + } + gb_fprintf(f, "\n"); + } + + gb_fprintf(f, "\t]\n"); + gb_fprintf(f, "}\n"); + } else { + for_array(i, global_error_collector.error_values) { + ErrorValue ev = global_error_collector.error_values[i]; + for (isize j = 0; j < ev.msgs.count; j++) { + String msg = ev.msgs[j]; + gb_file_write(f, msg.text, msg.len); + + if (terse_errors() && string_contains_char(msg, '\n')) { + break; + } } } } diff --git a/src/main.cpp b/src/main.cpp index 0f28e137f..672a9318e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -292,6 +292,7 @@ enum BuildFlagKind { BuildFlag_WarningsAsErrors, BuildFlag_TerseErrors, BuildFlag_VerboseErrors, + BuildFlag_JsonErrors, BuildFlag_ErrorPosStyle, BuildFlag_MaxErrorCount, @@ -480,6 +481,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_WarningsAsErrors, str_lit("warnings-as-errors"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_TerseErrors, str_lit("terse-errors"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_VerboseErrors, str_lit("verbose-errors"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_JsonErrors, str_lit("json-errors"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_ErrorPosStyle, str_lit("error-pos-style"), BuildFlagParam_String, Command_all); add_flag(&build_flags, BuildFlag_MaxErrorCount, str_lit("max-error-count"), BuildFlagParam_Integer, Command_all); @@ -1184,6 +1186,10 @@ gb_internal bool parse_build_flags(Array args) { build_context.terse_errors = false; break; + case BuildFlag_JsonErrors: + build_context.json_errors = true; + break; + case BuildFlag_ErrorPosStyle: GB_ASSERT(value.kind == ExactValue_String); @@ -1984,6 +1990,10 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Prints a terse error message without showing the code on that line and the location in that line."); print_usage_line(0, ""); + print_usage_line(1, "-json-errors"); + print_usage_line(2, "Prints the error messages as json to stderr."); + print_usage_line(0, ""); + print_usage_line(1, "-error-pos-style:"); print_usage_line(2, "Available options:"); print_usage_line(3, "-error-pos-style:unix file/path:45:3:"); -- cgit v1.2.3 From 433109ff52d2db76069273cd53b7aebf6aea9be0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 19 Mar 2024 16:29:45 +0000 Subject: Replace `gb_exit(1)` with `exit_with_errors()` where appropriate --- src/checker.cpp | 4 ++-- src/docs_writer.cpp | 2 +- src/error.cpp | 4 ++++ src/llvm_backend.cpp | 14 +++++++------- src/main.cpp | 2 +- src/parser.cpp | 4 ++-- 6 files changed, 17 insertions(+), 13 deletions(-) (limited to 'src/error.cpp') diff --git a/src/checker.cpp b/src/checker.cpp index 836f803fc..0efe61fba 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1204,7 +1204,7 @@ gb_internal void init_universal(void) { } if (defined_values_double_declaration) { - gb_exit(1); + exit_with_errors(); } @@ -4504,7 +4504,7 @@ gb_internal void add_import_dependency_node(Checker *c, Ast *decl, PtrMapscope != nullptr); diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 26d8027a9..824445ed5 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -1170,7 +1170,7 @@ gb_internal void odin_doc_write_to_file(OdinDocWriter *w, char const *filename) gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, filename); if (err != gbFileError_None) { gb_printf_err("Failed to write .odin-doc to: %s\n", filename); - gb_exit(1); + exit_with_errors(); return; } defer (gb_file_close(&f)); diff --git a/src/error.cpp b/src/error.cpp index 509470602..8d550e969 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -613,6 +613,10 @@ gb_internal void compiler_error(char const *fmt, ...) { } +gb_internal void exit_with_errors(void) { + print_all_errors(); + gb_exit(1); +} diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index b8ee7e7fa..cc9b3ac5d 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1350,7 +1350,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_emit_worker_proc) { if (LLVMTargetMachineEmitToFile(wd->target_machine, wd->m->mod, cast(char *)wd->filepath_obj.text, wd->code_gen_file_type, &llvm_error)) { gb_printf_err("LLVM Error: %s\n", llvm_error); - gb_exit(1); + exit_with_errors(); } debugf("Generated File: %.*s\n", LIT(wd->filepath_obj)); return 0; @@ -1919,7 +1919,7 @@ verify gb_printf_err("LLVM Error: %s\n", llvm_error); } } - gb_exit(1); + exit_with_errors(); return 1; } #endif @@ -2104,11 +2104,11 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) { String filepath_ll = lb_filepath_ll_for_module(m); if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) { gb_printf_err("LLVM Error: %s\n", llvm_error); - gb_exit(1); + exit_with_errors(); return false; } } - gb_exit(1); + exit_with_errors(); return 1; } return 0; @@ -2193,7 +2193,7 @@ gb_internal bool lb_llvm_object_generation(lbGenerator *gen, bool do_threading) if (LLVMTargetMachineEmitToFile(m->target_machine, m->mod, cast(char *)filepath_obj.text, code_gen_file_type, &llvm_error)) { gb_printf_err("LLVM Error: %s\n", llvm_error); - gb_exit(1); + exit_with_errors(); return false; } debugf("Generated File: %.*s\n", LIT(filepath_obj)); @@ -2393,7 +2393,7 @@ gb_internal void lb_generate_procedure(lbModule *m, lbProcedure *p) { gb_printf_err("LLVM Error: %s\n", llvm_error); } LLVMVerifyFunction(p->value, LLVMPrintMessageAction); - gb_exit(1); + exit_with_errors(); } } @@ -2962,7 +2962,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { String filepath_ll = lb_filepath_ll_for_module(m); if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) { gb_printf_err("LLVM Error: %s\n", llvm_error); - gb_exit(1); + exit_with_errors(); return false; } array_add(&gen->output_temp_paths, filepath_ll); diff --git a/src/main.cpp b/src/main.cpp index 672a9318e..ab721a143 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1404,7 +1404,7 @@ gb_internal void timings_export_all(Timings *t, Checker *c, bool timings_are_fin gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, fileName); if (err != gbFileError_None) { gb_printf_err("Failed to export timings to: %s\n", fileName); - gb_exit(1); + exit_with_errors(); return; } else { gb_printf("\nExporting timings to '%s'... ", fileName); diff --git a/src/parser.cpp b/src/parser.cpp index 14035d6d7..1aa40ccbf 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1484,7 +1484,7 @@ gb_internal Token expect_token(AstFile *f, TokenKind kind) { String p = token_to_string(prev); syntax_error(f->curr_token, "Expected '%.*s', got '%.*s'", LIT(c), LIT(p)); if (prev.kind == Token_EOF) { - gb_exit(1); + exit_with_errors(); } } @@ -6177,7 +6177,7 @@ gb_internal ParseFileError process_imported_file(Parser *p, ImportedFile importe if (err == ParseFile_EmptyFile) { if (fi.fullpath == p->init_fullpath) { syntax_error(pos, "Initial file is empty - %.*s\n", LIT(p->init_fullpath)); - gb_exit(1); + exit_with_errors(); } } else { switch (err) { -- cgit v1.2.3