Commit 2ccb48ddc3

Andrew Kelley <andrew@ziglang.org>
2019-10-07 18:20:59
generated docs: show doc comments on functions
1 parent 85b8854
lib/std/special/docs/index.html
@@ -7,6 +7,7 @@
     <style type="text/css">
         body {
             font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
+            max-width: 60em;
         }
         .hidden {
             display: none;
@@ -64,6 +65,7 @@
     <div id="fnProto" class="hidden">
       <pre id="fnProtoCode"></pre>
     </div>
+    <div id="fnDocs" class="hidden"></div>
     <div id="sectPkgs" class="hidden">
         <h2>Packages</h2>
         <ul id="listPkgs">
lib/std/special/docs/main.js
@@ -10,6 +10,7 @@
     var domListFns = document.getElementById("listFns");
     var domFnProto = document.getElementById("fnProto");
     var domFnProtoCode = document.getElementById("fnProtoCode");
+    var domFnDocs = document.getElementById("fnDocs");
 
     var typeKindTypeId;
     var typeKindFnId;
@@ -53,6 +54,11 @@
     function render() {
         domStatus.classList.add("hidden");
         domFnProto.classList.add("hidden");
+        domFnDocs.classList.add("hidden");
+        domSectPkgs.classList.add("hidden");
+        domSectTypes.classList.add("hidden");
+        domSectFns.classList.add("hidden");
+
 
         renderTitle();
 
@@ -107,13 +113,15 @@
     }
 
     function renderFn(fnDecl) {
-        domSectPkgs.classList.add("hidden");
-        domSectTypes.classList.add("hidden");
-        domSectFns.classList.add("hidden");
-
         var typeObj = zigAnalysis.types[fnDecl.type];
         domFnProtoCode.textContent = "fn " + fnDecl.name + typeObj.name.substring(2);
 
+        var srcNode = zigAnalysis.astNodes[fnDecl.src];
+        if (srcNode.docs != null) {
+            domFnDocs.innerHTML = markdown(srcNode.docs);
+            domFnDocs.classList.remove("hidden");
+        }
+
         domFnProto.classList.remove("hidden");
     }
 
@@ -379,4 +387,11 @@
         }
         return list;
     }
+
+    var escapeHtmlReplacements = { "&": "&amp;", '"': "&quot;", "<": "&lt;", ">": "&gt;" };
+    function markdown(mdText) {
+        return mdText.replace(/[&"<>]/g, function (m) {
+            return escapeHtmlReplacements[m];
+        });
+    }
 })();
src/all_types.hpp
@@ -1322,6 +1322,9 @@ bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b);
 uint32_t tld_ptr_hash(const Tld *ptr);
 bool tld_ptr_eql(const Tld *a, const Tld *b);
 
+uint32_t node_ptr_hash(const AstNode *ptr);
+bool node_ptr_eql(const AstNode *a, const AstNode *b);
+
 struct ZigTypeUnion {
     AstNode *decl_node;
     TypeUnionField *fields;
src/analyze.cpp
@@ -7320,6 +7320,14 @@ bool tld_ptr_eql(const Tld *a, const Tld *b) {
     return a == b;
 }
 
+uint32_t node_ptr_hash(const AstNode *ptr) {
+    return hash_ptr((void*)ptr);
+}
+
+bool node_ptr_eql(const AstNode *a, const AstNode *b) {
+    return a == b;
+}
+
 ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
     Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name));
     resolve_top_level_decl(codegen, tld, nullptr, false);
src/buffer.hpp
@@ -38,6 +38,12 @@ static inline char *buf_ptr(Buf *buf) {
     return buf->list.items;
 }
 
+static inline const char *buf_ptr(const Buf *buf) {
+    assert(buf);
+    assert(buf->list.length);
+    return buf->list.items;
+}
+
 static inline void buf_resize(Buf *buf, size_t new_len) {
     buf->list.resize(new_len + 1);
     buf->list.at(buf_len(buf)) = 0;
src/dump_analysis.cpp
@@ -351,6 +351,9 @@ struct AnalDumpCtx {
 
     ZigList<Tld *> decl_list;
     HashMap<const Tld *, uint32_t, tld_ptr_hash, tld_ptr_eql> decl_map;
+
+    ZigList<AstNode *> node_list;
+    HashMap<const AstNode *, uint32_t, node_ptr_hash, node_ptr_eql> node_map;
 };
 
 static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty);
@@ -416,6 +419,17 @@ static uint32_t anal_dump_get_file_id(AnalDumpCtx *ctx, Buf *file) {
     return file_id;
 }
 
+static uint32_t anal_dump_get_node_id(AnalDumpCtx *ctx, AstNode *node) {
+    uint32_t node_id = ctx->node_list.length;
+    auto existing_entry = ctx->node_map.put_unique(node, node_id);
+    if (existing_entry == nullptr) {
+        ctx->node_list.append(node);
+    } else {
+        node_id = existing_entry->value;
+    }
+    return node_id;
+}
+
 static uint32_t anal_dump_get_decl_id(AnalDumpCtx *ctx, Tld *tld) {
     uint32_t decl_id = ctx->decl_list.length;
     auto existing_entry = ctx->decl_map.put_unique(tld, decl_id);
@@ -475,6 +489,11 @@ static void anal_dump_file_ref(AnalDumpCtx *ctx, Buf *file) {
     jw_int(&ctx->jw, file_id);
 }
 
+static void anal_dump_node_ref(AnalDumpCtx *ctx, AstNode *node) {
+    uint32_t node_id = anal_dump_get_node_id(ctx, node);
+    jw_int(&ctx->jw, node_id);
+}
+
 static void anal_dump_decl_ref(AnalDumpCtx *ctx, Tld *tld) {
     uint32_t decl_id = anal_dump_get_decl_id(ctx, tld);
     jw_int(&ctx->jw, decl_id);
@@ -536,11 +555,8 @@ static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) {
         jw_object_field(jw, "import");
         anal_dump_type_ref(ctx, tld->import);
 
-        jw_object_field(jw, "line");
-        jw_int(jw, tld->source_node->line);
-
-        jw_object_field(jw, "col");
-        jw_int(jw, tld->source_node->column);
+        jw_object_field(jw, "src");
+        anal_dump_node_ref(ctx, tld->source_node);
 
         jw_object_field(jw, "name");
         jw_string(jw, buf_ptr(tld->name));
@@ -712,6 +728,50 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
     jw_end_object(jw);
 }
 
+void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) {
+    JsonWriter *jw = &ctx->jw;
+
+    jw_begin_object(jw);
+
+    jw_object_field(jw, "file");
+    anal_dump_file_ref(ctx, node->owner->data.structure.root_struct->path);
+
+    jw_object_field(jw, "line");
+    jw_int(jw, node->line);
+
+    jw_object_field(jw, "col");
+    jw_int(jw, node->column);
+
+    const Buf *doc_comments_buf;
+    switch (node->type) {
+        case NodeTypeParamDecl:
+            doc_comments_buf = &node->data.param_decl.doc_comments;
+            break;
+        case NodeTypeFnProto:
+            doc_comments_buf = &node->data.fn_proto.doc_comments;
+            break;
+        case NodeTypeVariableDeclaration:
+            doc_comments_buf = &node->data.variable_declaration.doc_comments;
+            break;
+        case NodeTypeErrorSetField:
+            doc_comments_buf = &node->data.err_set_field.doc_comments;
+            break;
+        case NodeTypeStructField:
+            doc_comments_buf = &node->data.struct_field.doc_comments;
+            break;
+        default:
+            doc_comments_buf = nullptr;
+            break;
+    }
+    if (doc_comments_buf->list.length != 0) {
+        jw_object_field(jw, "docs");
+        jw_string(jw, buf_ptr(doc_comments_buf));
+    }
+
+    jw_end_object(jw);
+}
+
+
 void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl) {
     Error err;
     AnalDumpCtx ctx = {};
@@ -722,6 +782,7 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
     ctx.pkg_map.init(16);
     ctx.file_map.init(16);
     ctx.decl_map.init(16);
+    ctx.node_map.init(16);
 
     jw_begin_object(jw);
 
@@ -794,5 +855,14 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const
     }
     jw_end_array(jw);
 
+    jw_object_field(jw, "astNodes");
+    jw_begin_array(jw);
+    for (uint32_t i = 0; i < ctx.node_list.length; i += 1) {
+        const AstNode *node = ctx.node_list.at(i);
+        jw_array_elem(jw);
+        anal_dump_node(&ctx, node);
+    }
+    jw_end_array(jw);
+
     jw_end_object(jw);
 }
src/parser.cpp
@@ -503,9 +503,9 @@ static Token *ast_parse_doc_comments(ParseContext *pc, Buf *buf) {
         if (buf->list.length == 0) {
             buf_resize(buf, 0);
         }
-        // chops off '///' and '\n'
+        // chops off '///' but leaves '\n'
         buf_append_mem(buf, buf_ptr(pc->buf) + doc_token->start_pos + 3,
-                doc_token->end_pos - doc_token->start_pos - 4);
+                doc_token->end_pos - doc_token->start_pos - 3);
     }
     return doc_token;
 }