aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2024-01-22 17:21:52 +0100
committerLaytan Laats <laytanlaats@hotmail.com>2024-06-06 19:44:54 +0200
commit9a95049393ea98ef6222bf217ab44dd127c3f960 (patch)
tree8d03057733860b041964dffbe9f04b2c01493d60 /src
parentb196b84ef24e90a8c1cfeb6226b43171c376c7b2 (diff)
-show-defineables and -export-defineables
Diffstat (limited to 'src')
-rw-r--r--src/build_settings.cpp2
-rw-r--r--src/check_builtin.cpp11
-rw-r--r--src/checker.cpp2
-rw-r--r--src/checker.hpp12
-rw-r--r--src/main.cpp124
5 files changed, 150 insertions, 1 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index 251dd06dd..d25d553a9 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -844,6 +844,8 @@ struct BuildContext {
bool show_unused;
bool show_unused_with_location;
bool show_more_timings;
+ bool show_defineables;
+ String export_defineables_file;
bool show_system_calls;
bool keep_temp_files;
bool ignore_unknown_attributes;
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 7e3bcb7ee..b2afa3d0c 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -1777,7 +1777,7 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o
}
String name = arg->Ident.token.string;
-
+
operand->type = def.type;
operand->mode = def.mode;
@@ -1793,6 +1793,15 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o
operand->value = found->Constant.value;
}
}
+
+ Defineable defineable = {};
+ defineable.name = name;
+ defineable.default_value = def.value;
+ defineable.pos = arg->Ident.token.pos;
+
+ MUTEX_GUARD(&c->info->defineables_mutex);
+ array_add(&c->info->defineables, defineable);
+
} else {
error(call, "Unknown directive call: #%.*s", LIT(name));
}
diff --git a/src/checker.cpp b/src/checker.cpp
index 8a58bb425..0f23e308b 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -1275,6 +1275,7 @@ gb_internal void init_checker_info(CheckerInfo *i) {
array_init(&i->init_procedures, a, 0, 0);
array_init(&i->fini_procedures, a, 0, 0);
array_init(&i->required_foreign_imports_through_force, a, 0, 0);
+ array_init(&i->defineables, a);
map_init(&i->objc_msgSend_types);
string_map_init(&i->load_file_cache);
@@ -1304,6 +1305,7 @@ gb_internal void destroy_checker_info(CheckerInfo *i) {
string_map_destroy(&i->packages);
array_free(&i->variable_init_order);
array_free(&i->required_foreign_imports_through_force);
+ array_free(&i->defineables);
mpsc_destroy(&i->entity_queue);
mpsc_destroy(&i->definition_queue);
diff --git a/src/checker.hpp b/src/checker.hpp
index 2ac4c8e7a..fc37f5769 100644
--- a/src/checker.hpp
+++ b/src/checker.hpp
@@ -376,6 +376,15 @@ struct GenTypesData {
RecursiveMutex mutex;
};
+struct Defineable {
+ String name;
+ ExactValue default_value;
+ TokenPos pos;
+
+ String default_value_str;
+ String pos_str;
+};
+
// CheckerInfo stores all the symbol information for a type-checked program
struct CheckerInfo {
Checker *checker;
@@ -402,6 +411,9 @@ struct CheckerInfo {
Array<Entity *> entities;
Array<Entity *> required_foreign_imports_through_force;
+ BlockingMutex defineables_mutex;
+ Array<Defineable> defineables;
+
// Below are accessed within procedures
RwMutex global_untyped_mutex;
diff --git a/src/main.cpp b/src/main.cpp
index 70def5802..a3e87fb6a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -288,6 +288,9 @@ enum BuildFlagKind {
BuildFlag_NoThreadedChecker,
BuildFlag_ShowDebugMessages,
+ BuildFlag_ShowDefineables,
+ BuildFlag_ExportDefineables,
+
BuildFlag_Vet,
BuildFlag_VetShadowing,
BuildFlag_VetUnused,
@@ -483,6 +486,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_NoThreadedChecker, str_lit("no-threaded-checker"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_ShowDebugMessages, str_lit("show-debug-messages"), BuildFlagParam_None, Command_all);
+ add_flag(&build_flags, BuildFlag_ShowDefineables, str_lit("show-defineables"), BuildFlagParam_None, Command__does_check);
+ add_flag(&build_flags, BuildFlag_ExportDefineables, str_lit("export-defineables"), BuildFlagParam_String, Command__does_check);
+
add_flag(&build_flags, BuildFlag_Vet, str_lit("vet"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_VetUnused, str_lit("vet-unused"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_VetUnusedVariables, str_lit("vet-unused-variables"), BuildFlagParam_None, Command__does_check);
@@ -814,6 +820,24 @@ gb_internal bool parse_build_flags(Array<String> args) {
break;
}
+ case BuildFlag_ShowDefineables: {
+ GB_ASSERT(value.kind == ExactValue_Invalid);
+ build_context.show_defineables = true;
+ break;
+ }
+ case BuildFlag_ExportDefineables: {
+ GB_ASSERT(value.kind == ExactValue_String);
+
+ String export_path = string_trim_whitespace(value.value_string);
+ if (is_build_flag_path_valid(export_path)) {
+ build_context.export_defineables_file = path_to_full_path(heap_allocator(), export_path);
+ } else {
+ gb_printf_err("Invalid -export-defineables path, got %.*s\n", LIT(export_path));
+ bad_flags = true;
+ }
+
+ break;
+ }
case BuildFlag_ShowSystemCalls: {
GB_ASSERT(value.kind == ExactValue_Invalid);
build_context.show_system_calls = true;
@@ -1553,6 +1577,84 @@ gb_internal void timings_export_all(Timings *t, Checker *c, bool timings_are_fin
gb_printf("Done.\n");
}
+gb_internal void temp_alloc_defineable_strings(Checker *c) {
+ for_array(i, c->info.defineables) {
+ Defineable *def = &c->info.defineables[i];
+ def->default_value_str = make_string_c(write_exact_value_to_string(gb_string_make(temporary_allocator(), ""), def->default_value));
+ def->pos_str = make_string_c(token_pos_to_string(def->pos));
+ }
+}
+
+gb_internal GB_COMPARE_PROC(defineables_cmp) {
+ Defineable *x = (Defineable *)a;
+ Defineable *y = (Defineable *)b;
+
+ int cmp = 0;
+
+ String x_file = get_file_path_string(x->pos.file_id);
+ String y_file = get_file_path_string(y->pos.file_id);
+ cmp = string_compare(x_file, y_file);
+ if (cmp) {
+ return cmp;
+ }
+
+ return i32_cmp(x->pos.offset, y->pos.offset);
+}
+
+gb_internal void sort_defineables(Checker *c) {
+ gb_sort_array(c->info.defineables.data, c->info.defineables.count, defineables_cmp);
+}
+
+gb_internal void export_defineables(Checker *c, String path) {
+ gbFile f = {};
+ gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, (char *)path.text);
+ if (err != gbFileError_None) {
+ gb_printf_err("Failed to export defineables to: %.*s\n", LIT(path));
+ gb_exit(1);
+ return;
+ } else {
+ gb_printf("Exporting defineables to '%.*s'...\n", LIT(path));
+ }
+ defer (gb_file_close(&f));
+
+ gb_fprintf(&f, "Defineable,Default Value,Location\n");
+ for_array(i, c->info.defineables) {
+ Defineable *def = &c->info.defineables[i];
+ gb_fprintf(&f,"%.*s,%.*s,%.*s\n", LIT(def->name), LIT(def->default_value_str), LIT(def->pos_str));
+ }
+}
+
+gb_internal void show_defineables(Checker *c) {
+ int max_name_len = strlen("Defineable");
+ int max_default_len = strlen("Default Value");
+ int max_pos_len = strlen("Location");
+
+ for_array(i, c->info.defineables) {
+ Defineable *def = &c->info.defineables[i];
+ if (def->name.len > max_name_len) {
+ max_name_len = def->name.len;
+ }
+
+ if (def->default_value_str.len > max_default_len) {
+ max_default_len = def->default_value_str.len;
+ }
+
+ if (def->pos_str.len > max_pos_len) {
+ max_pos_len = def->pos_str.len;
+ }
+ }
+
+ printf("%-*s - %-*s - %-*s\n", max_name_len, "Defineable", max_default_len, "Default Value", max_pos_len, "Location");
+
+ for_array(i, c->info.defineables) {
+ Defineable *def = &c->info.defineables[i];
+ printf("%-*.*s - %-*.*s - %-*.*s\n",
+ max_name_len, LIT(def->name),
+ max_default_len, LIT(def->default_value_str),
+ max_pos_len, LIT(def->pos_str));
+ }
+}
+
gb_internal void show_timings(Checker *c, Timings *t) {
Parser *p = c->parser;
isize lines = p->total_line_count;
@@ -1955,6 +2057,15 @@ gb_internal void print_show_help(String const arg0, String const &command) {
print_usage_line(2, "Usage in code:");
print_usage_line(3, "#config(SPAM, default_value)");
print_usage_line(0, "");
+
+ print_usage_line(1, "-show-defineables");
+ print_usage_line(2, "Shows an overview of all the #config usages in the project.");
+ print_usage_line(0, "");
+
+ print_usage_line(1, "-export-defineables:<filename>");
+ print_usage_line(2, "Exports an overview of all the #config usages in CSV format to the given file path.");
+ print_usage_line(2, "Example: -export-defineables:defineables.csv");
+ print_usage_line(0, "");
}
if (build) {
@@ -2960,6 +3071,19 @@ int main(int arg_count, char const **arg_ptr) {
print_all_errors();
}
+ if (build_context.show_defineables || build_context.export_defineables_file != "") {
+ TEMPORARY_ALLOCATOR_GUARD();
+ temp_alloc_defineable_strings(checker);
+ sort_defineables(checker);
+
+ if (build_context.show_defineables) {
+ show_defineables(checker);
+ }
+
+ if (build_context.export_defineables_file != "") {
+ export_defineables(checker, build_context.export_defineables_file);
+ }
+ }
if (build_context.command_kind == Command_strip_semicolon) {
return strip_semicolons(parser);