authorgravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2023-07-14 19:11:55+02:00
committergravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2023-07-14 19:11:55+02:00
log7dd1cf26f9b0cb104ada166a10ff356ca272577a
tree7d9bbb58a50d2a46200879693f62f83661904650
parenta187141056687231c7fd2c333280e6fc20062d11

autodoc: improved linking for declrefs


1 files changed, 69 insertions(+), 110 deletions(-)

lib/docs/main.js+69-110
...@@ -281,7 +281,8 @@ const NAV_MODES = {...@@ -281,7 +281,8 @@ const NAV_MODES = {
281 // return null;281 // return null;
282 // }282 // }
283283
284 function resolveValue(value) {284 function resolveValue(value, trackDecls) {
285 let seenDecls = [];
285 let i = 0;286 let i = 0;
286 while (true) {287 while (true) {
287 i += 1;288 i += 1;
...@@ -295,6 +296,7 @@ const NAV_MODES = {...@@ -295,6 +296,7 @@ const NAV_MODES = {
295 }296 }
296297
297 if ("declRef" in value.expr) {298 if ("declRef" in value.expr) {
299 seenDecls.push(value.expr.declRef);
298 value = getDecl(value.expr.declRef).value;300 value = getDecl(value.expr.declRef).value;
299 continue;301 continue;
300 }302 }
...@@ -307,6 +309,7 @@ const NAV_MODES = {...@@ -307,6 +309,7 @@ const NAV_MODES = {
307 continue;309 continue;
308 }310 }
309311
312 if (trackDecls) return { value, seenDecls };
310 return value;313 return value;
311 }314 }
312 }315 }
...@@ -1134,9 +1137,8 @@ Happy writing!...@@ -1134,9 +1137,8 @@ Happy writing!
1134 }1137 }
1135 case "declRef": {1138 case "declRef": {
1136 const name = getDecl(expr.declRef).name;1139 const name = getDecl(expr.declRef).name;
1137 const canonPath = getCanonDeclPath(expr.declRef);1140 const link = declLinkOrSrcLink(expr.declRef);
1138 if (canonPath) {1141 if (link) {
1139 const link = navLink(canonPath.modNames, canonPath.declNames);
1140 yield { src: name, tag: Tag.identifier, link };1142 yield { src: name, tag: Tag.identifier, link };
1141 } else {1143 } else {
1142 yield { src: name, tag: Tag.identifier };1144 yield { src: name, tag: Tag.identifier };
...@@ -2028,7 +2030,6 @@ Happy writing!...@@ -2028,7 +2030,6 @@ Happy writing!
2028 let linkFnNameDecl = opts.linkFnNameDecl;2030 let linkFnNameDecl = opts.linkFnNameDecl;
2029 opts.fnDecl = null;2031 opts.fnDecl = null;
2030 opts.linkFnNameDecl = null;2032 opts.linkFnNameDecl = null;
2031 let payloadHtml = "";
2032 if (opts.addParensIfFnSignature && fnObj.src == 0) {2033 if (opts.addParensIfFnSignature && fnObj.src == 0) {
2033 yield Tok.l_paren;2034 yield Tok.l_paren;
2034 }2035 }
...@@ -2108,6 +2109,7 @@ Happy writing!...@@ -2108,6 +2109,7 @@ Happy writing!
2108 }2109 }
2109 }2110 }
21102111
2112 // TODO: most of this seems redundant
2111 if (isVarArgs && i === fnObj.params.length - 1) {2113 if (isVarArgs && i === fnObj.params.length - 1) {
2112 yield Tok.period;2114 yield Tok.period;
2113 yield Tok.period;2115 yield Tok.period;
...@@ -3234,7 +3236,7 @@ Happy writing!...@@ -3234,7 +3236,7 @@ Happy writing!
3234 }3236 }
32353237
3236 function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) {3238 function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) {
3237 let declVal = resolveValue(decl.value);3239 let {value: declVal, seenDecls} = resolveValue(decl.value, true);
3238 let declNames = item.declNames.concat([decl.name]);3240 let declNames = item.declNames.concat([decl.name]);
3239 let declIndexes = item.declIndexes.concat([declIndex]);3241 let declIndexes = item.declIndexes.concat([declIndex]);
32403242
...@@ -3245,6 +3247,15 @@ Happy writing!...@@ -3245,6 +3247,15 @@ Happy writing!
3245 declIndexes: declIndexes,3247 declIndexes: declIndexes,
3246 };3248 };
32473249
3250 for (let sd of seenDecls) {
3251 if (list[sd] != null) continue;
3252 list[sd] = {
3253 modNames: modNames,
3254 declNames: declNames,
3255 declIndexes: declIndexes,
3256 };
3257 }
3258
3248 // add to search index3259 // add to search index
3249 {3260 {
3250 declSearchIndex.add(decl.name, { declIndex });3261 declSearchIndex.add(decl.name, { declIndex });
...@@ -3282,12 +3293,60 @@ Happy writing!...@@ -3282,12 +3293,60 @@ Happy writing!
3282 }3293 }
3283 }3294 }
32843295
3296 function declLinkOrSrcLink(index) {
3297
3298 let match = getCanonDeclPath(index);
3299 if (match) return navLink(match.modNames, match.declNames);
3300
3301 // could not find a precomputed decl path
3302 const decl = getDecl(index);
3303
3304 // try to find a public decl by scanning declRefs and declPaths
3305 let value = decl.value;
3306 let i = 0;
3307 while (true) {
3308 i += 1;
3309 if (i >= 10000) {
3310 throw "getCanonDeclPath quota exceeded"
3311 }
3312
3313 if ("refPath" in value.expr) {
3314 value = { expr: value.expr.refPath[value.expr.refPath.length - 1] };
3315 continue;
3316 }
3317
3318 if ("declRef" in value.expr) {
3319 let cp = canonDeclPaths[value.expr.declRef];
3320 if (cp) return navLink(cp.modNames, cp.declNames);
3321
3322 value = getDecl(value.expr.declRef).value;
3323 continue;
3324 }
3325
3326 if ("as" in value.expr) {
3327 value = {
3328 typeRef: zigAnalysis.exprs[value.expr.as.typeRefArg],
3329 expr: zigAnalysis.exprs[value.expr.as.exprArg],
3330 };
3331 continue;
3332 }
3333
3334 // if we got here it means that we failed
3335 // produce a link to source code instead
3336 return sourceFileLink(decl);
3337
3338 }
3339
3340 }
3341
3285 function getCanonDeclPath(index) {3342 function getCanonDeclPath(index) {
3286 if (canonDeclPaths == null) {3343 if (canonDeclPaths == null) {
3287 canonDeclPaths = computeCanonDeclPaths();3344 canonDeclPaths = computeCanonDeclPaths();
3288 }3345 }
3289 //let cd = (canonDeclPaths);3346
3290 return canonDeclPaths[index];3347 return canonDeclPaths[index];
3348
3349
3291 }3350 }
32923351
3293 function getCanonTypeDecl(index) {3352 function getCanonTypeDecl(index) {
...@@ -3395,6 +3454,8 @@ Happy writing!...@@ -3395,6 +3454,8 @@ Happy writing!
33953454
3396 }3455 }
33973456
3457
3458
3398 function detectDeclPath(text, context) {3459 function detectDeclPath(text, context) {
3399 let result = "";3460 let result = "";
3400 let separator = ":";3461 let separator = ":";
...@@ -3888,109 +3949,7 @@ Happy writing!...@@ -3888,109 +3949,7 @@ Happy writing!
3888 domSectSearchResults.classList.remove("hidden");3949 domSectSearchResults.classList.remove("hidden");
3889 }3950 }
38903951
3891 function renderSearchAPIOld() {3952
3892 let matchedItems = [];
3893 let ignoreCase = curNavSearch.toLowerCase() === curNavSearch;
3894 let terms = getSearchTerms();
3895
3896 decl_loop: for (
3897 let declIndex = 0;
3898 declIndex < zigAnalysis.decls.length;
3899 declIndex += 1
3900 ) {
3901 let canonPath = getCanonDeclPath(declIndex);
3902 if (canonPath == null) continue;
3903
3904 let decl = getDecl(declIndex);
3905 let lastModName = canonPath.modNames[canonPath.modNames.length - 1];
3906 let fullPathSearchText =
3907 lastModName + "." + canonPath.declNames.join(".");
3908 let astNode = getAstNode(decl.src);
3909 let fileAndDocs = ""; //zigAnalysis.files[astNode.file];
3910 // TODO: understand what this piece of code is trying to achieve
3911 // also right now `files` are expressed as a hashmap.
3912 if (astNode.docs != null) {
3913 fileAndDocs += "\n" + astNode.docs;
3914 }
3915 let fullPathSearchTextLower = fullPathSearchText;
3916 if (ignoreCase) {
3917 fullPathSearchTextLower = fullPathSearchTextLower.toLowerCase();
3918 fileAndDocs = fileAndDocs.toLowerCase();
3919 }
3920
3921 let points = 0;
3922 for (let termIndex = 0; termIndex < terms.length; termIndex += 1) {
3923 let term = terms[termIndex];
3924
3925 // exact, case sensitive match of full decl path
3926 if (fullPathSearchText === term) {
3927 points += 4;
3928 continue;
3929 }
3930 // exact, case sensitive match of just decl name
3931 if (decl.name == term) {
3932 points += 3;
3933 continue;
3934 }
3935 // substring, case insensitive match of full decl path
3936 if (fullPathSearchTextLower.indexOf(term) >= 0) {
3937 points += 2;
3938 continue;
3939 }
3940 if (fileAndDocs.indexOf(term) >= 0) {
3941 points += 1;
3942 continue;
3943 }
3944
3945 continue decl_loop;
3946 }
3947
3948 matchedItems.push({
3949 decl: decl,
3950 path: canonPath,
3951 points: points,
3952 });
3953 }
3954
3955 if (matchedItems.length !== 0) {
3956 matchedItems.sort(function(a, b) {
3957 let cmp = operatorCompare(b.points, a.points);
3958 if (cmp != 0) return cmp;
3959 return operatorCompare(a.decl.name, b.decl.name);
3960 });
3961
3962 let searchTrimmed = false;
3963 const searchTrimResultsMaxItems = 60;
3964 if (searchTrimResults && matchedItems.length > searchTrimResultsMaxItems) {
3965 matchedItems = matchedItems.slice(0, searchTrimResultsMaxItems);
3966 searchTrimmed = true;
3967 }
3968
3969 // Build up the list of search results
3970 let matchedItemsHTML = "";
3971
3972 for (let i = 0; i < matchedItems.length; i += 1) {
3973 const match = matchedItems[i];
3974 const lastModName = match.path.modNames[match.path.modNames.length - 1];
3975
3976 const text = lastModName + "." + match.path.declNames.join(".");
3977 const href = navLink(match.path.modNames, match.path.declNames);
3978
3979 matchedItemsHTML += "<li><a href=\"" + href + "\">" + text + "</a></li>";
3980 }
3981
3982 // Replace the search results using our newly constructed HTML string
3983 domListSearchResults.innerHTML = matchedItemsHTML;
3984 if (searchTrimmed) {
3985 domSectSearchAllResultsLink.classList.remove("hidden");
3986 }
3987 renderSearchCursor();
3988
3989 domSectSearchResults.classList.remove("hidden");
3990 } else {
3991 domSectSearchNoResults.classList.remove("hidden");
3992 }
3993 }
39943953
3995 function renderSearchCursor() {3954 function renderSearchCursor() {
3996 for (let i = 0; i < domListSearchResults.children.length; i += 1) {3955 for (let i = 0; i < domListSearchResults.children.length; i += 1) {