@@ -172,7 +172,7 @@ window.initSearch = function(rawSearchIndex) {
172172 throw new Error ( "`\"` cannot be used in generics" ) ;
173173 } else if ( query . literalSearch ) {
174174 throw new Error ( "Cannot have more than one literal search element" ) ;
175- } else if ( parserState . totalElems !== 0 ) {
175+ } else if ( parserState . totalElems - parserState . genericsElems > 0 ) {
176176 throw new Error ( "Cannot use literal search when there is more than one element" ) ;
177177 }
178178 parserState . pos += 1 ;
@@ -234,11 +234,11 @@ window.initSearch = function(rawSearchIndex) {
234234 *
235235 * @return {QueryElement } - The newly created `QueryElement`.
236236 */
237- function createQueryElement ( query , parserState , name , generics ) {
237+ function createQueryElement ( query , parserState , name , generics , isInGenerics ) {
238238 if ( name === '*' || ( name . length === 0 && generics . length === 0 ) ) {
239239 return ;
240240 }
241- if ( query . literalSearch && parserState . totalElems > 0 ) {
241+ if ( query . literalSearch && parserState . totalElems - parserState . genericsElems > 0 ) {
242242 throw new Error ( "You cannot have more than one element if you use quotes" ) ;
243243 }
244244 var pathSegments = name . split ( "::" ) ;
@@ -261,6 +261,9 @@ window.initSearch = function(rawSearchIndex) {
261261 throw new Error ( "Found generics without a path" ) ;
262262 }
263263 parserState . totalElems += 1 ;
264+ if ( isInGenerics ) {
265+ parserState . genericsElems += 1 ;
266+ }
264267 return {
265268 name : name ,
266269 fullPath : pathSegments ,
@@ -315,6 +318,8 @@ window.initSearch = function(rawSearchIndex) {
315318 {
316319 if ( isInGenerics ) {
317320 throw new Error ( "Unexpected `<` after `<`" ) ;
321+ } else if ( start >= end ) {
322+ throw new Error ( "Found generics without a path" ) ;
318323 }
319324 parserState . pos += 1 ;
320325 getItemsBefore ( query , parserState , generics , ">" ) ;
@@ -327,7 +332,8 @@ window.initSearch = function(rawSearchIndex) {
327332 query ,
328333 parserState ,
329334 parserState . userQuery . slice ( start , end ) ,
330- generics
335+ generics ,
336+ isInGenerics
331337 )
332338 ) ;
333339 }
@@ -346,13 +352,15 @@ window.initSearch = function(rawSearchIndex) {
346352 * character.
347353 */
348354 function getItemsBefore ( query , parserState , elems , endChar ) {
349- var turns = 0 ;
355+ var foundStopChar = true ;
356+
350357 while ( parserState . pos < parserState . length ) {
351358 var c = parserState . userQuery [ parserState . pos ] ;
352359 if ( c === endChar ) {
353360 break ;
354- } else if ( c === "," && endChar !== "" && turns > 0 ) {
361+ } else if ( c === "," || c === " " ) {
355362 parserState . pos += 1 ;
363+ foundStopChar = true ;
356364 continue ;
357365 } else if ( c === ":" && isPathStart ( parserState ) ) {
358366 throw new Error ( "Unexpected `::`: paths cannot start with `::`" ) ;
@@ -365,15 +373,21 @@ window.initSearch = function(rawSearchIndex) {
365373 }
366374 throw new Error ( "Unexpected `" + c + "` after " + extra ) ;
367375 }
376+ if ( ! foundStopChar ) {
377+ if ( endChar !== "" ) {
378+ throw new Error ( `Expected \`,\`, \` \` or \`${ endChar } \`, found \`${ c } \`` ) ;
379+ }
380+ throw new Error ( `Expected \`,\` or \` \`, found \`${ c } \`` ) ;
381+ }
368382 var posBefore = parserState . pos ;
369383 getNextElem ( query , parserState , elems , endChar === ">" ) ;
370- turns += 1 ;
371384 // This case can be encountered if `getNextElem` encounted a "stop character" right from
372- // the start. For example if you have `,,`. In this case, we simply move up the current
373- // position to continue the parsing.
385+ // the start. For example if you have `,,` or `<>` . In this case, we simply move up the
386+ // current position to continue the parsing.
374387 if ( posBefore === parserState . pos ) {
375388 parserState . pos += 1 ;
376389 }
390+ foundStopChar = false ;
377391 }
378392 // We are either at the end of the string or on the `endChar`` character, let's move forward
379393 // in any case.
@@ -389,10 +403,12 @@ window.initSearch = function(rawSearchIndex) {
389403 */
390404 function parseInput ( query , parserState ) {
391405 var c , before ;
406+ var foundStopChar = true ;
392407
393408 while ( parserState . pos < parserState . length ) {
394409 c = parserState . userQuery [ parserState . pos ] ;
395410 if ( isStopCharacter ( c ) ) {
411+ foundStopChar = true ;
396412 if ( c === "," || c === " " ) {
397413 parserState . pos += 1 ;
398414 continue ;
@@ -402,6 +418,7 @@ window.initSearch = function(rawSearchIndex) {
402418 }
403419 throw new Error ( `Unexpected \`${ c } \` (did you mean \`->\`?)` ) ;
404420 }
421+ throw new Error ( `Unexpected \`${ c } \`` ) ;
405422 } else if ( c === ":" &&
406423 parserState . typeFilter === null &&
407424 ! isPathStart ( parserState ) )
@@ -419,8 +436,15 @@ window.initSearch = function(rawSearchIndex) {
419436 parserState . pos += 1 ;
420437 parserState . totalElems = 0 ;
421438 query . literalSearch = false ;
439+ foundStopChar = true ;
422440 continue ;
423441 }
442+ if ( ! foundStopChar ) {
443+ if ( parserState . typeFilter !== null ) {
444+ throw new Error ( `Expected \`,\`, \` \` or \`->\`, found \`${ c } \`` ) ;
445+ }
446+ throw new Error ( `Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${ c } \`` ) ;
447+ }
424448 before = query . elems . length ;
425449 getNextElem ( query , parserState , query . elems , false ) ;
426450 if ( query . elems . length === before ) {
@@ -432,6 +456,7 @@ window.initSearch = function(rawSearchIndex) {
432456 }
433457 parserState . pos += 1 ;
434458 }
459+ foundStopChar = false ;
435460 }
436461 while ( parserState . pos < parserState . length ) {
437462 c = parserState . userQuery [ parserState . pos ] ;
@@ -515,17 +540,17 @@ window.initSearch = function(rawSearchIndex) {
515540 * arg = path [generics]
516541 * arg-without-generic = path
517542 * type-sep = COMMA/WS *(COMMA/WS)
518- * nonempty-arg-list = arg *(type-sep arg) *(COMMA/WS )
519- * nonempty-arg-list-without-generics = arg-without-generic *(type-sep arg-without-generic)
520- * *(COMMA/WS )
521- * generics = OPEN-ANGLE-BRACKET *WS [ nonempty-arg-list-without-generics ] *WS
543+ * nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep )
544+ * nonempty-arg-list-without-generics = *(type-sep) arg-without-generic
545+ * *(type-sep arg-without-generic) *(type-sep )
546+ * generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list-without-generics ] *(type-sep)
522547 * CLOSE-ANGLE-BRACKET
523- * return-args = RETURN-ARROW *WS nonempty-arg-list
548+ * return-args = RETURN-ARROW *(type-sep) nonempty-arg-list
524549 *
525- * exact-search = [type-filter *WS COLON] *WS QUOTE ident QUOTE *WS [ generics]
526- * type-search = [type-filter *WS COLON] *WS path *WS nonempty-arg-list
550+ * exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ]
551+ * type-search = [type-filter *WS COLON] [ nonempty-arg-list ] [ return-args ]
527552 *
528- * query = *WS (exact-search / type-search / return-args ) *WS
553+ * query = *WS (exact-search / type-search) *WS
529554 *
530555 * type-filter = (
531556 * "mod" /
@@ -578,6 +603,7 @@ window.initSearch = function(rawSearchIndex) {
578603 pos : 0 ,
579604 // Total number of elements (includes generics).
580605 totalElems : 0 ,
606+ genericsElems : 0 ,
581607 typeFilter : null ,
582608 userQuery : userQuery . toLowerCase ( ) ,
583609 } ;
@@ -606,7 +632,7 @@ window.initSearch = function(rawSearchIndex) {
606632 query . foundElems = query . elems . length + query . returned . length ;
607633 if ( query . foundElems === 0 && parserState . length !== 0 ) {
608634 // In this case, we'll simply keep whatever was entered by the user...
609- query . elems . push ( createQueryElement ( query , parserState , userQuery , [ ] ) ) ;
635+ query . elems . push ( createQueryElement ( query , parserState , userQuery , [ ] , false ) ) ;
610636 query . foundElems += 1 ;
611637 }
612638 return query ;
0 commit comments