浏览代码

-show-defineables and -export-defineables

Laytan Laats 1 年之前
父节点
当前提交
9a95049393
共有 5 个文件被更改,包括 150 次插入1 次删除
  1. 2 0
      src/build_settings.cpp
  2. 10 1
      src/check_builtin.cpp
  3. 2 0
      src/checker.cpp
  4. 12 0
      src/checker.hpp
  5. 124 0
      src/main.cpp

+ 2 - 0
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;

+ 10 - 1
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));
 	}

+ 2 - 0
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);

+ 12 - 0
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;

+ 124 - 0
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);