From 0135d2271600db92d1ae727b2a5935d0fc711c13 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Sun, 30 Jan 2022 19:12:56 +0100 Subject: [PATCH] autodocs: add support for indirect decl references --- lib/docs/main.js | 74 +++++++++++++++++++++++++++++---------------- src/Autodoc.zig | 59 +++++++++++++++++++++++++++++------- src/Compilation.zig | 1 + 3 files changed, 97 insertions(+), 37 deletions(-) diff --git a/lib/docs/main.js b/lib/docs/main.js index 15e0d7567e..44f003a569 100644 --- a/lib/docs/main.js +++ b/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 += '#FAILURE#'; } else if ("decl_ref" in field) { - var name = zigAnalysis.decls[field.decl_ref].name; - html += ''; - html += ''+ name +''; + 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 += ''; + html += '' + decl.name + ''; html += ''; + html += ' ('+ valTypeName +')'; + } else if ("type" in field) { + var name = zigAnalysis.types[field.type].name; + html += '' + name + ''; } else { html += 'var'; } @@ -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] = { diff --git a/src/Autodoc.zig b/src/Autodoc.zig index bd9398a82e..b45682f381 100644 --- a/src/Autodoc.zig +++ b/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; diff --git a/src/Compilation.zig b/src/Compilation.zig index cadc665598..d4e3c13133 100644 --- a/src/Compilation.zig +++ b/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(); } }