123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140 |
- template <typename T>
- struct OdinDocWriterItemTracker {
- isize len;
- isize cap;
- isize offset;
- };
- enum OdinDocWriterState {
- OdinDocWriterState_Preparing,
- OdinDocWriterState_Writing,
- };
- char const* OdinDocWriterState_strings[] {
- "preparing",
- "writing ",
- };
- struct OdinDocWriter {
- CheckerInfo *info;
- OdinDocWriterState state;
- void *data;
- isize data_len;
- OdinDocHeader *header;
- StringMap<OdinDocString> string_cache;
- PtrMap<AstFile *, OdinDocFileIndex> file_cache;
- PtrMap<AstPackage *, OdinDocPkgIndex> pkg_cache;
- PtrMap<Entity *, OdinDocEntityIndex> entity_cache;
- PtrMap<Type *, OdinDocTypeIndex> type_cache;
- OdinDocWriterItemTracker<OdinDocFile> files;
- OdinDocWriterItemTracker<OdinDocPkg> pkgs;
- OdinDocWriterItemTracker<OdinDocEntity> entities;
- OdinDocWriterItemTracker<OdinDocType> types;
- OdinDocWriterItemTracker<u8> strings;
- OdinDocWriterItemTracker<u8> blob;
- };
- OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e);
- OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type);
- template <typename T>
- void odin_doc_writer_item_tracker_init(OdinDocWriterItemTracker<T> *t, isize size) {
- t->len = size;
- t->cap = size;
- }
- void odin_doc_writer_prepare(OdinDocWriter *w) {
- w->state = OdinDocWriterState_Preparing;
- gbAllocator a = heap_allocator();
- string_map_init(&w->string_cache, a);
- map_init(&w->file_cache, a);
- map_init(&w->pkg_cache, a);
- map_init(&w->entity_cache, a);
- map_init(&w->type_cache, a);
- odin_doc_writer_item_tracker_init(&w->files, 1);
- odin_doc_writer_item_tracker_init(&w->pkgs, 1);
- odin_doc_writer_item_tracker_init(&w->entities, 1);
- odin_doc_writer_item_tracker_init(&w->types, 1);
- odin_doc_writer_item_tracker_init(&w->strings, 16);
- odin_doc_writer_item_tracker_init(&w->blob, 16);
- }
- void odin_doc_writer_destroy(OdinDocWriter *w) {
- gb_free(heap_allocator(), w->data);
- string_map_destroy(&w->string_cache);
- map_destroy(&w->file_cache);
- map_destroy(&w->pkg_cache);
- map_destroy(&w->entity_cache);
- map_destroy(&w->type_cache);
- }
- template <typename T>
- void odin_doc_writer_tracker_size(isize *offset, OdinDocWriterItemTracker<T> *t, isize alignment=1) {
- isize size = t->cap*gb_size_of(T);
- isize align = gb_max(gb_align_of(T), alignment);
- *offset = align_formula_isize(*offset, align);
- t->offset = *offset;
- *offset += size;
- }
- isize odin_doc_writer_calc_total_size(OdinDocWriter *w) {
- isize total_size = gb_size_of(OdinDocHeader);
- odin_doc_writer_tracker_size(&total_size, &w->files);
- odin_doc_writer_tracker_size(&total_size, &w->pkgs);
- odin_doc_writer_tracker_size(&total_size, &w->entities);
- odin_doc_writer_tracker_size(&total_size, &w->types);
- odin_doc_writer_tracker_size(&total_size, &w->strings, 16);
- odin_doc_writer_tracker_size(&total_size, &w->blob, 16);
- return total_size;
- }
- void odin_doc_writer_start_writing(OdinDocWriter *w) {
- w->state = OdinDocWriterState_Writing;
- string_map_clear(&w->string_cache);
- map_clear(&w->file_cache);
- map_clear(&w->pkg_cache);
- map_clear(&w->entity_cache);
- map_clear(&w->type_cache);
- isize total_size = odin_doc_writer_calc_total_size(w);
- total_size = align_formula_isize(total_size, 8);
- w->data = gb_alloc_align(heap_allocator(), total_size, 8);
- w->data_len = total_size;
- w->header = cast(OdinDocHeader *)w->data;
- }
- u32 hash_data_after_header(OdinDocHeaderBase *base, void *data, isize data_len) {
- u8 *start = cast(u8 *)data;
- u8 *end = start + base->total_size;
- start += base->header_size;
- u32 h = 0x811c9dc5;
- for (u8 *b = start; b != end; b++) {
- h = (h ^ cast(u32)*b) * 0x01000193;
- }
- return h;
- }
- template <typename T>
- void odin_doc_writer_assign_tracker(OdinDocArray<T> *array, OdinDocWriterItemTracker<T> const &t) {
- array->offset = cast(u32)t.offset;
- array->length = cast(u32)t.len;
- }
- void odin_doc_writer_end_writing(OdinDocWriter *w) {
- OdinDocHeader *h = w->header;
- gb_memmove(h->base.magic, OdinDocHeader_MagicString, gb_strlen(OdinDocHeader_MagicString));
- h->base.version.major = OdinDocVersionType_Major;
- h->base.version.minor = OdinDocVersionType_Minor;
- h->base.version.patch = OdinDocVersionType_Patch;
- h->base.total_size = cast(u32)w->data_len;
- h->base.header_size = gb_size_of(*h);
- h->base.hash = hash_data_after_header(&h->base, w->data, w->data_len);
- odin_doc_writer_assign_tracker(&h->files, w->files);
- odin_doc_writer_assign_tracker(&h->pkgs, w->pkgs);
- odin_doc_writer_assign_tracker(&h->entities, w->entities);
- odin_doc_writer_assign_tracker(&h->types, w->types);
- }
- template <typename T>
- u32 odin_doc_write_item(OdinDocWriter *w, OdinDocWriterItemTracker<T> *t, T const *item, T **dst=nullptr) {
- if (w->state == OdinDocWriterState_Preparing) {
- t->cap += 1;
- if (dst) *dst = nullptr;
- return 0;
- } else {
- GB_ASSERT_MSG(t->len < t->cap, "%td < %td", t->len, t->cap);
- isize item_index = t->len++;
- uintptr data = cast(uintptr)w->data + cast(uintptr)(t->offset + gb_size_of(T)*item_index);
- if (item) {
- gb_memmove(cast(T *)data, item, gb_size_of(T));
- }
- if (dst) *dst = cast(T *)data;
- return cast(u32)item_index;
- }
- }
- template <typename T>
- T *odin_doc_get_item(OdinDocWriter *w, OdinDocWriterItemTracker<T> *t, u32 index) {
- if (w->state != OdinDocWriterState_Writing) {
- return nullptr;
- }
- GB_ASSERT(index < cast(u32)t->len);
- uintptr data = cast(uintptr)w->data + cast(uintptr)(t->offset + gb_size_of(T)*index);
- return cast(T *)data;
- }
- OdinDocString odin_doc_write_string_without_cache(OdinDocWriter *w, String const &str) {
- OdinDocString res = {};
- if (w->state == OdinDocWriterState_Preparing) {
- w->strings.cap += str.len+1;
- } else {
- GB_ASSERT_MSG(w->strings.len+str.len+1 <= w->strings.cap, "%td <= %td", w->strings.len+str.len, w->strings.cap);
- isize offset = w->strings.offset + w->strings.len;
- u8 *data = cast(u8 *)w->data + offset;
- gb_memmove(data, str.text, str.len);
- data[str.len] = 0;
- w->strings.len += str.len+1;
- res.offset = cast(u32)offset;
- res.length = cast(u32)str.len;
- }
- return res;
- }
- OdinDocString odin_doc_write_string(OdinDocWriter *w, String const &str) {
- OdinDocString *c = string_map_get(&w->string_cache, str);
- if (c != nullptr) {
- if (w->state == OdinDocWriterState_Writing) {
- GB_ASSERT(from_string(&w->header->base, *c) == str);
- }
- return *c;
- }
- OdinDocString res = odin_doc_write_string_without_cache(w, str);
- string_map_set(&w->string_cache, str, res);
- return res;
- }
- template <typename T>
- OdinDocArray<T> odin_write_slice(OdinDocWriter *w, T *data, isize len) {
- GB_ASSERT(gb_align_of(T) <= 4);
- if (len <= 0) {
- return {0, 0};
- }
- isize alignment = 4;
- if (w->state == OdinDocWriterState_Preparing) {
- w->blob.cap = align_formula_isize(w->blob.cap, alignment);
- w->blob.cap += len * gb_size_of(T);
- return {0, 0};
- }
- w->blob.len = align_formula_isize(w->blob.len, alignment);
- isize offset = w->blob.offset + w->blob.len;
- u8 *dst = cast(u8 *)w->data + offset;
- gb_memmove(dst, data, len*gb_size_of(T));
- w->blob.len += len * gb_size_of(T);
- return {cast(u32)offset, cast(u32)len};
- }
- template <typename T>
- OdinDocArray<T> odin_write_item_as_slice(OdinDocWriter *w, T data) {
- return odin_write_slice(w, &data, 1);
- }
- OdinDocPosition odin_doc_token_pos_cast(OdinDocWriter *w, TokenPos const &pos) {
- OdinDocFileIndex file_index = 0;
- if (pos.file_id != 0) {
- AstFile *file = global_files[pos.file_id];
- if (file != nullptr) {
- OdinDocFileIndex *file_index_found = map_get(&w->file_cache, file);
- GB_ASSERT(file_index_found != nullptr);
- file_index = *file_index_found;
- }
- }
- OdinDocPosition doc_pos = {};
- doc_pos.file = file_index;
- doc_pos.line = cast(u32)pos.line;
- doc_pos.column = cast(u32)pos.column;
- doc_pos.offset = cast(u32)pos.offset;
- return doc_pos;
- }
- bool odin_doc_append_comment_group_string(Array<u8> *buf, CommentGroup *g) {
- if (g == nullptr) {
- return false;
- }
- isize len = 0;
- for_array(i, g->list) {
- String comment = g->list[i].string;
- len += comment.len;
- len += 1; // for \n
- }
- if (len <= g->list.count) {
- return false;
- }
- isize count = 0;
- for_array(i, g->list) {
- String comment = g->list[i].string;
- String original_comment = comment;
- bool slash_slash = false;
- if (comment[1] == '/') {
- slash_slash = true;
- comment.text += 2;
- comment.len -= 2;
- } else if (comment[1] == '*') {
- comment.text += 2;
- comment.len -= 4;
- }
- // Ignore the first space
- if (comment.len > 0 && comment[0] == ' ') {
- comment.text += 1;
- comment.len -= 1;
- }
- if (slash_slash) {
- if (string_starts_with(comment, str_lit("+"))) {
- continue;
- }
- if (string_starts_with(comment, str_lit("@("))) {
- continue;
- }
- }
- if (slash_slash) {
- array_add_elems(buf, comment.text, comment.len);
- array_add(buf, cast(u8)'\n');
- count += 1;
- } else {
- isize pos = 0;
- for (; pos < comment.len; pos++) {
- isize end = pos;
- for (; end < comment.len; end++) {
- if (comment[end] == '\n') {
- break;
- }
- }
- String line = substring(comment, pos, end);
- pos = end;
- String trimmed_line = string_trim_whitespace(line);
- if (trimmed_line.len == 0) {
- if (count == 0) {
- continue;
- }
- }
- /*
- * Remove comments with
- * styles
- * like this
- */
- if (string_starts_with(line, str_lit("* "))) {
- line = substring(line, 2, line.len);
- }
- array_add_elems(buf, line.text, line.len);
- array_add(buf, cast(u8)'\n');
- count += 1;
- }
- }
- }
- if (count > 0) {
- array_add(buf, cast(u8)'\n');
- return true;
- }
- return false;
- }
- OdinDocString odin_doc_pkg_doc_string(OdinDocWriter *w, AstPackage *pkg) {
- if (pkg == nullptr) {
- return {};
- }
- auto buf = array_make<u8>(permanent_allocator(), 0, 0); // Minor leak
- for_array(i, pkg->files) {
- AstFile *f = pkg->files[i];
- if (f->pkg_decl) {
- GB_ASSERT(f->pkg_decl->kind == Ast_PackageDecl);
- odin_doc_append_comment_group_string(&buf, f->pkg_decl->PackageDecl.docs);
- }
- }
- return odin_doc_write_string_without_cache(w, make_string(buf.data, buf.count));
- }
- OdinDocString odin_doc_comment_group_string(OdinDocWriter *w, CommentGroup *g) {
- if (g == nullptr) {
- return {};
- }
- auto buf = array_make<u8>(permanent_allocator(), 0, 0); // Minor leak
- odin_doc_append_comment_group_string(&buf, g);
- return odin_doc_write_string_without_cache(w, make_string(buf.data, buf.count));
- }
- OdinDocString odin_doc_expr_string(OdinDocWriter *w, Ast *expr) {
- if (expr == nullptr) {
- return {};
- }
- gbString s = write_expr_to_string( // Minor leak
- gb_string_make(permanent_allocator(), ""),
- expr,
- build_context.cmd_doc_flags & CmdDocFlag_Short
- );
- return odin_doc_write_string(w, make_string(cast(u8 *)s, gb_string_length(s)));
- }
- OdinDocArray<OdinDocAttribute> odin_doc_attributes(OdinDocWriter *w, Array<Ast *> const &attributes) {
- isize count = 0;
- for_array(i, attributes) {
- Ast *attr = attributes[i];
- if (attr->kind != Ast_Attribute) continue;
- count += attr->Attribute.elems.count;
- };
- auto attribs = array_make<OdinDocAttribute>(heap_allocator(), 0, count);
- defer (array_free(&attribs));
- for_array(i, attributes) {
- Ast *attr = attributes[i];
- if (attr->kind != Ast_Attribute) continue;
- for_array(j, attr->Attribute.elems) {
- Ast *elem = attr->Attribute.elems[j];
- String name = {};
- Ast *value = nullptr;
- switch (elem->kind) {
- case_ast_node(i, Ident, elem);
- name = i->token.string;
- case_end;
- case_ast_node(i, Implicit, elem);
- name = i->string;
- case_end;
- case_ast_node(fv, FieldValue, elem);
- if (fv->field->kind == Ast_Ident) {
- name = fv->field->Ident.token.string;
- } else if (fv->field->kind == Ast_Implicit) {
- name = fv->field->Implicit.string;
- }
- value = fv->value;
- case_end;
- default:
- continue;
- }
- OdinDocAttribute doc_attrib = {};
- doc_attrib.name = odin_doc_write_string(w, name);
- doc_attrib.value = odin_doc_expr_string(w, value);
- array_add(&attribs, doc_attrib);
- }
- }
- return odin_write_slice(w, attribs.data, attribs.count);
- }
- OdinDocArray<OdinDocString> odin_doc_where_clauses(OdinDocWriter *w, Slice<Ast *> const &where_clauses) {
- if (where_clauses.count == 0) {
- return {};
- }
- auto clauses = array_make<OdinDocString>(heap_allocator(), where_clauses.count);
- defer (array_free(&clauses));
- for_array(i, where_clauses) {
- clauses[i] = odin_doc_expr_string(w, where_clauses[i]);
- }
- return odin_write_slice(w, clauses.data, clauses.count);
- }
- OdinDocArray<OdinDocTypeIndex> odin_doc_type_as_slice(OdinDocWriter *w, Type *type) {
- OdinDocTypeIndex index = odin_doc_type(w, type);
- return odin_write_item_as_slice(w, index);
- }
- OdinDocArray<OdinDocEntityIndex> odin_doc_add_entity_as_slice(OdinDocWriter *w, Entity *e) {
- OdinDocEntityIndex index = odin_doc_add_entity(w, e);
- return odin_write_item_as_slice(w, index);
- }
- OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) {
- if (type == nullptr) {
- return 0;
- }
- OdinDocTypeIndex *found = map_get(&w->type_cache, type);
- if (found) {
- return *found;
- }
- for_array(i, w->type_cache.entries) {
- // NOTE(bill): THIS IS SLOW
- Type *other = w->type_cache.entries[i].key;
- if (are_types_identical_unique_tuples(type, other)) {
- OdinDocTypeIndex index = w->type_cache.entries[i].value;
- map_set(&w->type_cache, type, index);
- return index;
- }
- }
- OdinDocType *dst = nullptr;
- OdinDocType doc_type = {};
- OdinDocTypeIndex type_index = 0;
- type_index = odin_doc_write_item(w, &w->types, &doc_type, &dst);
- map_set(&w->type_cache, type, type_index);
- switch (type->kind) {
- case Type_Basic:
- doc_type.kind = OdinDocType_Basic;
- doc_type.name = odin_doc_write_string(w, type->Basic.name);
- if (is_type_untyped(type)) {
- doc_type.flags |= OdinDocTypeFlag_Basic_untyped;
- }
- break;
- case Type_Named:
- doc_type.kind = OdinDocType_Named;
- doc_type.name = odin_doc_write_string(w, type->Named.name);
- doc_type.types = odin_doc_type_as_slice(w, base_type(type));
- doc_type.entities = odin_doc_add_entity_as_slice(w, type->Named.type_name);
- break;
- case Type_Generic:
- {
- String name = type->Generic.name;
- if (type->Generic.entity) {
- name = type->Generic.entity->token.string;
- }
- doc_type.kind = OdinDocType_Generic;
- doc_type.name = odin_doc_write_string(w, name);
- if (type->Generic.specialized) {
- doc_type.types = odin_doc_type_as_slice(w, type->Generic.specialized);
- }
- }
- break;
- case Type_Pointer:
- doc_type.kind = OdinDocType_Pointer;
- doc_type.types = odin_doc_type_as_slice(w, type->Pointer.elem);
- break;
- case Type_MultiPointer:
- doc_type.kind = OdinDocType_MultiPointer;
- doc_type.types = odin_doc_type_as_slice(w, type->MultiPointer.elem);
- break;
- case Type_Array:
- doc_type.kind = OdinDocType_Array;
- doc_type.elem_count_len = 1;
- doc_type.elem_counts[0] = type->Array.count;
- doc_type.types = odin_doc_type_as_slice(w, type->Array.elem);
- break;
- case Type_EnumeratedArray:
- doc_type.kind = OdinDocType_EnumeratedArray;
- doc_type.elem_count_len = 1;
- doc_type.elem_counts[0] = type->EnumeratedArray.count;
- {
- OdinDocTypeIndex types[2] = {};
- types[0] = odin_doc_type(w, type->EnumeratedArray.index);
- types[1] = odin_doc_type(w, type->EnumeratedArray.elem);
- doc_type.types = odin_write_slice(w, types, gb_count_of(types));
- }
- break;
- case Type_Slice:
- doc_type.kind = OdinDocType_Slice;
- doc_type.types = odin_doc_type_as_slice(w, type->Slice.elem);
- break;
- case Type_DynamicArray:
- doc_type.kind = OdinDocType_DynamicArray;
- doc_type.types = odin_doc_type_as_slice(w, type->DynamicArray.elem);
- break;
- case Type_Map:
- doc_type.kind = OdinDocType_Map;
- {
- OdinDocTypeIndex types[2] = {};
- types[0] = odin_doc_type(w, type->Map.key);
- types[1] = odin_doc_type(w, type->Map.value);
- doc_type.types = odin_write_slice(w, types, gb_count_of(types));
- }
- break;
- case Type_Struct:
- doc_type.kind = OdinDocType_Struct;
- if (type->Struct.soa_kind != StructSoa_None) {
- switch (type->Struct.soa_kind) {
- case StructSoa_Fixed:
- doc_type.kind = OdinDocType_SOAStructFixed;
- doc_type.elem_count_len = 1;
- doc_type.elem_counts[0] = type->Struct.soa_count;
- break;
- case StructSoa_Slice:
- doc_type.kind = OdinDocType_SOAStructSlice;
- break;
- case StructSoa_Dynamic:
- doc_type.kind = OdinDocType_SOAStructDynamic;
- break;
- }
- doc_type.types = odin_doc_type_as_slice(w, type->Struct.soa_elem);
- } else {
- if (type->Struct.is_polymorphic) { doc_type.flags |= OdinDocTypeFlag_Struct_polymorphic; }
- if (type->Struct.is_packed) { doc_type.flags |= OdinDocTypeFlag_Struct_packed; }
- if (type->Struct.is_raw_union) { doc_type.flags |= OdinDocTypeFlag_Struct_raw_union; }
- auto fields = array_make<OdinDocEntityIndex>(heap_allocator(), type->Struct.fields.count);
- defer (array_free(&fields));
- for_array(i, type->Struct.fields) {
- fields[i] = odin_doc_add_entity(w, type->Struct.fields[i]);
- }
- doc_type.entities = odin_write_slice(w, fields.data, fields.count);
- doc_type.polmorphic_params = odin_doc_type(w, type->Struct.polymorphic_params);
- if (type->Struct.node) {
- ast_node(st, StructType, type->Struct.node);
- if (st->align) {
- doc_type.custom_align = odin_doc_expr_string(w, st->align);
- }
- doc_type.where_clauses = odin_doc_where_clauses(w, st->where_clauses);
- }
- auto tags = array_make<OdinDocString>(heap_allocator(), type->Struct.fields.count);
- defer (array_free(&tags));
- for_array(i, type->Struct.fields) {
- tags[i] = odin_doc_write_string(w, type->Struct.tags[i]);
- }
- doc_type.tags = odin_write_slice(w, tags.data, tags.count);
- }
- break;
- case Type_Union:
- doc_type.kind = OdinDocType_Union;
- if (type->Union.is_polymorphic) { doc_type.flags |= OdinDocTypeFlag_Union_polymorphic; }
- if (type->Union.no_nil) { doc_type.flags |= OdinDocTypeFlag_Union_no_nil; }
- if (type->Union.maybe) { doc_type.flags |= OdinDocTypeFlag_Union_maybe; }
- {
- auto variants = array_make<OdinDocTypeIndex>(heap_allocator(), type->Union.variants.count);
- defer (array_free(&variants));
- for_array(i, type->Union.variants) {
- variants[i] = odin_doc_type(w, type->Union.variants[i]);
- }
- doc_type.types = odin_write_slice(w, variants.data, variants.count);
- doc_type.polmorphic_params = odin_doc_type(w, type->Union.polymorphic_params);
- }
- if (type->Union.node) {
- ast_node(ut, UnionType, type->Union.node);
- if (ut->align) {
- doc_type.custom_align = odin_doc_expr_string(w, ut->align);
- }
- doc_type.where_clauses = odin_doc_where_clauses(w, ut->where_clauses);
- }
- break;
- case Type_Enum:
- doc_type.kind = OdinDocType_Enum;
- {
- auto fields = array_make<OdinDocEntityIndex>(heap_allocator(), type->Enum.fields.count);
- defer (array_free(&fields));
- for_array(i, type->Enum.fields) {
- fields[i] = odin_doc_add_entity(w, type->Enum.fields[i]);
- }
- doc_type.entities = odin_write_slice(w, fields.data, fields.count);
- if (type->Enum.base_type) {
- doc_type.types = odin_doc_type_as_slice(w, type->Enum.base_type);
- }
- }
- break;
- case Type_Tuple:
- doc_type.kind = OdinDocType_Tuple;
- {
- auto variables = array_make<OdinDocEntityIndex>(heap_allocator(), type->Tuple.variables.count);
- defer (array_free(&variables));
- for_array(i, type->Tuple.variables) {
- variables[i] = odin_doc_add_entity(w, type->Tuple.variables[i]);
- }
- doc_type.entities = odin_write_slice(w, variables.data, variables.count);
- }
- break;
- case Type_Proc:
- doc_type.kind = OdinDocType_Proc;
- if (type->Proc.is_polymorphic) { doc_type.flags |= OdinDocTypeFlag_Proc_polymorphic; }
- if (type->Proc.diverging) { doc_type.flags |= OdinDocTypeFlag_Proc_diverging; }
- if (type->Proc.optional_ok) { doc_type.flags |= OdinDocTypeFlag_Proc_optional_ok; }
- if (type->Proc.variadic) { doc_type.flags |= OdinDocTypeFlag_Proc_variadic; }
- if (type->Proc.c_vararg) { doc_type.flags |= OdinDocTypeFlag_Proc_c_vararg; }
- {
- OdinDocTypeIndex types[2];
- types[0] = odin_doc_type(w, type->Proc.params);
- types[1] = odin_doc_type(w, type->Proc.results);
- doc_type.types = odin_write_slice(w, types, gb_count_of(types));
- String calling_convention = {};
- switch (type->Proc.calling_convention) {
- case ProcCC_Invalid:
- // no need
- break;
- case ProcCC_Odin:
- if (default_calling_convention() != ProcCC_Odin) {
- calling_convention = str_lit("odin");
- }
- break;
- case ProcCC_Contextless:
- if (default_calling_convention() != ProcCC_Contextless) {
- calling_convention = str_lit("contextless");
- }
- break;
- case ProcCC_CDecl:
- calling_convention = str_lit("cdecl");
- break;
- case ProcCC_StdCall:
- calling_convention = str_lit("stdcall");
- break;
- case ProcCC_FastCall:
- calling_convention = str_lit("fastcall");
- break;
- case ProcCC_None:
- calling_convention = str_lit("none");
- break;
- case ProcCC_Naked:
- calling_convention = str_lit("naked");
- break;
- case ProcCC_InlineAsm:
- calling_convention = str_lit("inline-assembly");
- break;
- }
- doc_type.calling_convention = odin_doc_write_string(w, calling_convention);
- }
- break;
- case Type_BitSet:
- doc_type.kind = OdinDocType_BitSet;
- {
- isize type_count = 0;
- OdinDocTypeIndex types[2] = {};
- if (type->BitSet.elem) {
- types[type_count++] = odin_doc_type(w, type->BitSet.elem);
- }
- if (type->BitSet.underlying) {
- types[type_count++] = odin_doc_type(w, type->BitSet.underlying);
- doc_type.flags |= OdinDocTypeFlag_BitSet_UnderlyingType;
- }
- doc_type.types = odin_write_slice(w, types, type_count);
- doc_type.elem_count_len = 2;
- doc_type.elem_counts[0] = type->BitSet.lower;
- doc_type.elem_counts[1] = type->BitSet.upper;
- }
- break;
- case Type_SimdVector:
- doc_type.kind = OdinDocType_SimdVector;
- doc_type.elem_count_len = 1;
- doc_type.elem_counts[0] = type->SimdVector.count;
- doc_type.types = odin_doc_type_as_slice(w, type->SimdVector.elem);
- // TODO(bill):
- break;
- case Type_RelativePointer:
- doc_type.kind = OdinDocType_RelativePointer;
- {
- OdinDocTypeIndex types[2] = {};
- types[0] = odin_doc_type(w, type->RelativePointer.pointer_type);
- types[1] = odin_doc_type(w, type->RelativePointer.base_integer);
- doc_type.types = odin_write_slice(w, types, gb_count_of(types));
- }
- break;
- case Type_RelativeSlice:
- doc_type.kind = OdinDocType_RelativeSlice;
- {
- OdinDocTypeIndex types[2] = {};
- types[0] = odin_doc_type(w, type->RelativeSlice.slice_type);
- types[1] = odin_doc_type(w, type->RelativeSlice.base_integer);
- doc_type.types = odin_write_slice(w, types, gb_count_of(types));
- }
- break;
-
- case Type_Matrix:
- doc_type.kind = OdinDocType_Matrix;
- doc_type.elem_count_len = 2;
- doc_type.elem_counts[0] = type->Matrix.row_count;
- doc_type.elem_counts[1] = type->Matrix.column_count;
- doc_type.types = odin_doc_type_as_slice(w, type->Matrix.elem);
- break;
- }
- if (dst) {
- *dst = doc_type;
- }
- return type_index;
- }
- OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) {
- if (e == nullptr) {
- return 0;
- }
- OdinDocEntityIndex *prev_index = map_get(&w->entity_cache, e);
- if (prev_index) {
- return *prev_index;
- }
- if (e->pkg != nullptr && map_get(&w->pkg_cache, e->pkg) == nullptr) {
- return 0;
- }
- OdinDocEntity doc_entity = {};
- OdinDocEntity* dst = nullptr;
- OdinDocEntityIndex doc_entity_index = odin_doc_write_item(w, &w->entities, &doc_entity, &dst);
- map_set(&w->entity_cache, e, doc_entity_index);
- Ast *type_expr = nullptr;
- Ast *init_expr = nullptr;
- Ast *decl_node = nullptr;
- CommentGroup *comment = nullptr;
- CommentGroup *docs = nullptr;
- if (e->decl_info != nullptr) {
- type_expr = e->decl_info->type_expr;
- init_expr = e->decl_info->init_expr;
- decl_node = e->decl_info->decl_node;
- comment = e->decl_info->comment;
- docs = e->decl_info->docs;
- }
- if (e->kind == Entity_Variable) {
- if (!comment) { comment = e->Variable.comment; }
- if (!docs) { docs = e->Variable.docs; }
- } else if (e->kind == Entity_Constant) {
- if (!comment) { comment = e->Constant.comment; }
- if (!docs) { docs = e->Constant.docs; }
- }
- String link_name = {};
- OdinDocEntityKind kind = OdinDocEntity_Invalid;
- u64 flags = 0;
- i32 field_group_index = -1;
- switch (e->kind) {
- case Entity_Invalid: kind = OdinDocEntity_Invalid; break;
- case Entity_Constant: kind = OdinDocEntity_Constant; break;
- case Entity_Variable: kind = OdinDocEntity_Variable; break;
- case Entity_TypeName: kind = OdinDocEntity_TypeName; break;
- case Entity_Procedure: kind = OdinDocEntity_Procedure; break;
- case Entity_ProcGroup: kind = OdinDocEntity_ProcGroup; break;
- case Entity_ImportName: kind = OdinDocEntity_ImportName; break;
- case Entity_LibraryName: kind = OdinDocEntity_LibraryName; break;
- }
- switch (e->kind) {
- case Entity_TypeName:
- if (e->TypeName.is_type_alias) {
- flags |= OdinDocEntityFlag_Type_Alias;
- }
- break;
- case Entity_Variable:
- if (e->Variable.is_foreign) { flags |= OdinDocEntityFlag_Foreign; }
- if (e->Variable.is_export) { flags |= OdinDocEntityFlag_Export; }
- if (e->Variable.thread_local_model != "") {
- flags |= OdinDocEntityFlag_Var_Thread_Local;
- }
- if (e->flags & EntityFlag_Static) { flags |= OdinDocEntityFlag_Var_Static; }
- link_name = e->Variable.link_name;
- if (init_expr == nullptr) {
- init_expr = e->Variable.init_expr;
- }
- field_group_index = e->Variable.field_group_index;
- break;
- case Entity_Constant:
- field_group_index = e->Constant.field_group_index;
- break;
- case Entity_Procedure:
- if (e->Procedure.is_foreign) { flags |= OdinDocEntityFlag_Foreign; }
- if (e->Procedure.is_export) { flags |= OdinDocEntityFlag_Export; }
- link_name = e->Procedure.link_name;
- break;
- }
- if (e->flags & EntityFlag_Param) {
- if (e->flags & EntityFlag_Using) { flags |= OdinDocEntityFlag_Param_Using; }
- if (e->flags & EntityFlag_ConstInput) { flags |= OdinDocEntityFlag_Param_Const; }
- if (e->flags & EntityFlag_AutoCast) { flags |= OdinDocEntityFlag_Param_AutoCast; }
- if (e->flags & EntityFlag_Ellipsis) { flags |= OdinDocEntityFlag_Param_Ellipsis; }
- if (e->flags & EntityFlag_NoAlias) { flags |= OdinDocEntityFlag_Param_NoAlias; }
- if (e->flags & EntityFlag_AnyInt) { flags |= OdinDocEntityFlag_Param_AnyInt; }
- }
- if (e->scope && (e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) && !is_entity_exported(e)) {
- flags |= OdinDocEntityFlag_Private;
- }
- OdinDocString init_string = {};
- if (init_expr) {
- init_string = odin_doc_expr_string(w, init_expr);
- } else {
- if (e->kind == Entity_Constant) {
- if (e->Constant.flags & EntityConstantFlag_ImplicitEnumValue) {
- init_string = {}; // Blank
- } else if (e->Constant.param_value.original_ast_expr) {
- init_string = odin_doc_expr_string(w, e->Constant.param_value.original_ast_expr);
- } else {
- init_string = odin_doc_write_string(w, make_string_c(exact_value_to_string(e->Constant.value)));
- }
- } else if (e->kind == Entity_Variable) {
- if (e->Variable.param_value.original_ast_expr) {
- init_string = odin_doc_expr_string(w, e->Variable.param_value.original_ast_expr);
- }
- }
- }
- doc_entity.kind = kind;
- doc_entity.flags = flags;
- doc_entity.pos = odin_doc_token_pos_cast(w, e->token.pos);
- doc_entity.name = odin_doc_write_string(w, e->token.string);
- doc_entity.type = 0; // Set later
- doc_entity.init_string = init_string;
- doc_entity.comment = odin_doc_comment_group_string(w, comment);
- doc_entity.docs = odin_doc_comment_group_string(w, docs);
- doc_entity.field_group_index = field_group_index;
- doc_entity.foreign_library = 0; // Set later
- doc_entity.link_name = odin_doc_write_string(w, link_name);
- if (e->decl_info != nullptr) {
- doc_entity.attributes = odin_doc_attributes(w, e->decl_info->attributes);
- }
- doc_entity.grouped_entities = {}; // Set later
- if (dst) {
- *dst = doc_entity;
- }
- return doc_entity_index;
- }
- void odin_doc_update_entities(OdinDocWriter *w) {
- {
- // NOTE(bill): Double pass, just in case entities are created on odin_doc_type
- auto entities = array_make<Entity *>(heap_allocator(), w->entity_cache.entries.count);
- defer (array_free(&entities));
- for_array(i, w->entity_cache.entries) {
- Entity *e = w->entity_cache.entries[i].key;
- entities[i] = e;
- }
- for_array(i, entities) {
- Entity *e = entities[i];
- OdinDocTypeIndex type_index = odin_doc_type(w, e->type);
- gb_unused(type_index);
- }
- }
- for_array(i, w->entity_cache.entries) {
- Entity *e = w->entity_cache.entries[i].key;
- OdinDocEntityIndex entity_index = w->entity_cache.entries[i].value;
- OdinDocTypeIndex type_index = odin_doc_type(w, e->type);
- OdinDocEntityIndex foreign_library = 0;
- OdinDocArray<OdinDocEntityIndex> grouped_entities = {};
- switch (e->kind) {
- case Entity_Variable:
- foreign_library = odin_doc_add_entity(w, e->Variable.foreign_library);
- break;
- case Entity_Procedure:
- foreign_library = odin_doc_add_entity(w, e->Procedure.foreign_library);
- break;
- case Entity_ProcGroup:
- {
- auto pges = array_make<OdinDocEntityIndex>(heap_allocator(), 0, e->ProcGroup.entities.count);
- defer (array_free(&pges));
- for_array(j, e->ProcGroup.entities) {
- OdinDocEntityIndex index = odin_doc_add_entity(w, e->ProcGroup.entities[j]);
- array_add(&pges, index);
- }
- grouped_entities = odin_write_slice(w, pges.data, pges.count);
- }
- break;
- }
- OdinDocEntity *dst = odin_doc_get_item(w, &w->entities, entity_index);
- if (dst) {
- dst->type = type_index;
- dst->foreign_library = foreign_library;
- dst->grouped_entities = grouped_entities;
- }
- }
- }
- OdinDocArray<OdinDocEntityIndex> odin_doc_add_pkg_entities(OdinDocWriter *w, AstPackage *pkg) {
- if (pkg->scope == nullptr) {
- return {};
- }
- if (map_get(&w->pkg_cache, pkg) == nullptr) {
- return {};
- }
- auto entities = array_make<Entity *>(heap_allocator(), 0, pkg->scope->elements.entries.count);
- defer (array_free(&entities));
- for_array(i, pkg->scope->elements.entries) {
- Entity *e = pkg->scope->elements.entries[i].value;
- switch (e->kind) {
- case Entity_Invalid:
- case Entity_Builtin:
- case Entity_Nil:
- case Entity_Label:
- continue;
- case Entity_Constant:
- case Entity_Variable:
- case Entity_TypeName:
- case Entity_Procedure:
- case Entity_ProcGroup:
- case Entity_ImportName:
- case Entity_LibraryName:
- // Fine
- break;
- }
- array_add(&entities, e);
- }
- gb_sort_array(entities.data, entities.count, cmp_entities_for_printing);
- auto entity_indices = array_make<OdinDocEntityIndex>(heap_allocator(), 0, w->entity_cache.entries.count);
- defer (array_free(&entity_indices));
- for_array(i, entities) {
- Entity *e = entities[i];
- if (e->pkg != pkg) {
- continue;
- }
- if (!is_entity_exported(e)) {
- continue;
- }
- if (e->token.string.len == 0) {
- continue;
- }
- OdinDocEntityIndex doc_entity_index = 0;
- doc_entity_index = odin_doc_add_entity(w, e);
- array_add(&entity_indices, doc_entity_index);
- }
- return odin_write_slice(w, entity_indices.data, entity_indices.count);
- }
- void odin_doc_write_docs(OdinDocWriter *w) {
- auto pkgs = array_make<AstPackage *>(heap_allocator(), 0, w->info->packages.entries.count);
- defer (array_free(&pkgs));
- for_array(i, w->info->packages.entries) {
- AstPackage *pkg = w->info->packages.entries[i].value;
- if (build_context.cmd_doc_flags & CmdDocFlag_AllPackages) {
- array_add(&pkgs, pkg);
- } else {
- if (pkg->kind == Package_Init) {
- array_add(&pkgs, pkg);
- } else if (pkg->is_extra) {
- array_add(&pkgs, pkg);
- }
- }
- }
- gb_sort_array(pkgs.data, pkgs.count, cmp_ast_package_by_name);
- for_array(i, pkgs) {
- gbAllocator allocator = heap_allocator();
- AstPackage *pkg = pkgs[i];
- u32 pkg_flags = 0;
- switch (pkg->kind) {
- case Package_Normal:
- break;
- case Package_Runtime:
- pkg_flags |= OdinDocPkgFlag_Runtime;
- break;
- case Package_Init:
- pkg_flags |= OdinDocPkgFlag_Init;
- break;
- }
- if (pkg->name == "builtin") {
- pkg_flags |= OdinDocPkgFlag_Builtin;
- } else if (pkg->name == "intrinsics") {
- pkg_flags |= OdinDocPkgFlag_Builtin;
- }
- OdinDocPkg doc_pkg = {};
- doc_pkg.fullpath = odin_doc_write_string(w, pkg->fullpath);
- doc_pkg.name = odin_doc_write_string(w, pkg->name);
- doc_pkg.flags = pkg_flags;
- doc_pkg.docs = odin_doc_pkg_doc_string(w, pkg);
- OdinDocPkg *dst = nullptr;
- OdinDocPkgIndex pkg_index = odin_doc_write_item(w, &w->pkgs, &doc_pkg, &dst);
- map_set(&w->pkg_cache, pkg, pkg_index);
- auto file_indices = array_make<OdinDocFileIndex>(heap_allocator(), 0, pkg->files.count);
- defer (array_free(&file_indices));
- for_array(j, pkg->files) {
- AstFile *file = pkg->files[j];
- OdinDocFile doc_file = {};
- doc_file.pkg = pkg_index;
- doc_file.name = odin_doc_write_string(w, file->fullpath);
- OdinDocFileIndex file_index = odin_doc_write_item(w, &w->files, &doc_file);
- map_set(&w->file_cache, file, file_index);
- array_add(&file_indices, file_index);
- }
- doc_pkg.files = odin_write_slice(w, file_indices.data, file_indices.count);
- doc_pkg.entities = odin_doc_add_pkg_entities(w, pkg);
- if (dst) {
- *dst = doc_pkg;
- }
- }
- odin_doc_update_entities(w);
- }
- void odin_doc_write_to_file(OdinDocWriter *w, char const *filename) {
- gbFile f = {};
- 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);
- return;
- }
- defer (gb_file_close(&f));
- if (gb_file_write(&f, w->data, w->data_len)) {
- err = gb_file_truncate(&f, w->data_len);
- gb_printf("Wrote .odin-doc file to: %s\n", filename);
- }
- }
- void odin_doc_write(CheckerInfo *info, char const *filename) {
- OdinDocWriter w_ = {};
- OdinDocWriter *w = &w_;
- defer (odin_doc_writer_destroy(w));
- w->info = info;
- odin_doc_writer_prepare(w);
- odin_doc_write_docs(w);
- odin_doc_writer_start_writing(w);
- odin_doc_write_docs(w);
- odin_doc_writer_end_writing(w);
- odin_doc_write_to_file(w, filename);
- }
|