@@ -499,6 +499,7 @@ function initSearch(rawSearchIndex) {
499
499
fullPath : [ "never" ] ,
500
500
pathWithoutLast : [ ] ,
501
501
pathLast : "never" ,
502
+ normalizedPathLast : "never" ,
502
503
generics : [ ] ,
503
504
bindings : new Map ( ) ,
504
505
typeFilter : "primitive" ,
@@ -537,12 +538,14 @@ function initSearch(rawSearchIndex) {
537
538
const bindingName = parserState . isInBinding ;
538
539
parserState . isInBinding = null ;
539
540
const bindings = new Map ( ) ;
541
+ const pathLast = pathSegments [ pathSegments . length - 1 ] ;
540
542
return {
541
543
name : name . trim ( ) ,
542
544
id : null ,
543
545
fullPath : pathSegments ,
544
546
pathWithoutLast : pathSegments . slice ( 0 , pathSegments . length - 1 ) ,
545
- pathLast : pathSegments [ pathSegments . length - 1 ] ,
547
+ pathLast,
548
+ normalizedPathLast : pathLast . replace ( / _ / g, "" ) ,
546
549
generics : generics . filter ( gen => {
547
550
// Syntactically, bindings are parsed as generics,
548
551
// but the query engine treats them differently.
@@ -689,6 +692,7 @@ function initSearch(rawSearchIndex) {
689
692
fullPath : [ "[]" ] ,
690
693
pathWithoutLast : [ ] ,
691
694
pathLast : "[]" ,
695
+ normalizedPathLast : "[]" ,
692
696
generics,
693
697
typeFilter : "primitive" ,
694
698
bindingName : isInBinding ,
@@ -1168,13 +1172,12 @@ function initSearch(rawSearchIndex) {
1168
1172
* Executes the parsed query and builds a {ResultsTable}.
1169
1173
*
1170
1174
* @param {ParsedQuery } parsedQuery - The parsed user query
1171
- * @param {Object } searchWords - The list of search words to query against
1172
1175
* @param {Object } [filterCrates] - Crate to search in if defined
1173
1176
* @param {Object } [currentCrate] - Current crate, to rank results from this crate higher
1174
1177
*
1175
1178
* @return {ResultsTable }
1176
1179
*/
1177
- function execQuery ( parsedQuery , searchWords , filterCrates , currentCrate ) {
1180
+ function execQuery ( parsedQuery , filterCrates , currentCrate ) {
1178
1181
const results_others = new Map ( ) , results_in_args = new Map ( ) ,
1179
1182
results_returned = new Map ( ) ;
1180
1183
@@ -1232,8 +1235,8 @@ function initSearch(rawSearchIndex) {
1232
1235
const userQuery = parsedQuery . userQuery ;
1233
1236
const result_list = [ ] ;
1234
1237
for ( const result of results . values ( ) ) {
1235
- result . word = searchWords [ result . id ] ;
1236
- result . item = searchIndex [ result . id ] || { } ;
1238
+ result . item = searchIndex [ result . id ] ;
1239
+ result . word = searchIndex [ result . id ] . word ;
1237
1240
result_list . push ( result ) ;
1238
1241
}
1239
1242
@@ -1928,7 +1931,7 @@ function initSearch(rawSearchIndex) {
1928
1931
* The `results` map contains information which will be used to sort the search results:
1929
1932
*
1930
1933
* * `fullId` is a `string`` used as the key of the object we use for the `results` map.
1931
- * * `id` is the index in both `searchWords` and ` searchIndex` arrays for this element.
1934
+ * * `id` is the index in the ` searchIndex` array for this element.
1932
1935
* * `index` is an `integer`` used to sort by the position of the word in the item's name.
1933
1936
* * `dist` is the main metric used to sort the search results.
1934
1937
* * `path_dist` is zero if a single-component search query is used, otherwise it's the
@@ -1986,9 +1989,8 @@ function initSearch(rawSearchIndex) {
1986
1989
if ( ! row || ( filterCrates !== null && row . crate !== filterCrates ) ) {
1987
1990
return ;
1988
1991
}
1989
- let index = - 1 , path_dist = 0 ;
1992
+ let path_dist = 0 ;
1990
1993
const fullId = row . id ;
1991
- const searchWord = searchWords [ pos ] ;
1992
1994
1993
1995
// fpDist is a minimum possible type distance, where "type distance" is the number of
1994
1996
// atoms in the function not present in the query
@@ -2021,19 +2023,10 @@ function initSearch(rawSearchIndex) {
2021
2023
return ;
2022
2024
}
2023
2025
2024
- const row_index = row . normalizedName . indexOf ( elem . pathLast ) ;
2025
- const word_index = searchWord . indexOf ( elem . pathLast ) ;
2026
-
2027
- // lower indexes are "better" matches
2028
- // rank based on the "best" match
2029
- if ( row_index === - 1 ) {
2030
- index = word_index ;
2031
- } else if ( word_index === - 1 ) {
2032
- index = row_index ;
2033
- } else if ( word_index < row_index ) {
2034
- index = word_index ;
2035
- } else {
2036
- index = row_index ;
2026
+ let index = row . word . indexOf ( elem . pathLast ) ;
2027
+ const normalizedIndex = row . normalizedName . indexOf ( elem . pathLast ) ;
2028
+ if ( index === - 1 || ( index > normalizedIndex && normalizedIndex !== - 1 ) ) {
2029
+ index = normalizedIndex ;
2037
2030
}
2038
2031
2039
2032
if ( elem . fullPath . length > 1 ) {
@@ -2044,13 +2037,13 @@ function initSearch(rawSearchIndex) {
2044
2037
}
2045
2038
2046
2039
if ( parsedQuery . literalSearch ) {
2047
- if ( searchWord === elem . name ) {
2040
+ if ( row . word === elem . pathLast ) {
2048
2041
addIntoResults ( results_others , fullId , pos , index , 0 , path_dist ) ;
2049
2042
}
2050
2043
return ;
2051
2044
}
2052
2045
2053
- const dist = editDistance ( searchWord , elem . pathLast , maxEditDistance ) ;
2046
+ const dist = editDistance ( row . normalizedName , elem . normalizedPathLast , maxEditDistance ) ;
2054
2047
2055
2048
if ( index === - 1 && dist + path_dist > maxEditDistance ) {
2056
2049
return ;
@@ -2135,15 +2128,15 @@ function initSearch(rawSearchIndex) {
2135
2128
* @param {boolean } isAssocType
2136
2129
*/
2137
2130
function convertNameToId ( elem , isAssocType ) {
2138
- if ( typeNameIdMap . has ( elem . pathLast ) &&
2139
- ( isAssocType || ! typeNameIdMap . get ( elem . pathLast ) . assocOnly ) ) {
2140
- elem . id = typeNameIdMap . get ( elem . pathLast ) . id ;
2131
+ if ( typeNameIdMap . has ( elem . normalizedPathLast ) &&
2132
+ ( isAssocType || ! typeNameIdMap . get ( elem . normalizedPathLast ) . assocOnly ) ) {
2133
+ elem . id = typeNameIdMap . get ( elem . normalizedPathLast ) . id ;
2141
2134
} else if ( ! parsedQuery . literalSearch ) {
2142
2135
let match = null ;
2143
2136
let matchDist = maxEditDistance + 1 ;
2144
2137
let matchName = "" ;
2145
2138
for ( const [ name , { id, assocOnly} ] of typeNameIdMap ) {
2146
- const dist = editDistance ( name , elem . pathLast , maxEditDistance ) ;
2139
+ const dist = editDistance ( name , elem . normalizedPathLast , maxEditDistance ) ;
2147
2140
if ( dist <= matchDist && dist <= maxEditDistance &&
2148
2141
( isAssocType || ! assocOnly ) ) {
2149
2142
if ( dist === matchDist && matchName > name ) {
@@ -2236,7 +2229,7 @@ function initSearch(rawSearchIndex) {
2236
2229
if ( parsedQuery . foundElems === 1 && parsedQuery . returned . length === 0 ) {
2237
2230
if ( parsedQuery . elems . length === 1 ) {
2238
2231
const elem = parsedQuery . elems [ 0 ] ;
2239
- for ( let i = 0 , nSearchWords = searchWords . length ; i < nSearchWords ; ++ i ) {
2232
+ for ( let i = 0 , nSearchIndex = searchIndex . length ; i < nSearchIndex ; ++ i ) {
2240
2233
// It means we want to check for this element everywhere (in names, args and
2241
2234
// returned).
2242
2235
handleSingleArg (
@@ -2267,7 +2260,7 @@ function initSearch(rawSearchIndex) {
2267
2260
} ;
2268
2261
parsedQuery . elems . sort ( sortQ ) ;
2269
2262
parsedQuery . returned . sort ( sortQ ) ;
2270
- for ( let i = 0 , nSearchWords = searchWords . length ; i < nSearchWords ; ++ i ) {
2263
+ for ( let i = 0 , nSearchIndex = searchIndex . length ; i < nSearchIndex ; ++ i ) {
2271
2264
handleArgs ( searchIndex [ i ] , i , results_others ) ;
2272
2265
}
2273
2266
}
@@ -2651,7 +2644,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
2651
2644
updateSearchHistory ( buildUrl ( query . original , filterCrates ) ) ;
2652
2645
2653
2646
showResults (
2654
- execQuery ( query , searchWords , filterCrates , window . currentCrate ) ,
2647
+ execQuery ( query , filterCrates , window . currentCrate ) ,
2655
2648
params . go_to_first ,
2656
2649
filterCrates ) ;
2657
2650
}
@@ -2920,12 +2913,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
2920
2913
2921
2914
function buildIndex ( rawSearchIndex ) {
2922
2915
searchIndex = [ ] ;
2923
- /**
2924
- * List of normalized search words (ASCII lowercased, and undescores removed).
2925
- *
2926
- * @type {Array<string> }
2927
- */
2928
- const searchWords = [ ] ;
2929
2916
typeNameIdMap = new Map ( ) ;
2930
2917
const charA = "A" . charCodeAt ( 0 ) ;
2931
2918
let currentIndex = 0 ;
@@ -3004,7 +2991,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
3004
2991
* }}
3005
2992
*/
3006
2993
for ( const [ crate , crateCorpus ] of rawSearchIndex ) {
3007
- searchWords . push ( crate ) ;
3008
2994
// This object should have exactly the same set of fields as the "row"
3009
2995
// object defined below. Your JavaScript runtime will thank you.
3010
2996
// https://mathiasbynens.be/notes/shapes-ics
@@ -3017,6 +3003,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
3017
3003
parent : undefined ,
3018
3004
type : null ,
3019
3005
id : id ,
3006
+ word : crate ,
3020
3007
normalizedName : crate . indexOf ( "_" ) === - 1 ? crate : crate . replace ( / _ / g, "" ) ,
3021
3008
deprecated : null ,
3022
3009
implDisambiguator : null ,
@@ -3084,12 +3071,9 @@ ${item.displayPath}<span class="${type}">${name}</span>\
3084
3071
len = itemTypes . length ;
3085
3072
for ( let i = 0 ; i < len ; ++ i ) {
3086
3073
let word = "" ;
3087
- // This object should have exactly the same set of fields as the "crateRow"
3088
- // object defined above.
3089
3074
if ( typeof itemNames [ i ] === "string" ) {
3090
3075
word = itemNames [ i ] . toLowerCase ( ) ;
3091
3076
}
3092
- searchWords . push ( word ) ;
3093
3077
const path = itemPaths . has ( i ) ? itemPaths . get ( i ) : lastPath ;
3094
3078
let type = null ;
3095
3079
if ( itemFunctionSearchTypes [ i ] !== 0 ) {
@@ -3113,6 +3097,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
3113
3097
}
3114
3098
}
3115
3099
}
3100
+ // This object should have exactly the same set of fields as the "crateRow"
3101
+ // object defined above.
3116
3102
const row = {
3117
3103
crate : crate ,
3118
3104
ty : itemTypes . charCodeAt ( i ) - charA ,
@@ -3122,6 +3108,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
3122
3108
parent : itemParentIdxs [ i ] > 0 ? paths [ itemParentIdxs [ i ] - 1 ] : undefined ,
3123
3109
type,
3124
3110
id : id ,
3111
+ word,
3125
3112
normalizedName : word . indexOf ( "_" ) === - 1 ? word : word . replace ( / _ / g, "" ) ,
3126
3113
deprecated : deprecatedItems . has ( i ) ,
3127
3114
implDisambiguator : implDisambiguator . has ( i ) ? implDisambiguator . get ( i ) : null ,
@@ -3153,7 +3140,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
3153
3140
}
3154
3141
currentIndex += itemTypes . length ;
3155
3142
}
3156
- return searchWords ;
3157
3143
}
3158
3144
3159
3145
/**
@@ -3332,10 +3318,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
3332
3318
search ( true ) ;
3333
3319
}
3334
3320
3335
- /**
3336
- * @type {Array<string> }
3337
- */
3338
- const searchWords = buildIndex ( rawSearchIndex ) ;
3321
+ buildIndex ( rawSearchIndex ) ;
3339
3322
if ( typeof window !== "undefined" ) {
3340
3323
registerSearchEvents ( ) ;
3341
3324
// If there's a search term in the URL, execute the search now.
@@ -3349,7 +3332,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
3349
3332
exports . execQuery = execQuery ;
3350
3333
exports . parseQuery = parseQuery ;
3351
3334
}
3352
- return searchWords ;
3353
3335
}
3354
3336
3355
3337
if ( typeof window !== "undefined" ) {
0 commit comments