| ... | ... | @@ -281,7 +281,8 @@ const NAV_MODES = { |
| 281 | 281 | // return null; |
| 282 | 282 | // } |
| 283 | 283 | |
| 284 | | function resolveValue(value) { |
| 284 | function resolveValue(value, trackDecls) { |
| 285 | let seenDecls = []; |
| 285 | 286 | let i = 0; |
| 286 | 287 | while (true) { |
| 287 | 288 | i += 1; |
| ... | ... | @@ -295,6 +296,7 @@ const NAV_MODES = { |
| 295 | 296 | } |
| 296 | 297 | |
| 297 | 298 | if ("declRef" in value.expr) { |
| 299 | seenDecls.push(value.expr.declRef); |
| 298 | 300 | value = getDecl(value.expr.declRef).value; |
| 299 | 301 | continue; |
| 300 | 302 | } |
| ... | ... | @@ -307,6 +309,7 @@ const NAV_MODES = { |
| 307 | 309 | continue; |
| 308 | 310 | } |
| 309 | 311 | |
| 312 | if (trackDecls) return { value, seenDecls }; |
| 310 | 313 | return value; |
| 311 | 314 | } |
| 312 | 315 | } |
| ... | ... | @@ -1134,9 +1137,8 @@ Happy writing! |
| 1134 | 1137 | } |
| 1135 | 1138 | case "declRef": { |
| 1136 | 1139 | 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) { |
| 1140 | 1142 | yield { src: name, tag: Tag.identifier, link }; |
| 1141 | 1143 | } else { |
| 1142 | 1144 | yield { src: name, tag: Tag.identifier }; |
| ... | ... | @@ -2028,7 +2030,6 @@ Happy writing! |
| 2028 | 2030 | let linkFnNameDecl = opts.linkFnNameDecl; |
| 2029 | 2031 | opts.fnDecl = null; |
| 2030 | 2032 | opts.linkFnNameDecl = null; |
| 2031 | | let payloadHtml = ""; |
| 2032 | 2033 | if (opts.addParensIfFnSignature && fnObj.src == 0) { |
| 2033 | 2034 | yield Tok.l_paren; |
| 2034 | 2035 | } |
| ... | ... | @@ -2108,6 +2109,7 @@ Happy writing! |
| 2108 | 2109 | } |
| 2109 | 2110 | } |
| 2110 | 2111 | |
| 2112 | // TODO: most of this seems redundant |
| 2111 | 2113 | if (isVarArgs && i === fnObj.params.length - 1) { |
| 2112 | 2114 | yield Tok.period; |
| 2113 | 2115 | yield Tok.period; |
| ... | ... | @@ -3234,7 +3236,7 @@ Happy writing! |
| 3234 | 3236 | } |
| 3235 | 3237 | |
| 3236 | 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 | 3240 | let declNames = item.declNames.concat([decl.name]); |
| 3239 | 3241 | let declIndexes = item.declIndexes.concat([declIndex]); |
| 3240 | 3242 | |
| ... | ... | @@ -3245,6 +3247,15 @@ Happy writing! |
| 3245 | 3247 | declIndexes: declIndexes, |
| 3246 | 3248 | }; |
| 3247 | 3249 | |
| 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 | 3259 | // add to search index |
| 3249 | 3260 | { |
| 3250 | 3261 | declSearchIndex.add(decl.name, { declIndex }); |
| ... | ... | @@ -3282,12 +3293,60 @@ Happy writing! |
| 3282 | 3293 | } |
| 3283 | 3294 | } |
| 3284 | 3295 | |
| 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 | 3342 | function getCanonDeclPath(index) { |
| 3286 | 3343 | if (canonDeclPaths == null) { |
| 3287 | 3344 | canonDeclPaths = computeCanonDeclPaths(); |
| 3288 | 3345 | } |
| 3289 | | //let cd = (canonDeclPaths); |
| 3346 | |
| 3290 | 3347 | return canonDeclPaths[index]; |
| 3348 | |
| 3349 | |
| 3291 | 3350 | } |
| 3292 | 3351 | |
| 3293 | 3352 | function getCanonTypeDecl(index) { |
| ... | ... | @@ -3395,6 +3454,8 @@ Happy writing! |
| 3395 | 3454 | |
| 3396 | 3455 | } |
| 3397 | 3456 | |
| 3457 | |
| 3458 | |
| 3398 | 3459 | function detectDeclPath(text, context) { |
| 3399 | 3460 | let result = ""; |
| 3400 | 3461 | let separator = ":"; |
| ... | ... | @@ -3888,109 +3949,7 @@ Happy writing! |
| 3888 | 3949 | domSectSearchResults.classList.remove("hidden"); |
| 3889 | 3950 | } |
| 3890 | 3951 | |
| 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 | |
| 3994 | 3953 | |
| 3995 | 3954 | function renderSearchCursor() { |
| 3996 | 3955 | for (let i = 0; i < domListSearchResults.children.length; i += 1) { |