autodocs: fix rendering of non-type decls

This commit is contained in:
Loris Cro 2022-02-04 19:28:12 +01:00 committed by Andrew Kelley
parent ce40f34cbc
commit a04045c709
2 changed files with 185 additions and 86 deletions

View File

@ -1,3 +1,5 @@
//'use strict';
(function() {
var domStatus = document.getElementById("status");
var domSectNav = document.getElementById("sectNav");
@ -101,6 +103,98 @@
}
}
function isDecl(x) {
return "value" in x;
}
function isType(x) {
return "kind" in x && !("value" in x);
}
function isContainerType(x) {
return isType(x) && typeKindIsContainer(x.kind) ;
}
function declContainsType(x){
console.assert("value" in x);
}
function typeKindIsContainer(typeKind) {
return typeKind === typeKinds.Struct ||
typeKind === typeKinds.Union ||
typeKind === typeKinds.Enum;
}
function declCanRepresentTypeKind(typeKind) {
return typeKind === typeKinds.ErrorSet || typeKindIsContainer(typeKind);
}
function resolveDeclValue(decl) {
var i = 0;
while(i < 1000) {
i += 1;
if ("declRef" in decl.value) {
decl = zigAnalysis.decls[decl.value.declRef];
continue;
}
return decl.value;
}
console.assert(false);
}
function resolveDeclValueTypeId(decl){
var i = 0;
while(i < 1000) {
i += 1;
console.assert(isDecl(decl));
if ("type" in decl.value) {
return typeTypeId;
}
if ("declRef" in decl.value) {
decl = zigAnalysis.decls[decl.value.declRef];
continue;
}
if ("int" in decl.value) {
return resolveTypeRefToTypeId(decl.value.int.typeRef);
}
if ("float" in decl.value) {
return resolveTypeRefToTypeId(decl.value.float.typeRef);
}
if ("struct" in decl.value) {
return resolveTypeRefToTypeId(decl.value.struct.typeRef);
}
console.log("TODO: handle in `resolveDeclValueTypeId` more cases: ", decl);
console.assert(false);
}
console.assert(false);
}
function resolveTypeRefToTypeId(ref) {
if ("unspecified" in ref) {
console.log("found an unspecified type!")
return -1;
}
if ("declRef" in ref) {
return resolveDeclValueTypeId(ref.declRef);
}
if ("type" in ref) {
return ref.type;
}
console.assert(false);
}
function render() {
domStatus.classList.add("hidden");
domFnProto.classList.add("hidden");
@ -154,38 +248,43 @@
if (childDecl == null) {
return render404();
}
var container = getDeclContainerType(childDecl);
if (container == null) {
var childDeclValue = resolveDeclValue(childDecl);
if ("type" in childDeclValue){
if (i + 1 === curNav.declNames.length) {
curNav.declObjs.push(childDecl);
curNav.declObjs.push(zigAnalysis.types[childDeclValue.type]);
break;
} else {
return render404();
}
}
currentType = container;
currentType = childDecl;
curNav.declObjs.push(currentType);
}
renderNav();
var lastDeclOrType = curNav.declObjs[curNav.declObjs.length - 1];
if (lastDeclOrType.pubDecls != null) {
renderContainer(lastDeclOrType);
var last = curNav.declObjs[curNav.declObjs.length - 1];
var lastIsDecl = isDecl(last);
var lastIsType = isType(last);
var lastIsContainerType = isContainerType(last);
if (lastIsContainerType) {
renderContainer(last);
}
if (lastDeclOrType.kind == null) {
return renderUnknownDecl(lastDeclOrType);
} else if (lastDeclOrType.kind === 'var') {
return renderVar(lastDeclOrType);
} else if (lastDeclOrType.kind === 'const' && "value" in lastDeclOrType && !("type" in lastDeclOrType.value)) {
var typeObj = zigAnalysis.types[getDeclValTypeId(lastDeclOrType)];
if (!lastIsDecl && !lastIsType) {
return renderUnknownDecl(last);
} else if (lastIsDecl && last.kind === 'var') {
return renderVar(last);
} else if (lastIsDecl && last.kind === 'const' && !(declContainsType(last))) {
var typeObj = zigAnalysis.types[resolveDeclValueTypeId(last)];
if (typeObj.kind === typeKinds.Fn) {
return renderFn(lastDeclOrType);
return renderFn(last);
} else {
return renderValue(lastDeclOrType);
return renderValue(last);
}
} else {
renderType(lastDeclOrType);
renderType(last);
}
}
@ -210,7 +309,7 @@
var typeObj = zigAnalysis.types[typeIndex];
if (typeObj.kind !== typeKinds.Struct)
return false;
return typeObj.fields == null || typeObj.fields.length === 0;
return !typeObj.fields;
}
function typeIsGenericFn(typeIndex) {
@ -642,14 +741,16 @@
return "f" + typeObj.bits;
}
case typeKinds.Int:
return '<span class="tok-type">' + typeObj.name + '</span>';
// 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;
// }
var signed = (typeObj.i != null) ? 'i' : 'u';
var bits = typeObj[signed] || typeObj.name;
var name = typeObj.name ? typeObj.name : signed + bits;
if (wantHtml) {
return '<span class="tok-type">' + name + '</span>';
} else {
return name;
}
case typeKinds.ComptimeInt:
if (wantHtml) {
return '<span class="tok-type">comptime_int</span>';
@ -960,12 +1061,15 @@
function renderValue(decl) {
var declTypeId = getDeclValTypeId(decl);
var declTypeId = resolveDeclValueTypeId(decl);
var declValueText = "";
switch(Object.keys(decl.value)[0]) {
case "int":
declValueText += decl.value.int.value;
break;
case "float":
declValueText += decl.value.float.value;
break;
default:
console.log("TODO: renderValue for ", Object.keys(decl.value)[0]);
declValueText += "#TODO#";
@ -985,7 +1089,7 @@
}
function renderVar(decl) {
var declTypeId = getDeclValTypeId(decl);
var declTypeId = resolveDeclValueTypeId(decl);
domFnProtoCode.innerHTML = '<span class="tok-kw">var</span> ' +
escapeHtml(decl.name) + ': ' + typeIndexName(declTypeId, true, true);
@ -1006,27 +1110,28 @@
var varsList = [];
var valsList = [];
for (var i = 0; i < container.pubDecls.length; i += 1) {
var declLen = container.pubDecls ? container.pubDecls.length : 0;
for (var i = 0; i < declLen; i += 1) {
var decl = zigAnalysis.decls[container.pubDecls[i]];
var declValTypeId = getDeclValTypeId(decl);
var declTypeId = resolveDeclValueTypeId(decl);
if (decl.kind === 'var') {
varsList.push(decl);
continue;
} else if (decl.kind === 'const' && "value" in decl) {
if (declValTypeId === typeTypeId) {
if (typeIsErrSet(declValTypeId)) {
} else if (decl.kind === 'const') {
if (declTypeId === typeTypeId) {
if (typeIsErrSet(declTypeId)) {
errSetsList.push(decl);
} else if (typeIsStructWithNoFields(declValTypeId)) {
} else if (typeIsStructWithNoFields(declTypeId)) {
namespacesList.push(decl);
} else {
typesList.push(decl);
}
} else {
var typeKind = zigAnalysis.types[declValTypeId].kind;
var typeKind = zigAnalysis.types[declTypeId].kind;
if (typeKind === typeKinds.Fn) {
// TODO: this is broken but I don't understand functions yet
if (allCompTimeFnCallsHaveTypeResult(decl.type, declValTypeId)) {
if (allCompTimeFnCallsHaveTypeResult(decl.type, declTypeId)) {
typesList.push(decl);
} else {
fnsList.push(decl);
@ -1108,7 +1213,7 @@
domSectFns.classList.remove("hidden");
}
if (container.fields != null && container.fields.length !== 0) {
if (container.fields) {
resizeDomList(domListFields, container.fields.length, '<div></div>');
var containerNode = zigAnalysis.astNodes[container.src];
@ -1128,7 +1233,10 @@
html += '<span class="tok-kw" style="color:red;">#FAILURE#</span>';
} else if ("declRef" in field) {
var decl = zigAnalysis.decls[field.declRef];
var valType = zigAnalysis.types[getDeclValTypeId(decl)];
var val = resolveDeclValue(decl);
console.assert("type" in val);
var valType = zigAnalysis.types[val.type];
var valTypeName = valType.name;
if (valType.kind === typeKinds.Struct) {
valTypeName = "struct";
@ -1175,7 +1283,7 @@
tdNameA.setAttribute('href', navLinkDecl(decl.name));
tdNameA.textContent = decl.name;
tdType.innerHTML = typeIndexName(getDeclValTypeId(decl), true, true);
tdType.innerHTML = typeIndexName(resolveDeclValueTypeId(decl), true, true);
var docs = zigAnalysis.astNodes[decl.src].docs;
if (docs != null) {
@ -1202,7 +1310,7 @@
tdNameA.setAttribute('href', navLinkDecl(decl.name));
tdNameA.textContent = decl.name;
tdType.innerHTML = typeIndexName(getDeclValTypeId(decl), true, true);
tdType.innerHTML = typeIndexName(resolveDeclValueTypeId(decl), true, true);
var docs = zigAnalysis.astNodes[decl.src].docs;
if (docs != null) {
@ -1304,7 +1412,7 @@
}
function findSubDecl(parentType, childName) {
if (parentType.pubDecls == null) throw new Error("parent object has no public decls");
if (!parentType.pubDecls) throw new Error("parent object has no public decls");
for (var i = 0; i < parentType.pubDecls.length; i += 1) {
var declIndex = parentType.pubDecls[i];
var childDecl = zigAnalysis.decls[declIndex];
@ -1315,12 +1423,8 @@
return null;
}
function getDeclContainerType(decl) {
if (decl.type === typeTypeId) {
return zigAnalysis.types[getDeclValTypeId(decl)];
}
return null;
}
function computeCanonicalPackagePaths() {
var list = new Array(zigAnalysis.packages.length);
@ -1350,37 +1454,6 @@
return list;
}
function typeKindIsContainer(typeKind) {
return typeKind === typeKinds.Struct ||
typeKind === typeKinds.Union ||
typeKind === typeKinds.Enum;
}
function declCanRepresentTypeKind(typeKind) {
return typeKind === typeKinds.ErrorSet || typeKindIsContainer(typeKind);
}
// Handles both WalkResult and TypeRef
function getDeclValTypeId(decl) {
var val = decl.value;
while (true) {
if ( "declRef" in val) {
val = zigAnalysis.decls[val.declRef].value;
continue;
}
if ("int" in val) {
val = val.int.typeRef;
}
if ("type" in val) {
return val.type;
}
console.assert("type" in val);
}
return val.type;
}
function computeCanonDeclPaths() {
var list = new Array(zigAnalysis.decls.length);
@ -1397,14 +1470,15 @@
while (stack.length !== 0) {
var item = stack.shift();
if (item.type.pubDecls != null) {
for (var declI = 0; declI < item.type.pubDecls.length; declI += 1) {
if (isContainerType(item.type)) {
var len = item.type.pubDecls ? item.type.pubDecls.length : 0;
for (var declI = 0; declI < len; declI += 1) {
var mainDeclIndex = item.type.pubDecls[declI];
if (list[mainDeclIndex] != null) continue;
var decl = zigAnalysis.decls[mainDeclIndex];
var declValTypeId = getDeclValTypeId(decl);
if (decl.type === typeTypeId &&
var declValTypeId = resolveDeclValueTypeId(decl);
if (declValTypeId === typeTypeId &&
declCanRepresentTypeKind(zigAnalysis.types[declValTypeId].kind))
{
canonTypeDecls[declValTypeId] = mainDeclIndex;
@ -1414,11 +1488,12 @@
pkgNames: pkgNames,
declNames: declNames,
};
var containerType = getDeclContainerType(decl);
if (containerType != null) {
var declType = zigAnalysis.types[declValTypeId];
if (isContainerType(declType)) {
stack.push({
declNames: declNames,
type: containerType,
type: declType,
});
}
}

View File

@ -88,13 +88,14 @@ pub fn generateZirData(self: *Autodoc) !void {
.c_longlong_type,
.c_ulonglong_type,
.c_longdouble_type,
.comptime_int_type,
=> @enumToInt(std.builtin.TypeId.Int),
.f16_type,
.f32_type,
.f64_type,
.f128_type,
=> @enumToInt(std.builtin.TypeId.Float),
.comptime_int_type => @enumToInt(std.builtin.TypeId.ComptimeInt),
.comptime_float_type => @enumToInt(std.builtin.TypeId.ComptimeFloat),
.bool_type => @enumToInt(std.builtin.TypeId.Bool),
.void_type => @enumToInt(std.builtin.TypeId.Void),
.type_type => @enumToInt(std.builtin.TypeId.Type),
@ -275,7 +276,11 @@ const DocData = struct {
value: usize, // direct value
negated: bool = false,
},
float: struct {
typeRef: TypeRef,
value: f64, // direct value
negated: bool = false,
},
pub fn jsonStringify(
self: WalkResult,
options: std.json.StringifyOptions,
@ -304,6 +309,16 @@ const DocData = struct {
\\, "value": {s}{} }} }}
, .{ neg, v.value });
},
.float => |v| {
const neg = if (v.negated) "-" else "";
try w.print(
\\{{ "float": {{ "typeRef":
, .{});
try v.typeRef.jsonStringify(options, w);
try w.print(
\\, "value": {s}{} }} }}
, .{ neg, v.value });
},
.bool => |v| {
try w.print(
\\{{ "bool":{} }}
@ -350,6 +365,15 @@ fn walkInstruction(
},
};
},
.float => {
const float = data[inst_index].float;
return DocData.WalkResult{
.float = .{
.typeRef = .{ .type = @enumToInt(Ref.comptime_float_type) },
.value = float,
},
};
},
.negate => {
const un_node = data[inst_index].un_node;
var operand = try self.walkRef(zir, parent_scope, un_node.operand);