autodocs: add support for indirect decl references

This commit is contained in:
Loris Cro 2022-01-30 19:12:56 +01:00 committed by Andrew Kelley
parent 38281c8ed4
commit 0135d22716
3 changed files with 97 additions and 37 deletions

View File

@ -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] = {

View File

@ -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;

View File

@ -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();
}
}