diff --git a/lib/std/special/doc/index.html b/lib/std/special/doc/index.html new file mode 100644 index 000000000000..b00a8f04639a --- /dev/null +++ b/lib/std/special/doc/index.html @@ -0,0 +1,35 @@ + + + + + Documentation - Zig + + + + +

Loading...

+ + + + + + diff --git a/lib/std/special/doc/main.js b/lib/std/special/doc/main.js new file mode 100644 index 000000000000..2ce822e64b65 --- /dev/null +++ b/lib/std/special/doc/main.js @@ -0,0 +1,126 @@ +(function() { + var domStatus = document.getElementById("status"); + var domSectPkgs = document.getElementById("sectPkgs"); + var domListPkgs = document.getElementById("listPkgs"); + var domSectTypes = document.getElementById("sectTypes"); + var domListTypes = document.getElementById("listTypes"); + + var curNav = { + kind: "pkg", + index: zigAnalysis.rootPkg, + }; + + var rootIsStd = detectRootIsStd(); + var typeKindTypeId = findTypeKindType(); + var typeTypeId = findTypeTypeId(); + render(); + + function render() { + domStatus.classList.add("hidden"); + + if (curNav.kind === "pkg") { + var pkg = zigAnalysis.packages[curNav.index]; + renderPkgList(pkg); + var pkgStruct = zigAnalysis.types[pkg.main]; + renderContainer(pkgStruct); + } else { + throw new Error("TODO"); + } + } + + function renderPkgList(pkg) { + var list = []; + for (var key in pkg.table) { + if (key === "root" && rootIsStd) continue; + list.push({ + name: key, + pkg: pkg.table[key], + }); + } + list.sort(function(a, b) { + return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase()); + }); + + resizeDomList(domListPkgs, list.length, '
  • '); + var domItems = domListPkgs.children; + for (var i = 0; i < list.length; i += 1) { + var domItem = domItems[i]; + domItem.textContent = list[i].name; + } + + domSectPkgs.classList.remove("hidden"); + } + + function resizeDomList(listDom, desiredLen, templateHtml) { + // add the missing dom entries + var i, ev; + for (i = listDom.childElementCount; i < desiredLen; i += 1) { + listDom.insertAdjacentHTML('beforeend', templateHtml); + } + // remove extra dom entries + while (desiredLen < listDom.childElementCount) { + listDom.removeChild(listDom.lastChild); + } + } + + function renderContainer(container) { + // Find only the types of this package + var list = []; + for (var i = 0; i < container.decls.length; i += 1) { + var decl = zigAnalysis.decls[container.decls[i]]; + if (decl.type == typeTypeId) { + list.push(decl); + } + } + list.sort(function(a, b) { + return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase()); + }); + + resizeDomList(domListTypes, list.length, '
  • '); + for (var i = 0; i < list.length; i += 1) { + var domItem = domListTypes.children[i]; + var decl = list[i]; + domItem.textContent = decl.name; + } + + domSectTypes.classList.remove("hidden"); + } + + function operatorCompare(a, b) { + if (a === b) { + return 0; + } else if (a < b) { + return -1; + } else { + return 1; + } + } + + function detectRootIsStd() { + var rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg]; + if (rootPkg.table["std"] == null) { + // no std mapped into the root package + return false; + } + var stdPkg = zigAnalysis.packages[rootPkg.table["std"]]; + return rootPkg.file === stdPkg.file; + } + + function findTypeKindType() { + for (var i = 0; i < zigAnalysis.typeKinds.length; i += 1) { + if (zigAnalysis.typeKinds[i] === "Type") { + return i; + } + } + throw new Error("No type kind 'Type' found"); + } + + function findTypeTypeId() { + for (var i = 0; i < zigAnalysis.types.length; i += 1) { + if (zigAnalysis.types[i].kind == typeKindTypeId) { + return i; + } + } + throw new Error("No type 'type' found"); + } +})(); diff --git a/src/all_types.hpp b/src/all_types.hpp index 6ebfe934b48d..1119d2bf4e9f 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2063,6 +2063,7 @@ struct CodeGen { bool have_stack_probing; bool function_sections; bool enable_dump_analysis; + bool enable_doc_generation; Buf *mmacosx_version_min; Buf *mios_version_min; diff --git a/src/codegen.cpp b/src/codegen.cpp index 0f86635646c9..88ff179ca78e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -10158,6 +10158,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_bool(ch, g->is_dummy_so); cache_bool(ch, g->function_sections); cache_bool(ch, g->enable_dump_analysis); + cache_bool(ch, g->enable_doc_generation); cache_buf_opt(ch, g->mmacosx_version_min); cache_buf_opt(ch, g->mios_version_min); cache_usize(ch, g->version_major); @@ -10347,12 +10348,48 @@ void codegen_build_and_link(CodeGen *g) { fprintf(stderr, "Unable to open '%s': %s\n", analysis_json_filename, strerror(errno)); exit(1); } - zig_print_analysis_dump(g, f); + zig_print_analysis_dump(g, f, " ", "\n"); if (fclose(f) != 0) { fprintf(stderr, "Unable to write '%s': %s\n", analysis_json_filename, strerror(errno)); exit(1); } + } + if (g->enable_doc_generation) { + Buf *doc_dir_path = buf_sprintf("%s" OS_SEP "doc", buf_ptr(g->output_dir)); + if ((err = os_make_path(doc_dir_path))) { + fprintf(stderr, "Unable to create directory %s: %s\n", buf_ptr(doc_dir_path), err_str(err)); + exit(1); + } + Buf *index_html_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "doc" OS_SEP "index.html", + buf_ptr(g->zig_std_dir)); + Buf *index_html_dest_path = buf_sprintf("%s" OS_SEP "index.html", buf_ptr(doc_dir_path)); + Buf *main_js_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "doc" OS_SEP "main.js", + buf_ptr(g->zig_std_dir)); + Buf *main_js_dest_path = buf_sprintf("%s" OS_SEP "main.js", buf_ptr(doc_dir_path)); + if ((err = os_copy_file(index_html_src_path, index_html_dest_path))) { + fprintf(stderr, "Unable to copy %s to %s: %s\n", buf_ptr(index_html_src_path), + buf_ptr(index_html_dest_path), err_str(err)); + exit(1); + } + if ((err = os_copy_file(main_js_src_path, main_js_dest_path))) { + fprintf(stderr, "Unable to copy %s to %s: %s\n", buf_ptr(main_js_src_path), + buf_ptr(main_js_dest_path), err_str(err)); + exit(1); + } + const char *data_js_filename = buf_ptr(buf_sprintf("%s" OS_SEP "data.js", buf_ptr(doc_dir_path))); + FILE *f = fopen(data_js_filename, "wb"); + if (f == nullptr) { + fprintf(stderr, "Unable to open '%s': %s\n", data_js_filename, strerror(errno)); + exit(1); + } + fprintf(f, "zigAnalysis="); + zig_print_analysis_dump(g, f, "", ""); + fprintf(f, ";"); + if (fclose(f) != 0) { + fprintf(stderr, "Unable to write '%s': %s\n", data_js_filename, strerror(errno)); + exit(1); + } } // If we're outputting assembly or llvm IR we skip linking. diff --git a/src/dump_analysis.cpp b/src/dump_analysis.cpp index 401fa37ded06..b110e0e03832 100644 --- a/src/dump_analysis.cpp +++ b/src/dump_analysis.cpp @@ -688,12 +688,12 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { jw_end_object(jw); } -void zig_print_analysis_dump(CodeGen *g, FILE *f) { +void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl) { Error err; AnalDumpCtx ctx = {}; ctx.g = g; JsonWriter *jw = &ctx.jw; - jw_init(jw, f, " ", "\n"); + jw_init(jw, f, one_indent, nl); ctx.type_map.init(16); ctx.pkg_map.init(16); ctx.file_map.init(16); @@ -728,6 +728,9 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f) { Buf triple_buf = BUF_INIT; target_triple_zig(&triple_buf, g->zig_target); jw_string(jw, buf_ptr(&triple_buf)); + + jw_object_field(jw, "rootName"); + jw_string(jw, buf_ptr(g->root_out_name)); } jw_end_object(jw); diff --git a/src/dump_analysis.hpp b/src/dump_analysis.hpp index 44a87290e5f0..6d1c644ea208 100644 --- a/src/dump_analysis.hpp +++ b/src/dump_analysis.hpp @@ -12,6 +12,6 @@ #include void zig_print_stack_report(CodeGen *g, FILE *f); -void zig_print_analysis_dump(CodeGen *g, FILE *f); +void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl); #endif diff --git a/src/main.cpp b/src/main.cpp index 5300938f850e..9b8bddabd79b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,7 +64,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " -fno-PIC disable Position Independent Code\n" " -ftime-report print timing diagnostics\n" " -fstack-report print stack size diagnostics\n" - " -fdump-analysis write analysis.json file for use with zig docs\n" + " -fdump-analysis write analysis.json file with type information\n" + " -fgenerate-docs create a doc/ dir with html documentation\n" " --libc [file] Provide a file which specifies libc paths\n" " --name [name] override output name\n" " --output-dir [dir] override output directory (defaults to cwd)\n" @@ -481,6 +482,7 @@ int main(int argc, char **argv) { bool timing_info = false; bool stack_report = false; bool enable_dump_analysis = false; + bool enable_doc_generation = false; const char *cache_dir = nullptr; CliPkg *cur_pkg = allocate(1); BuildMode build_mode = BuildModeDebug; @@ -666,6 +668,8 @@ int main(int argc, char **argv) { stack_report = true; } else if (strcmp(arg, "-fdump-analysis") == 0) { enable_dump_analysis = true; + } else if (strcmp(arg, "-fgenerate-docs") == 0) { + enable_doc_generation = true; } else if (strcmp(arg, "--enable-valgrind") == 0) { valgrind_support = ValgrindSupportEnabled; } else if (strcmp(arg, "--disable-valgrind") == 0) { @@ -1143,6 +1147,7 @@ int main(int argc, char **argv) { g->enable_time_report = timing_info; g->enable_stack_report = stack_report; g->enable_dump_analysis = enable_dump_analysis; + g->enable_doc_generation = enable_doc_generation; codegen_set_out_name(g, buf_out_name); codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); g->want_single_threaded = want_single_threaded;