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 = {
281281 // return null;
282282 // }
283283
284 function resolveValue(value) {
284 function resolveValue(value, trackDecls) {
285 let seenDecls = [];
285286 let i = 0;
286287 while (true) {
287288 i += 1;
......@@ -295,6 +296,7 @@ const NAV_MODES = {
295296 }
296297
297298 if ("declRef" in value.expr) {
299 seenDecls.push(value.expr.declRef);
298300 value = getDecl(value.expr.declRef).value;
299301 continue;
300302 }
......@@ -307,6 +309,7 @@ const NAV_MODES = {
307309 continue;
308310 }
309311
312 if (trackDecls) return { value, seenDecls };
310313 return value;
311314 }
312315 }
......@@ -1134,9 +1137,8 @@ Happy writing!
11341137 }
11351138 case "declRef": {
11361139 const name = getDecl(expr.declRef).name;
1137 const canonPath = getCanonDeclPath(expr.declRef);
1138 if (canonPath) {
1139 const link = navLink(canonPath.modNames, canonPath.declNames);
1140 const link = declLinkOrSrcLink(expr.declRef);
1141 if (link) {
11401142 yield { src: name, tag: Tag.identifier, link };
11411143 } else {
11421144 yield { src: name, tag: Tag.identifier };
......@@ -2028,7 +2030,6 @@ Happy writing!
20282030 let linkFnNameDecl = opts.linkFnNameDecl;
20292031 opts.fnDecl = null;
20302032 opts.linkFnNameDecl = null;
2031 let payloadHtml = "";
20322033 if (opts.addParensIfFnSignature && fnObj.src == 0) {
20332034 yield Tok.l_paren;
20342035 }
......@@ -2108,6 +2109,7 @@ Happy writing!
21082109 }
21092110 }
21102111
2112 // TODO: most of this seems redundant
21112113 if (isVarArgs && i === fnObj.params.length - 1) {
21122114 yield Tok.period;
21132115 yield Tok.period;
......@@ -3234,7 +3236,7 @@ Happy writing!
32343236 }
32353237
32363238 function addDeclToSearchResults(decl, declIndex, modNames, item, list, stack) {
3237 let declVal = resolveValue(decl.value);
3239 let {value: declVal, seenDecls} = resolveValue(decl.value, true);
32383240 let declNames = item.declNames.concat([decl.name]);
32393241 let declIndexes = item.declIndexes.concat([declIndex]);
32403242
......@@ -3245,6 +3247,15 @@ Happy writing!
32453247 declIndexes: declIndexes,
32463248 };
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
32483259 // add to search index
32493260 {
32503261 declSearchIndex.add(decl.name, { declIndex });
......@@ -3282,12 +3293,60 @@ Happy writing!
32823293 }
32833294 }
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
32853342 function getCanonDeclPath(index) {
32863343 if (canonDeclPaths == null) {
32873344 canonDeclPaths = computeCanonDeclPaths();
32883345 }
3289 //let cd = (canonDeclPaths);
3346
32903347 return canonDeclPaths[index];
3348
3349
32913350 }
32923351
32933352 function getCanonTypeDecl(index) {
......@@ -3395,6 +3454,8 @@ Happy writing!
33953454
33963455 }
33973456
3457
3458
33983459 function detectDeclPath(text, context) {
33993460 let result = "";
34003461 let separator = ":";
......@@ -3888,109 +3949,7 @@ Happy writing!
38883949 domSectSearchResults.classList.remove("hidden");
38893950 }
38903951
3891 function renderSearchAPIOld() {
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 }
3952
39943953
39953954 function renderSearchCursor() {
39963955 for (let i = 0; i < domListSearchResults.children.length; i += 1) {