diff options
| -rw-r--r-- | src/librustdoc/html/static/js/search.js | 62 | ||||
| -rw-r--r-- | src/test/rustdoc-js-std/parser-errors.js | 88 | ||||
| -rw-r--r-- | src/test/rustdoc-js-std/parser-generics.js | 27 | ||||
| -rw-r--r-- | src/test/rustdoc-js-std/parser-returned.js | 38 | ||||
| -rw-r--r-- | src/test/rustdoc-js-std/parser-weird-queries.js | 26 |
5 files changed, 201 insertions, 40 deletions
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index cb078b5134d..239fef494ad 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -172,7 +172,7 @@ window.initSearch = function(rawSearchIndex) { throw new Error("`\"` cannot be used in generics"); } else if (query.literalSearch) { throw new Error("Cannot have more than one literal search element"); - } else if (parserState.totalElems !== 0) { + } else if (parserState.totalElems - parserState.genericsElems > 0) { throw new Error("Cannot use literal search when there is more than one element"); } parserState.pos += 1; @@ -234,11 +234,11 @@ window.initSearch = function(rawSearchIndex) { * * @return {QueryElement} - The newly created `QueryElement`. */ - function createQueryElement(query, parserState, name, generics) { + function createQueryElement(query, parserState, name, generics, isInGenerics) { if (name === '*' || (name.length === 0 && generics.length === 0)) { return; } - if (query.literalSearch && parserState.totalElems > 0) { + if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) { throw new Error("You cannot have more than one element if you use quotes"); } var pathSegments = name.split("::"); @@ -261,6 +261,9 @@ window.initSearch = function(rawSearchIndex) { throw new Error("Found generics without a path"); } parserState.totalElems += 1; + if (isInGenerics) { + parserState.genericsElems += 1; + } return { name: name, fullPath: pathSegments, @@ -315,6 +318,8 @@ window.initSearch = function(rawSearchIndex) { { if (isInGenerics) { throw new Error("Unexpected `<` after `<`"); + } else if (start >= end) { + throw new Error("Found generics without a path"); } parserState.pos += 1; getItemsBefore(query, parserState, generics, ">"); @@ -327,7 +332,8 @@ window.initSearch = function(rawSearchIndex) { query, parserState, parserState.userQuery.slice(start, end), - generics + generics, + isInGenerics ) ); } @@ -346,13 +352,15 @@ window.initSearch = function(rawSearchIndex) { * character. */ function getItemsBefore(query, parserState, elems, endChar) { - var turns = 0; + var foundStopChar = true; + while (parserState.pos < parserState.length) { var c = parserState.userQuery[parserState.pos]; if (c === endChar) { break; - } else if (c === "," && endChar !== "" && turns > 0) { + } else if (c === "," || c === " ") { parserState.pos += 1; + foundStopChar = true; continue; } else if (c === ":" && isPathStart(parserState)) { throw new Error("Unexpected `::`: paths cannot start with `::`"); @@ -365,15 +373,21 @@ window.initSearch = function(rawSearchIndex) { } throw new Error("Unexpected `" + c + "` after " + extra); } + if (!foundStopChar) { + if (endChar !== "") { + throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``); + } + throw new Error(`Expected \`,\` or \` \`, found \`${c}\``); + } var posBefore = parserState.pos; getNextElem(query, parserState, elems, endChar === ">"); - turns += 1; // This case can be encountered if `getNextElem` encounted a "stop character" right from - // the start. For example if you have `,,`. In this case, we simply move up the current - // position to continue the parsing. + // the start. For example if you have `,,` or `<>`. In this case, we simply move up the + // current position to continue the parsing. if (posBefore === parserState.pos) { parserState.pos += 1; } + foundStopChar = false; } // We are either at the end of the string or on the `endChar`` character, let's move forward // in any case. @@ -389,10 +403,12 @@ window.initSearch = function(rawSearchIndex) { */ function parseInput(query, parserState) { var c, before; + var foundStopChar = true; while (parserState.pos < parserState.length) { c = parserState.userQuery[parserState.pos]; if (isStopCharacter(c)) { + foundStopChar = true; if (c === "," || c === " ") { parserState.pos += 1; continue; @@ -402,6 +418,7 @@ window.initSearch = function(rawSearchIndex) { } throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`); } + throw new Error(`Unexpected \`${c}\``); } else if (c === ":" && parserState.typeFilter === null && !isPathStart(parserState)) @@ -419,8 +436,15 @@ window.initSearch = function(rawSearchIndex) { parserState.pos += 1; parserState.totalElems = 0; query.literalSearch = false; + foundStopChar = true; continue; } + if (!foundStopChar) { + if (parserState.typeFilter !== null) { + throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``); + } + throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``); + } before = query.elems.length; getNextElem(query, parserState, query.elems, false); if (query.elems.length === before) { @@ -432,6 +456,7 @@ window.initSearch = function(rawSearchIndex) { } parserState.pos += 1; } + foundStopChar = false; } while (parserState.pos < parserState.length) { c = parserState.userQuery[parserState.pos]; @@ -515,17 +540,17 @@ window.initSearch = function(rawSearchIndex) { * arg = path [generics] * arg-without-generic = path * type-sep = COMMA/WS *(COMMA/WS) - * nonempty-arg-list = arg *(type-sep arg) *(COMMA/WS) - * nonempty-arg-list-without-generics = arg-without-generic *(type-sep arg-without-generic) - * *(COMMA/WS) - * generics = OPEN-ANGLE-BRACKET *WS [ nonempty-arg-list-without-generics ] *WS + * nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep) + * nonempty-arg-list-without-generics = *(type-sep) arg-without-generic + * *(type-sep arg-without-generic) *(type-sep) + * generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list-without-generics ] *(type-sep) * CLOSE-ANGLE-BRACKET - * return-args = RETURN-ARROW *WS nonempty-arg-list + * return-args = RETURN-ARROW *(type-sep) nonempty-arg-list * - * exact-search = [type-filter *WS COLON] *WS QUOTE ident QUOTE *WS [generics] - * type-search = [type-filter *WS COLON] *WS path *WS nonempty-arg-list + * exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ] + * type-search = [type-filter *WS COLON] [ nonempty-arg-list ] [ return-args ] * - * query = *WS (exact-search / type-search / return-args) *WS + * query = *WS (exact-search / type-search) *WS * * type-filter = ( * "mod" / @@ -578,6 +603,7 @@ window.initSearch = function(rawSearchIndex) { pos: 0, // Total number of elements (includes generics). totalElems: 0, + genericsElems: 0, typeFilter: null, userQuery: userQuery.toLowerCase(), }; @@ -606,7 +632,7 @@ window.initSearch = function(rawSearchIndex) { query.foundElems = query.elems.length + query.returned.length; if (query.foundElems === 0 && parserState.length !== 0) { // In this case, we'll simply keep whatever was entered by the user... - query.elems.push(createQueryElement(query, parserState, userQuery, [])); + query.elems.push(createQueryElement(query, parserState, userQuery, [], false)); query.foundElems += 1; } return query; diff --git a/src/test/rustdoc-js-std/parser-errors.js b/src/test/rustdoc-js-std/parser-errors.js index 42d69ed3fe0..bd024a932a1 100644 --- a/src/test/rustdoc-js-std/parser-errors.js +++ b/src/test/rustdoc-js-std/parser-errors.js @@ -1,15 +1,14 @@ const QUERY = [ '<P>', '-> <P>', - '<"P">', + 'a<"P">', '"P" "P"', 'P "P"', '"p" p', '"const": p', - "<:a>", - "<::a>", + "a<:a>", + "a<::a>", "((a))", - "->,a", "(p -> p", "::a::b", "a::::b", @@ -22,6 +21,12 @@ const QUERY = [ "a>bb", "ab'", "a->", + '"p" <a>', + '"p" a<a>', + "a,<", + "aaaaa<>b", + "fn:aaaaa<>b", + "->a<>b", ]; const PARSED = [ @@ -46,10 +51,10 @@ const PARSED = [ { elems: [], foundElems: 0, - original: "<\"P\">", + original: "a<\"P\">", returned: [], typeFilter: -1, - userQuery: "<\"p\">", + userQuery: "a<\"p\">", error: "`\"` cannot be used in generics", }, { @@ -91,19 +96,19 @@ const PARSED = [ { elems: [], foundElems: 0, - original: "<:a>", + original: "a<:a>", returned: [], typeFilter: -1, - userQuery: "<:a>", + userQuery: "a<:a>", error: "Unexpected `:` after `<`", }, { elems: [], foundElems: 0, - original: "<::a>", + original: "a<::a>", returned: [], typeFilter: -1, - userQuery: "<::a>", + userQuery: "a<::a>", error: "Unexpected `::`: paths cannot start with `::`", }, { @@ -118,15 +123,6 @@ const PARSED = [ { elems: [], foundElems: 0, - original: "->,a", - returned: [], - typeFilter: -1, - userQuery: "->,a", - error: "Unexpected `,` after `->`", - }, - { - elems: [], - foundElems: 0, original: "(p -> p", returned: [], typeFilter: -1, @@ -232,4 +228,58 @@ const PARSED = [ userQuery: "a->", error: "Expected at least one item after `->`", }, + { + elems: [], + foundElems: 0, + original: '"p" <a>', + returned: [], + typeFilter: -1, + userQuery: '"p" <a>', + error: "Found generics without a path", + }, + { + elems: [], + foundElems: 0, + original: '"p" a<a>', + returned: [], + typeFilter: -1, + userQuery: '"p" a<a>', + error: "You cannot have more than one element if you use quotes", + }, + { + elems: [], + foundElems: 0, + original: 'a,<', + returned: [], + typeFilter: -1, + userQuery: 'a,<', + error: 'Found generics without a path', + }, + { + elems: [], + foundElems: 0, + original: 'aaaaa<>b', + returned: [], + typeFilter: -1, + userQuery: 'aaaaa<>b', + error: 'Expected `,`, ` `, `:` or `->`, found `b`', + }, + { + elems: [], + foundElems: 0, + original: 'fn:aaaaa<>b', + returned: [], + typeFilter: -1, + userQuery: 'fn:aaaaa<>b', + error: 'Expected `,`, ` ` or `->`, found `b`', + }, + { + elems: [], + foundElems: 0, + original: '->a<>b', + returned: [], + typeFilter: -1, + userQuery: '->a<>b', + error: 'Expected `,` or ` `, found `b`', + }, ]; diff --git a/src/test/rustdoc-js-std/parser-generics.js b/src/test/rustdoc-js-std/parser-generics.js index cc92f2333d2..0cf7f5019aa 100644 --- a/src/test/rustdoc-js-std/parser-generics.js +++ b/src/test/rustdoc-js-std/parser-generics.js @@ -1,4 +1,4 @@ -const QUERY = ['A<B<C<D>, E>', 'p<> u8']; +const QUERY = ['A<B<C<D>, E>', 'p<> u8', '"p"<a>']; const PARSED = [ { @@ -34,4 +34,29 @@ const PARSED = [ userQuery: "p<> u8", error: null, }, + { + elems: [ + { + name: "p", + fullPath: ["p"], + pathWithoutLast: [], + pathLast: "p", + generics: [ + { + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + }, + ], + }, + ], + foundElems: 1, + original: '"p"<a>', + returned: [], + typeFilter: -1, + userQuery: '"p"<a>', + error: null, + }, ]; diff --git a/src/test/rustdoc-js-std/parser-returned.js b/src/test/rustdoc-js-std/parser-returned.js index 8910275c91e..b45466aa940 100644 --- a/src/test/rustdoc-js-std/parser-returned.js +++ b/src/test/rustdoc-js-std/parser-returned.js @@ -1,4 +1,4 @@ -const QUERY = ['-> F<P>', '-> P']; +const QUERY = ['-> F<P>', '-> P', '->,a', 'aaaaa->a']; const PARSED = [ { @@ -39,4 +39,40 @@ const PARSED = [ userQuery: "-> p", error: null, }, + { + elems: [], + foundElems: 1, + original: "->,a", + returned: [{ + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + }], + typeFilter: -1, + userQuery: "->,a", + error: null, + }, + { + elems: [{ + name: "aaaaa", + fullPath: ["aaaaa"], + pathWithoutLast: [], + pathLast: "aaaaa", + generics: [], + }], + foundElems: 2, + original: "aaaaa->a", + returned: [{ + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + }], + typeFilter: -1, + userQuery: "aaaaa->a", + error: null, + }, ]; diff --git a/src/test/rustdoc-js-std/parser-weird-queries.js b/src/test/rustdoc-js-std/parser-weird-queries.js index 87ebe21c49b..4b4ce64284e 100644 --- a/src/test/rustdoc-js-std/parser-weird-queries.js +++ b/src/test/rustdoc-js-std/parser-weird-queries.js @@ -1,7 +1,7 @@ // This test is mostly to check that the parser still kinda outputs something // (and doesn't enter an infinite loop!) even though the query is completely // invalid. -const QUERY = ['a b', 'a b', 'a,b(c)']; +const QUERY = ['a b', 'a b', 'a,b(c)', 'aaa,a']; const PARSED = [ { @@ -61,4 +61,28 @@ const PARSED = [ userQuery: "a,b(c)", error: "Unexpected `(`", }, + { + elems: [ + { + name: "aaa", + fullPath: ["aaa"], + pathWithoutLast: [], + pathLast: "aaa", + generics: [], + }, + { + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + }, + ], + foundElems: 2, + original: "aaa,a", + returned: [], + typeFilter: -1, + userQuery: "aaa,a", + error: null, + }, ]; |
