autodoc: improve type checking in main.js

This commit is contained in:
Loris Cro 2022-03-30 19:06:02 +02:00 committed by Andrew Kelley
parent 64feb222b5
commit 72e5b4fb74

View File

@ -57,15 +57,19 @@
/**
* @typedef {
{ kind: number } & (
| { name: string } // Type, Void, Bool, NoReturn, Int, Float, ComptimeExpr, ComptimeFloat, ComptimeInt, Undefined, Null, ErrorUnion, BoundFn, Opaque, Frame, AnyFrame, Vector, EnumLiteral
| { name: string; child: TypeRef } // Optional
| { len: WalkResult; child: TypeRef } // Array
| { name: string; fields: { name: string; docs: string }[] } // ErrorSet
| { size: "One" | "Many" | "Slice" | "C"; child: TypeRef } // Pointer
| { name: string; src: number; privDecls: number[]; pubDecls: number[]; fields: WalkResult[] } // Struct, Enum, Union
| { name: string; src: number; ret: WalkResult; params: WalkResult[] } // Fn
)
| { kind: number, name: string; src: number; privDecls: number[]; pubDecls: number[]; fields: WalkResult[] } // Struct, Enum, Union
} ContainerType
*/
/**
* @typedef {
| { kind: number, name: string } // Type, Void, Bool, NoReturn, Int, Float, ComptimeExpr, ComptimeFloat, ComptimeInt, Undefined, Null, ErrorUnion, BoundFn, Opaque, Frame, AnyFrame, Vector, EnumLiteral
| { kind: number, name: string; child: TypeRef } // Optional
| { kind: number, len: WalkResult; child: TypeRef } // Array
| { kind: number, name: string; fields: { name: string; docs: string }[] } // ErrorSet
| { kind: number, size: "One" | "Many" | "Slice" | "C"; child: TypeRef } // Pointer
| ContainerType
| { kind: number, name: string; src: number; ret: WalkResult; params: WalkResult[] } // Fn
} Type
*/
@ -156,7 +160,7 @@
errors: {};
astNodes: AstNode[];
calls: Call[];
files: Record<string, number>;
files: Record<string, string>;
types: Type[];
decls: Decl[];
comptimeExprs: ComptimeExpr[];
@ -168,53 +172,57 @@
var zigAnalysis;
(function() {
var domStatus = document.getElementById("status");
var domSectNav = document.getElementById("sectNav");
var domListNav = document.getElementById("listNav");
var domSectMainPkg = document.getElementById("sectMainPkg");
var domSectPkgs = document.getElementById("sectPkgs");
var domListPkgs = document.getElementById("listPkgs");
var domSectTypes = document.getElementById("sectTypes");
var domListTypes = document.getElementById("listTypes");
var domSectTests = document.getElementById("sectTests");
var domListTests = document.getElementById("listTests");
var domSectNamespaces = document.getElementById("sectNamespaces");
var domListNamespaces = document.getElementById("listNamespaces");
var domSectErrSets = document.getElementById("sectErrSets");
var domListErrSets = document.getElementById("listErrSets");
var domSectFns = document.getElementById("sectFns");
var domListFns = document.getElementById("listFns");
var domSectFields = document.getElementById("sectFields");
var domListFields = document.getElementById("listFields");
var domSectGlobalVars = document.getElementById("sectGlobalVars");
var domListGlobalVars = document.getElementById("listGlobalVars");
var domSectValues = document.getElementById("sectValues");
var domListValues = document.getElementById("listValues");
var domFnProto = document.getElementById("fnProto");
var domFnProtoCode = document.getElementById("fnProtoCode");
var domSectParams = document.getElementById("sectParams");
var domListParams = document.getElementById("listParams");
var domTldDocs = document.getElementById("tldDocs");
var domSectFnErrors = document.getElementById("sectFnErrors");
var domListFnErrors = document.getElementById("listFnErrors");
var domTableFnErrors = document.getElementById("tableFnErrors");
var domFnErrorsAnyError = document.getElementById("fnErrorsAnyError");
var domFnExamples = document.getElementById("fnExamples");
var domListFnExamples = document.getElementById("listFnExamples");
var domFnNoExamples = document.getElementById("fnNoExamples");
var domDeclNoRef = document.getElementById("declNoRef");
var domSearch = document.getElementById("search");
var domSectSearchResults = document.getElementById("sectSearchResults");
var domListSearchResults = document.getElementById("listSearchResults");
var domSectSearchNoResults = document.getElementById("sectSearchNoResults");
var domSectInfo = document.getElementById("sectInfo");
var domTdTarget = document.getElementById("tdTarget");
var domPrivDeclsBox = document.getElementById("privDeclsBox");
var domTdZigVer = document.getElementById("tdZigVer");
var domHdrName = document.getElementById("hdrName");
var domHelpModal = document.getElementById("helpDialog");
var domStatus = /** @type HTMLElement */(document.getElementById("status"));
var domSectNav = /** @type HTMLElement */(document.getElementById("sectNav"));
var domListNav = /** @type HTMLElement */(document.getElementById("listNav"));
var domSectMainPkg = /** @type HTMLElement */(document.getElementById("sectMainPkg"));
var domSectPkgs = /** @type HTMLElement */(document.getElementById("sectPkgs"));
var domListPkgs = /** @type HTMLElement */(document.getElementById("listPkgs"));
var domSectTypes = /** @type HTMLElement */(document.getElementById("sectTypes"));
var domListTypes = /** @type HTMLElement */(document.getElementById("listTypes"));
var domSectTests = /** @type HTMLElement */(document.getElementById("sectTests"));
var domListTests = /** @type HTMLElement */(document.getElementById("listTests"));
var domSectNamespaces = /** @type HTMLElement */(document.getElementById("sectNamespaces"));
var domListNamespaces = /** @type HTMLElement */(document.getElementById("listNamespaces"));
var domSectErrSets = /** @type HTMLElement */(document.getElementById("sectErrSets"));
var domListErrSets = /** @type HTMLElement */(document.getElementById("listErrSets"));
var domSectFns = /** @type HTMLElement */(document.getElementById("sectFns"));
var domListFns = /** @type HTMLElement */(document.getElementById("listFns"));
var domSectFields = /** @type HTMLElement */(document.getElementById("sectFields"));
var domListFields = /** @type HTMLElement */(document.getElementById("listFields"));
var domSectGlobalVars = /** @type HTMLElement */(document.getElementById("sectGlobalVars"));
var domListGlobalVars = /** @type HTMLElement */(document.getElementById("listGlobalVars"));
var domSectValues = /** @type HTMLElement */(document.getElementById("sectValues"));
var domListValues = /** @type HTMLElement */(document.getElementById("listValues"));
var domFnProto = /** @type HTMLElement */(document.getElementById("fnProto"));
var domFnProtoCode = /** @type HTMLElement */(document.getElementById("fnProtoCode"));
var domSectParams = /** @type HTMLElement */(document.getElementById("sectParams"));
var domListParams = /** @type HTMLElement */(document.getElementById("listParams"));
var domTldDocs = /** @type HTMLElement */(document.getElementById("tldDocs"));
var domSectFnErrors = /** @type HTMLElement */(document.getElementById("sectFnErrors"));
var domListFnErrors = /** @type HTMLElement */(document.getElementById("listFnErrors"));
var domTableFnErrors =/** @type HTMLElement */(document.getElementById("tableFnErrors"));
var domFnErrorsAnyError = /** @type HTMLElement */(document.getElementById("fnErrorsAnyError"));
var domFnExamples = /** @type HTMLElement */(document.getElementById("fnExamples"));
var domListFnExamples = /** @type HTMLElement */(document.getElementById("listFnExamples"));
var domFnNoExamples = /** @type HTMLElement */(document.getElementById("fnNoExamples"));
var domDeclNoRef = /** @type HTMLElement */(document.getElementById("declNoRef"));
var domSearch = /** @type HTMLInputElement */(document.getElementById("search"));
var domSectSearchResults = /** @type HTMLElement */(document.getElementById("sectSearchResults"));
var domListSearchResults = /** @type HTMLElement */(document.getElementById("listSearchResults"));
var domSectSearchNoResults = /** @type HTMLElement */(document.getElementById("sectSearchNoResults"));
var domSectInfo = /** @type HTMLElement */(document.getElementById("sectInfo"));
var domTdTarget = /** @type HTMLElement */(document.getElementById("tdTarget"));
var domPrivDeclsBox = /** @type HTMLElement */(document.getElementById("privDeclsBox"));
var domTdZigVer = /** @type HTMLElement */(document.getElementById("tdZigVer"));
var domHdrName = /** @type HTMLElement */(document.getElementById("hdrName"));
var domHelpModal = /** @type HTMLElement */(document.getElementById("helpDialog"));
/** @type number | null */
var searchTimer = null;
/** @type Object<string, string> */
var escapeHtmlReplacements = { "&": "&amp;", '"': "&quot;", "<": "&lt;", ">": "&gt;" };
var typeKinds = indexTypeKinds();
@ -298,12 +306,6 @@ var zigAnalysis;
return isType(x) && typeKindIsContainer(x.kind) ;
}
function declContainsType(x){
console.assert("value" in x);
}
function typeShorthandName(type) {
var name = type.name;
if (type.kind === typeKinds.Struct) {
@ -1434,6 +1436,10 @@ var zigAnalysis;
}
/**
* @param {number[]} decls
* @param {Decl[]} typesList, namespacesList, errSetsList, fnsList, varsList, valsList, testsList
*/
function categorizeDecls(decls,
typesList, namespacesList, errSetsList,
fnsList, varsList, valsList, testsList) {
@ -1495,13 +1501,23 @@ var zigAnalysis;
}
}
/**
* @param {ContainerType} container
*/
function renderContainer(container) {
/** @type {Decl[]} */
var typesList = [];
/** @type {Decl[]} */
var namespacesList = [];
/** @type {Decl[]} */
var errSetsList = [];
/** @type {Decl[]} */
var fnsList = [];
/** @type {Decl[]} */
var varsList = [];
/** @type {Decl[]} */
var valsList = [];
/** @type {Decl[]} */
var testsList = [];
categorizeDecls(container.pubDecls,
@ -1911,20 +1927,32 @@ var zigAnalysis;
return canonTypeDecls[index];
}
/** @param {string} text */
function escapeHtml(text) {
return text.replace(/[&"<>]/g, function (m) {
return escapeHtmlReplacements[m];
});
}
/** @param {string} docs */
function shortDescMarkdown(docs) {
var parts = docs.trim().split("\n");
var firstLine = parts[0];
return markdown(firstLine);
}
/** @param {string} input */
function markdown(input) {
const raw_lines = input.split('\n'); // zig allows no '\r', so we don't need to split on CR
/**
* @type Array<{
* indent: number,
* raw_text: string,
* text: string,
* type: string,
* ordered_number: number,
* }>
*/
const lines = [];
// PHASE 1:
@ -1941,6 +1969,7 @@ var zigAnalysis;
raw_text: raw_line,
text: raw_line.trim(),
type: "p", // p, h1 … h6, code, ul, ol, blockquote, skip, empty
ordered_number: -1, // NOTE: hack to make the type checker happy
};
if (!is_reading_code) {
@ -1977,7 +2006,7 @@ var zigAnalysis;
line.text = line.text.substr(1);
}
else if (line.text.match(/^\d+\..*$/)) { // if line starts with {number}{dot}
const match = line.text.match(/(\d+)\./);
const match = /** @type {RegExpMatchArray} */(line.text.match(/(\d+)\./));
line.type = "ul";
line.text = line.text.substr(match[0].length);
line.ordered_number = Number(match[1].length);
@ -2010,7 +2039,10 @@ var zigAnalysis;
// Render HTML from markdown lines.
// Look at each line and emit fitting HTML code
function markdownInlines(innerText, stopChar) {
/**
* @param {string } innerText
*/
function markdownInlines(innerText) {
// inline types:
// **{INLINE}** : <strong>
@ -2023,6 +2055,8 @@ var zigAnalysis;
// ![{TEXT}]({URL}) : <img>
// [[std;format.fmt]] : <a> (inner link)
/** @typedef {{marker: string, tag: string}} Fmt*/
/** @type {Array<Fmt>} */
const formats = [
{
marker: "**",
@ -2042,6 +2076,7 @@ var zigAnalysis;
}
];
/** @type {Array<Fmt>} */
const stack = [];
var innerHTML = "";
@ -2093,7 +2128,7 @@ var zigAnalysis;
in_code = true;
} else {
var any = false;
for (var idx = (stack.length > 0 ? -1 : 0); idx < formats.length; idx++) {
for (let idx = /** @type {number} */(stack.length > 0 ? -1 : 0); idx < formats.length; idx++) {
const fmt = idx >= 0 ? formats[idx] : stack[stack.length - 1];
if (innerText.substr(i, fmt.marker.length) == fmt.marker) {
flushRun();
@ -2117,48 +2152,60 @@ var zigAnalysis;
flushRun();
while (stack.length > 0) {
const fmt = stack.pop();
const fmt = /** @type {Fmt} */(stack.pop());
innerHTML += "</" + fmt.tag + ">";
}
return innerHTML;
}
/**
* @param {string} type
* @param {number} line_no
*/
function previousLineIs(type, line_no) {
if (line_no > 0) {
return (lines[line_no - 1].type == type);
} else {
return false;
}
}
/**
* @param {string} type
* @param {number} line_no
*/
function nextLineIs(type, line_no) {
if (line_no < (lines.length - 1)) {
return (lines[line_no + 1].type == type);
} else {
return false;
}
}
/** @param {number} line_no */
function getPreviousLineIndent(line_no) {
if (line_no > 0) {
return lines[line_no - 1].indent;
} else {
return 0;
}
}
/** @param {number} line_no */
function getNextLineIndent(line_no) {
if (line_no < (lines.length - 1)) {
return lines[line_no + 1].indent;
} else {
return 0;
}
}
var html = "";
for (var line_no = 0; line_no < lines.length; line_no++) {
const line = lines[line_no];
function previousLineIs(type) {
if (line_no > 0) {
return (lines[line_no - 1].type == type);
} else {
return false;
}
}
function nextLineIs(type) {
if (line_no < (lines.length - 1)) {
return (lines[line_no + 1].type == type);
} else {
return false;
}
}
function getPreviousLineIndent() {
if (line_no > 0) {
return lines[line_no - 1].indent;
} else {
return 0;
}
}
function getNextLineIndent() {
if (line_no < (lines.length - 1)) {
return lines[line_no + 1].indent;
} else {
return 0;
}
}
switch (line.type) {
case "h1":
@ -2172,33 +2219,33 @@ var zigAnalysis;
case "ul":
case "ol":
if (!previousLineIs("ul") || getPreviousLineIndent() < line.indent) {
if (!previousLineIs("ul", line_no) || getPreviousLineIndent(line_no) < line.indent) {
html += "<" + line.type + ">\n";
}
html += "<li>" + markdownInlines(line.text) + "</li>\n";
if (!nextLineIs("ul") || getNextLineIndent() < line.indent) {
if (!nextLineIs("ul", line_no) || getNextLineIndent(line_no) < line.indent) {
html += "</" + line.type + ">\n";
}
break;
case "p":
if (!previousLineIs("p")) {
if (!previousLineIs("p", line_no)) {
html += "<p>\n";
}
html += markdownInlines(line.text) + "\n";
if (!nextLineIs("p")) {
if (!nextLineIs("p", line_no)) {
html += "</p>\n";
}
break;
case "code":
if (!previousLineIs("code")) {
if (!previousLineIs("code", line_no)) {
html += "<pre><code>";
}
html += escapeHtml(line.text) + "\n";
if (!nextLineIs("code")) {
if (!nextLineIs("code", line_no)) {
html += "</code></pre>\n";
}
break;
@ -2219,12 +2266,13 @@ var zigAnalysis;
}
if (liDom != null) {
var aDom = liDom.children[0];
location.href = aDom.getAttribute("href");
location.href = /** @type {string} */(aDom.getAttribute("href"));
curSearchIndex = -1;
}
domSearch.blur();
}
/** @param {KeyboardEvent} ev */
function onSearchKeyDown(ev) {
switch (getKeyString(ev)) {
case "Enter":
@ -2268,6 +2316,8 @@ var zigAnalysis;
}
}
/** @param {number} dir */
function moveSearchCursor(dir) {
if (curSearchIndex < 0 || curSearchIndex >= domListSearchResults.children.length) {
if (dir > 0) {
@ -2287,6 +2337,7 @@ var zigAnalysis;
renderSearchCursor();
}
/** @param {KeyboardEvent} ev */
function getKeyString(ev) {
var name;
var ignoreShift = false;
@ -2313,6 +2364,7 @@ var zigAnalysis;
return name;
}
/** @param {KeyboardEvent} ev */
function onWindowKeyDown(ev) {
switch (getKeyString(ev)) {
case "Esc":
@ -2451,7 +2503,7 @@ function renderSearch() {
function renderSearchCursor() {
for (var i = 0; i < domListSearchResults.children.length; i += 1) {
var liDom = domListSearchResults.children[i];
var liDom = /** @type HTMLElement */(domListSearchResults.children[i]);
if (curSearchIndex === i) {
liDom.classList.add("selected");
} else {
@ -2462,35 +2514,42 @@ function renderSearchCursor() {
function indexNodesToCalls() {
var map = {};
for (var i = 0; i < zigAnalysis.calls.length; i += 1) {
var call = zigAnalysis.calls[i];
var fn = zigAnalysis.fns[call.fn];
if (map[fn.src] == null) {
map[fn.src] = [i];
} else {
map[fn.src].push(i);
}
}
return map;
}
// function indexNodesToCalls() {
// var map = {};
// for (var i = 0; i < zigAnalysis.calls.length; i += 1) {
// var call = zigAnalysis.calls[i];
// var fn = zigAnalysis.fns[call.fn];
// if (map[fn.src] == null) {
// map[fn.src] = [i];
// } else {
// map[fn.src].push(i);
// }
// }
// return map;
// }
/**
* @param {{ name: string }} a
* @param {{ name: string }} b
*/
function byNameProperty(a, b) {
return operatorCompare(a.name, b.name);
}
/**
* @template T
* @param {T} obj
* @returns {T}
*/
function clone(obj) {
var res = {};
var res = /** @type T */({});
for (var key in obj) {
res[key] = obj[key];
}
return res;
}
function firstObjectKey(obj) {
for (var key in obj) {
return key;
}
}
})();