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;