@@ -578,7 +578,10 @@ function initSearch(rawSearchIndex) {
578578 // Syntactically, bindings are parsed as generics,
579579 // but the query engine treats them differently.
580580 if ( gen . bindingName !== null ) {
581- bindings . set ( gen . bindingName . name , [ gen , ...gen . bindingName . generics ] ) ;
581+ if ( gen . name !== null ) {
582+ gen . bindingName . generics . unshift ( gen ) ;
583+ }
584+ bindings . set ( gen . bindingName . name , gen . bindingName . generics ) ;
582585 return false ;
583586 }
584587 return true ;
@@ -678,6 +681,38 @@ function initSearch(rawSearchIndex) {
678681 return end ;
679682 }
680683
684+ function getFilteredNextElem ( query , parserState , elems , isInGenerics ) {
685+ const start = parserState . pos ;
686+ if ( parserState . userQuery [ parserState . pos ] === ":" && ! isPathStart ( parserState ) ) {
687+ throw [ "Expected type filter before " , ":" ] ;
688+ }
689+ getNextElem ( query , parserState , elems , isInGenerics ) ;
690+ if ( parserState . userQuery [ parserState . pos ] === ":" && ! isPathStart ( parserState ) ) {
691+ if ( parserState . typeFilter !== null ) {
692+ throw [
693+ "Unexpected " ,
694+ ":" ,
695+ " (expected path after type filter " ,
696+ parserState . typeFilter + ":" ,
697+ ")" ,
698+ ] ;
699+ }
700+ if ( elems . length === 0 ) {
701+ throw [ "Expected type filter before " , ":" ] ;
702+ } else if ( query . literalSearch ) {
703+ throw [ "Cannot use quotes on type filter" ] ;
704+ }
705+ // The type filter doesn't count as an element since it's a modifier.
706+ const typeFilterElem = elems . pop ( ) ;
707+ checkExtraTypeFilterCharacters ( start , parserState ) ;
708+ parserState . typeFilter = typeFilterElem . name ;
709+ parserState . pos += 1 ;
710+ parserState . totalElems -= 1 ;
711+ query . literalSearch = false ;
712+ getNextElem ( query , parserState , elems , isInGenerics ) ;
713+ }
714+ }
715+
681716 /**
682717 * @param {ParsedQuery } query
683718 * @param {ParserState } parserState
@@ -752,6 +787,32 @@ function initSearch(rawSearchIndex) {
752787 }
753788 parserState . pos += 1 ;
754789 getItemsBefore ( query , parserState , generics , ">" ) ;
790+ } else if ( parserState . pos < parserState . length &&
791+ parserState . userQuery [ parserState . pos ] === "("
792+ ) {
793+ if ( start >= end ) {
794+ throw [ "Found generics without a path" ] ;
795+ }
796+ if ( parserState . isInBinding ) {
797+ throw [ "Unexpected " , "(" , " after " , "=" ] ;
798+ }
799+ parserState . pos += 1 ;
800+ const typeFilter = parserState . typeFilter ;
801+ parserState . typeFilter = null ;
802+ getItemsBefore ( query , parserState , generics , ")" ) ;
803+ skipWhitespace ( parserState ) ;
804+ if ( isReturnArrow ( parserState ) ) {
805+ parserState . pos += 2 ;
806+ skipWhitespace ( parserState ) ;
807+ getFilteredNextElem ( query , parserState , generics , isInGenerics ) ;
808+ generics [ generics . length - 1 ] . bindingName = makePrimitiveElement ( "output" ) ;
809+ } else {
810+ generics . push ( makePrimitiveElement ( null , {
811+ bindingName : makePrimitiveElement ( "output" ) ,
812+ typeFilter : null ,
813+ } ) ) ;
814+ }
815+ parserState . typeFilter = typeFilter ;
755816 }
756817 if ( isStringElem ) {
757818 skipWhitespace ( parserState ) ;
@@ -811,7 +872,6 @@ function initSearch(rawSearchIndex) {
811872 function getItemsBefore ( query , parserState , elems , endChar ) {
812873 let foundStopChar = true ;
813874 let foundSeparator = false ;
814- let start = parserState . pos ;
815875
816876 // If this is a generic, keep the outer item's type filter around.
817877 const oldTypeFilter = parserState . typeFilter ;
@@ -874,24 +934,6 @@ function initSearch(rawSearchIndex) {
874934 continue ;
875935 } else if ( c === ":" && isPathStart ( parserState ) ) {
876936 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 ;
895937 } else if ( isEndCharacter ( c ) ) {
896938 throw [ "Unexpected " , c , " after " , extra ] ;
897939 }
@@ -926,8 +968,7 @@ function initSearch(rawSearchIndex) {
926968 ] ;
927969 }
928970 const posBefore = parserState . pos ;
929- start = parserState . pos ;
930- getNextElem ( query , parserState , elems , endChar !== "" ) ;
971+ getFilteredNextElem ( query , parserState , elems , endChar !== "" ) ;
931972 if ( endChar !== "" && parserState . pos >= parserState . length ) {
932973 throw [ "Unclosed " , extra ] ;
933974 }
@@ -1004,7 +1045,6 @@ function initSearch(rawSearchIndex) {
10041045 */
10051046 function parseInput ( query , parserState ) {
10061047 let foundStopChar = true ;
1007- let start = parserState . pos ;
10081048
10091049 while ( parserState . pos < parserState . length ) {
10101050 const c = parserState . userQuery [ parserState . pos ] ;
@@ -1022,29 +1062,6 @@ function initSearch(rawSearchIndex) {
10221062 throw [ "Unexpected " , c , " after " , parserState . userQuery [ parserState . pos - 1 ] ] ;
10231063 }
10241064 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 ;
10481065 } else if ( c === " " ) {
10491066 skipWhitespace ( parserState ) ;
10501067 continue ;
@@ -1080,8 +1097,7 @@ function initSearch(rawSearchIndex) {
10801097 ] ;
10811098 }
10821099 const before = query . elems . length ;
1083- start = parserState . pos ;
1084- getNextElem ( query , parserState , query . elems , false ) ;
1100+ getFilteredNextElem ( query , parserState , query . elems , false ) ;
10851101 if ( query . elems . length === before ) {
10861102 // Nothing was added, weird... Let's increase the position to not remain stuck.
10871103 parserState . pos += 1 ;
0 commit comments