blob 0bbca2b3 (103897B) - Raw
1 'use strict'; 2 3 /** 4 * @typedef { 5 | "Type" 6 | "Void" 7 | "Bool" 8 | "NoReturn" 9 | "Int" 10 | "Float" 11 | "Pointer" 12 | "Array" 13 | "Struct" 14 | "ComptimeFloat" 15 | "ComptimeInt" 16 | "Undefined" 17 | "Null" 18 | "Optional" 19 | "ErrorUnion" 20 | "ErrorSet" 21 | "Enum" 22 | "Union" 23 | "Fn" 24 | "BoundFn" 25 | "Opaque" 26 | "Frame" 27 | "AnyFrame" 28 | "Vector" 29 | "EnumLiteral" 30 | "ComptimeExpr" 31 | "Unanalyzed" 32 } TypeKind 33 */ 34 35 /** 36 * @typedef {{ 37 typeRef: Expr?, 38 expr: Expr, 39 }} WalkResult 40 */ 41 42 /** 43 * @typedef {{ 44 void: {}, 45 unreachable: {}, 46 anytype: {}, 47 type: number, 48 comptimeExpr: number, 49 call: number, 50 int: number, 51 float: number, 52 bool: boolean, 53 undefined: WalkResult, 54 null: WalkResult, 55 typeOf: WalkResult, 56 compileError: string 57 string: string, 58 struct: Expr[], 59 refPath: Expr[], 60 declRef: number, 61 array: ZigArray, 62 enumLiteral: string, 63 }} Expr 64 */ 65 66 /** 67 * @typedef {{ 68 kind: number, 69 name: string, 70 src: number, 71 privDecls: number[], 72 pubDecls: number[], 73 fields: WalkResult[] 74 }} ContainerType 75 */ 76 77 /** 78 * @typedef {{ 79 kind: number, 80 name: string, 81 src: number, 82 ret: WalkResult, 83 params: WalkResult[], 84 generic: boolean, 85 }} Fn 86 */ 87 88 /** 89 * @typedef {{ 90 kind: number, 91 name: string, 92 fields: { name: string, docs: string }[] 93 fn: number | undefined, 94 }} ErrSetType 95 */ 96 97 /** 98 * @typedef {{ 99 kind: number, 100 err: WalkResult, 101 payload: WalkResult, 102 }} ErrUnionType 103 */ 104 105 // Type, Void, Bool, NoReturn, Int, Float, ComptimeExpr, ComptimeFloat, ComptimeInt, Undefined, Null, ErrorUnion, BoundFn, Opaque, Frame, AnyFrame, Vector, EnumLiteral 106 /** 107 * @typedef {{ 108 kind: number, 109 name: string 110 }} NumberType 111 */ 112 113 /** 114 * @typedef {{ 115 kind: number, 116 size: number, 117 child: WalkResult 118 align: number, 119 bitOffsetInHost: number, 120 hostIntBytes: number, 121 volatile: boolean, 122 const: boolean, 123 }} PointerType 124 */ 125 126 /** 127 * @typedef {{ 128 kind: number, 129 len: WalkResult 130 child: WalkResult 131 }} ArrayType 132 */ 133 134 /** 135 * @typedef {{ 136 kind: number, 137 name: string, 138 child: Expr, 139 }} OptionalType 140 */ 141 142 /** 143 * @typedef { 144 | OptionalType 145 | ArrayType 146 | PointerType 147 | ContainerType 148 | Fn 149 | ErrSetType 150 | ErrUnionType 151 | NumberType 152 } Type 153 */ 154 155 156 /** 157 * @typedef {{ 158 func: Expr, 159 args: Expr[], 160 ret: Expr, 161 }} Call 162 */ 163 164 /** 165 * @typedef {{ 166 file: number, 167 line: number, 168 col: number, 169 name?: string, 170 docs?: string, 171 fields?: number[], 172 comptime: boolean, 173 noalias: boolean, 174 varArgs: boolean, 175 }} AstNode 176 */ 177 178 /** 179 * @typedef {{ 180 name: string, 181 kind: string, 182 src: number, 183 value: WalkResult, 184 decltest?: number, 185 isTest: boolean, 186 }} Decl 187 */ 188 189 /** 190 * @typedef {{ 191 name: string, 192 file: number, 193 main: number, 194 table: Record<string, number>, 195 }} Package 196 */ 197 198 /** 199 * @typedef {{ 200 typeRef: WalkResult, 201 data: WalkResult[], 202 }} ZigArray 203 */ 204 205 /** 206 * @typedef {{ 207 code: string, 208 typeRef: WalkResult, 209 }} ComptimeExpr 210 */ 211 212 /** 213 * @typedef {{ 214 typeKinds: TypeKind[]; 215 rootPkg: number; 216 params: { 217 zigId: string; 218 zigVersion: string; 219 target: string; 220 rootName: string; 221 builds: { target: string }; 222 }; 223 packages: Package[]; 224 errors: {}; 225 astNodes: AstNode[]; 226 calls: Call[]; 227 files: Record<string, string>; 228 types: Type[]; 229 decls: Decl[]; 230 comptimeExprs: ComptimeExpr[]; 231 fns: Fn[]; 232 }} DocData 233 */ 234 235 /** @type {DocData} */ 236 var zigAnalysis; 237 238 (function() { 239 let domStatus = /** @type HTMLElement */(document.getElementById("status")); 240 let domSectNav = /** @type HTMLElement */(document.getElementById("sectNav")); 241 let domListNav = /** @type HTMLElement */(document.getElementById("listNav")); 242 let domSectMainPkg = /** @type HTMLElement */(document.getElementById("sectMainPkg")); 243 let domSectPkgs = /** @type HTMLElement */(document.getElementById("sectPkgs")); 244 let domListPkgs = /** @type HTMLElement */(document.getElementById("listPkgs")); 245 let domSectTypes = /** @type HTMLElement */(document.getElementById("sectTypes")); 246 let domListTypes = /** @type HTMLElement */(document.getElementById("listTypes")); 247 let domSectTests = /** @type HTMLElement */(document.getElementById("sectTests")); 248 let domListTests = /** @type HTMLElement */(document.getElementById("listTests")); 249 let domSectNamespaces = /** @type HTMLElement */(document.getElementById("sectNamespaces")); 250 let domListNamespaces = /** @type HTMLElement */(document.getElementById("listNamespaces")); 251 let domSectErrSets = /** @type HTMLElement */(document.getElementById("sectErrSets")); 252 let domListErrSets = /** @type HTMLElement */(document.getElementById("listErrSets")); 253 let domSectFns = /** @type HTMLElement */(document.getElementById("sectFns")); 254 let domListFns = /** @type HTMLElement */(document.getElementById("listFns")); 255 let domSectFields = /** @type HTMLElement */(document.getElementById("sectFields")); 256 let domListFields = /** @type HTMLElement */(document.getElementById("listFields")); 257 let domSectGlobalVars = /** @type HTMLElement */(document.getElementById("sectGlobalVars")); 258 let domListGlobalVars = /** @type HTMLElement */(document.getElementById("listGlobalVars")); 259 let domSectValues = /** @type HTMLElement */(document.getElementById("sectValues")); 260 let domListValues = /** @type HTMLElement */(document.getElementById("listValues")); 261 let domFnProto = /** @type HTMLElement */(document.getElementById("fnProto")); 262 let domFnProtoCode = /** @type HTMLElement */(document.getElementById("fnProtoCode")); 263 let domSectParams = /** @type HTMLElement */(document.getElementById("sectParams")); 264 let domListParams = /** @type HTMLElement */(document.getElementById("listParams")); 265 let domTldDocs = /** @type HTMLElement */(document.getElementById("tldDocs")); 266 let domSectFnErrors = /** @type HTMLElement */(document.getElementById("sectFnErrors")); 267 let domListFnErrors = /** @type HTMLElement */(document.getElementById("listFnErrors")); 268 let domTableFnErrors =/** @type HTMLElement */(document.getElementById("tableFnErrors")); 269 let domFnErrorsAnyError = /** @type HTMLElement */(document.getElementById("fnErrorsAnyError")); 270 let domFnExamples = /** @type HTMLElement */(document.getElementById("fnExamples")); 271 // let domListFnExamples = /** @type HTMLElement */(document.getElementById("listFnExamples")); 272 let domFnNoExamples = /** @type HTMLElement */(document.getElementById("fnNoExamples")); 273 let domDeclNoRef = /** @type HTMLElement */(document.getElementById("declNoRef")); 274 let domSearch = /** @type HTMLInputElement */(document.getElementById("search")); 275 let domSectSearchResults = /** @type HTMLElement */(document.getElementById("sectSearchResults")); 276 277 let domListSearchResults = /** @type HTMLElement */(document.getElementById("listSearchResults")); 278 let domSectSearchNoResults = /** @type HTMLElement */(document.getElementById("sectSearchNoResults")); 279 let domSectInfo = /** @type HTMLElement */(document.getElementById("sectInfo")); 280 // let domTdTarget = /** @type HTMLElement */(document.getElementById("tdTarget")); 281 let domPrivDeclsBox = /** @type HTMLInputElement */(document.getElementById("privDeclsBox")); 282 let domTdZigVer = /** @type HTMLElement */(document.getElementById("tdZigVer")); 283 let domHdrName = /** @type HTMLElement */(document.getElementById("hdrName")); 284 let domHelpModal = /** @type HTMLElement */(document.getElementById("helpDialog")); 285 286 /** @type number | null */ 287 let searchTimer = null; 288 289 /** @type Object<string, string> */ 290 let escapeHtmlReplacements = { "&": "&", '"': """, "<": "<", ">": ">" }; 291 292 let typeKinds = /** @type {Record<string, number>} */(indexTypeKinds()); 293 let typeTypeId = /** @type {number} */ (findTypeTypeId()); 294 let pointerSizeEnum = { One: 0, Many: 1, Slice: 2, C: 3 }; 295 296 // for each package, is an array with packages to get to this one 297 let canonPkgPaths = computeCanonicalPackagePaths(); 298 299 /** @typedef {{declNames: string[], pkgNames: string[]}} CanonDecl */ 300 301 // for each decl, is an array with {declNames, pkgNames} to get to this one 302 /** @type CanonDecl[] | null */ 303 let canonDeclPaths = null; // lazy; use getCanonDeclPath 304 305 // for each type, is an array with {declNames, pkgNames} to get to this one 306 /** @type number[] | null */ 307 let canonTypeDecls = null; // lazy; use getCanonTypeDecl 308 309 /** @typedef {{ 310 * showPrivDecls: boolean, 311 * pkgNames: string[], 312 * pkgObjs: Package[], 313 * declNames: string[], 314 * declObjs: (Decl | Type)[], 315 * callName: any, 316 * }} CurNav 317 */ 318 319 /** @type {CurNav} */ 320 let curNav = { 321 showPrivDecls: false, 322 // each element is a package name, e.g. @import("a") then within there @import("b") 323 // starting implicitly from root package 324 pkgNames: [], 325 // same as above except actual packages, not names 326 pkgObjs: [], 327 // Each element is a decl name, `a.b.c`, a is 0, b is 1, c is 2, etc. 328 // empty array means refers to the package itself 329 declNames: [], 330 // these will be all types, except the last one may be a type or a decl 331 declObjs: [], 332 333 // (a, b, c, d) comptime call; result is the value the docs refer to 334 callName: null, 335 }; 336 337 let curNavSearch = ""; 338 let curSearchIndex = -1; 339 let imFeelingLucky = false; 340 341 let rootIsStd = detectRootIsStd(); 342 343 // map of decl index to list of non-generic fn indexes 344 // let nodesToFnsMap = indexNodesToFns(); 345 // map of decl index to list of comptime fn calls 346 // let nodesToCallsMap = indexNodesToCalls(); 347 348 domSearch.addEventListener('keydown', onSearchKeyDown, false); 349 domPrivDeclsBox.addEventListener('change', function() { 350 if (this.checked != curNav.showPrivDecls) { 351 if (this.checked && location.hash.length > 1 && location.hash[1] != '*'){ 352 location.hash = "#*" + location.hash.substring(1); 353 return; 354 } 355 if (!this.checked && location.hash.length > 1 && location.hash[1] == '*') { 356 location.hash = "#" + location.hash.substring(2); 357 return; 358 } 359 } 360 }, false); 361 window.addEventListener('hashchange', onHashChange, false); 362 window.addEventListener('keydown', onWindowKeyDown, false); 363 onHashChange(); 364 365 function renderTitle() { 366 let list = curNav.pkgNames.concat(curNav.declNames); 367 let suffix = " - Zig"; 368 if (list.length === 0) { 369 if (rootIsStd) { 370 document.title = "std" + suffix; 371 } else { 372 document.title = zigAnalysis.params.rootName + suffix; 373 } 374 } else { 375 document.title = list.join('.') + suffix; 376 } 377 } 378 379 /** @param {Type | Decl} x */ 380 function isDecl(x) { 381 return "value" in x; 382 } 383 384 /** @param {Type | Decl} x */ 385 function isType(x) { 386 return "kind" in x && !("value" in x); 387 } 388 389 /** @param {Type | Decl} x */ 390 function isContainerType(x) { 391 return isType(x) && typeKindIsContainer(/** @type {Type} */(x).kind) ; 392 } 393 394 /** @param {Expr} expr */ 395 function typeShorthandName(expr) { 396 let resolvedExpr = resolveValue({expr: expr}); 397 if (!("type" in resolvedExpr)) { 398 return null; 399 } 400 let type = /** @type {Type} */(zigAnalysis.types[resolvedExpr.type]); 401 402 outer: for (let i = 0; i < 10000; i += 1) { 403 switch (type.kind) { 404 case typeKinds.Optional: 405 case typeKinds.Pointer: 406 let child = /** @type {PointerType | OptionalType} */(type).child; 407 let resolvedChild = resolveValue(child); 408 if ("type" in resolvedChild) { 409 type = zigAnalysis.types[resolvedChild.type]; 410 continue; 411 } else { 412 return null; 413 } 414 default: 415 break outer; 416 } 417 418 if (i == 9999) throw "Exhausted typeShorthandName quota"; 419 } 420 421 422 423 let name = undefined; 424 if (type.kind === typeKinds.Struct) { 425 name = "struct"; 426 } else if (type.kind === typeKinds.Enum) { 427 name = "enum"; 428 } else if (type.kind === typeKinds.Union) { 429 name = "union"; 430 } else { 431 console.log("TODO: unhalndled case in typeShortName"); 432 return null; 433 } 434 435 return escapeHtml(name); 436 } 437 438 /** @param {number} typeKind */ 439 function typeKindIsContainer(typeKind) { 440 return typeKind === typeKinds.Struct || 441 typeKind === typeKinds.Union || 442 typeKind === typeKinds.Enum; 443 } 444 445 /** @param {number} typeKind */ 446 function declCanRepresentTypeKind(typeKind) { 447 return typeKind === typeKinds.ErrorSet || typeKindIsContainer(typeKind); 448 } 449 450 // /** 451 // * @param {WalkResult[]} path 452 // * @return {WalkResult | null} 453 // */ 454 // function findCteInRefPath(path) { 455 // for (let i = path.length - 1; i >= 0; i -= 1) { 456 // const ref = path[i]; 457 // if ("string" in ref) continue; 458 // if ("comptimeExpr" in ref) return ref; 459 // if ("refPath" in ref) return findCteInRefPath(ref.refPath); 460 // return null; 461 // } 462 463 // return null; 464 // } 465 466 /** 467 * @param {WalkResult} value 468 * @return {WalkResult} 469 */ 470 function resolveValue(value) { 471 let i = 0; 472 while(i < 1000) { 473 i += 1; 474 475 if ("refPath" in value.expr) { 476 value = {expr: value.expr.refPath[value.expr.refPath.length -1]}; 477 continue; 478 } 479 480 if ("declRef" in value.expr) { 481 value = zigAnalysis.decls[value.expr.declRef].value; 482 continue; 483 } 484 485 // if ("as" in value.expr) { 486 // value = { 487 // typeRef: zigAnalysis.exprs[value.expr.as.typeRefArg], 488 // expr: zigAnalysis.exprs[value.expr.as.exprArg], 489 // }; 490 // continue; 491 // } 492 493 return value; 494 495 } 496 console.assert(false); 497 return /** @type {WalkResult} */({}); 498 } 499 500 /** 501 * @param {Decl} decl 502 * @return {WalkResult} 503 */ 504 // function typeOfDecl(decl){ 505 // return decl.value.typeRef; 506 // 507 // let i = 0; 508 // while(i < 1000) { 509 // i += 1; 510 // console.assert(isDecl(decl)); 511 // if ("type" in decl.value) { 512 // return /** @type {WalkResult} */({ type: typeTypeId }); 513 // } 514 // 515 //// if ("string" in decl.value) { 516 //// return /** @type {WalkResult} */({ type: { 517 //// kind: typeKinds.Pointer, 518 //// size: pointerSizeEnum.One, 519 //// child: }); 520 //// } 521 // 522 // if ("refPath" in decl.value) { 523 // decl = /** @type {Decl} */({ 524 // value: decl.value.refPath[decl.value.refPath.length -1] 525 // }); 526 // continue; 527 // } 528 // 529 // if ("declRef" in decl.value) { 530 // decl = zigAnalysis.decls[decl.value.declRef]; 531 // continue; 532 // } 533 // 534 // if ("int" in decl.value) { 535 // return decl.value.int.typeRef; 536 // } 537 // 538 // if ("float" in decl.value) { 539 // return decl.value.float.typeRef; 540 // } 541 // 542 // if ("array" in decl.value) { 543 // return decl.value.array.typeRef; 544 // } 545 // 546 // if ("struct" in decl.value) { 547 // return decl.value.struct.typeRef; 548 // } 549 // 550 // if ("comptimeExpr" in decl.value) { 551 // const cte = zigAnalysis.comptimeExprs[decl.value.comptimeExpr]; 552 // return cte.typeRef; 553 // } 554 // 555 // if ("call" in decl.value) { 556 // const fn_call = zigAnalysis.calls[decl.value.call]; 557 // let fn_decl = undefined; 558 // if ("declRef" in fn_call.func) { 559 // fn_decl = zigAnalysis.decls[fn_call.func.declRef]; 560 // } else if ("refPath" in fn_call.func) { 561 // console.assert("declRef" in fn_call.func.refPath[fn_call.func.refPath.length -1]); 562 // fn_decl = zigAnalysis.decls[fn_call.func.refPath[fn_call.func.refPath.length -1].declRef]; 563 // } else throw {}; 564 // 565 // const fn_decl_value = resolveValue(fn_decl.value); 566 // console.assert("type" in fn_decl_value); //TODO handle comptimeExpr 567 // const fn_type = /** @type {Fn} */(zigAnalysis.types[fn_decl_value.type]); 568 // console.assert(fn_type.kind === typeKinds.Fn); 569 // return fn_type.ret; 570 // } 571 // 572 // if ("void" in decl.value) { 573 // return /** @type {WalkResult} */({ type: typeTypeId }); 574 // } 575 // 576 // if ("bool" in decl.value) { 577 // return /** @type {WalkResult} */({ type: typeKinds.Bool }); 578 // } 579 // 580 // console.log("TODO: handle in `typeOfDecl` more cases: ", decl); 581 // console.assert(false); 582 // throw {}; 583 // } 584 // console.assert(false); 585 // return /** @type {WalkResult} */({}); 586 // } 587 588 function render() { 589 domStatus.classList.add("hidden"); 590 domFnProto.classList.add("hidden"); 591 domSectParams.classList.add("hidden"); 592 domTldDocs.classList.add("hidden"); 593 domSectMainPkg.classList.add("hidden"); 594 domSectPkgs.classList.add("hidden"); 595 domSectTypes.classList.add("hidden"); 596 domSectTests.classList.add("hidden"); 597 domSectNamespaces.classList.add("hidden"); 598 domSectErrSets.classList.add("hidden"); 599 domSectFns.classList.add("hidden"); 600 domSectFields.classList.add("hidden"); 601 domSectSearchResults.classList.add("hidden"); 602 domSectSearchNoResults.classList.add("hidden"); 603 domSectInfo.classList.add("hidden"); 604 domHdrName.classList.add("hidden"); 605 domSectNav.classList.add("hidden"); 606 domSectFnErrors.classList.add("hidden"); 607 domFnExamples.classList.add("hidden"); 608 domFnNoExamples.classList.add("hidden"); 609 domDeclNoRef.classList.add("hidden"); 610 domFnErrorsAnyError.classList.add("hidden"); 611 domTableFnErrors.classList.add("hidden"); 612 domSectGlobalVars.classList.add("hidden"); 613 domSectValues.classList.add("hidden"); 614 615 renderTitle(); 616 renderInfo(); 617 renderPkgList(); 618 619 domPrivDeclsBox.checked = curNav.showPrivDecls; 620 621 if (curNavSearch !== "") { 622 return renderSearch(); 623 } 624 625 let rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg]; 626 let pkg = rootPkg; 627 curNav.pkgObjs = [pkg]; 628 for (let i = 0; i < curNav.pkgNames.length; i += 1) { 629 let childPkg = zigAnalysis.packages[pkg.table[curNav.pkgNames[i]]]; 630 if (childPkg == null) { 631 return render404(); 632 } 633 pkg = childPkg; 634 curNav.pkgObjs.push(pkg); 635 } 636 637 /** @type {Decl | Type} */ 638 let currentType = zigAnalysis.types[pkg.main]; 639 curNav.declObjs = [currentType]; 640 for (let i = 0; i < curNav.declNames.length; i += 1) { 641 642 /** @type {Decl | Type | null} */ 643 let childDecl = findSubDecl(/** @type {ContainerType} */(currentType), curNav.declNames[i]); 644 if (childDecl == null) { 645 return render404(); 646 } 647 648 let childDeclValue = resolveValue(/** @type {Decl} */(childDecl).value).expr; 649 if ("type" in childDeclValue) { 650 651 const t = zigAnalysis.types[childDeclValue.type]; 652 if (t.kind != typeKinds.Fn) { 653 childDecl = t; 654 } 655 } 656 657 currentType = /** @type {Decl | Type} */(childDecl); 658 curNav.declObjs.push(currentType); 659 } 660 661 renderNav(); 662 663 let last = curNav.declObjs[curNav.declObjs.length - 1]; 664 let lastIsDecl = isDecl(last); 665 let lastIsType = isType(last); 666 let lastIsContainerType = isContainerType(last); 667 668 if (lastIsContainerType) { 669 return renderContainer(/** @type {ContainerType} */(last)); 670 } 671 672 if (!lastIsDecl && !lastIsType) { 673 return renderUnknownDecl(/** @type {Decl} */(last)); 674 } 675 676 if (lastIsType) { 677 return renderType(/** @type {Type} */(last)); 678 } 679 680 if (lastIsDecl && last.kind === 'var') { 681 return renderVar(/** @type {Decl} */(last)); 682 } 683 684 if (lastIsDecl && last.kind === 'const') { 685 let typeObj = zigAnalysis.types[resolveValue(/** @type {Decl} */(last).value).expr.type]; 686 if (typeObj && typeObj.kind === typeKinds.Fn) { 687 return renderFn(/** @type {Decl} */(last)); 688 } 689 690 return renderValue(/** @type {Decl} */(last)); 691 } 692 } 693 694 /** @param {Decl} decl */ 695 function renderUnknownDecl(decl) { 696 domDeclNoRef.classList.remove("hidden"); 697 698 let docs = zigAnalysis.astNodes[decl.src].docs; 699 if (docs != null) { 700 domTldDocs.innerHTML = markdown(docs); 701 } else { 702 domTldDocs.innerHTML = '<p>There are no doc comments for this declaration.</p>'; 703 } 704 domTldDocs.classList.remove("hidden"); 705 } 706 707 /** @param {number} typeIndex */ 708 function typeIsErrSet(typeIndex) { 709 let typeObj = zigAnalysis.types[typeIndex]; 710 return typeObj.kind === typeKinds.ErrorSet; 711 } 712 713 /** @param {number} typeIndex */ 714 function typeIsStructWithNoFields(typeIndex) { 715 let typeObj = zigAnalysis.types[typeIndex]; 716 if (typeObj.kind !== typeKinds.Struct) 717 return false; 718 return /** @type {ContainerType} */(typeObj).fields.length == 0; 719 } 720 721 /** @param {number} typeIndex */ 722 function typeIsGenericFn(typeIndex) { 723 let typeObj = zigAnalysis.types[typeIndex]; 724 if (typeObj.kind !== typeKinds.Fn) { 725 return false; 726 } 727 return /** @type {Fn} */(typeObj).generic; 728 } 729 730 /** @param {Decl} fnDecl */ 731 function renderFn(fnDecl) { 732 if ("refPath" in fnDecl.value.expr) { 733 let last = fnDecl.value.expr.refPath.length - 1; 734 let lastExpr = fnDecl.value.expr.refPath[last]; 735 console.assert("declRef" in lastExpr); 736 fnDecl = zigAnalysis.decls[lastExpr.declRef]; 737 } 738 739 let value = resolveValue(fnDecl.value); 740 console.assert("type" in value.expr); 741 let typeObj = /** @type {Fn} */(zigAnalysis.types[value.expr.type]); 742 743 domFnProtoCode.innerHTML = exprName(value.expr, { 744 wantHtml: true, 745 wantLink: true, 746 fnDecl, 747 }); 748 749 let docsSource = null; 750 let srcNode = zigAnalysis.astNodes[fnDecl.src]; 751 if (srcNode.docs != null) { 752 docsSource = srcNode.docs; 753 } 754 755 renderFnParamDocs(fnDecl, typeObj); 756 757 let retExpr = resolveValue({expr:typeObj.ret}).expr; 758 if ("type" in retExpr) { 759 let retIndex = retExpr.type; 760 let errSetTypeIndex = /** @type {number | null} */(null); 761 let retType = zigAnalysis.types[retIndex]; 762 if (retType.kind === typeKinds.ErrorSet) { 763 errSetTypeIndex = retIndex; 764 } else if (retType.kind === typeKinds.ErrorUnion) { 765 errSetTypeIndex = /** @type {ErrUnionType} */(retType).err.type; 766 } 767 if (errSetTypeIndex != null) { 768 let errSetType = /** @type {ErrSetType} */(zigAnalysis.types[errSetTypeIndex]); 769 renderErrorSet(errSetType); 770 } 771 } 772 773 let protoSrcIndex = fnDecl.src; 774 if (typeIsGenericFn(value.expr.type)) { 775 throw "TODO"; 776 // let instantiations = nodesToFnsMap[protoSrcIndex]; 777 // let calls = nodesToCallsMap[protoSrcIndex]; 778 // if (instantiations == null && calls == null) { 779 // domFnNoExamples.classList.remove("hidden"); 780 // } else if (calls != null) { 781 // // if (fnObj.combined === undefined) fnObj.combined = allCompTimeFnCallsResult(calls); 782 // if (fnObj.combined != null) renderContainer(fnObj.combined); 783 784 // resizeDomList(domListFnExamples, calls.length, '<li></li>'); 785 786 // for (let callI = 0; callI < calls.length; callI += 1) { 787 // let liDom = domListFnExamples.children[callI]; 788 // liDom.innerHTML = getCallHtml(fnDecl, calls[callI]); 789 // } 790 791 // domFnExamples.classList.remove("hidden"); 792 // } else if (instantiations != null) { 793 // // TODO 794 // } 795 } else { 796 797 domFnExamples.classList.add("hidden"); 798 domFnNoExamples.classList.add("hidden"); 799 } 800 801 let protoSrcNode = zigAnalysis.astNodes[protoSrcIndex]; 802 if (docsSource == null && protoSrcNode != null && protoSrcNode.docs != null) { 803 docsSource = protoSrcNode.docs; 804 } 805 if (docsSource != null) { 806 domTldDocs.innerHTML = markdown(docsSource); 807 domTldDocs.classList.remove("hidden"); 808 } 809 domFnProto.classList.remove("hidden"); 810 } 811 812 /** 813 * @param {Decl} fnDecl 814 * @param {Fn} typeObj 815 */ 816 function renderFnParamDocs(fnDecl, typeObj) { 817 let docCount = 0; 818 819 let fnNode = zigAnalysis.astNodes[fnDecl.src]; 820 let fields = /** @type {number[]} */(fnNode.fields); 821 let isVarArgs = fnNode.varArgs; 822 823 for (let i = 0; i < fields.length; i += 1) { 824 let field = fields[i]; 825 let fieldNode = zigAnalysis.astNodes[field]; 826 if (fieldNode.docs != null) { 827 docCount += 1; 828 } 829 } 830 if (docCount == 0) { 831 return; 832 } 833 834 resizeDomList(domListParams, docCount, '<div></div>'); 835 let domIndex = 0; 836 837 for (let i = 0; i < fields.length; i += 1) { 838 let field = fields[i]; 839 let fieldNode = zigAnalysis.astNodes[field]; 840 if (fieldNode.docs == null) { 841 continue; 842 } 843 let divDom = domListParams.children[domIndex]; 844 domIndex += 1; 845 846 847 let value = typeObj.params[i]; 848 let html = '<pre>' + escapeHtml(/** @type {string} */(fieldNode.name)) + ": "; 849 if (isVarArgs && i === typeObj.params.length - 1) { 850 html += '...'; 851 } else { 852 let name = exprName(value, {wantHtml: false, wantLink: false}); 853 html += '<span class="tok-kw">' + name + '</span>'; 854 } 855 856 html += ',</pre>'; 857 858 let docs = fieldNode.docs; 859 if (docs != null) { 860 html += markdown(docs); 861 } 862 divDom.innerHTML = html; 863 } 864 domSectParams.classList.remove("hidden"); 865 } 866 867 function renderNav() { 868 let len = curNav.pkgNames.length + curNav.declNames.length; 869 resizeDomList(domListNav, len, '<li><a href="#"></a></li>'); 870 let list = []; 871 let hrefPkgNames = []; 872 let hrefDeclNames = /** @type {string[]} */([]); 873 for (let i = 0; i < curNav.pkgNames.length; i += 1) { 874 hrefPkgNames.push(curNav.pkgNames[i]); 875 list.push({ 876 name: curNav.pkgNames[i], 877 link: navLink(hrefPkgNames, hrefDeclNames), 878 }); 879 } 880 for (let i = 0; i < curNav.declNames.length; i += 1) { 881 hrefDeclNames.push(curNav.declNames[i]); 882 list.push({ 883 name: curNav.declNames[i], 884 link: navLink(hrefPkgNames, hrefDeclNames), 885 }); 886 } 887 888 for (let i = 0; i < list.length; i += 1) { 889 let liDom = domListNav.children[i]; 890 let aDom = liDom.children[0]; 891 aDom.textContent = list[i].name; 892 aDom.setAttribute('href', list[i].link); 893 if (i + 1 == list.length) { 894 aDom.classList.add("active"); 895 } else { 896 aDom.classList.remove("active"); 897 } 898 } 899 900 domSectNav.classList.remove("hidden"); 901 } 902 903 function renderInfo() { 904 domTdZigVer.textContent = zigAnalysis.params.zigVersion; 905 //domTdTarget.textContent = zigAnalysis.params.builds[0].target; 906 907 domSectInfo.classList.remove("hidden"); 908 } 909 910 function render404() { 911 domStatus.textContent = "404 Not Found"; 912 domStatus.classList.remove("hidden"); 913 } 914 915 function renderPkgList() { 916 let rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg]; 917 let list = []; 918 for (let key in rootPkg.table) { 919 let pkgIndex = rootPkg.table[key]; 920 if (zigAnalysis.packages[pkgIndex] == null) continue; 921 list.push({ 922 name: key, 923 pkg: pkgIndex, 924 }); 925 } 926 927 { 928 let aDom = domSectMainPkg.children[1].children[0].children[0]; 929 aDom.textContent = zigAnalysis.params.rootName; 930 aDom.setAttribute('href', navLinkPkg(zigAnalysis.rootPkg)); 931 if (zigAnalysis.params.rootName === curNav.pkgNames[0]) { 932 aDom.classList.add("active"); 933 } else { 934 aDom.classList.remove("active"); 935 } 936 domSectMainPkg.classList.remove("hidden"); 937 } 938 939 list.sort(function(a, b) { 940 return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase()); 941 }); 942 943 if (list.length !== 0) { 944 resizeDomList(domListPkgs, list.length, '<li><a href="#"></a></li>'); 945 for (let i = 0; i < list.length; i += 1) { 946 let liDom = domListPkgs.children[i]; 947 let aDom = liDom.children[0]; 948 aDom.textContent = list[i].name; 949 aDom.setAttribute('href', navLinkPkg(list[i].pkg)); 950 if (list[i].name === curNav.pkgNames[0]) { 951 aDom.classList.add("active"); 952 } else { 953 aDom.classList.remove("active"); 954 } 955 } 956 957 domSectPkgs.classList.remove("hidden"); 958 } 959 } 960 961 /** 962 * @param {string[]} pkgNames 963 * @param {string[]} declNames 964 * @param {string} [callName] 965 */ 966 967 function navLink(pkgNames, declNames, callName) { 968 let base = '#'; 969 if (curNav.showPrivDecls) { 970 base += "*"; 971 } 972 973 if (pkgNames.length === 0 && declNames.length === 0) { 974 return base; 975 } else if (declNames.length === 0 && callName == null) { 976 return base + pkgNames.join('.'); 977 } else if (callName == null) { 978 return base + pkgNames.join('.') + ';' + declNames.join('.'); 979 } else { 980 return base + pkgNames.join('.') + ';' + declNames.join('.') + ';' + callName; 981 } 982 } 983 984 /** @param {number} pkgIndex */ 985 function navLinkPkg(pkgIndex) { 986 return navLink(canonPkgPaths[pkgIndex], []); 987 } 988 989 /** @param {string} childName */ 990 function navLinkDecl(childName) { 991 return navLink(curNav.pkgNames, curNav.declNames.concat([childName])); 992 } 993 994 // /** @param {Call} callObj */ 995 // function navLinkCall(callObj) { 996 // let declNamesCopy = curNav.declNames.concat([]); 997 // let callName = /** @type {string} */(declNamesCopy.pop()); 998 999 // callName += '('; 1000 // for (let arg_i = 0; arg_i < callObj.args.length; arg_i += 1) { 1001 // if (arg_i !== 0) callName += ','; 1002 // let argObj = callObj.args[arg_i]; 1003 // callName += getValueText(argObj, argObj, false, false); 1004 // } 1005 // callName += ')'; 1006 1007 // declNamesCopy.push(callName); 1008 // return navLink(curNav.pkgNames, declNamesCopy); 1009 // } 1010 1011 /** 1012 * @param {any} dlDom 1013 * @param {number} desiredLen 1014 */ 1015 function resizeDomListDl(dlDom, desiredLen) { 1016 // add the missing dom entries 1017 for (let i = dlDom.childElementCount / 2; i < desiredLen; i += 1) { 1018 dlDom.insertAdjacentHTML('beforeend', '<dt></dt><dd></dd>'); 1019 } 1020 // remove extra dom entries 1021 while (desiredLen < dlDom.childElementCount / 2) { 1022 dlDom.removeChild(dlDom.lastChild); 1023 dlDom.removeChild(dlDom.lastChild); 1024 } 1025 } 1026 1027 /** 1028 * @param {any} listDom 1029 * @param {number} desiredLen 1030 * @param {string} templateHtml 1031 */ 1032 function resizeDomList(listDom, desiredLen, templateHtml) { 1033 // add the missing dom entries 1034 for (let i = listDom.childElementCount; i < desiredLen; i += 1) { 1035 listDom.insertAdjacentHTML('beforeend', templateHtml); 1036 } 1037 // remove extra dom entries 1038 while (desiredLen < listDom.childElementCount) { 1039 listDom.removeChild(listDom.lastChild); 1040 } 1041 } 1042 /** 1043 * @param {WalkResult} wr, 1044 * @return {Expr} 1045 */ 1046 function walkResultTypeRef(wr) { 1047 if (wr.typeRef) return wr.typeRef; 1048 let resolved = resolveValue(wr); 1049 if (wr === resolved) { 1050 return {type: 0}; 1051 } 1052 return walkResultTypeRef(resolved); 1053 } 1054 /** 1055 * @typedef {{ 1056 wantHtml: boolean, 1057 }} RenderWrOptions 1058 * @param {Expr} expr, 1059 * @param {RenderWrOptions} opts, 1060 * @return {string} 1061 */ 1062 function exprName(expr, opts) { 1063 switch (Object.keys(expr)[0]) { 1064 default: throw "oh no"; 1065 case "errorUnion": { 1066 const errUnionObj = zigAnalysis.types[expr.errorUnion]; 1067 let lhs = exprName(errUnionObj.lhs, opts); 1068 let rhs = exprName(errUnionObj.rhs, opts); 1069 return lhs + "!" + rhs; 1070 1071 } 1072 case "struct": { 1073 const struct_name = zigAnalysis.decls[expr.struct[0].val.typeRef.refPath[0].declRef].name; 1074 let struct_body = ""; 1075 struct_body += struct_name + "{ "; 1076 for (let i = 0; i < expr.struct.length; i++) { 1077 const val = expr.struct[i].name 1078 const exprArg = zigAnalysis.exprs[expr.struct[i].val.expr.as.exprArg]; 1079 let value_field = exprArg[Object.keys(exprArg)[0]]; 1080 if (value_field instanceof Object) { 1081 value_field = zigAnalysis.decls[value_field[0].val.typeRef.refPath[0].declRef].name; 1082 }; 1083 struct_body += "." + val + " = " + value_field; 1084 if (i !== expr.struct.length - 1) { 1085 struct_body += ", "; 1086 } else { 1087 struct_body += " "; 1088 } 1089 } 1090 struct_body += "}"; 1091 return struct_body; 1092 } 1093 case "typeOf_peer": { 1094 let payloadHtml = "@TypeOf(" 1095 for (let i = 0; i < expr.typeOf_peer.length; i++) { 1096 let elem = zigAnalysis.exprs[expr.typeOf_peer[i]]; 1097 payloadHtml += exprName(elem, {wantHtml: true, wantLink:true}); 1098 if (i !== expr.typeOf_peer.length - 1) { 1099 payloadHtml += ", "; 1100 } 1101 } 1102 payloadHtml += ")"; 1103 return payloadHtml; 1104 1105 } 1106 case "typeOf": { 1107 const typeRefArg = zigAnalysis.exprs[expr.typeOf]; 1108 let payloadHtml = "@TypeOf(" + exprName(typeRefArg, {wantHtml: true, wantLink:true}) + ")"; 1109 return payloadHtml; 1110 } 1111 case "null": { 1112 return "null"; 1113 } 1114 case "array": { 1115 let payloadHtml = ".{"; 1116 for (let i = 0; i < expr.array.length; i++) { 1117 if (i != 0) payloadHtml += ", "; 1118 let elem = zigAnalysis.exprs[expr.array[i]]; 1119 payloadHtml += exprName(elem, opts); 1120 } 1121 return payloadHtml + "}"; 1122 } 1123 case "comptimeExpr": { 1124 return zigAnalysis.comptimeExprs[expr.comptimeExpr].code; 1125 } 1126 case "call": { 1127 let call = zigAnalysis.calls[expr.call]; 1128 let payloadHtml = ""; 1129 1130 1131 switch(Object.keys(call.func)[0]){ 1132 default: throw "TODO"; 1133 case "declRef": 1134 case "refPath": { 1135 payloadHtml += exprName(call.func, opts); 1136 break; 1137 } 1138 } 1139 payloadHtml += "("; 1140 1141 for (let i = 0; i < call.args.length; i++) { 1142 if (i != 0) payloadHtml += ", "; 1143 payloadHtml += exprName(call.args[i], opts); 1144 } 1145 1146 payloadHtml += ")"; 1147 return payloadHtml; 1148 } 1149 case "as": { 1150 const typeRefArg = zigAnalysis.exprs[expr.as.typeRefArg]; 1151 const exprArg = zigAnalysis.exprs[expr.as.exprArg]; 1152 return "@as(" + exprName(typeRefArg, opts) + 1153 ", " + exprName(exprArg, opts) + ")"; 1154 } 1155 case "declRef": { 1156 return zigAnalysis.decls[expr.declRef].name; 1157 } 1158 case "refPath": { 1159 return expr.refPath.map(x => exprName(x, opts)).join("."); 1160 } 1161 case "int": { 1162 return "" + expr.int; 1163 } 1164 case "string": { 1165 return "\"" + escapeHtml(expr.string) + "\""; 1166 } 1167 1168 case "anytype": { 1169 return "anytype"; 1170 } 1171 1172 case "this":{ 1173 return "this"; 1174 } 1175 1176 case "type": { 1177 let name = ""; 1178 1179 let typeObj = expr.type; 1180 if (typeof typeObj === 'number') typeObj = zigAnalysis.types[typeObj]; 1181 switch (typeObj.kind) { 1182 default: throw "TODO"; 1183 case typeKinds.Unanalyzed: 1184 { 1185 return "Unanalyzed"; 1186 } 1187 case typeKinds.ComptimeExpr: 1188 { 1189 return "anyopaque"; 1190 } 1191 case typeKinds.Array: 1192 { 1193 let arrayObj = /** @type {ArrayType} */ (typeObj); 1194 let name = "["; 1195 let lenName = exprName(arrayObj.len, opts); 1196 let sentinel = arrayObj.sentinel ? ":"+exprName(arrayObj.sentinel, opts) : ""; 1197 // let is_mutable = arrayObj.is_multable ? "const " : ""; 1198 1199 if (opts.wantHtml) { 1200 name += 1201 '<span class="tok-number">' + lenName + sentinel + "</span>"; 1202 } else { 1203 name += lenName + sentinel; 1204 } 1205 name += "]"; 1206 // name += is_mutable; 1207 name += exprName(arrayObj.child, opts); 1208 return name; 1209 } 1210 case typeKinds.Optional: 1211 return "?" + exprName(/**@type {OptionalType} */(typeObj).child, opts); 1212 case typeKinds.Pointer: 1213 { 1214 let ptrObj = /** @type {PointerType} */(typeObj); 1215 let sentinel = ptrObj.sentinel ? ":"+exprName(ptrObj.sentinel, opts) : ""; 1216 let is_mutable = !ptrObj.is_mutable ? "const " : ""; 1217 let name = ""; 1218 switch (ptrObj.size) { 1219 default: 1220 console.log("TODO: implement unhandled pointer size case"); 1221 case pointerSizeEnum.One: 1222 name += "*"; 1223 name += is_mutable; 1224 break; 1225 case pointerSizeEnum.Many: 1226 name += "[*"; 1227 name += sentinel; 1228 name += "]"; 1229 name += is_mutable; 1230 break; 1231 case pointerSizeEnum.Slice: 1232 name += "["; 1233 name += sentinel; 1234 name += "]"; 1235 name += is_mutable; 1236 break; 1237 case pointerSizeEnum.C: 1238 name += "[*c"; 1239 name += sentinel; 1240 name += "]"; 1241 name += is_mutable; 1242 break; 1243 } 1244 // @check: after the major changes in arrays the consts are came from switch above 1245 // if (!ptrObj.is_mutable) { 1246 // if (opts.wantHtml) { 1247 // name += '<span class="tok-kw">const</span> '; 1248 // } else { 1249 // name += "const "; 1250 // } 1251 // } 1252 if (ptrObj.is_allowzero) { 1253 name += "allowzero "; 1254 } 1255 if (ptrObj.is_volatile) { 1256 name += "volatile "; 1257 } 1258 if (ptrObj.has_addrspace) { 1259 name += "addrspace("; 1260 name += "." + ""; 1261 name += ") "; 1262 } 1263 if (ptrObj.has_align) { 1264 if (opts.wantHtml) { 1265 name += '<span class="tok-kw">align</span>('; 1266 } else { 1267 name += "align("; 1268 } 1269 if (opts.wantHtml) { 1270 name += '<span class="tok-number">' + ptrObj.align + '</span>'; 1271 } else { 1272 name += ptrObj.align; 1273 } 1274 if (ptrObj.hostIntBytes != null) { 1275 name += ":"; 1276 if (opts.wantHtml) { 1277 name += '<span class="tok-number">' + ptrObj.bitOffsetInHost + '</span>'; 1278 } else { 1279 name += ptrObj.bitOffsetInHost; 1280 } 1281 name += ":"; 1282 if (opts.wantHtml) { 1283 name += '<span class="tok-number">' + ptrObj.hostIntBytes + '</span>'; 1284 } else { 1285 name += ptrObj.hostIntBytes; 1286 } 1287 } 1288 name += ") "; 1289 } 1290 //name += typeValueName(ptrObj.child, wantHtml, wantSubLink, null); 1291 name += exprName(ptrObj.child, opts); 1292 return name; 1293 } 1294 case typeKinds.Float: 1295 { 1296 let floatObj = /** @type {NumberType} */ (typeObj); 1297 1298 if (opts.wantHtml) { 1299 return '<span class="tok-type">' + floatObj.name + '</span>'; 1300 } else { 1301 return floatObj.name; 1302 } 1303 } 1304 case typeKinds.Int: 1305 { 1306 let intObj = /** @type {NumberType} */(typeObj); 1307 let name = intObj.name; 1308 if (opts.wantHtml) { 1309 return '<span class="tok-type">' + name + '</span>'; 1310 } else { 1311 return name; 1312 } 1313 } 1314 case typeKinds.ComptimeInt: 1315 if (opts.wantHtml) { 1316 return '<span class="tok-type">comptime_int</span>'; 1317 } else { 1318 return "comptime_int"; 1319 } 1320 case typeKinds.ComptimeFloat: 1321 if (opts.wantHtml) { 1322 return '<span class="tok-type">comptime_float</span>'; 1323 } else { 1324 return "comptime_float"; 1325 } 1326 case typeKinds.Type: 1327 if (opts.wantHtml) { 1328 return '<span class="tok-type">type</span>'; 1329 } else { 1330 return "type"; 1331 } 1332 case typeKinds.Bool: 1333 if (opts.wantHtml) { 1334 return '<span class="tok-type">bool</span>'; 1335 } else { 1336 return "bool"; 1337 } 1338 case typeKinds.Void: 1339 if (opts.wantHtml) { 1340 return '<span class="tok-type">void</span>'; 1341 } else { 1342 return "void"; 1343 } 1344 case typeKinds.EnumLiteral: 1345 if (opts.wantHtml) { 1346 return '<span class="tok-type">(enum literal)</span>'; 1347 } else { 1348 return "(enum literal)"; 1349 } 1350 case typeKinds.NoReturn: 1351 if (opts.wantHtml) { 1352 return '<span class="tok-type">noreturn</span>'; 1353 } else { 1354 return "noreturn"; 1355 } 1356 case typeKinds.ErrorSet: 1357 { 1358 let errSetObj = /** @type {ErrSetType} */(typeObj); 1359 if (errSetObj.fields == null) { 1360 return '<span class="tok-type">anyerror</span>'; 1361 } else { 1362 // throw "TODO"; 1363 let html = "error{" + errSetObj.fields[0].name + "}"; 1364 return html; 1365 } 1366 } 1367 1368 case typeKinds.ErrorUnion: 1369 { 1370 let errUnionObj = /** @type {ErrUnionType} */(typeObj); 1371 let lhs = exprName(errUnionObj.lhs, opts); 1372 let rhs = exprName(errUnionObj.rhs, opts); 1373 return lhs + "!" + rhs; 1374 } 1375 case typeKinds.Fn: 1376 { 1377 let fnObj = /** @type {Fn} */(typeObj); 1378 let payloadHtml = ""; 1379 if (opts.wantHtml) { 1380 if (fnObj.is_extern) { 1381 payloadHtml += "pub \"extern\" "; 1382 } 1383 payloadHtml += '<span class="tok-kw">fn</span>'; 1384 if (opts.fnDecl) { 1385 payloadHtml += ' <span class="tok-fn">'; 1386 if (opts.linkFnNameDecl) { 1387 payloadHtml += '<a href="' + opts.linkFnNameDecl + '">' + 1388 escapeHtml(opts.fnDecl.name) + '</a>'; 1389 } else { 1390 payloadHtml += escapeHtml(opts.fnDecl.name); 1391 } 1392 payloadHtml += '</span>'; 1393 } 1394 } else { 1395 payloadHtml += 'fn '; 1396 } 1397 payloadHtml += '('; 1398 if (fnObj.params) { 1399 let fields = null; 1400 let isVarArgs = false; 1401 let fnNode = zigAnalysis.astNodes[fnObj.src]; 1402 fields = fnNode.fields; 1403 isVarArgs = fnNode.varArgs; 1404 1405 for (let i = 0; i < fnObj.params.length; i += 1) { 1406 if (i != 0) { 1407 payloadHtml += ', '; 1408 } 1409 1410 let value = fnObj.params[i]; 1411 let paramValue = resolveValue({expr: value}); 1412 1413 if (fields != null) { 1414 let paramNode = zigAnalysis.astNodes[fields[i]]; 1415 1416 if (paramNode.varArgs) { 1417 payloadHtml += '...'; 1418 continue; 1419 } 1420 1421 if (paramNode.noalias) { 1422 if (opts.wantHtml) { 1423 payloadHtml += '<span class="tok-kw">noalias</span> '; 1424 } else { 1425 payloadHtml += 'noalias '; 1426 } 1427 } 1428 1429 if (paramNode.comptime) { 1430 if (opts.wantHtml) { 1431 payloadHtml += '<span class="tok-kw">comptime</span> '; 1432 } else { 1433 payloadHtml += 'comptime '; 1434 } 1435 } 1436 1437 let paramName = paramNode.name; 1438 if (paramName != null) { 1439 // skip if it matches the type name 1440 if (!shouldSkipParamName(paramValue, paramName)) { 1441 payloadHtml += paramName + ': '; 1442 } 1443 } 1444 } 1445 1446 if (isVarArgs && i === fnObj.params.length - 1) { 1447 payloadHtml += '...'; 1448 } 1449 else if ("typeOf" in value) { 1450 if (opts.wantHtml) { 1451 payloadHtml += '<a href="">'; 1452 payloadHtml += 1453 '<span class="tok-kw" style="color:lightblue;">' 1454 + exprName(value, opts) + '</span>'; 1455 payloadHtml += '</a>'; 1456 } else { 1457 payloadHtml += exprName(value, opts); 1458 } 1459 1460 } 1461 else if ("typeOf_peer" in value) { 1462 if (opts.wantHtml) { 1463 payloadHtml += '<a href="">'; 1464 payloadHtml += 1465 '<span class="tok-kw" style="color:lightblue;">' 1466 + exprName(value, opts) + '</span>'; 1467 payloadHtml += '</a>'; 1468 } else { 1469 payloadHtml += exprName(value, opts); 1470 } 1471 1472 } 1473 else if ("declRef" in value) { 1474 if (opts.wantHtml) { 1475 payloadHtml += '<a href="">'; 1476 payloadHtml += 1477 '<span class="tok-kw" style="color:lightblue;">' 1478 + exprName(value, opts) + '</span>'; 1479 payloadHtml += '</a>'; 1480 } else { 1481 payloadHtml += exprName(value, opts); 1482 } 1483 1484 } 1485 else if ("call" in value) { 1486 if (opts.wantHtml) { 1487 payloadHtml += '<a href="">'; 1488 payloadHtml += 1489 '<span class="tok-kw" style="color:lightblue;">' 1490 + exprName(value, opts) + '</span>'; 1491 payloadHtml += '</a>'; 1492 } else { 1493 payloadHtml += exprName(value, opts); 1494 } 1495 } 1496 else if ("refPath" in value) { 1497 if (opts.wantHtml) { 1498 payloadHtml += '<a href="">'; 1499 payloadHtml += 1500 '<span class="tok-kw" style="color:lightblue;">' 1501 + exprName(value, opts) + '</span>'; 1502 payloadHtml += '</a>'; 1503 } else { 1504 payloadHtml += exprName(value, opts); 1505 } 1506 } else if ("type" in value) { 1507 let name = exprName(value, { 1508 wantHtml: false, 1509 wantLink: false, 1510 fnDecl: opts.fnDecl, 1511 linkFnNameDecl: opts.linkFnNameDecl, 1512 }); 1513 payloadHtml += '<span class="tok-kw">' + escapeHtml(name) + '</span>'; 1514 } else if ("comptimeExpr" in value) { 1515 let comptimeExpr = zigAnalysis.comptimeExprs[value.comptimeExpr].code; 1516 if (opts.wantHtml) { 1517 payloadHtml += '<span class="tok-kw">' + comptimeExpr + '</span>'; 1518 } else { 1519 payloadHtml += comptimeExpr; 1520 } 1521 } else if (opts.wantHtml) { 1522 payloadHtml += '<span class="tok-kw">anytype</span>'; 1523 } else { 1524 payloadHtml += 'anytype'; 1525 } 1526 } 1527 } 1528 1529 payloadHtml += ') '; 1530 if (fnObj.has_cc) { 1531 let cc = zigAnalysis.types[fnObj.cc] 1532 payloadHtml += "callconv(." + cc.name + ") "; 1533 } 1534 1535 if (fnObj.is_inferred_error) { 1536 payloadHtml += "!"; 1537 } 1538 if (fnObj.ret != null) { 1539 payloadHtml += exprName(fnObj.ret, opts); 1540 } else if (opts.wantHtml) { 1541 payloadHtml += '<span class="tok-kw">anytype</span>'; 1542 } else { 1543 payloadHtml += 'anytype'; 1544 } 1545 return payloadHtml; 1546 } 1547 // if (wantHtml) { 1548 // return escapeHtml(typeObj.name); 1549 // } else { 1550 // return typeObj.name; 1551 // } 1552 } 1553 } 1554 1555 } 1556 } 1557 1558 1559 /** 1560 * @param {Expr} typeRef 1561 * @param {string} paramName 1562 */ 1563 function shouldSkipParamName(typeRef, paramName) { 1564 let resolvedTypeRef = resolveValue({expr: typeRef}); 1565 if ("type" in resolvedTypeRef) { 1566 let typeObj = zigAnalysis.types[resolvedTypeRef.type]; 1567 if (typeObj.kind === typeKinds.Pointer){ 1568 let ptrObj = /** @type {PointerType} */(typeObj); 1569 if (getPtrSize(ptrObj) === pointerSizeEnum.One) { 1570 const value = resolveValue(ptrObj.child); 1571 return typeValueName(value, false, true).toLowerCase() === paramName; 1572 } 1573 } 1574 } 1575 return false; 1576 } 1577 1578 /** @param {PointerType} typeObj */ 1579 function getPtrSize(typeObj) { 1580 return (typeObj.size == null) ? pointerSizeEnum.One : typeObj.size; 1581 } 1582 1583 /** @param {Type} typeObj */ 1584 function renderType(typeObj) { 1585 let name; 1586 if (rootIsStd && typeObj === zigAnalysis.types[zigAnalysis.packages[zigAnalysis.rootPkg].main]) { 1587 name = "std"; 1588 } else { 1589 name = exprName({type:typeObj}, false, false); 1590 } 1591 if (name != null && name != "") { 1592 domHdrName.innerText = name + " (" + zigAnalysis.typeKinds[typeObj.kind] + ")"; 1593 domHdrName.classList.remove("hidden"); 1594 } 1595 if (typeObj.kind == typeKinds.ErrorSet) { 1596 renderErrorSet(/** @type {ErrSetType} */(typeObj)); 1597 } 1598 } 1599 1600 /** @param {ErrSetType} errSetType */ 1601 function renderErrorSet(errSetType) { 1602 if (errSetType.fields == null) { 1603 domFnErrorsAnyError.classList.remove("hidden"); 1604 } else { 1605 let errorList = []; 1606 for (let i = 0; i < errSetType.fields.length; i += 1) { 1607 let errObj = errSetType.fields[i]; 1608 //let srcObj = zigAnalysis.astNodes[errObj.src]; 1609 errorList.push(errObj); 1610 } 1611 errorList.sort(function(a, b) { 1612 return operatorCompare(a.name.toLowerCase(), b.name.toLowerCase()); 1613 }); 1614 1615 resizeDomListDl(domListFnErrors, errorList.length); 1616 for (let i = 0; i < errorList.length; i += 1) { 1617 let nameTdDom = domListFnErrors.children[i * 2 + 0]; 1618 let descTdDom = domListFnErrors.children[i * 2 + 1]; 1619 nameTdDom.textContent = errorList[i].name; 1620 let docs = errorList[i].docs; 1621 if (docs != null) { 1622 descTdDom.innerHTML = markdown(docs); 1623 } else { 1624 descTdDom.textContent = ""; 1625 } 1626 } 1627 domTableFnErrors.classList.remove("hidden"); 1628 } 1629 domSectFnErrors.classList.remove("hidden"); 1630 } 1631 1632 // function allCompTimeFnCallsHaveTypeResult(typeIndex, value) { 1633 // let srcIndex = zigAnalysis.fns[value].src; 1634 // let calls = nodesToCallsMap[srcIndex]; 1635 // if (calls == null) return false; 1636 // for (let i = 0; i < calls.length; i += 1) { 1637 // let call = zigAnalysis.calls[calls[i]]; 1638 // if (call.result.type !== typeTypeId) return false; 1639 // } 1640 // return true; 1641 // } 1642 // 1643 // function allCompTimeFnCallsResult(calls) { 1644 // let firstTypeObj = null; 1645 // let containerObj = { 1646 // privDecls: [], 1647 // }; 1648 // for (let callI = 0; callI < calls.length; callI += 1) { 1649 // let call = zigAnalysis.calls[calls[callI]]; 1650 // if (call.result.type !== typeTypeId) return null; 1651 // let typeObj = zigAnalysis.types[call.result.value]; 1652 // if (!typeKindIsContainer(typeObj.kind)) return null; 1653 // if (firstTypeObj == null) { 1654 // firstTypeObj = typeObj; 1655 // containerObj.src = typeObj.src; 1656 // } else if (firstTypeObj.src !== typeObj.src) { 1657 // return null; 1658 // } 1659 // 1660 // if (containerObj.fields == null) { 1661 // containerObj.fields = (typeObj.fields || []).concat([]); 1662 // } else for (let fieldI = 0; fieldI < typeObj.fields.length; fieldI += 1) { 1663 // let prev = containerObj.fields[fieldI]; 1664 // let next = typeObj.fields[fieldI]; 1665 // if (prev === next) continue; 1666 // if (typeof(prev) === 'object') { 1667 // if (prev[next] == null) prev[next] = typeObj; 1668 // } else { 1669 // containerObj.fields[fieldI] = {}; 1670 // containerObj.fields[fieldI][prev] = firstTypeObj; 1671 // containerObj.fields[fieldI][next] = typeObj; 1672 // } 1673 // } 1674 // 1675 // if (containerObj.pubDecls == null) { 1676 // containerObj.pubDecls = (typeObj.pubDecls || []).concat([]); 1677 // } else for (let declI = 0; declI < typeObj.pubDecls.length; declI += 1) { 1678 // let prev = containerObj.pubDecls[declI]; 1679 // let next = typeObj.pubDecls[declI]; 1680 // if (prev === next) continue; 1681 // // TODO instead of showing "examples" as the public declarations, 1682 // // do logic like this: 1683 // //if (typeof(prev) !== 'object') { 1684 // // let newDeclId = zigAnalysis.decls.length; 1685 // // prev = clone(zigAnalysis.decls[prev]); 1686 // // prev.id = newDeclId; 1687 // // zigAnalysis.decls.push(prev); 1688 // // containerObj.pubDecls[declI] = prev; 1689 // //} 1690 // //mergeDecls(prev, next, firstTypeObj, typeObj); 1691 // } 1692 // } 1693 // for (let declI = 0; declI < containerObj.pubDecls.length; declI += 1) { 1694 // let decl = containerObj.pubDecls[declI]; 1695 // if (typeof(decl) === 'object') { 1696 // containerObj.pubDecls[declI] = containerObj.pubDecls[declI].id; 1697 // } 1698 // } 1699 // return containerObj; 1700 // } 1701 1702 1703 1704 /** @param {Decl} decl */ 1705 function renderValue(decl) { 1706 let resolvedValue = resolveValue(decl.value) 1707 1708 domFnProtoCode.innerHTML = '<span class="tok-kw">const</span> ' + 1709 escapeHtml(decl.name) + ': ' + exprName(resolvedValue.typeRef, {wantHtml: true, wantLink:true}) + 1710 " = " + exprName(decl.value.expr, {wantHtml: true, wantLink:true}) + ";"; 1711 1712 let docs = zigAnalysis.astNodes[decl.src].docs; 1713 if (docs != null) { 1714 domTldDocs.innerHTML = markdown(docs); 1715 domTldDocs.classList.remove("hidden"); 1716 } 1717 1718 domFnProto.classList.remove("hidden"); 1719 } 1720 1721 /** @param {Decl} decl */ 1722 function renderVar(decl) { 1723 let declTypeRef = typeOfDecl(decl); 1724 domFnProtoCode.innerHTML = '<span class="tok-kw">var</span> ' + 1725 escapeHtml(decl.name) + ': ' + typeValueName(declTypeRef, true, true); 1726 1727 let docs = zigAnalysis.astNodes[decl.src].docs; 1728 if (docs != null) { 1729 domTldDocs.innerHTML = markdown(docs); 1730 domTldDocs.classList.remove("hidden"); 1731 } 1732 1733 domFnProto.classList.remove("hidden"); 1734 } 1735 1736 1737 /** 1738 * @param {number[]} decls 1739 * @param {Decl[]} typesList 1740 * @param {Decl[]} namespacesList, 1741 * @param {Decl[]} errSetsList, 1742 * @param {Decl[]} fnsList, 1743 * @param {Decl[]} varsList, 1744 * @param {Decl[]} valsList, 1745 * @param {Decl[]} testsList 1746 */ 1747 function categorizeDecls(decls, 1748 typesList, namespacesList, errSetsList, 1749 fnsList, varsList, valsList, testsList) { 1750 1751 for (let i = 0; i < decls.length; i += 1) { 1752 let decl = zigAnalysis.decls[decls[i]]; 1753 let declValue = resolveValue(decl.value); 1754 1755 if (decl.isTest) { 1756 testsList.push(decl); 1757 continue; 1758 } 1759 1760 if (decl.kind === 'var') { 1761 varsList.push(decl); 1762 continue; 1763 } 1764 1765 if (decl.kind === 'const') { 1766 if ("type" in declValue.expr) { 1767 // We have the actual type expression at hand. 1768 const typeExpr = zigAnalysis.types[declValue.expr.type]; 1769 if (typeExpr.kind == typeKinds.Fn) { 1770 const funcRetExpr = resolveValue({ 1771 expr: /** @type {Fn} */(typeExpr).ret 1772 }); 1773 if ("type" in funcRetExpr.expr && funcRetExpr.expr.type == typeTypeId) { 1774 if (typeIsErrSet(declValue.expr.type)) { 1775 errSetsList.push(decl); 1776 } else if (typeIsStructWithNoFields(declValue.expr.type)) { 1777 namespacesList.push(decl); 1778 } else { 1779 typesList.push(decl); 1780 } 1781 } else { 1782 fnsList.push(decl); 1783 } 1784 } else { 1785 if (typeIsErrSet(declValue.expr.type)) { 1786 errSetsList.push(decl); 1787 } else if (typeIsStructWithNoFields(declValue.expr.type)) { 1788 namespacesList.push(decl); 1789 } else { 1790 typesList.push(decl); 1791 } 1792 } 1793 } else if ("typeRef" in declValue) { 1794 if ("type" in declValue.typeRef && declValue.typeRef == typeTypeId) { 1795 // We don't know what the type expression is, but we know it's a type. 1796 typesList.push(decl); 1797 } else { 1798 valsList.push(decl); 1799 } 1800 } else { 1801 valsList.push(decl); 1802 } 1803 } 1804 } 1805 } 1806 1807 /** 1808 * @param {ContainerType} container 1809 */ 1810 function renderContainer(container) { 1811 /** @type {Decl[]} */ 1812 let typesList = []; 1813 /** @type {Decl[]} */ 1814 let namespacesList = []; 1815 /** @type {Decl[]} */ 1816 let errSetsList = []; 1817 /** @type {Decl[]} */ 1818 let fnsList = []; 1819 /** @type {Decl[]} */ 1820 let varsList = []; 1821 /** @type {Decl[]} */ 1822 let valsList = []; 1823 /** @type {Decl[]} */ 1824 let testsList = []; 1825 1826 categorizeDecls(container.pubDecls, 1827 typesList, namespacesList, errSetsList, 1828 fnsList, varsList, valsList, testsList); 1829 if (curNav.showPrivDecls) categorizeDecls(container.privDecls, 1830 typesList, namespacesList, errSetsList, 1831 fnsList, varsList, valsList, testsList); 1832 1833 1834 typesList.sort(byNameProperty); 1835 namespacesList.sort(byNameProperty); 1836 errSetsList.sort(byNameProperty); 1837 fnsList.sort(byNameProperty); 1838 varsList.sort(byNameProperty); 1839 valsList.sort(byNameProperty); 1840 testsList.sort(byNameProperty); 1841 1842 if (container.src != null) { 1843 let docs = zigAnalysis.astNodes[container.src].docs; 1844 if (docs != null) { 1845 domTldDocs.innerHTML = markdown(docs); 1846 domTldDocs.classList.remove("hidden"); 1847 } 1848 } 1849 1850 if (typesList.length !== 0) { 1851 resizeDomList(domListTypes, typesList.length, '<li><a href="#"></a></li>'); 1852 for (let i = 0; i < typesList.length; i += 1) { 1853 let liDom = domListTypes.children[i]; 1854 let aDom = liDom.children[0]; 1855 let decl = typesList[i]; 1856 aDom.textContent = decl.name; 1857 aDom.setAttribute('href', navLinkDecl(decl.name)); 1858 } 1859 domSectTypes.classList.remove("hidden"); 1860 } 1861 if (namespacesList.length !== 0) { 1862 resizeDomList(domListNamespaces, namespacesList.length, '<li><a href="#"></a></li>'); 1863 for (let i = 0; i < namespacesList.length; i += 1) { 1864 let liDom = domListNamespaces.children[i]; 1865 let aDom = liDom.children[0]; 1866 let decl = namespacesList[i]; 1867 aDom.textContent = decl.name; 1868 aDom.setAttribute('href', navLinkDecl(decl.name)); 1869 } 1870 domSectNamespaces.classList.remove("hidden"); 1871 } 1872 1873 if (errSetsList.length !== 0) { 1874 resizeDomList(domListErrSets, errSetsList.length, '<li><a href="#"></a></li>'); 1875 for (let i = 0; i < errSetsList.length; i += 1) { 1876 let liDom = domListErrSets.children[i]; 1877 let aDom = liDom.children[0]; 1878 let decl = errSetsList[i]; 1879 aDom.textContent = decl.name; 1880 aDom.setAttribute('href', navLinkDecl(decl.name)); 1881 } 1882 domSectErrSets.classList.remove("hidden"); 1883 } 1884 1885 if (fnsList.length !== 0) { 1886 resizeDomList(domListFns, fnsList.length, '<tr><td></td><td></td></tr>'); 1887 for (let i = 0; i < fnsList.length; i += 1) { 1888 let decl = fnsList[i]; 1889 let trDom = domListFns.children[i]; 1890 1891 let tdFnCode = trDom.children[0]; 1892 let tdDesc = trDom.children[1]; 1893 1894 let declType = resolveValue(decl.value); 1895 console.assert("type" in declType.expr); 1896 1897 tdFnCode.innerHTML = exprName(declType.expr,{ 1898 wantHtml: true, 1899 wantLink: true, 1900 fnDecl: decl, 1901 linkFnNameDecl: navLinkDecl(decl.name), 1902 }); 1903 1904 let docs = zigAnalysis.astNodes[decl.src].docs; 1905 if (docs != null) { 1906 tdDesc.innerHTML = shortDescMarkdown(docs); 1907 } else { 1908 tdDesc.textContent = ""; 1909 } 1910 } 1911 domSectFns.classList.remove("hidden"); 1912 } 1913 1914 let containerNode = zigAnalysis.astNodes[container.src]; 1915 if (containerNode.fields && containerNode.fields.length > 0) { 1916 resizeDomList(domListFields, containerNode.fields.length, '<div></div>'); 1917 1918 for (let i = 0; i < containerNode.fields.length; i += 1) { 1919 let fieldNode = zigAnalysis.astNodes[containerNode.fields[i]]; 1920 let divDom = domListFields.children[i]; 1921 let fieldName = /** @type {string} */(fieldNode.name); 1922 1923 let html = '<div class="mobile-scroll-container"><pre class="scroll-item">' + escapeHtml(fieldName); 1924 1925 if (container.kind === typeKinds.Enum) { 1926 html += ' = <span class="tok-number">' + fieldName + '</span>'; 1927 } else { 1928 let fieldTypeExpr = container.fields[i]; 1929 html += ": "; 1930 let name = exprName(fieldTypeExpr, false, false); 1931 html += '<span class="tok-kw">'+ name +'</span>'; 1932 let tsn = typeShorthandName(fieldTypeExpr); 1933 if (tsn) { 1934 html += '<span> ('+ tsn +')</span>'; 1935 1936 } 1937 } 1938 1939 html += ',</pre></div>'; 1940 1941 let docs = fieldNode.docs; 1942 if (docs != null) { 1943 html += markdown(docs); 1944 } 1945 divDom.innerHTML = html; 1946 } 1947 domSectFields.classList.remove("hidden"); 1948 } 1949 1950 if (varsList.length !== 0) { 1951 resizeDomList(domListGlobalVars, varsList.length, 1952 '<tr><td><a href="#"></a></td><td></td><td></td></tr>'); 1953 for (let i = 0; i < varsList.length; i += 1) { 1954 let decl = varsList[i]; 1955 let trDom = domListGlobalVars.children[i]; 1956 1957 let tdName = trDom.children[0]; 1958 let tdNameA = tdName.children[0]; 1959 let tdType = trDom.children[1]; 1960 let tdDesc = trDom.children[2]; 1961 1962 tdNameA.setAttribute('href', navLinkDecl(decl.name)); 1963 tdNameA.textContent = decl.name; 1964 1965 tdType.innerHTML = typeValueName(typeOfDecl(decl), true, true); 1966 1967 let docs = zigAnalysis.astNodes[decl.src].docs; 1968 if (docs != null) { 1969 tdDesc.innerHTML = shortDescMarkdown(docs); 1970 } else { 1971 tdDesc.textContent = ""; 1972 } 1973 } 1974 domSectGlobalVars.classList.remove("hidden"); 1975 } 1976 1977 if (valsList.length !== 0) { 1978 resizeDomList(domListValues, valsList.length, 1979 '<tr><td><a href="#"></a></td><td></td><td></td></tr>'); 1980 for (let i = 0; i < valsList.length; i += 1) { 1981 let decl = valsList[i]; 1982 let trDom = domListValues.children[i]; 1983 1984 let tdName = trDom.children[0]; 1985 let tdNameA = tdName.children[0]; 1986 let tdType = trDom.children[1]; 1987 let tdDesc = trDom.children[2]; 1988 1989 tdNameA.setAttribute('href', navLinkDecl(decl.name)); 1990 tdNameA.textContent = decl.name; 1991 1992 tdType.innerHTML = exprName(walkResultTypeRef(decl.value), 1993 {wantHtml:true, wantLink:true}); 1994 1995 let docs = zigAnalysis.astNodes[decl.src].docs; 1996 if (docs != null) { 1997 tdDesc.innerHTML = shortDescMarkdown(docs); 1998 } else { 1999 tdDesc.textContent = ""; 2000 } 2001 } 2002 domSectValues.classList.remove("hidden"); 2003 } 2004 2005 if (testsList.length !== 0) { 2006 resizeDomList(domListTests, testsList.length, 2007 '<tr><td><a href="#"></a></td><td></td><td></td></tr>'); 2008 for (let i = 0; i < testsList.length; i += 1) { 2009 let decl = testsList[i]; 2010 let trDom = domListTests.children[i]; 2011 2012 let tdName = trDom.children[0]; 2013 let tdNameA = tdName.children[0]; 2014 let tdType = trDom.children[1]; 2015 let tdDesc = trDom.children[2]; 2016 2017 tdNameA.setAttribute('href', navLinkDecl(decl.name)); 2018 tdNameA.textContent = decl.name; 2019 2020 tdType.innerHTML = exprName(walkResultTypeRef(decl.value), 2021 {wantHtml:true, wantLink:true}); 2022 2023 let docs = zigAnalysis.astNodes[decl.src].docs; 2024 if (docs != null) { 2025 tdDesc.innerHTML = shortDescMarkdown(docs); 2026 } else { 2027 tdDesc.textContent = ""; 2028 } 2029 } 2030 domSectTests.classList.remove("hidden"); 2031 } 2032 } 2033 2034 2035 /** 2036 * @param {string | number} a 2037 * @param {string | number} b 2038 */ 2039 function operatorCompare(a, b) { 2040 if (a === b) { 2041 return 0; 2042 } else if (a < b) { 2043 return -1; 2044 } else { 2045 return 1; 2046 } 2047 } 2048 2049 function detectRootIsStd() { 2050 let rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg]; 2051 if (rootPkg.table["std"] == null) { 2052 // no std mapped into the root package 2053 return false; 2054 } 2055 let stdPkg = zigAnalysis.packages[rootPkg.table["std"]]; 2056 if (stdPkg == null) return false; 2057 return rootPkg.file === stdPkg.file; 2058 } 2059 2060 function indexTypeKinds() { 2061 let map = /** @type {Record<string, number>} */({}); 2062 for (let i = 0; i < zigAnalysis.typeKinds.length; i += 1) { 2063 map[zigAnalysis.typeKinds[i]] = i; 2064 } 2065 // This is just for debugging purposes, not needed to function 2066 let assertList = ["Type","Void","Bool","NoReturn","Int","Float","Pointer","Array","Struct", 2067 "ComptimeFloat","ComptimeInt","Undefined","Null","Optional","ErrorUnion","ErrorSet","Enum", 2068 "Union","Fn","BoundFn","Opaque","Frame","AnyFrame","Vector","EnumLiteral"]; 2069 for (let i = 0; i < assertList.length; i += 1) { 2070 if (map[assertList[i]] == null) throw new Error("No type kind '" + assertList[i] + "' found"); 2071 } 2072 return map; 2073 } 2074 2075 function findTypeTypeId() { 2076 for (let i = 0; i < zigAnalysis.types.length; i += 1) { 2077 if (zigAnalysis.types[i].kind == typeKinds.Type) { 2078 return i; 2079 } 2080 } 2081 throw new Error("No type 'type' found"); 2082 } 2083 2084 function updateCurNav() { 2085 2086 curNav = { 2087 showPrivDecls: false, 2088 pkgNames: [], 2089 pkgObjs: [], 2090 declNames: [], 2091 declObjs: [], 2092 callName: null, 2093 }; 2094 curNavSearch = ""; 2095 2096 if (location.hash[0] === '#' && location.hash.length > 1) { 2097 let query = location.hash.substring(1); 2098 if (query[0] === '*') { 2099 curNav.showPrivDecls = true; 2100 query = query.substring(1); 2101 } 2102 2103 let qpos = query.indexOf("?"); 2104 let nonSearchPart; 2105 if (qpos === -1) { 2106 nonSearchPart = query; 2107 } else { 2108 nonSearchPart = query.substring(0, qpos); 2109 curNavSearch = decodeURIComponent(query.substring(qpos + 1)); 2110 } 2111 2112 let parts = nonSearchPart.split(";"); 2113 curNav.pkgNames = decodeURIComponent(parts[0]).split("."); 2114 if (parts[1] != null) { 2115 curNav.declNames = decodeURIComponent(parts[1]).split("."); 2116 } 2117 } 2118 2119 if (curNav.pkgNames.length === 0 && rootIsStd) { 2120 curNav.pkgNames = ["std"]; 2121 } 2122 } 2123 2124 function onHashChange() { 2125 updateCurNav(); 2126 if (domSearch.value !== curNavSearch) { 2127 domSearch.value = curNavSearch; 2128 } 2129 render(); 2130 if (imFeelingLucky) { 2131 imFeelingLucky = false; 2132 activateSelectedResult(); 2133 } 2134 } 2135 2136 /** 2137 * @param {ContainerType} parentType 2138 * @param {string} childName 2139 */ 2140 function findSubDecl(parentType, childName) { 2141 if (!parentType.pubDecls) return null; 2142 for (let i = 0; i < parentType.pubDecls.length; i += 1) { 2143 let declIndex = parentType.pubDecls[i]; 2144 let childDecl = zigAnalysis.decls[declIndex]; 2145 if (childDecl.name === childName) { 2146 return childDecl; 2147 } 2148 } 2149 if (!parentType.privDecls) return null; 2150 for (let i = 0; i < parentType.privDecls.length; i += 1) { 2151 let declIndex = parentType.privDecls[i]; 2152 let childDecl = zigAnalysis.decls[declIndex]; 2153 if (childDecl.name === childName) { 2154 return childDecl; 2155 } 2156 } 2157 return null; 2158 } 2159 2160 2161 2162 2163 function computeCanonicalPackagePaths() { 2164 let list = new Array(zigAnalysis.packages.length); 2165 // Now we try to find all the packages from root. 2166 let rootPkg = zigAnalysis.packages[zigAnalysis.rootPkg]; 2167 // Breadth-first to keep the path shortest possible. 2168 let stack = [{ 2169 path: /** @type {string[]} */([]), 2170 pkg: rootPkg, 2171 }]; 2172 while (stack.length !== 0) { 2173 let item = /** @type {{path: string[], pkg: Package}} */(stack.shift()); 2174 for (let key in item.pkg.table) { 2175 let childPkgIndex = item.pkg.table[key]; 2176 if (list[childPkgIndex] != null) continue; 2177 let childPkg = zigAnalysis.packages[childPkgIndex]; 2178 if (childPkg == null) continue; 2179 2180 let newPath = item.path.concat([key]) 2181 list[childPkgIndex] = newPath; 2182 stack.push({ 2183 path: newPath, 2184 pkg: childPkg, 2185 }); 2186 } 2187 } 2188 return list; 2189 } 2190 2191 2192 /** @return {CanonDecl[]} */ 2193 function computeCanonDeclPaths() { 2194 let list = new Array(zigAnalysis.decls.length); 2195 canonTypeDecls = new Array(zigAnalysis.types.length); 2196 2197 for (let pkgI = 0; pkgI < zigAnalysis.packages.length; pkgI += 1) { 2198 if (pkgI === zigAnalysis.rootPkg && rootIsStd) continue; 2199 let pkg = zigAnalysis.packages[pkgI]; 2200 let pkgNames = canonPkgPaths[pkgI]; 2201 let stack = [{ 2202 declNames: /** @type {string[]} */([]), 2203 type: zigAnalysis.types[pkg.main], 2204 }]; 2205 while (stack.length !== 0) { 2206 let item = /** @type {{declNames: string[], type: Type}} */(stack.shift()); 2207 2208 if (isContainerType(item.type)) { 2209 let t = /** @type {ContainerType} */(item.type); 2210 2211 let len = t.pubDecls ? t.pubDecls.length : 0; 2212 for (let declI = 0; declI < len; declI += 1) { 2213 let mainDeclIndex = t.pubDecls[declI]; 2214 if (list[mainDeclIndex] != null) continue; 2215 2216 let decl = zigAnalysis.decls[mainDeclIndex]; 2217 let declVal = decl.value; //resolveValue(decl.value); 2218 let declNames = item.declNames.concat([decl.name]); 2219 list[mainDeclIndex] = { 2220 pkgNames: pkgNames, 2221 declNames: declNames, 2222 }; 2223 if ("type" in declVal.expr) { 2224 let value = zigAnalysis.types[declVal.expr.type]; 2225 if (declCanRepresentTypeKind(value.kind)) 2226 { 2227 canonTypeDecls[declVal.type] = mainDeclIndex; 2228 } 2229 2230 if (isContainerType(value)) { 2231 stack.push({ 2232 declNames: declNames, 2233 type:value, 2234 }); 2235 } 2236 } 2237 } 2238 } 2239 } 2240 } 2241 return list; 2242 } 2243 2244 /** @param {number} index */ 2245 function getCanonDeclPath(index) { 2246 if (canonDeclPaths == null) { 2247 canonDeclPaths = computeCanonDeclPaths(); 2248 } 2249 //let cd = /** @type {CanonDecl[]}*/(canonDeclPaths); 2250 return canonDeclPaths[index]; 2251 } 2252 2253 /** @param {number} index */ 2254 function getCanonTypeDecl(index) { 2255 getCanonDeclPath(0); 2256 //let ct = /** @type {number[]}*/(canonTypeDecls); 2257 return canonTypeDecls[index]; 2258 } 2259 2260 /** @param {string} text */ 2261 function escapeHtml(text) { 2262 return text.replace(/[&"<>]/g, function (m) { 2263 return escapeHtmlReplacements[m]; 2264 }); 2265 } 2266 2267 /** @param {string} docs */ 2268 function shortDescMarkdown(docs) { 2269 let parts = docs.trim().split("\n"); 2270 let firstLine = parts[0]; 2271 return markdown(firstLine); 2272 } 2273 2274 /** @param {string} input */ 2275 function markdown(input) { 2276 const raw_lines = input.split('\n'); // zig allows no '\r', so we don't need to split on CR 2277 /** 2278 * @type Array<{ 2279 * indent: number, 2280 * raw_text: string, 2281 * text: string, 2282 * type: string, 2283 * ordered_number: number, 2284 * }> 2285 */ 2286 const lines = []; 2287 2288 // PHASE 1: 2289 // Dissect lines and determine the type for each line. 2290 // Also computes indentation level and removes unnecessary whitespace 2291 2292 let is_reading_code = false; 2293 let code_indent = 0; 2294 for (let line_no = 0; line_no < raw_lines.length; line_no++) { 2295 const raw_line = raw_lines[line_no]; 2296 2297 const line = { 2298 indent: 0, 2299 raw_text: raw_line, 2300 text: raw_line.trim(), 2301 type: "p", // p, h1 … h6, code, ul, ol, blockquote, skip, empty 2302 ordered_number: -1, // NOTE: hack to make the type checker happy 2303 }; 2304 2305 if (!is_reading_code) { 2306 while ((line.indent < line.raw_text.length) && line.raw_text[line.indent] == ' ') { 2307 line.indent += 1; 2308 } 2309 2310 if (line.text.startsWith("######")) { 2311 line.type = "h6"; 2312 line.text = line.text.substr(6); 2313 } 2314 else if (line.text.startsWith("#####")) { 2315 line.type = "h5"; 2316 line.text = line.text.substr(5); 2317 } 2318 else if (line.text.startsWith("####")) { 2319 line.type = "h4"; 2320 line.text = line.text.substr(4); 2321 } 2322 else if (line.text.startsWith("###")) { 2323 line.type = "h3"; 2324 line.text = line.text.substr(3); 2325 } 2326 else if (line.text.startsWith("##")) { 2327 line.type = "h2"; 2328 line.text = line.text.substr(2); 2329 } 2330 else if (line.text.startsWith("#")) { 2331 line.type = "h1"; 2332 line.text = line.text.substr(1); 2333 } 2334 else if (line.text.startsWith("-")) { 2335 line.type = "ul"; 2336 line.text = line.text.substr(1); 2337 } 2338 else if (line.text.match(/^\d+\..*$/)) { // if line starts with {number}{dot} 2339 const match = /** @type {RegExpMatchArray} */(line.text.match(/(\d+)\./)); 2340 line.type = "ul"; 2341 line.text = line.text.substr(match[0].length); 2342 line.ordered_number = Number(match[1].length); 2343 } 2344 else if (line.text == "```") { 2345 line.type = "skip"; 2346 is_reading_code = true; 2347 code_indent = line.indent; 2348 } 2349 else if (line.text == "") { 2350 line.type = "empty"; 2351 } 2352 } 2353 else { 2354 if (line.text == "```") { 2355 is_reading_code = false; 2356 line.type = "skip"; 2357 } else { 2358 line.type = "code"; 2359 line.text = line.raw_text.substr(code_indent); // remove the indent of the ``` from all the code block 2360 } 2361 } 2362 2363 if (line.type != "skip") { 2364 lines.push(line); 2365 } 2366 } 2367 2368 // PHASE 2: 2369 // Render HTML from markdown lines. 2370 // Look at each line and emit fitting HTML code 2371 2372 /** 2373 * @param {string } innerText 2374 */ 2375 function markdownInlines(innerText) { 2376 2377 // inline types: 2378 // **{INLINE}** : <strong> 2379 // __{INLINE}__ : <u> 2380 // ~~{INLINE}~~ : <s> 2381 // *{INLINE}* : <emph> 2382 // _{INLINE}_ : <emph> 2383 // `{TEXT}` : <code> 2384 // [{INLINE}]({URL}) : <a> 2385 //  : <img> 2386 // [[std;format.fmt]] : <a> (inner link) 2387 2388 /** @typedef {{marker: string, tag: string}} Fmt*/ 2389 /** @type {Array<Fmt>} */ 2390 const formats = [ 2391 { 2392 marker: "**", 2393 tag: "strong", 2394 }, 2395 { 2396 marker: "~~", 2397 tag: "s", 2398 }, 2399 { 2400 marker: "__", 2401 tag: "u", 2402 }, 2403 { 2404 marker: "*", 2405 tag: "em", 2406 } 2407 ]; 2408 2409 /** @type {Array<Fmt>} */ 2410 const stack = []; 2411 2412 let innerHTML = ""; 2413 let currentRun = ""; 2414 2415 function flushRun() { 2416 if (currentRun != "") { 2417 innerHTML += escapeHtml(currentRun); 2418 } 2419 currentRun = ""; 2420 } 2421 2422 let parsing_code = false; 2423 let codetag = ""; 2424 let in_code = false; 2425 2426 for (let i = 0; i < innerText.length; i++) { 2427 2428 if (parsing_code && in_code) { 2429 if (innerText.substr(i, codetag.length) == codetag) { 2430 // remove leading and trailing whitespace if string both starts and ends with one. 2431 if (currentRun[0] == " " && currentRun[currentRun.length - 1] == " ") { 2432 currentRun = currentRun.substr(1, currentRun.length - 2); 2433 } 2434 flushRun(); 2435 i += codetag.length - 1; 2436 in_code = false; 2437 parsing_code = false; 2438 innerHTML += "</code>"; 2439 codetag = ""; 2440 } else { 2441 currentRun += innerText[i]; 2442 } 2443 continue; 2444 } 2445 2446 if (innerText[i] == "`") { 2447 flushRun(); 2448 if (!parsing_code) { 2449 innerHTML += "<code>"; 2450 } 2451 parsing_code = true; 2452 codetag += "`"; 2453 continue; 2454 } 2455 2456 if (parsing_code) { 2457 currentRun += innerText[i]; 2458 in_code = true; 2459 } else { 2460 let any = false; 2461 for (let idx = /** @type {number} */(stack.length > 0 ? -1 : 0); idx < formats.length; idx++) { 2462 const fmt = idx >= 0 ? formats[idx] : stack[stack.length - 1]; 2463 if (innerText.substr(i, fmt.marker.length) == fmt.marker) { 2464 flushRun(); 2465 if (stack[stack.length - 1] == fmt) { 2466 stack.pop(); 2467 innerHTML += "</" + fmt.tag + ">"; 2468 } else { 2469 stack.push(fmt); 2470 innerHTML += "<" + fmt.tag + ">"; 2471 } 2472 i += fmt.marker.length - 1; 2473 any = true; 2474 break; 2475 } 2476 } 2477 if (!any) { 2478 currentRun += innerText[i]; 2479 } 2480 } 2481 } 2482 flushRun(); 2483 2484 while (stack.length > 0) { 2485 const fmt = /** @type {Fmt} */(stack.pop()); 2486 innerHTML += "</" + fmt.tag + ">"; 2487 } 2488 2489 return innerHTML; 2490 } 2491 2492 /** 2493 * @param {string} type 2494 * @param {number} line_no 2495 */ 2496 function previousLineIs(type, line_no) { 2497 if (line_no > 0) { 2498 return (lines[line_no - 1].type == type); 2499 } else { 2500 return false; 2501 } 2502 } 2503 2504 /** 2505 * @param {string} type 2506 * @param {number} line_no 2507 */ 2508 function nextLineIs(type, line_no) { 2509 if (line_no < (lines.length - 1)) { 2510 return (lines[line_no + 1].type == type); 2511 } else { 2512 return false; 2513 } 2514 } 2515 2516 /** @param {number} line_no */ 2517 function getPreviousLineIndent(line_no) { 2518 if (line_no > 0) { 2519 return lines[line_no - 1].indent; 2520 } else { 2521 return 0; 2522 } 2523 } 2524 2525 /** @param {number} line_no */ 2526 function getNextLineIndent(line_no) { 2527 if (line_no < (lines.length - 1)) { 2528 return lines[line_no + 1].indent; 2529 } else { 2530 return 0; 2531 } 2532 } 2533 2534 let html = ""; 2535 for (let line_no = 0; line_no < lines.length; line_no++) { 2536 const line = lines[line_no]; 2537 2538 2539 2540 switch (line.type) { 2541 case "h1": 2542 case "h2": 2543 case "h3": 2544 case "h4": 2545 case "h5": 2546 case "h6": 2547 html += "<" + line.type + ">" + markdownInlines(line.text) + "</" + line.type + ">\n"; 2548 break; 2549 2550 case "ul": 2551 case "ol": 2552 if (!previousLineIs("ul", line_no) || getPreviousLineIndent(line_no) < line.indent) { 2553 html += "<" + line.type + ">\n"; 2554 } 2555 2556 html += "<li>" + markdownInlines(line.text) + "</li>\n"; 2557 2558 if (!nextLineIs("ul", line_no) || getNextLineIndent(line_no) < line.indent) { 2559 html += "</" + line.type + ">\n"; 2560 } 2561 break; 2562 2563 case "p": 2564 if (!previousLineIs("p", line_no)) { 2565 html += "<p>\n"; 2566 } 2567 html += markdownInlines(line.text) + "\n"; 2568 if (!nextLineIs("p", line_no)) { 2569 html += "</p>\n"; 2570 } 2571 break; 2572 2573 case "code": 2574 if (!previousLineIs("code", line_no)) { 2575 html += "<pre><code>"; 2576 } 2577 html += escapeHtml(line.text) + "\n"; 2578 if (!nextLineIs("code", line_no)) { 2579 html += "</code></pre>\n"; 2580 } 2581 break; 2582 } 2583 } 2584 2585 return html; 2586 } 2587 2588 function activateSelectedResult() { 2589 if (domSectSearchResults.classList.contains("hidden")) { 2590 return; 2591 } 2592 2593 let liDom = domListSearchResults.children[curSearchIndex]; 2594 if (liDom == null && domListSearchResults.children.length !== 0) { 2595 liDom = domListSearchResults.children[0]; 2596 } 2597 if (liDom != null) { 2598 let aDom = liDom.children[0]; 2599 location.href = /** @type {string} */(aDom.getAttribute("href")); 2600 curSearchIndex = -1; 2601 } 2602 domSearch.blur(); 2603 } 2604 2605 /** @param {KeyboardEvent} ev */ 2606 function onSearchKeyDown(ev) { 2607 switch (getKeyString(ev)) { 2608 case "Enter": 2609 // detect if this search changes anything 2610 let terms1 = getSearchTerms(); 2611 startSearch(); 2612 updateCurNav(); 2613 let terms2 = getSearchTerms(); 2614 // we might have to wait for onHashChange to trigger 2615 imFeelingLucky = (terms1.join(' ') !== terms2.join(' ')); 2616 if (!imFeelingLucky) activateSelectedResult(); 2617 2618 ev.preventDefault(); 2619 ev.stopPropagation(); 2620 return; 2621 case "Esc": 2622 domSearch.value = ""; 2623 domSearch.blur(); 2624 curSearchIndex = -1; 2625 ev.preventDefault(); 2626 ev.stopPropagation(); 2627 startSearch(); 2628 return; 2629 case "Up": 2630 moveSearchCursor(-1); 2631 ev.preventDefault(); 2632 ev.stopPropagation(); 2633 return; 2634 case "Down": 2635 moveSearchCursor(1); 2636 ev.preventDefault(); 2637 ev.stopPropagation(); 2638 return; 2639 default: 2640 if (ev.shiftKey || ev.ctrlKey || ev.altKey) return; 2641 2642 curSearchIndex = -1; 2643 ev.stopPropagation(); 2644 startAsyncSearch(); 2645 return; 2646 } 2647 } 2648 2649 2650 /** @param {number} dir */ 2651 function moveSearchCursor(dir) { 2652 if (curSearchIndex < 0 || curSearchIndex >= domListSearchResults.children.length) { 2653 if (dir > 0) { 2654 curSearchIndex = -1 + dir; 2655 } else if (dir < 0) { 2656 curSearchIndex = domListSearchResults.children.length + dir; 2657 } 2658 } else { 2659 curSearchIndex += dir; 2660 } 2661 if (curSearchIndex < 0) { 2662 curSearchIndex = 0; 2663 } 2664 if (curSearchIndex >= domListSearchResults.children.length) { 2665 curSearchIndex = domListSearchResults.children.length - 1; 2666 } 2667 renderSearchCursor(); 2668 } 2669 2670 /** @param {KeyboardEvent} ev */ 2671 function getKeyString(ev) { 2672 let name; 2673 let ignoreShift = false; 2674 switch (ev.which) { 2675 case 13: 2676 name = "Enter"; 2677 break; 2678 case 27: 2679 name = "Esc"; 2680 break; 2681 case 38: 2682 name = "Up"; 2683 break; 2684 case 40: 2685 name = "Down"; 2686 break; 2687 default: 2688 ignoreShift = true; 2689 name = (ev.key != null) ? ev.key : String.fromCharCode(ev.charCode || ev.keyCode); 2690 } 2691 if (!ignoreShift && ev.shiftKey) name = "Shift+" + name; 2692 if (ev.altKey) name = "Alt+" + name; 2693 if (ev.ctrlKey) name = "Ctrl+" + name; 2694 return name; 2695 } 2696 2697 /** @param {KeyboardEvent} ev */ 2698 function onWindowKeyDown(ev) { 2699 switch (getKeyString(ev)) { 2700 case "Esc": 2701 if (!domHelpModal.classList.contains("hidden")) { 2702 domHelpModal.classList.add("hidden"); 2703 ev.preventDefault(); 2704 ev.stopPropagation(); 2705 } 2706 break; 2707 case "s": 2708 domSearch.focus(); 2709 domSearch.select(); 2710 ev.preventDefault(); 2711 ev.stopPropagation(); 2712 startAsyncSearch(); 2713 break; 2714 case "?": 2715 ev.preventDefault(); 2716 ev.stopPropagation(); 2717 showHelpModal(); 2718 break; 2719 } 2720 } 2721 2722 function showHelpModal() { 2723 domHelpModal.classList.remove("hidden"); 2724 domHelpModal.style.left = (window.innerWidth / 2 - domHelpModal.clientWidth / 2) + "px"; 2725 domHelpModal.style.top = (window.innerHeight / 2 - domHelpModal.clientHeight / 2) + "px"; 2726 domHelpModal.focus(); 2727 } 2728 2729 function clearAsyncSearch() { 2730 if (searchTimer != null) { 2731 clearTimeout(searchTimer); 2732 searchTimer = null; 2733 } 2734 } 2735 2736 function startAsyncSearch() { 2737 clearAsyncSearch(); 2738 searchTimer = setTimeout(startSearch, 100); 2739 } 2740 function startSearch() { 2741 clearAsyncSearch(); 2742 let oldHash = location.hash; 2743 let parts = oldHash.split("?"); 2744 let newPart2 = (domSearch.value === "") ? "" : ("?" + domSearch.value); 2745 location.hash = (parts.length === 1) ? (oldHash + newPart2) : (parts[0] + newPart2); 2746 } 2747 function getSearchTerms() { 2748 let list = curNavSearch.trim().split(/[ \r\n\t]+/); 2749 list.sort(); 2750 return list; 2751 } 2752 function renderSearch() { 2753 let matchedItems = []; 2754 let ignoreCase = (curNavSearch.toLowerCase() === curNavSearch); 2755 let terms = getSearchTerms(); 2756 2757 decl_loop: for (let declIndex = 0; declIndex < zigAnalysis.decls.length; declIndex += 1) { 2758 let canonPath = getCanonDeclPath(declIndex); 2759 if (canonPath == null) continue; 2760 2761 let decl = zigAnalysis.decls[declIndex]; 2762 let lastPkgName = canonPath.pkgNames[canonPath.pkgNames.length - 1]; 2763 let fullPathSearchText = lastPkgName + "." + canonPath.declNames.join('.'); 2764 let astNode = zigAnalysis.astNodes[decl.src]; 2765 let fileAndDocs = "" //zigAnalysis.files[astNode.file]; 2766 // TODO: understand what this piece of code is trying to achieve 2767 // also right now `files` are expressed as a hashmap. 2768 if (astNode.docs != null) { 2769 fileAndDocs += "\n" + astNode.docs; 2770 } 2771 let fullPathSearchTextLower = fullPathSearchText; 2772 if (ignoreCase) { 2773 fullPathSearchTextLower = fullPathSearchTextLower.toLowerCase(); 2774 fileAndDocs = fileAndDocs.toLowerCase(); 2775 } 2776 2777 let points = 0; 2778 for (let termIndex = 0; termIndex < terms.length; termIndex += 1) { 2779 let term = terms[termIndex]; 2780 2781 // exact, case sensitive match of full decl path 2782 if (fullPathSearchText === term) { 2783 points += 4; 2784 continue; 2785 } 2786 // exact, case sensitive match of just decl name 2787 if (decl.name == term) { 2788 points += 3; 2789 continue; 2790 } 2791 // substring, case insensitive match of full decl path 2792 if (fullPathSearchTextLower.indexOf(term) >= 0) { 2793 points += 2; 2794 continue; 2795 } 2796 if (fileAndDocs.indexOf(term) >= 0) { 2797 points += 1; 2798 continue; 2799 } 2800 2801 continue decl_loop; 2802 } 2803 2804 matchedItems.push({ 2805 decl: decl, 2806 path: canonPath, 2807 points: points, 2808 }); 2809 } 2810 2811 if (matchedItems.length !== 0) { 2812 resizeDomList(domListSearchResults, matchedItems.length, '<li><a href="#"></a></li>'); 2813 2814 matchedItems.sort(function(a, b) { 2815 let cmp = operatorCompare(b.points, a.points); 2816 if (cmp != 0) return cmp; 2817 return operatorCompare(a.decl.name, b.decl.name); 2818 }); 2819 2820 for (let i = 0; i < matchedItems.length; i += 1) { 2821 let liDom = domListSearchResults.children[i]; 2822 let aDom = liDom.children[0]; 2823 let match = matchedItems[i]; 2824 let lastPkgName = match.path.pkgNames[match.path.pkgNames.length - 1]; 2825 aDom.textContent = lastPkgName + "." + match.path.declNames.join('.'); 2826 aDom.setAttribute('href', navLink(match.path.pkgNames, match.path.declNames)); 2827 } 2828 renderSearchCursor(); 2829 2830 domSectSearchResults.classList.remove("hidden"); 2831 } else { 2832 domSectSearchNoResults.classList.remove("hidden"); 2833 } 2834 } 2835 2836 function renderSearchCursor() { 2837 for (let i = 0; i < domListSearchResults.children.length; i += 1) { 2838 let liDom = /** @type HTMLElement */(domListSearchResults.children[i]); 2839 if (curSearchIndex === i) { 2840 liDom.classList.add("selected"); 2841 } else { 2842 liDom.classList.remove("selected"); 2843 } 2844 } 2845 } 2846 2847 2848 2849 // function indexNodesToCalls() { 2850 // let map = {}; 2851 // for (let i = 0; i < zigAnalysis.calls.length; i += 1) { 2852 // let call = zigAnalysis.calls[i]; 2853 // let fn = zigAnalysis.fns[call.fn]; 2854 // if (map[fn.src] == null) { 2855 // map[fn.src] = [i]; 2856 // } else { 2857 // map[fn.src].push(i); 2858 // } 2859 // } 2860 // return map; 2861 // } 2862 2863 2864 /** 2865 * @param {{ name: string }} a 2866 * @param {{ name: string }} b 2867 */ 2868 function byNameProperty(a, b) { 2869 return operatorCompare(a.name, b.name); 2870 } 2871 2872 2873 2874 })();