@@ -89,6 +89,10 @@ const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../";
89
89
// of permutations we need to check.
90
90
const UNBOXING_LIMIT = 5 ;
91
91
92
+ // used for search query verification
93
+ const REGEX_IDENT = / \p{ ID_Start} \p{ ID_Continue} * | _ \p{ ID_Continue} + / uy;
94
+ const REGEX_INVALID_TYPE_FILTER = / [ ^ a - z ] / ui;
95
+
92
96
// In the search display, allows to switch between tabs.
93
97
function printTab ( nb ) {
94
98
let iter = 0 ;
@@ -410,18 +414,21 @@ function initSearch(rawSearchIndex) {
410
414
}
411
415
412
416
/**
413
- * Returns `true` if the given `c` character is valid for an ident.
417
+ * If the current parser position is at the beginning of an identifier,
418
+ * move the position to the end of it and return `true`. Otherwise, return `false`.
414
419
*
415
- * @param {string } c
420
+ * @param {ParserState } parserState
416
421
*
417
422
* @return {boolean }
418
423
*/
419
- function isIdentCharacter ( c ) {
420
- return (
421
- c === "_" ||
422
- ( c >= "0" && c <= "9" ) ||
423
- ( c >= "a" && c <= "z" ) ||
424
- ( c >= "A" && c <= "Z" ) ) ;
424
+ function consumeIdent ( parserState ) {
425
+ REGEX_IDENT . lastIndex = parserState . pos ;
426
+ const match = parserState . userQuery . match ( REGEX_IDENT ) ;
427
+ if ( match ) {
428
+ parserState . pos += match [ 0 ] . length ;
429
+ return true ;
430
+ }
431
+ return false ;
425
432
}
426
433
427
434
/**
@@ -618,70 +625,62 @@ function initSearch(rawSearchIndex) {
618
625
* @return {integer }
619
626
*/
620
627
function getIdentEndPosition ( parserState ) {
621
- const start = parserState . pos ;
628
+ let afterIdent = consumeIdent ( parserState ) ;
622
629
let end = parserState . pos ;
623
- let foundExclamation = - 1 ;
630
+ let macroExclamation = - 1 ;
624
631
while ( parserState . pos < parserState . length ) {
625
632
const c = parserState . userQuery [ parserState . pos ] ;
626
- if ( ! isIdentCharacter ( c ) ) {
627
- if ( c === "!" ) {
628
- if ( foundExclamation !== - 1 ) {
629
- throw [ "Cannot have more than one " , "!" , " in an ident" ] ;
630
- } else if ( parserState . pos + 1 < parserState . length &&
631
- isIdentCharacter ( parserState . userQuery [ parserState . pos + 1 ] )
632
- ) {
633
+ if ( c === "!" ) {
634
+ if ( macroExclamation !== - 1 ) {
635
+ throw [ "Cannot have more than one " , "!" , " in an ident" ] ;
636
+ } else if ( parserState . pos + 1 < parserState . length ) {
637
+ const pos = parserState . pos ;
638
+ parserState . pos ++ ;
639
+ const beforeIdent = consumeIdent ( parserState ) ;
640
+ parserState . pos = pos ;
641
+ if ( beforeIdent ) {
633
642
throw [ "Unexpected " , "!" , ": it can only be at the end of an ident" ] ;
634
643
}
635
- foundExclamation = parserState . pos ;
636
- } else if ( isPathSeparator ( c ) ) {
637
- if ( c === ":" ) {
638
- if ( ! isPathStart ( parserState ) ) {
644
+ }
645
+ if ( afterIdent ) macroExclamation = parserState . pos ;
646
+ } else if ( isPathSeparator ( c ) ) {
647
+ if ( c === ":" ) {
648
+ if ( ! isPathStart ( parserState ) ) {
649
+ break ;
650
+ }
651
+ // Skip current ":".
652
+ parserState . pos += 1 ;
653
+ } else {
654
+ while ( parserState . pos + 1 < parserState . length ) {
655
+ const next_c = parserState . userQuery [ parserState . pos + 1 ] ;
656
+ if ( next_c !== " " ) {
639
657
break ;
640
658
}
641
- // Skip current ":".
642
659
parserState . pos += 1 ;
643
- } else {
644
- while ( parserState . pos + 1 < parserState . length ) {
645
- const next_c = parserState . userQuery [ parserState . pos + 1 ] ;
646
- if ( next_c !== " " ) {
647
- break ;
648
- }
649
- parserState . pos += 1 ;
650
- }
651
660
}
652
- if ( foundExclamation !== - 1 ) {
653
- if ( foundExclamation !== start &&
654
- isIdentCharacter ( parserState . userQuery [ foundExclamation - 1 ] )
655
- ) {
656
- throw [ "Cannot have associated items in macros" ] ;
657
- } else {
658
- // while the never type has no associated macros, we still
659
- // can parse a path like that
660
- foundExclamation = - 1 ;
661
- }
662
- }
663
- } else if (
664
- c === "[" ||
665
- c === "(" ||
666
- isEndCharacter ( c ) ||
667
- isSpecialStartCharacter ( c ) ||
668
- isSeparatorCharacter ( c )
669
- ) {
670
- break ;
671
- } else if ( parserState . pos > 0 ) {
672
- throw [ "Unexpected " , c , " after " , parserState . userQuery [ parserState . pos - 1 ] ] ;
673
- } else {
674
- throw [ "Unexpected " , c ] ;
675
661
}
662
+ if ( macroExclamation !== - 1 ) {
663
+ throw [ "Cannot have associated items in macros" ] ;
664
+ }
665
+ } else if (
666
+ c === "[" ||
667
+ c === "(" ||
668
+ isEndCharacter ( c ) ||
669
+ isSpecialStartCharacter ( c ) ||
670
+ isSeparatorCharacter ( c )
671
+ ) {
672
+ break ;
673
+ } else if ( parserState . pos > 0 ) {
674
+ throw [ "Unexpected " , c , " after " , parserState . userQuery [ parserState . pos - 1 ] ,
675
+ " (not a valid identifier)" ] ;
676
+ } else {
677
+ throw [ "Unexpected " , c , " (not a valid identifier)" ] ;
676
678
}
677
679
parserState . pos += 1 ;
680
+ afterIdent = consumeIdent ( parserState ) ;
678
681
end = parserState . pos ;
679
682
}
680
- // if start == end - 1, we got the never type
681
- if ( foundExclamation !== - 1 &&
682
- foundExclamation !== start &&
683
- isIdentCharacter ( parserState . userQuery [ foundExclamation - 1 ] )
684
- ) {
683
+ if ( macroExclamation !== - 1 ) {
685
684
if ( parserState . typeFilter === null ) {
686
685
parserState . typeFilter = "macro" ;
687
686
} else if ( parserState . typeFilter !== "macro" ) {
@@ -693,7 +692,7 @@ function initSearch(rawSearchIndex) {
693
692
" both specified" ,
694
693
] ;
695
694
}
696
- end = foundExclamation ;
695
+ end = macroExclamation ;
697
696
}
698
697
return end ;
699
698
}
@@ -1071,16 +1070,15 @@ function initSearch(rawSearchIndex) {
1071
1070
function checkExtraTypeFilterCharacters ( start , parserState ) {
1072
1071
const query = parserState . userQuery . slice ( start , parserState . pos ) . trim ( ) ;
1073
1072
1074
- for ( const c in query ) {
1075
- if ( ! isIdentCharacter ( query [ c ] ) ) {
1076
- throw [
1077
- "Unexpected " ,
1078
- query [ c ] ,
1079
- " in type filter (before " ,
1080
- ":" ,
1081
- ")" ,
1082
- ] ;
1083
- }
1073
+ const match = query . match ( REGEX_INVALID_TYPE_FILTER ) ;
1074
+ if ( match ) {
1075
+ throw [
1076
+ "Unexpected " ,
1077
+ match [ 0 ] ,
1078
+ " in type filter (before " ,
1079
+ ":" ,
1080
+ ")" ,
1081
+ ] ;
1084
1082
}
1085
1083
}
1086
1084
@@ -2127,7 +2125,7 @@ function initSearch(rawSearchIndex) {
2127
2125
} ;
2128
2126
}
2129
2127
2130
- function handleAliases ( ret , query , filterCrates , currentCrate ) {
2128
+ async function handleAliases ( ret , query , filterCrates , currentCrate ) {
2131
2129
const lowerQuery = query . toLowerCase ( ) ;
2132
2130
// We separate aliases and crate aliases because we want to have current crate
2133
2131
// aliases to be before the others in the displayed results.
@@ -2163,6 +2161,15 @@ function initSearch(rawSearchIndex) {
2163
2161
crateAliases . sort ( sortFunc ) ;
2164
2162
aliases . sort ( sortFunc ) ;
2165
2163
2164
+ const fetchDesc = alias => {
2165
+ return searchIndexEmptyDesc . get ( alias . crate ) . contains ( alias . bitIndex ) ?
2166
+ "" : searchState . loadDesc ( alias ) ;
2167
+ } ;
2168
+ const [ crateDescs , descs ] = await Promise . all ( [
2169
+ Promise . all ( crateAliases . map ( fetchDesc ) ) ,
2170
+ Promise . all ( aliases . map ( fetchDesc ) ) ,
2171
+ ] ) ;
2172
+
2166
2173
const pushFunc = alias => {
2167
2174
alias . alias = query ;
2168
2175
const res = buildHrefAndPath ( alias ) ;
@@ -2176,7 +2183,13 @@ function initSearch(rawSearchIndex) {
2176
2183
}
2177
2184
} ;
2178
2185
2186
+ aliases . forEach ( ( alias , i ) => {
2187
+ alias . desc = descs [ i ] ;
2188
+ } ) ;
2179
2189
aliases . forEach ( pushFunc ) ;
2190
+ crateAliases . forEach ( ( alias , i ) => {
2191
+ alias . desc = crateDescs [ i ] ;
2192
+ } ) ;
2180
2193
crateAliases . forEach ( pushFunc ) ;
2181
2194
}
2182
2195
@@ -2538,7 +2551,8 @@ function initSearch(rawSearchIndex) {
2538
2551
sorted_returned ,
2539
2552
sorted_others ,
2540
2553
parsedQuery ) ;
2541
- handleAliases ( ret , parsedQuery . original . replace ( / " / g, "" ) , filterCrates , currentCrate ) ;
2554
+ await handleAliases ( ret , parsedQuery . original . replace ( / " / g, "" ) ,
2555
+ filterCrates , currentCrate ) ;
2542
2556
await Promise . all ( [ ret . others , ret . returned , ret . in_args ] . map ( async list => {
2543
2557
const descs = await Promise . all ( list . map ( result => {
2544
2558
return searchIndexEmptyDesc . get ( result . crate ) . contains ( result . bitIndex ) ?
0 commit comments