1+ // ignore-tidy-filelength
12/* global addClass, getNakedUrl, getSettingValue */
23/* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */
34
@@ -578,7 +579,10 @@ function initSearch(rawSearchIndex) {
578579 // Syntactically, bindings are parsed as generics,
579580 // but the query engine treats them differently.
580581 if ( gen . bindingName !== null ) {
581- bindings . set ( gen . bindingName . name , [ gen , ...gen . bindingName . generics ] ) ;
582+ if ( gen . name !== null ) {
583+ gen . bindingName . generics . unshift ( gen ) ;
584+ }
585+ bindings . set ( gen . bindingName . name , gen . bindingName . generics ) ;
582586 return false ;
583587 }
584588 return true ;
@@ -678,6 +682,38 @@ function initSearch(rawSearchIndex) {
678682 return end ;
679683 }
680684
685+ function getFilteredNextElem ( query , parserState , elems , isInGenerics ) {
686+ const start = parserState . pos ;
687+ if ( parserState . userQuery [ parserState . pos ] === ":" && ! isPathStart ( parserState ) ) {
688+ throw [ "Expected type filter before " , ":" ] ;
689+ }
690+ getNextElem ( query , parserState , elems , isInGenerics ) ;
691+ if ( parserState . userQuery [ parserState . pos ] === ":" && ! isPathStart ( parserState ) ) {
692+ if ( parserState . typeFilter !== null ) {
693+ throw [
694+ "Unexpected " ,
695+ ":" ,
696+ " (expected path after type filter " ,
697+ parserState . typeFilter + ":" ,
698+ ")" ,
699+ ] ;
700+ }
701+ if ( elems . length === 0 ) {
702+ throw [ "Expected type filter before " , ":" ] ;
703+ } else if ( query . literalSearch ) {
704+ throw [ "Cannot use quotes on type filter" ] ;
705+ }
706+ // The type filter doesn't count as an element since it's a modifier.
707+ const typeFilterElem = elems . pop ( ) ;
708+ checkExtraTypeFilterCharacters ( start , parserState ) ;
709+ parserState . typeFilter = typeFilterElem . name ;
710+ parserState . pos += 1 ;
711+ parserState . totalElems -= 1 ;
712+ query . literalSearch = false ;
713+ getNextElem ( query , parserState , elems , isInGenerics ) ;
714+ }
715+ }
716+
681717 /**
682718 * @param {ParsedQuery } query
683719 * @param {ParserState } parserState
@@ -752,6 +788,32 @@ function initSearch(rawSearchIndex) {
752788 }
753789 parserState . pos += 1 ;
754790 getItemsBefore ( query , parserState , generics , ">" ) ;
791+ } else if ( parserState . pos < parserState . length &&
792+ parserState . userQuery [ parserState . pos ] === "("
793+ ) {
794+ if ( start >= end ) {
795+ throw [ "Found generics without a path" ] ;
796+ }
797+ if ( parserState . isInBinding ) {
798+ throw [ "Unexpected " , "(" , " after " , "=" ] ;
799+ }
800+ parserState . pos += 1 ;
801+ const typeFilter = parserState . typeFilter ;
802+ parserState . typeFilter = null ;
803+ getItemsBefore ( query , parserState , generics , ")" ) ;
804+ skipWhitespace ( parserState ) ;
805+ if ( isReturnArrow ( parserState ) ) {
806+ parserState . pos += 2 ;
807+ skipWhitespace ( parserState ) ;
808+ getFilteredNextElem ( query , parserState , generics , isInGenerics ) ;
809+ generics [ generics . length - 1 ] . bindingName = makePrimitiveElement ( "output" ) ;
810+ } else {
811+ generics . push ( makePrimitiveElement ( null , {
812+ bindingName : makePrimitiveElement ( "output" ) ,
813+ typeFilter : null ,
814+ } ) ) ;
815+ }
816+ parserState . typeFilter = typeFilter ;
755817 }
756818 if ( isStringElem ) {
757819 skipWhitespace ( parserState ) ;
@@ -811,7 +873,6 @@ function initSearch(rawSearchIndex) {
811873 function getItemsBefore ( query , parserState , elems , endChar ) {
812874 let foundStopChar = true ;
813875 let foundSeparator = false ;
814- let start = parserState . pos ;
815876
816877 // If this is a generic, keep the outer item's type filter around.
817878 const oldTypeFilter = parserState . typeFilter ;
@@ -874,24 +935,6 @@ function initSearch(rawSearchIndex) {
874935 continue ;
875936 } else if ( c === ":" && isPathStart ( parserState ) ) {
876937 throw [ "Unexpected " , "::" , ": paths cannot start with " , "::" ] ;
877- } else if ( c === ":" ) {
878- if ( parserState . typeFilter !== null ) {
879- throw [ "Unexpected " , ":" ] ;
880- }
881- if ( elems . length === 0 ) {
882- throw [ "Expected type filter before " , ":" ] ;
883- } else if ( query . literalSearch ) {
884- throw [ "Cannot use quotes on type filter" ] ;
885- }
886- // The type filter doesn't count as an element since it's a modifier.
887- const typeFilterElem = elems . pop ( ) ;
888- checkExtraTypeFilterCharacters ( start , parserState ) ;
889- parserState . typeFilter = typeFilterElem . name ;
890- parserState . pos += 1 ;
891- parserState . totalElems -= 1 ;
892- query . literalSearch = false ;
893- foundStopChar = true ;
894- continue ;
895938 } else if ( isEndCharacter ( c ) ) {
896939 throw [ "Unexpected " , c , " after " , extra ] ;
897940 }
@@ -926,8 +969,7 @@ function initSearch(rawSearchIndex) {
926969 ] ;
927970 }
928971 const posBefore = parserState . pos ;
929- start = parserState . pos ;
930- getNextElem ( query , parserState , elems , endChar !== "" ) ;
972+ getFilteredNextElem ( query , parserState , elems , endChar !== "" ) ;
931973 if ( endChar !== "" && parserState . pos >= parserState . length ) {
932974 throw [ "Unclosed " , extra ] ;
933975 }
@@ -1004,7 +1046,6 @@ function initSearch(rawSearchIndex) {
10041046 */
10051047 function parseInput ( query , parserState ) {
10061048 let foundStopChar = true ;
1007- let start = parserState . pos ;
10081049
10091050 while ( parserState . pos < parserState . length ) {
10101051 const c = parserState . userQuery [ parserState . pos ] ;
@@ -1022,29 +1063,6 @@ function initSearch(rawSearchIndex) {
10221063 throw [ "Unexpected " , c , " after " , parserState . userQuery [ parserState . pos - 1 ] ] ;
10231064 }
10241065 throw [ "Unexpected " , c ] ;
1025- } else if ( c === ":" && ! isPathStart ( parserState ) ) {
1026- if ( parserState . typeFilter !== null ) {
1027- throw [
1028- "Unexpected " ,
1029- ":" ,
1030- " (expected path after type filter " ,
1031- parserState . typeFilter + ":" ,
1032- ")" ,
1033- ] ;
1034- } else if ( query . elems . length === 0 ) {
1035- throw [ "Expected type filter before " , ":" ] ;
1036- } else if ( query . literalSearch ) {
1037- throw [ "Cannot use quotes on type filter" ] ;
1038- }
1039- // The type filter doesn't count as an element since it's a modifier.
1040- const typeFilterElem = query . elems . pop ( ) ;
1041- checkExtraTypeFilterCharacters ( start , parserState ) ;
1042- parserState . typeFilter = typeFilterElem . name ;
1043- parserState . pos += 1 ;
1044- parserState . totalElems -= 1 ;
1045- query . literalSearch = false ;
1046- foundStopChar = true ;
1047- continue ;
10481066 } else if ( c === " " ) {
10491067 skipWhitespace ( parserState ) ;
10501068 continue ;
@@ -1080,8 +1098,7 @@ function initSearch(rawSearchIndex) {
10801098 ] ;
10811099 }
10821100 const before = query . elems . length ;
1083- start = parserState . pos ;
1084- getNextElem ( query , parserState , query . elems , false ) ;
1101+ getFilteredNextElem ( query , parserState , query . elems , false ) ;
10851102 if ( query . elems . length === before ) {
10861103 // Nothing was added, weird... Let's increase the position to not remain stuck.
10871104 parserState . pos += 1 ;
0 commit comments