Commit 6814d6b332

Andrew Kelley <andrew@ziglang.org>
2019-10-08 17:52:06
generated docs: function parameters have links
1 parent a55db08
Changed files (3)
lib
std
special
src
lib/std/special/docs/index.html
@@ -145,6 +145,34 @@
       #listSearchResults li.selected {
         background-color: #93e196;
       }
+      .tok-kw {
+          color: #333;
+          font-weight: bold;
+      }
+      .tok-str {
+          color: #d14;
+      }
+      .tok-builtin {
+          color: #0086b3;
+      }
+      .tok-comment {
+          color: #777;
+          font-style: italic;
+      }
+      .tok-fn {
+          color: #900;
+          font-weight: bold;
+      }
+      .tok-null {
+          color: #008080;
+      }
+      .tok-number {
+          color: #008080;
+      }
+      .tok-type {
+          color: #458;
+          font-weight: bold;
+      }
 
       @media (prefers-color-scheme: dark) {
         body{
@@ -183,6 +211,30 @@
         #listSearchResults li.selected a {
           color: #fff;
         }
+        .tok-kw {
+            color: #eee;
+        }
+        .tok-str {
+            color: #2e5;
+        }
+        .tok-builtin {
+            color: #ff894c;
+        }
+        .tok-comment {
+            color: #aa7;
+        }
+        .tok-fn {
+            color: #e33;
+        }
+        .tok-null {
+            color: #ff8080;
+        }
+        .tok-number {
+            color: #ff8080;
+        }
+        .tok-type {
+            color: #68f;
+        }
       }
     </style>
   </head>
lib/std/special/docs/main.js
@@ -29,11 +29,17 @@
 
     var typeKindTypeId;
     var typeKindFnId;
+    var typeKindPtrId;
+    var typeKindFloatId;
+    var typeKindIntId;
     findTypeKinds();
 
     // for each package, is an array with packages to get to this one
     var canonPkgPaths = computeCanonicalPackagePaths();
+    // for each decl, is an array with {declNames, pkgNames} to get to this one
     var canonDeclPaths = null; // lazy; use getCanonDeclPath
+    // for each type, is an array with {declNames, pkgNames} to get to this one
+    var canonTypeDecls = null; // lazy; use getCanonTypeDecl
 
     var curNav = {
         // each element is a package name, e.g. @import("a") then within there @import("b")
@@ -158,7 +164,29 @@
 
     function renderFn(fnDecl) {
         var typeObj = zigAnalysis.types[fnDecl.type];
-        domFnProtoCode.textContent = "fn " + fnDecl.name + typeObj.name.substring(2);
+        var protoHtml = '<span class="tok-kw">fn</span> <span class="tok-fn">'
+            + escapeHtml(fnDecl.name) + '</span>(';
+        if (typeObj.args != null) {
+            for (var i = 0; i < typeObj.args.length; i += 1) {
+                if (i != 0) {
+                    protoHtml += ', ';
+                }
+                var argTypeIndex = typeObj.args[i];
+                if (argTypeIndex != null) {
+                    protoHtml += typeIndexName(argTypeIndex, true, true);
+                } else {
+                    protoHtml += '<span class="tok-kw">var</span>';
+                }
+            }
+        }
+
+        protoHtml += ') ';
+        if (typeObj.ret != null) {
+            protoHtml += typeIndexName(typeObj.ret, true, true);
+        } else {
+            protoHtml += '<span class="tok-kw">var</span>';
+        }
+        domFnProtoCode.innerHTML = protoHtml;
 
         var docsSource = null;
         var srcNode = zigAnalysis.astNodes[fnDecl.src];
@@ -306,9 +334,107 @@
         }
     }
 
+    function typeIndexName(typeIndex, wantHtml, wantLink) {
+        var typeObj = zigAnalysis.types[typeIndex];
+        if (wantLink) {
+            var declIndex = getCanonTypeDecl(typeIndex);
+            var declPath = getCanonDeclPath(declIndex);
+            var haveLink = declPath != null;
+            var typeNameHtml = typeName(typeObj, true, !haveLink);
+            if (haveLink) {
+                return '<a href="' + navLink(declPath.pkgNames, declPath.declNames) + '">' + typeNameHtml + '</a>';
+            } else {
+                return typeNameHtml;
+            }
+        } else {
+            return typeName(typeObj, wantHtml);
+        }
+    }
+
+    function typeName(typeObj, wantHtml, wantSubLink) {
+        switch (typeObj.kind) {
+            case typeKindPtrId:
+                var name = "";
+                switch (typeObj.len) {
+                    case 0:
+                    default:
+                        name += "*";
+                        break;
+                    case 1:
+                        name += "[*]";
+                        break;
+                    case 2:
+                        name += "[]";
+                        break;
+                    case 3:
+                        name += "[*c]";
+                        break;
+                }
+                if (typeObj['const']) {
+                    if (wantHtml) {
+                        name += '<span class="tok-kw">const</span> ';
+                    } else {
+                        name += "const ";
+                    }
+                }
+                if (typeObj['volatile']) {
+                    if (wantHtml) {
+                        name += '<span class="tok-kw">volatile</span> ';
+                    } else {
+                        name += "volatile ";
+                    }
+                }
+                if (typeObj.align != null) {
+                    if (wantHtml) {
+                        name += '<span class="tok-kw">align</span>(';
+                    } else {
+                        name += "align(";
+                    }
+                    if (wantHtml) {
+                        name += '<span class="tok-number">' + typeObj.align + '</span>';
+                    } else {
+                        name += typeObj.align;
+                    }
+                    if (typeObj.hostIntBytes != null) {
+                        name += ":" + typeObj.bitOffsetInHost + ":" + typeObj.hostIntBytes;
+                    }
+                    name += ") ";
+                }
+                name += typeIndexName(typeObj.elem, wantHtml, wantSubLink);
+                return name;
+            case typeKindFloatId:
+                if (wantHtml) {
+                    return '<span class="tok-type">f' + typeObj.bits + '</span>';
+                } else {
+                    return "f" + typeObj.bits;
+                }
+            case typeKindIntId:
+                var signed = (typeObj.i != null) ? 'i' : 'u';
+                var bits = typeObj[signed];
+                if (wantHtml) {
+                    return '<span class="tok-type">' + signed + bits + '</span>';
+                } else {
+                    return signed + bits;
+                }
+            case typeKindTypeId:
+                if (wantHtml) {
+                    return '<span class="tok-type">type</span>';
+                } else {
+                    return "type";
+                }
+            default:
+                if (wantHtml) {
+                    return escapeHtml(typeObj.name);
+                } else {
+                    return typeObj.name;
+                }
+        }
+    }
+
     function renderType(typeObj) {
-        if (typeObj.name != null && typeObj.name != "") {
-            domHdrName.innerText = zigAnalysis.typeKinds[typeObj.kind] + " " + typeObj.name;
+        var name = typeName(typeObj);
+        if (name != null && name != "") {
+            domHdrName.innerText = zigAnalysis.typeKinds[typeObj.kind] + " " + name;
             domHdrName.classList.remove("hidden");
         }
     }
@@ -402,6 +528,12 @@
                 typeKindTypeId = i;
             } else if (zigAnalysis.typeKinds[i] === "Fn") {
                 typeKindFnId = i;
+            } else if (zigAnalysis.typeKinds[i] === "Pointer") {
+                typeKindPtrId = i;
+            } else if (zigAnalysis.typeKinds[i] === "Float") {
+                typeKindFloatId = i;
+            } else if (zigAnalysis.typeKinds[i] === "Int") {
+                typeKindIntId = i;
             }
         }
         if (typeKindTypeId == null) {
@@ -410,6 +542,15 @@
         if (typeKindFnId == null) {
             throw new Error("No type kind 'Fn' found");
         }
+        if (typeKindPtrId == null) {
+            throw new Error("No type kind 'Pointer' found");
+        }
+        if (typeKindFloatId == null) {
+            throw new Error("No type kind 'Float' found");
+        }
+        if (typeKindIntId == null) {
+            throw new Error("No type kind 'Int' found");
+        }
     }
 
     function findTypeTypeId() {
@@ -500,6 +641,7 @@
 
     function computeCanonDeclPaths() {
         var list = new Array(zigAnalysis.decls.length);
+        canonTypeDecls = new Array(zigAnalysis.types.length);
 
         for (var pkgI = 0; pkgI < zigAnalysis.packages.length; pkgI += 1) {
             if (pkgI === zigAnalysis.rootPkg && rootIsStd) continue;
@@ -518,6 +660,9 @@
                         if (list[mainDeclIndex] != null) continue;
 
                         var decl = zigAnalysis.decls[mainDeclIndex];
+                        if (decl.type === typeTypeId) {
+                            canonTypeDecls[decl.value] = mainDeclIndex;
+                        }
                         var declNames = item.declNames.concat([decl.name]);
                         list[mainDeclIndex] = {
                             pkgNames: pkgNames,
@@ -544,12 +689,22 @@
         return canonDeclPaths[index];
     }
 
-    function markdown(mdText) {
-        return mdText.replace(/[&"<>]/g, function (m) {
+    function getCanonTypeDecl(index) {
+        getCanonDeclPath(0);
+        return canonTypeDecls[index];
+    }
+
+    function escapeHtml(text) {
+        return text.replace(/[&"<>]/g, function (m) {
             return escapeHtmlReplacements[m];
         });
     }
 
+    function markdown(mdText) {
+        // TODO implement more
+        return escapeHtml(mdText);
+    }
+
     function onSearchKeyDown(ev) {
         switch (ev.which) {
             case 13:
src/dump_analysis.cpp
@@ -683,24 +683,57 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty,
     zig_unreachable();
 }
 
+static void anal_dump_pointer_attrs(AnalDumpCtx *ctx, ZigType *ty) {
+    JsonWriter *jw = &ctx->jw;
+    if (ty->data.pointer.explicit_alignment != 0) {
+        jw_object_field(jw, "align");
+        jw_int(jw, ty->data.pointer.explicit_alignment);
+    }
+    if (ty->data.pointer.is_const) {
+        jw_object_field(jw, "const");
+        jw_bool(jw, true);
+    }
+    if (ty->data.pointer.is_volatile) {
+        jw_object_field(jw, "volatile");
+        jw_bool(jw, true);
+    }
+    if (ty->data.pointer.allow_zero) {
+        jw_object_field(jw, "allowZero");
+        jw_bool(jw, true);
+    }
+    if (ty->data.pointer.host_int_bytes != 0) {
+        jw_object_field(jw, "hostIntBytes");
+        jw_int(jw, ty->data.pointer.host_int_bytes);
+
+        jw_object_field(jw, "bitOffsetInHost");
+        jw_int(jw, ty->data.pointer.bit_offset_in_host);
+    }
+
+    jw_object_field(jw, "elem");
+    anal_dump_type_ref(ctx, ty->data.pointer.child_type);
+}
+
 static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
     JsonWriter *jw = &ctx->jw;
     jw_array_elem(jw);
     jw_begin_object(jw);
 
-    jw_object_field(jw, "name");
-    jw_string(jw, buf_ptr(&ty->name));
-
     jw_object_field(jw, "kind");
     jw_int(jw, type_id_index(ty));
 
     switch (ty->id) {
+        case ZigTypeIdMetaType:
+            break;
         case ZigTypeIdStruct: {
             if (ty->data.structure.is_slice) {
-                // TODO
+                jw_object_field(jw, "len");
+                jw_int(jw, 2);
+                anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index].type_entry);
                 break;
             }
 
+            jw_object_field(jw, "name");
+            jw_string(jw, buf_ptr(&ty->name));
             {
                 jw_object_field(jw, "pubDecls");
                 jw_begin_array(jw);
@@ -755,13 +788,61 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
             jw_int(jw, ty->data.floating.bit_count);
             break;
         }
+        case ZigTypeIdInt: {
+            if (ty->data.integral.is_signed) {
+                jw_object_field(jw, "i");
+            } else {
+                jw_object_field(jw, "u");
+            }
+            jw_int(jw, ty->data.integral.bit_count);
+            break;
+        }
         case ZigTypeIdFn: {
+            jw_object_field(jw, "name");
+            jw_string(jw, buf_ptr(&ty->name));
+
             jw_object_field(jw, "generic");
             jw_bool(jw, ty->data.fn.is_generic);
+
+            if (ty->data.fn.fn_type_id.return_type != nullptr) {
+                jw_object_field(jw, "ret");
+                anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.return_type);
+            }
+
+            if (ty->data.fn.fn_type_id.param_count != 0) {
+                jw_object_field(jw, "args");
+                jw_begin_array(jw);
+                for (size_t i = 0; i < ty->data.fn.fn_type_id.param_count; i += 1) {
+                    jw_array_elem(jw);
+                    if (ty->data.fn.fn_type_id.param_info[i].type != nullptr) {
+                        anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.param_info[i].type);
+                    } else {
+                        jw_null(jw);
+                    }
+                }
+                jw_end_array(jw);
+            }
+            break;
+        }
+        case ZigTypeIdPointer: {
+            switch (ty->data.pointer.ptr_len) {
+                case PtrLenSingle:
+                    break;
+                case PtrLenUnknown:
+                    jw_object_field(jw, "len");
+                    jw_int(jw, 1);
+                    break;
+                case PtrLenC:
+                    jw_object_field(jw, "len");
+                    jw_int(jw, 3);
+                    break;
+            }
+            anal_dump_pointer_attrs(ctx, ty);
             break;
         }
         default:
-            // TODO
+            jw_object_field(jw, "name");
+            jw_string(jw, buf_ptr(&ty->name));
             break;
     }
     jw_end_object(jw);