Commit 0135d22716

Loris Cro <kappaloris@gmail.com>
2022-01-30 19:12:56
autodocs: add support for indirect decl references
1 parent 38281c8
Changed files (3)
lib/docs/main.js
@@ -147,10 +147,10 @@
             curNav.pkgObjs.push(pkg);
         }
 
-        var decl = zigAnalysis.types[pkg.main];
-        curNav.declObjs = [decl];
+        var currentType = zigAnalysis.types[pkg.main];
+        curNav.declObjs = [currentType];
         for (var i = 0; i < curNav.declNames.length; i += 1) {
-            var childDecl = findSubDecl(decl, curNav.declNames[i]);
+            var childDecl = findSubDecl(currentType, curNav.declNames[i]);
             if (childDecl == null) {
                 return render404();
             }
@@ -163,29 +163,29 @@
                     return render404();
                 }
             }
-            decl = container;
-            curNav.declObjs.push(decl);
+            currentType = container;
+            curNav.declObjs.push(currentType);
         }
 
         renderNav();
 
-        var lastDecl = curNav.declObjs[curNav.declObjs.length - 1];
-        if (lastDecl.pubDecls != null) {
-            renderContainer(lastDecl);
+        var lastDeclType = curNav.declObjs[curNav.declObjs.length - 1];
+        if (lastDeclType.pubDecls != null) {
+            renderContainer(lastDeclType);
         }
-        if (lastDecl.kind == null) {
-            return renderUnknownDecl(lastDecl);
-        } else if (lastDecl.kind === 'var') {
-            return renderVar(lastDecl);
-        } else if (lastDecl.kind === 'const' && lastDecl.type != null) {
-            var typeObj = zigAnalysis.types[lastDecl.type];
+        if (lastDeclType.kind == null) {
+            return renderUnknownDecl(lastDeclType);
+        } else if (lastDeclType.kind === 'var') {
+            return renderVar(lastDeclType);
+        } else if (lastDeclType.kind === 'const' && lastDeclType.type != null) {
+            var typeObj = zigAnalysis.types[lastDeclType.type];
             if (typeObj.kind === typeKinds.Fn) {
-                return renderFn(lastDecl);
+                return renderFn(lastDeclType);
             } else {
-                return renderValue(lastDecl);
+                return renderValue(lastDeclType);
             }
         } else {
-            renderType(lastDecl);
+            renderType(lastDeclType);
         }
     }
 
@@ -994,15 +994,18 @@
 
         for (var i = 0; i < container.pubDecls.length; i += 1) {
             var decl = zigAnalysis.decls[container.pubDecls[i]];
+            var declValTypeId = getDeclValTypeId(decl);
 
             if (decl.kind === 'var') {
                 varsList.push(decl);
                 continue;
             } else if (decl.kind === 'const' && decl.type != null) {
                 if (decl.type === typeTypeId) {
-                    if (typeIsErrSet(decl.value)) {
+                    // todo: this actually makes sense for decl_vals too
+                    //       the problem is, how should we get to the final type though?
+                    if (typeIsErrSet(declValTypeId)) {
                         errSetsList.push(decl);
-                    } else if (typeIsStructWithNoFields(decl.value)) {
+                    } else if (typeIsStructWithNoFields(declValTypeId)) {
                         namespacesList.push(decl);
                     } else {
                         typesList.push(decl);
@@ -1010,7 +1013,7 @@
                 } else {
                     var typeKind = zigAnalysis.types[decl.type].kind;
                     if (typeKind === typeKinds.Fn) {
-                        if (allCompTimeFnCallsHaveTypeResult(decl.type, decl.value)) {
+                        if (allCompTimeFnCallsHaveTypeResult(decl.type, declValTypeId)) {
                             typesList.push(decl);
                         } else {
                             fnsList.push(decl);
@@ -1111,10 +1114,20 @@
                         if (field.failure === true) {
                             html += '<span class="tok-kw" style="color:red;">#FAILURE#</span>';
                         } else if ("decl_ref" in field) {
-                            var name = zigAnalysis.decls[field.decl_ref].name;
-                            html += '<a href="'+navLinkDecl(name)+'">';
-                            html += '<span class="tok-kw" style="color:lightblue;">'+ name +'</span>';
+                            var decl = zigAnalysis.decls[field.decl_ref];
+                            var valType = zigAnalysis.types[getDeclValTypeId(decl)];
+                            var valTypeName = valType.name;
+                            if (valType.kind === typeKinds.Struct) {
+                                valTypeName = "struct";                                
+                            }
+                            
+                            html += '<a href="'+navLinkDecl(decl.name)+'">';
+                            html += '<span class="tok-kw" style="color:lightblue;">' + decl.name + '</span>';
                             html += '</a>';
+                            html += ' ('+ valTypeName +')';
+                        } else if ("type" in field) {
+                            var name = zigAnalysis.types[field.type].name;
+                            html += '<span class="tok-kw">' + name + '</span>';
                         } else {
                             html += '<span class="tok-kw">var</span>';
                         }
@@ -1291,7 +1304,7 @@
 
     function getDeclContainerType(decl) {
         if (decl.type === typeTypeId) {
-            return zigAnalysis.types[decl.value];
+            return zigAnalysis.types[getDeclValTypeId(decl)];
         }
         return null;
     }
@@ -1334,6 +1347,14 @@
         return typeKind === typeKinds.ErrorSet || typeKindIsContainer(typeKind);
     }
 
+    function getDeclValTypeId(decl) {
+        while ( "decl_ref" in decl.value) {
+            decl = zigAnalysis.decls[decl.value.decl_ref];
+        }  
+        console.assert("type" in decl.value);
+        return decl.value.type;
+    }
+
     function computeCanonDeclPaths() {
         var list = new Array(zigAnalysis.decls.length);
         canonTypeDecls = new Array(zigAnalysis.types.length);
@@ -1355,10 +1376,11 @@
                         if (list[mainDeclIndex] != null) continue;
 
                         var decl = zigAnalysis.decls[mainDeclIndex];
+                        var declValTypeId = getDeclValTypeId(decl);
                         if (decl.type === typeTypeId &&
-                            declCanRepresentTypeKind(zigAnalysis.types[decl.value].kind))
+                            declCanRepresentTypeKind(zigAnalysis.types[declValTypeId].kind))
                         {
-                            canonTypeDecls[decl.value] = mainDeclIndex;
+                            canonTypeDecls[declValTypeId] = mainDeclIndex;
                         }
                         var declNames = item.declNames.concat([decl.name]);
                         list[mainDeclIndex] = {
src/Autodoc.zig
@@ -21,6 +21,10 @@ pub fn init(m: *Module, doc_location: ?Compilation.EmitLoc) Autodoc {
     };
 }
 
+pub fn deinit(_: *Autodoc) void {
+    arena_allocator.deinit();
+}
+
 pub fn generateZirData(self: *Autodoc) !void {
     if (self.doc_location) |loc| {
         if (loc.directory) |dir| {
@@ -48,13 +52,51 @@ pub fn generateZirData(self: *Autodoc) !void {
     {
 
         // TODO: we don't want to add .none, but the index math has to check out
-        var i: u32 = 1;
+        var i: u32 = 0;
         while (i <= @enumToInt(Zir.Inst.Ref.anyerror_void_error_union_type)) : (i += 1) {
             var tmpbuf = std.ArrayList(u8).init(self.arena);
             try Zir.Inst.Ref.typed_value_map[i].val.format("", .{}, tmpbuf.writer());
             try self.types.append(self.arena, .{
-                .kind = 0,
                 .name = tmpbuf.toOwnedSlice(),
+                .kind = switch (@intToEnum(Zir.Inst.Ref, i)) {
+                    else => |t| blk: {
+                        std.debug.print("TODO: categorize `{s}` in typeKinds\n", .{
+                            @tagName(t),
+                        });
+                        break :blk 7;
+                    },
+                    .u1_type,
+                    .u8_type,
+                    .i8_type,
+                    .u16_type,
+                    .i16_type,
+                    .u32_type,
+                    .i32_type,
+                    .u64_type,
+                    .i64_type,
+                    .u128_type,
+                    .i128_type,
+                    .usize_type,
+                    .isize_type,
+                    .c_short_type,
+                    .c_ushort_type,
+                    .c_int_type,
+                    .c_uint_type,
+                    .c_long_type,
+                    .c_ulong_type,
+                    .c_longlong_type,
+                    .c_ulonglong_type,
+                    .c_longdouble_type,
+                    => @enumToInt(std.builtin.TypeId.Int),
+                    .f16_type,
+                    .f32_type,
+                    .f64_type,
+                    .f128_type,
+                    => @enumToInt(std.builtin.TypeId.Float),
+                    .bool_type => @enumToInt(std.builtin.TypeId.Bool),
+                    .void_type => @enumToInt(std.builtin.TypeId.Void),
+                    .type_type => @enumToInt(std.builtin.TypeId.Type),
+                },
             });
         }
     }
@@ -167,7 +209,7 @@ const DocData = struct {
         kind: []const u8, // TODO: where do we find this info?
         src: usize, // index into astNodes
         type: usize, // index into types
-        value: usize,
+        value: WalkResult,
     };
 
     const AstNode = struct {
@@ -476,7 +518,6 @@ fn walkDecls(
         };
 
         const walk_result = try self.walkInstruction(zir, scope, decl_index);
-        const type_index = walk_result.type;
 
         if (is_pub) {
             try decl_indexes.append(self.arena, decls_slot_index);
@@ -487,8 +528,8 @@ fn walkDecls(
         self.decls.items[decls_slot_index] = .{
             .name = name,
             .src = ast_node_index,
-            .type = 0,
-            .value = type_index,
+            .type = @enumToInt(Zir.Inst.Ref.type_type),
+            .value = walk_result,
             .kind = "const", // find where this information can be found
         };
     }
@@ -561,13 +602,9 @@ fn collectFieldInfo(
                 else => {
                     const enum_value = @enumToInt(field_type);
                     if (enum_value < Zir.Inst.Ref.typed_value_map.len) {
-                        std.debug.print(
-                            "TODO: handle ref type: {s}",
-                            .{@tagName(field_type)},
-                        );
                         try field_type_indexes.append(
                             self.arena,
-                            DocData.WalkResult{ .failure = true },
+                            DocData.WalkResult{ .type = enum_value },
                         );
                     } else {
                         const zir_index = enum_value - Zir.Inst.Ref.typed_value_map.len;
src/Compilation.zig
@@ -2870,6 +2870,7 @@ pub fn performAllTheWork(
     if (comp.emit_docs) |doc_location| {
         if (comp.bin_file.options.module) |module| {
             var autodoc = Autodoc.init(module, doc_location);
+            defer autodoc.deinit();
             try autodoc.generateZirData();
         }
     }