aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-05-26 15:16:45 +0100
committergingerBill <bill@gingerbill.org>2019-05-26 15:16:45 +0100
commit5697d6df7466ef5f4e676f391c104ef165cadb6b (patch)
tree0ea6bf2619a510d97bc5ed19b8fd891740c334e1 /src/main.cpp
parent426c1ed6f407bcfd3c98e266075f9e9f2cca711c (diff)
-go-to-definitions (OGTD file format)
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp475
1 files changed, 43 insertions, 432 deletions
diff --git a/src/main.cpp b/src/main.cpp
index e557cd25e..05fa6c366 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -218,7 +218,10 @@ enum BuildFlagKind {
BuildFlag_UseLLD,
BuildFlag_Vet,
BuildFlag_IgnoreUnknownAttributes,
+
BuildFlag_Compact,
+ BuildFlag_GlobalDefinitions,
+ BuildFlag_GoToDefinitions,
#if defined(GB_SYSTEM_WINDOWS)
BuildFlag_ResourceFile,
@@ -303,7 +306,10 @@ bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_UseLLD, str_lit("lld"), BuildFlagParam_None);
add_flag(&build_flags, BuildFlag_Vet, str_lit("vet"), BuildFlagParam_None);
add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None);
+
add_flag(&build_flags, BuildFlag_Compact, str_lit("compact"), BuildFlagParam_None);
+ add_flag(&build_flags, BuildFlag_GlobalDefinitions, str_lit("global-definitions"), BuildFlagParam_None);
+ add_flag(&build_flags, BuildFlag_GoToDefinitions, str_lit("go-to-definitions"), BuildFlagParam_None);
#if defined(GB_SYSTEM_WINDOWS)
add_flag(&build_flags, BuildFlag_ResourceFile, str_lit("resource"), BuildFlagParam_String);
@@ -667,11 +673,34 @@ bool parse_build_flags(Array<String> args) {
break;
case BuildFlag_Compact:
- if (!build_context.print_query_data) {
+ if (!build_context.query_data_set_settings.ok) {
gb_printf_err("Invalid use of -compact flag, only allowed with 'odin query'\n");
bad_flags = true;
} else {
- build_context.print_query_data_compact = true;
+ build_context.query_data_set_settings.compact = true;
+ }
+ break;
+
+ case BuildFlag_GlobalDefinitions:
+ if (!build_context.query_data_set_settings.ok) {
+ gb_printf_err("Invalid use of -global-definitions flag, only allowed with 'odin query'\n");
+ bad_flags = true;
+ } else if (build_context.query_data_set_settings.kind != QueryDataSet_Invalid) {
+ gb_printf_err("Invalid use of -global-definitions flag, a previous flag for 'odin query' was set\n");
+ bad_flags = true;
+ } else {
+ build_context.query_data_set_settings.kind = QueryDataSet_GlobalDefinitions;
+ }
+ break;
+ case BuildFlag_GoToDefinitions:
+ if (!build_context.query_data_set_settings.ok) {
+ gb_printf_err("Invalid use of -go-to-definitions flag, only allowed with 'odin query'\n");
+ bad_flags = true;
+ } else if (build_context.query_data_set_settings.kind != QueryDataSet_Invalid) {
+ gb_printf_err("Invalid use of -global-definitions flag, a previous flag for 'odin query' was set\n");
+ bad_flags = true;
+ } else {
+ build_context.query_data_set_settings.kind = QueryDataSet_GoToDefinitions;
}
break;
@@ -731,6 +760,16 @@ bool parse_build_flags(Array<String> args) {
}
}
+
+ if (build_context.query_data_set_settings.ok) {
+ if (build_context.query_data_set_settings.kind == QueryDataSet_Invalid) {
+ gb_printf_err("'odin query' requires a flag determining the kind of query data set to be returned\n");
+ gb_printf_err("\t-global-definitions : outputs a JSON file of global definitions\n");
+ gb_printf_err("\t-go-to-definitions : outputs a OGTD binary file of go to definitions for identifiers within an Odin project\n");
+ bad_flags = true;
+ }
+ }
+
return !bad_flags;
}
@@ -828,434 +867,6 @@ void remove_temp_files(String output_base) {
-int query_data_package_compare(void const *a, void const *b) {
- AstPackage *x = *cast(AstPackage *const *)a;
- AstPackage *y = *cast(AstPackage *const *)b;
-
- if (x == y) {
- return 0;
- }
-
- if (x != nullptr && y != nullptr) {
- return string_compare(x->name, y->name);
- } else if (x != nullptr && y == nullptr) {
- return -1;
- } else if (x == nullptr && y != nullptr) {
- return +1;
- }
- return 0;
-}
-
-int query_data_definition_compare(void const *a, void const *b) {
- Entity *x = *cast(Entity *const *)a;
- Entity *y = *cast(Entity *const *)b;
-
- if (x == y) {
- return 0;
- } else if (x != nullptr && y == nullptr) {
- return -1;
- } else if (x == nullptr && y != nullptr) {
- return +1;
- }
-
- if (x->pkg != y->pkg) {
- i32 res = query_data_package_compare(&x->pkg, &y->pkg);
- if (res != 0) {
- return res;
- }
- }
-
- return string_compare(x->token.string, y->token.string);
-}
-
-int entity_name_compare(void const *a, void const *b) {
- Entity *x = *cast(Entity *const *)a;
- Entity *y = *cast(Entity *const *)b;
- if (x == y) {
- return 0;
- } else if (x != nullptr && y == nullptr) {
- return -1;
- } else if (x == nullptr && y != nullptr) {
- return +1;
- }
- return string_compare(x->token.string, y->token.string);
-}
-
-void generate_and_print_query_data(Checker *c, Timings *timings) {
- query_value_allocator = heap_allocator();
-
-
- auto *root = query_value_map();
-
- if (global_error_collector.errors.count > 0) {
- auto *errors = query_value_array();
- root->add("errors", errors);
- for_array(i, global_error_collector.errors) {
- String err = string_trim_whitespace(global_error_collector.errors[i]);
- errors->add(err);
- }
-
- }
-
- { // Packages
- auto *packages = query_value_array();
- root->add("packages", packages);
-
- auto sorted_packages = array_make<AstPackage *>(query_value_allocator, 0, c->info.packages.entries.count);
- defer (array_free(&sorted_packages));
-
- for_array(i, c->info.packages.entries) {
- AstPackage *pkg = c->info.packages.entries[i].value;
- if (pkg != nullptr) {
- array_add(&sorted_packages, pkg);
- }
- }
- gb_sort_array(sorted_packages.data, sorted_packages.count, query_data_package_compare);
- packages->reserve(sorted_packages.count);
-
- for_array(i, sorted_packages) {
- AstPackage *pkg = sorted_packages[i];
- String name = pkg->name;
- String fullpath = pkg->fullpath;
-
- auto *files = query_value_array();
- files->reserve(pkg->files.count);
- for_array(j, pkg->files) {
- AstFile *f = pkg->files[j];
- files->add(f->fullpath);
- }
-
- auto *package = query_value_map();
- package->reserve(3);
- packages->add(package);
-
- package->add("name", pkg->name);
- package->add("fullpath", pkg->fullpath);
- package->add("files", files);
- }
- }
-
- if (c->info.definitions.count > 0) {
- auto *definitions = query_value_array();
- root->add("definitions", definitions);
-
- auto sorted_definitions = array_make<Entity *>(query_value_allocator, 0, c->info.definitions.count);
- defer (array_free(&sorted_definitions));
-
- for_array(i, c->info.definitions) {
- Entity *e = c->info.definitions[i];
- String name = e->token.string;
- if (is_blank_ident(name)) {
- continue;
- }
- if ((e->scope->flags & (ScopeFlag_Pkg|ScopeFlag_File)) == 0) {
- continue;
- }
- if (e->parent_proc_decl != nullptr) {
- continue;
- }
- switch (e->kind) {
- case Entity_Builtin:
- case Entity_Nil:
- case Entity_Label:
- continue;
- }
- if (e->pkg == nullptr) {
- continue;
- }
- if (e->token.pos.line == 0) {
- continue;
- }
- if (e->kind == Entity_Procedure) {
- Type *t = base_type(e->type);
- if (t->kind != Type_Proc) {
- continue;
- }
- if (t->Proc.is_poly_specialized) {
- continue;
- }
- }
- if (e->kind == Entity_TypeName) {
- Type *t = base_type(e->type);
- if (t->kind == Type_Struct) {
- if (t->Struct.is_poly_specialized) {
- continue;
- }
- }
- if (t->kind == Type_Union) {
- if (t->Union.is_poly_specialized) {
- continue;
- }
- }
- }
-
- array_add(&sorted_definitions, e);
- }
-
- gb_sort_array(sorted_definitions.data, sorted_definitions.count, query_data_definition_compare);
- definitions->reserve(sorted_definitions.count);
-
- for_array(i, sorted_definitions) {
- Entity *e = sorted_definitions[i];
- String name = e->token.string;
-
- auto *def = query_value_map();
- def->reserve(16);
- definitions->add(def);
-
- def->add("package", e->pkg->name);
- def->add("name", name);
- def->add("filepath", e->token.pos.file);
- def->add("line", e->token.pos.line);
- def->add("column", e->token.pos.column);
- def->add("file_offset", e->token.pos.offset);
-
- switch (e->kind) {
- case Entity_Constant: def->add("kind", str_lit("constant")); break;
- case Entity_Variable: def->add("kind", str_lit("variable")); break;
- case Entity_TypeName: def->add("kind", str_lit("type name")); break;
- case Entity_Procedure: def->add("kind", str_lit("procedure")); break;
- case Entity_ProcGroup: def->add("kind", str_lit("procedure group")); break;
- case Entity_ImportName: def->add("kind", str_lit("import name")); break;
- case Entity_LibraryName: def->add("kind", str_lit("library name")); break;
- default: GB_PANIC("Invalid entity kind to be added");
- }
-
-
- if (e->type != nullptr && e->type != t_invalid) {
- Type *t = e->type;
- Type *bt = t;
-
- switch (e->kind) {
- case Entity_TypeName:
- if (!e->TypeName.is_type_alias) {
- bt = base_type(t);
- }
- break;
- }
-
- {
- gbString str = type_to_string(t);
- String type_str = make_string(cast(u8 *)str, gb_string_length(str));
- def->add("type", type_str);
- }
- if (t != bt) {
- gbString str = type_to_string(bt);
- String type_str = make_string(cast(u8 *)str, gb_string_length(str));
- def->add("base_type", type_str);
- }
- {
- String type_kind = {};
- Type *bt = base_type(t);
- switch (bt->kind) {
- case Type_Pointer: type_kind = str_lit("pointer"); break;
- case Type_Opaque: type_kind = str_lit("opaque"); break;
- case Type_Array: type_kind = str_lit("array"); break;
- case Type_Slice: type_kind = str_lit("slice"); break;
- case Type_DynamicArray: type_kind = str_lit("dynamic array"); break;
- case Type_Map: type_kind = str_lit("map"); break;
- case Type_Struct: type_kind = str_lit("struct"); break;
- case Type_Union: type_kind = str_lit("union"); break;
- case Type_Enum: type_kind = str_lit("enum"); break;
- case Type_Proc: type_kind = str_lit("procedure"); break;
- case Type_BitField: type_kind = str_lit("bit field"); break;
- case Type_BitSet: type_kind = str_lit("bit set"); break;
- case Type_SimdVector: type_kind = str_lit("simd vector"); break;
-
- case Type_Generic:
- case Type_Tuple:
- case Type_BitFieldValue:
- GB_PANIC("Invalid definition type");
- break;
- }
- if (type_kind.len > 0) {
- def->add("type_kind", type_kind);
- }
- }
- }
-
- if (e->kind == Entity_TypeName) {
- def->add("size", type_size_of(e->type));
- def->add("align", type_align_of(e->type));
-
-
- if (is_type_struct(e->type)) {
- auto *data = query_value_map();
- data->reserve(6);
-
- def->add("data", data);
-
- Type *t = base_type(e->type);
- GB_ASSERT(t->kind == Type_Struct);
-
- if (t->Struct.is_polymorphic) {
- data->add("polymorphic", t->Struct.is_polymorphic);
- }
- if (t->Struct.is_poly_specialized) {
- data->add("polymorphic_specialized", t->Struct.is_poly_specialized);
- }
- if (t->Struct.is_packed) {
- data->add("packed", t->Struct.is_packed);
- }
- if (t->Struct.is_raw_union) {
- data->add("raw_union", t->Struct.is_raw_union);
- }
-
- auto *fields = query_value_array();
- data->add("fields", fields);
- fields->reserve(t->Struct.fields.count);
- fields->packed = true;
-
- for_array(j, t->Struct.fields) {
- Entity *e = t->Struct.fields[j];
- String name = e->token.string;
- if (is_blank_ident(name)) {
- continue;
- }
-
- fields->add(name);
- }
- } else if (is_type_union(e->type)) {
- auto *data = query_value_map();
- data->reserve(4);
-
- def->add("data", data);
- Type *t = base_type(e->type);
- GB_ASSERT(t->kind == Type_Union);
-
- if (t->Union.is_polymorphic) {
- data->add("polymorphic", t->Union.is_polymorphic);
- }
- if (t->Union.is_poly_specialized) {
- data->add("polymorphic_specialized", t->Union.is_poly_specialized);
- }
-
- auto *variants = query_value_array();
- variants->reserve(t->Union.variants.count);
- data->add("variants", variants);
-
- for_array(j, t->Union.variants) {
- Type *vt = t->Union.variants[j];
-
- gbString str = type_to_string(vt);
- String type_str = make_string(cast(u8 *)str, gb_string_length(str));
- variants->add(type_str);
- }
- }
- }
-
- if (e->kind == Entity_Procedure) {
- Type *t = base_type(e->type);
- GB_ASSERT(t->kind == Type_Proc);
-
- bool is_polymorphic = t->Proc.is_polymorphic;
- bool is_poly_specialized = t->Proc.is_poly_specialized;
- bool ok = is_polymorphic || is_poly_specialized;
- if (ok) {
- auto *data = query_value_map();
- data->reserve(4);
-
- def->add("data", data);
- if (is_polymorphic) {
- data->add("polymorphic", is_polymorphic);
- }
- if (is_poly_specialized) {
- data->add("polymorphic_specialized", is_poly_specialized);
- }
- }
- }
-
- if (e->kind == Entity_ProcGroup) {
- auto *procedures = query_value_array();
- procedures->reserve(e->ProcGroup.entities.count);
-
- for_array(j, e->ProcGroup.entities) {
- Entity *p = e->ProcGroup.entities[j];
-
- auto *procedure = query_value_map();
- procedure->reserve(2);
- procedure->packed = true;
-
- procedures->add(procedure);
-
- procedure->add("package", p->pkg->name);
- procedure->add("name", p->token.string);
- }
- def->add("procedures", procedures);
- }
-
- DeclInfo *di = e->decl_info;
- if (di != nullptr) {
- if (di->is_using) {
- def->add("using", query_value_boolean(true));
- }
- }
- }
- }
-
- if (build_context.show_timings) {
- Timings *t = timings;
- timings__stop_current_section(t);
- t->total.finish = time_stamp_time_now();
- isize max_len = gb_min(36, t->total.label.len);
- for_array(i, t->sections) {
- TimeStamp ts = t->sections[i];
- max_len = gb_max(max_len, ts.label.len);
- }
- t->total_time_seconds = time_stamp_as_s(t->total, t->freq);
-
- auto *tims = query_value_map();
- tims->reserve(8);
- root->add("timings", tims);
- tims->add("time_unit", str_lit("s"));
-
- tims->add(t->total.label, cast(f64)t->total_time_seconds);
-
-
- Parser *p = c->parser;
- if (p != nullptr) {
- isize lines = p->total_line_count;
- isize tokens = p->total_token_count;
- isize files = 0;
- isize packages = p->packages.count;
- isize total_file_size = 0;
- for_array(i, p->packages) {
- files += p->packages[i]->files.count;
- for_array(j, p->packages[i]->files) {
- AstFile *file = p->packages[i]->files[j];
- total_file_size += file->tokenizer.end - file->tokenizer.start;
- }
- }
-
- tims->add("total_lines", lines);
- tims->add("total_tokens", tokens);
- tims->add("total_files", files);
- tims->add("total_packages", packages);
- tims->add("total_file_size", total_file_size);
-
- auto *sections = query_value_map();
- sections->reserve(t->sections.count);
- tims->add("sections", sections);
- for_array(i, t->sections) {
- TimeStamp ts = t->sections[i];
- f64 section_time = time_stamp_as_s(ts, t->freq);
-
- auto *section = query_value_map();
- section->reserve(2);
- sections->add(ts.label, section);
- section->add("time", section_time);
- section->add("total_fraction", section_time/t->total_time_seconds);
- }
- }
- }
-
-
- print_query_data_as_json(root, !build_context.print_query_data_compact);
- gb_printf("\n");
-}
-
-
-
i32 exec_llvm_opt(String output_base) {
#if defined(GB_SYSTEM_WINDOWS)
@@ -1378,7 +989,7 @@ int main(int arg_count, char **arg_ptr) {
return 1;
}
build_context.no_output_files = true;
- build_context.print_query_data = true;
+ build_context.query_data_set_settings.ok = true;
init_filename = args[2];
} else if (command == "docs") {
if (args.count < 3) {
@@ -1455,7 +1066,7 @@ int main(int arg_count, char **arg_ptr) {
if (build_context.no_output_files) {
- if (build_context.print_query_data) {
+ if (build_context.query_data_set_settings.ok) {
generate_and_print_query_data(&checker, &timings);
} else {
if (build_context.show_timings) {