@@ -264,6 +264,18 @@ function initSearch(rawSearchIndex) {
264
264
* Special type name IDs for searching by both array and slice (`[]` syntax).
265
265
*/
266
266
let typeNameIdOfArrayOrSlice ;
267
+ /**
268
+ * Special type name IDs for searching by tuple.
269
+ */
270
+ let typeNameIdOfTuple ;
271
+ /**
272
+ * Special type name IDs for searching by unit.
273
+ */
274
+ let typeNameIdOfUnit ;
275
+ /**
276
+ * Special type name IDs for searching by both tuple and unit (`()` syntax).
277
+ */
278
+ let typeNameIdOfTupleOrUnit ;
267
279
268
280
/**
269
281
* Add an item to the type Name->ID map, or, if one already exists, use it.
@@ -299,11 +311,7 @@ function initSearch(rawSearchIndex) {
299
311
}
300
312
301
313
function isEndCharacter ( c ) {
302
- return "=,>-]" . indexOf ( c ) !== - 1 ;
303
- }
304
-
305
- function isErrorCharacter ( c ) {
306
- return "()" . indexOf ( c ) !== - 1 ;
314
+ return "=,>-])" . indexOf ( c ) !== - 1 ;
307
315
}
308
316
309
317
function itemTypeFromName ( typename ) {
@@ -586,8 +594,6 @@ function initSearch(rawSearchIndex) {
586
594
throw [ "Unexpected " , "!" , ": it can only be at the end of an ident" ] ;
587
595
}
588
596
foundExclamation = parserState . pos ;
589
- } else if ( isErrorCharacter ( c ) ) {
590
- throw [ "Unexpected " , c ] ;
591
597
} else if ( isPathSeparator ( c ) ) {
592
598
if ( c === ":" ) {
593
599
if ( ! isPathStart ( parserState ) ) {
@@ -617,11 +623,14 @@ function initSearch(rawSearchIndex) {
617
623
}
618
624
} else if (
619
625
c === "[" ||
626
+ c === "(" ||
620
627
isEndCharacter ( c ) ||
621
628
isSpecialStartCharacter ( c ) ||
622
629
isSeparatorCharacter ( c )
623
630
) {
624
631
break ;
632
+ } else if ( parserState . pos > 0 ) {
633
+ throw [ "Unexpected " , c , " after " , parserState . userQuery [ parserState . pos - 1 ] ] ;
625
634
} else {
626
635
throw [ "Unexpected " , c ] ;
627
636
}
@@ -662,42 +671,55 @@ function initSearch(rawSearchIndex) {
662
671
skipWhitespace ( parserState ) ;
663
672
let start = parserState . pos ;
664
673
let end ;
665
- if ( parserState . userQuery [ parserState . pos ] === "[" ) {
674
+ if ( "[(" . indexOf ( parserState . userQuery [ parserState . pos ] ) !== - 1 ) {
675
+ let endChar = ")" ;
676
+ let name = "()" ;
677
+ let friendlyName = "tuple" ;
678
+
679
+ if ( parserState . userQuery [ parserState . pos ] === "[" ) {
680
+ endChar = "]" ;
681
+ name = "[]" ;
682
+ friendlyName = "slice" ;
683
+ }
666
684
parserState . pos += 1 ;
667
- getItemsBefore ( query , parserState , generics , "]" ) ;
685
+ const { foundSeparator } = getItemsBefore ( query , parserState , generics , endChar ) ;
668
686
const typeFilter = parserState . typeFilter ;
669
687
const isInBinding = parserState . isInBinding ;
670
688
if ( typeFilter !== null && typeFilter !== "primitive" ) {
671
689
throw [
672
690
"Invalid search type: primitive " ,
673
- "[]" ,
691
+ name ,
674
692
" and " ,
675
693
typeFilter ,
676
694
" both specified" ,
677
695
] ;
678
696
}
679
697
parserState . typeFilter = null ;
680
698
parserState . isInBinding = null ;
681
- parserState . totalElems += 1 ;
682
- if ( isInGenerics ) {
683
- parserState . genericsElems += 1 ;
684
- }
685
699
for ( const gen of generics ) {
686
700
if ( gen . bindingName !== null ) {
687
- throw [ "Type parameter " , "=" , " cannot be within slice " , "[]" ] ;
701
+ throw [ "Type parameter " , "=" , ` cannot be within ${ friendlyName } ` , name ] ;
688
702
}
689
703
}
690
- elems . push ( {
691
- name : "[]" ,
692
- id : null ,
693
- fullPath : [ "[]" ] ,
694
- pathWithoutLast : [ ] ,
695
- pathLast : "[]" ,
696
- generics,
697
- typeFilter : "primitive" ,
698
- bindingName : isInBinding ,
699
- bindings : new Map ( ) ,
700
- } ) ;
704
+ if ( name === "()" && ! foundSeparator && generics . length === 1 && typeFilter === null ) {
705
+ elems . push ( generics [ 0 ] ) ;
706
+ } else {
707
+ parserState . totalElems += 1 ;
708
+ if ( isInGenerics ) {
709
+ parserState . genericsElems += 1 ;
710
+ }
711
+ elems . push ( {
712
+ name : name ,
713
+ id : null ,
714
+ fullPath : [ name ] ,
715
+ pathWithoutLast : [ ] ,
716
+ pathLast : name ,
717
+ generics,
718
+ bindings : new Map ( ) ,
719
+ typeFilter : "primitive" ,
720
+ bindingName : isInBinding ,
721
+ } ) ;
722
+ }
701
723
} else {
702
724
const isStringElem = parserState . userQuery [ start ] === "\"" ;
703
725
// We handle the strings on their own mostly to make code easier to follow.
@@ -770,9 +792,11 @@ function initSearch(rawSearchIndex) {
770
792
* @param {Array<QueryElement> } elems - This is where the new {QueryElement} will be added.
771
793
* @param {string } endChar - This function will stop when it'll encounter this
772
794
* character.
795
+ * @returns {{foundSeparator: bool} }
773
796
*/
774
797
function getItemsBefore ( query , parserState , elems , endChar ) {
775
798
let foundStopChar = true ;
799
+ let foundSeparator = false ;
776
800
let start = parserState . pos ;
777
801
778
802
// If this is a generic, keep the outer item's type filter around.
@@ -786,6 +810,8 @@ function initSearch(rawSearchIndex) {
786
810
extra = "<" ;
787
811
} else if ( endChar === "]" ) {
788
812
extra = "[" ;
813
+ } else if ( endChar === ")" ) {
814
+ extra = "(" ;
789
815
} else if ( endChar === "" ) {
790
816
extra = "->" ;
791
817
} else {
@@ -802,6 +828,7 @@ function initSearch(rawSearchIndex) {
802
828
} else if ( isSeparatorCharacter ( c ) ) {
803
829
parserState . pos += 1 ;
804
830
foundStopChar = true ;
831
+ foundSeparator = true ;
805
832
continue ;
806
833
} else if ( c === ":" && isPathStart ( parserState ) ) {
807
834
throw [ "Unexpected " , "::" , ": paths cannot start with " , "::" ] ;
@@ -879,6 +906,8 @@ function initSearch(rawSearchIndex) {
879
906
880
907
parserState . typeFilter = oldTypeFilter ;
881
908
parserState . isInBinding = oldIsInBinding ;
909
+
910
+ return { foundSeparator } ;
882
911
}
883
912
884
913
/**
@@ -926,6 +955,8 @@ function initSearch(rawSearchIndex) {
926
955
break ;
927
956
}
928
957
throw [ "Unexpected " , c , " (did you mean " , "->" , "?)" ] ;
958
+ } else if ( parserState . pos > 0 ) {
959
+ throw [ "Unexpected " , c , " after " , parserState . userQuery [ parserState . pos - 1 ] ] ;
929
960
}
930
961
throw [ "Unexpected " , c ] ;
931
962
} else if ( c === ":" && ! isPathStart ( parserState ) ) {
@@ -1600,6 +1631,11 @@ function initSearch(rawSearchIndex) {
1600
1631
) {
1601
1632
// [] matches primitive:array or primitive:slice
1602
1633
// if it matches, then we're fine, and this is an appropriate match candidate
1634
+ } else if ( queryElem . id === typeNameIdOfTupleOrUnit &&
1635
+ ( fnType . id === typeNameIdOfTuple || fnType . id === typeNameIdOfUnit )
1636
+ ) {
1637
+ // () matches primitive:tuple or primitive:unit
1638
+ // if it matches, then we're fine, and this is an appropriate match candidate
1603
1639
} else if ( fnType . id !== queryElem . id || queryElem . id === null ) {
1604
1640
return false ;
1605
1641
}
@@ -1793,7 +1829,7 @@ function initSearch(rawSearchIndex) {
1793
1829
if ( row . id > 0 && elem . id > 0 && elem . pathWithoutLast . length === 0 &&
1794
1830
typePassesFilter ( elem . typeFilter , row . ty ) && elem . generics . length === 0 &&
1795
1831
// special case
1796
- elem . id !== typeNameIdOfArrayOrSlice
1832
+ elem . id !== typeNameIdOfArrayOrSlice && elem . id !== typeNameIdOfTupleOrUnit
1797
1833
) {
1798
1834
return row . id === elem . id || checkIfInList (
1799
1835
row . generics ,
@@ -2834,12 +2870,15 @@ ${item.displayPath}<span class="${type}">${name}</span>\
2834
2870
*/
2835
2871
function buildFunctionTypeFingerprint ( type , output , fps ) {
2836
2872
let input = type . id ;
2837
- // All forms of `[]` get collapsed down to one thing in the bloom filter.
2873
+ // All forms of `[]`/`()` get collapsed down to one thing in the bloom filter.
2838
2874
// Differentiating between arrays and slices, if the user asks for it, is
2839
2875
// still done in the matching algorithm.
2840
2876
if ( input === typeNameIdOfArray || input === typeNameIdOfSlice ) {
2841
2877
input = typeNameIdOfArrayOrSlice ;
2842
2878
}
2879
+ if ( input === typeNameIdOfTuple || input === typeNameIdOfUnit ) {
2880
+ input = typeNameIdOfTupleOrUnit ;
2881
+ }
2843
2882
// http://burtleburtle.net/bob/hash/integer.html
2844
2883
// ~~ is toInt32. It's used before adding, so
2845
2884
// the number stays in safe integer range.
@@ -2940,7 +2979,10 @@ ${item.displayPath}<span class="${type}">${name}</span>\
2940
2979
// that can be searched using `[]` syntax.
2941
2980
typeNameIdOfArray = buildTypeMapIndex ( "array" ) ;
2942
2981
typeNameIdOfSlice = buildTypeMapIndex ( "slice" ) ;
2982
+ typeNameIdOfTuple = buildTypeMapIndex ( "tuple" ) ;
2983
+ typeNameIdOfUnit = buildTypeMapIndex ( "unit" ) ;
2943
2984
typeNameIdOfArrayOrSlice = buildTypeMapIndex ( "[]" ) ;
2985
+ typeNameIdOfTupleOrUnit = buildTypeMapIndex ( "()" ) ;
2944
2986
2945
2987
// Function type fingerprints are 128-bit bloom filters that are used to
2946
2988
// estimate the distance between function and query.
0 commit comments