Skip to content

Commit da829d8

Browse files
Improve the BNF description a bit and fix some issues
1 parent 1f5c4c2 commit da829d8

File tree

5 files changed

+201
-40
lines changed

5 files changed

+201
-40
lines changed

src/librustdoc/html/static/js/search.js

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

src/test/rustdoc-js-std/parser-errors.js

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
const QUERY = [
22
'<P>',
33
'-> <P>',
4-
'<"P">',
4+
'a<"P">',
55
'"P" "P"',
66
'P "P"',
77
'"p" p',
88
'"const": p',
9-
"<:a>",
10-
"<::a>",
9+
"a<:a>",
10+
"a<::a>",
1111
"((a))",
12-
"->,a",
1312
"(p -> p",
1413
"::a::b",
1514
"a::::b",
@@ -22,6 +21,12 @@ const QUERY = [
2221
"a>bb",
2322
"ab'",
2423
"a->",
24+
'"p" <a>',
25+
'"p" a<a>',
26+
"a,<",
27+
"aaaaa<>b",
28+
"fn:aaaaa<>b",
29+
"->a<>b",
2530
];
2631

2732
const PARSED = [
@@ -46,10 +51,10 @@ const PARSED = [
4651
{
4752
elems: [],
4853
foundElems: 0,
49-
original: "<\"P\">",
54+
original: "a<\"P\">",
5055
returned: [],
5156
typeFilter: -1,
52-
userQuery: "<\"p\">",
57+
userQuery: "a<\"p\">",
5358
error: "`\"` cannot be used in generics",
5459
},
5560
{
@@ -91,19 +96,19 @@ const PARSED = [
9196
{
9297
elems: [],
9398
foundElems: 0,
94-
original: "<:a>",
99+
original: "a<:a>",
95100
returned: [],
96101
typeFilter: -1,
97-
userQuery: "<:a>",
102+
userQuery: "a<:a>",
98103
error: "Unexpected `:` after `<`",
99104
},
100105
{
101106
elems: [],
102107
foundElems: 0,
103-
original: "<::a>",
108+
original: "a<::a>",
104109
returned: [],
105110
typeFilter: -1,
106-
userQuery: "<::a>",
111+
userQuery: "a<::a>",
107112
error: "Unexpected `::`: paths cannot start with `::`",
108113
},
109114
{
@@ -115,15 +120,6 @@ const PARSED = [
115120
userQuery: "((a))",
116121
error: "Unexpected `(`",
117122
},
118-
{
119-
elems: [],
120-
foundElems: 0,
121-
original: "->,a",
122-
returned: [],
123-
typeFilter: -1,
124-
userQuery: "->,a",
125-
error: "Unexpected `,` after `->`",
126-
},
127123
{
128124
elems: [],
129125
foundElems: 0,
@@ -232,4 +228,58 @@ const PARSED = [
232228
userQuery: "a->",
233229
error: "Expected at least one item after `->`",
234230
},
231+
{
232+
elems: [],
233+
foundElems: 0,
234+
original: '"p" <a>',
235+
returned: [],
236+
typeFilter: -1,
237+
userQuery: '"p" <a>',
238+
error: "Found generics without a path",
239+
},
240+
{
241+
elems: [],
242+
foundElems: 0,
243+
original: '"p" a<a>',
244+
returned: [],
245+
typeFilter: -1,
246+
userQuery: '"p" a<a>',
247+
error: "You cannot have more than one element if you use quotes",
248+
},
249+
{
250+
elems: [],
251+
foundElems: 0,
252+
original: 'a,<',
253+
returned: [],
254+
typeFilter: -1,
255+
userQuery: 'a,<',
256+
error: 'Found generics without a path',
257+
},
258+
{
259+
elems: [],
260+
foundElems: 0,
261+
original: 'aaaaa<>b',
262+
returned: [],
263+
typeFilter: -1,
264+
userQuery: 'aaaaa<>b',
265+
error: 'Expected `,`, ` `, `:` or `->`, found `b`',
266+
},
267+
{
268+
elems: [],
269+
foundElems: 0,
270+
original: 'fn:aaaaa<>b',
271+
returned: [],
272+
typeFilter: -1,
273+
userQuery: 'fn:aaaaa<>b',
274+
error: 'Expected `,`, ` ` or `->`, found `b`',
275+
},
276+
{
277+
elems: [],
278+
foundElems: 0,
279+
original: '->a<>b',
280+
returned: [],
281+
typeFilter: -1,
282+
userQuery: '->a<>b',
283+
error: 'Expected `,` or ` `, found `b`',
284+
},
235285
];

src/test/rustdoc-js-std/parser-generics.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const QUERY = ['A<B<C<D>, E>', 'p<> u8'];
1+
const QUERY = ['A<B<C<D>, E>', 'p<> u8', '"p"<a>'];
22

33
const PARSED = [
44
{
@@ -34,4 +34,29 @@ const PARSED = [
3434
userQuery: "p<> u8",
3535
error: null,
3636
},
37+
{
38+
elems: [
39+
{
40+
name: "p",
41+
fullPath: ["p"],
42+
pathWithoutLast: [],
43+
pathLast: "p",
44+
generics: [
45+
{
46+
name: "a",
47+
fullPath: ["a"],
48+
pathWithoutLast: [],
49+
pathLast: "a",
50+
generics: [],
51+
},
52+
],
53+
},
54+
],
55+
foundElems: 1,
56+
original: '"p"<a>',
57+
returned: [],
58+
typeFilter: -1,
59+
userQuery: '"p"<a>',
60+
error: null,
61+
},
3762
];

0 commit comments

Comments
 (0)