Skip to content

Commit 4022878

Browse files
authored
Unrolled build for rust-lang#126057
Rollup merge of rust-lang#126057 - Sunshine40:rustdoc-search-non-english, r=notriddle Make html rendered by rustdoc allow searching non-English identifier / alias Fix alias search result showing `undefined` description. Inspired by rust-lang/mdBook#2393 . Not sure if it's worth it adding full-text search functionality to rustdoc rendered html.
2 parents 8fb1930 + ceaa42b commit 4022878

File tree

12 files changed

+362
-85
lines changed

12 files changed

+362
-85
lines changed

src/ci/docker/host-x86_64/mingw-check/Dockerfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builti
6161
/scripts/validate-toolstate.sh && \
6262
/scripts/validate-error-codes.sh && \
6363
reuse --include-submodules lint && \
64-
# Runs checks to ensure that there are no ES5 issues in our JS code.
65-
es-check es8 ../src/librustdoc/html/static/js/*.js && \
64+
# Runs checks to ensure that there are no issues in our JS code.
65+
es-check es2019 ../src/librustdoc/html/static/js/*.js && \
6666
eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js && \
6767
eslint -c ../src/tools/rustdoc-js/.eslintrc.js ../src/tools/rustdoc-js/tester.js && \
6868
eslint -c ../src/tools/rustdoc-gui/.eslintrc.js ../src/tools/rustdoc-gui/tester.js

src/librustdoc/html/static/.eslintrc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module.exports = {
55
},
66
"extends": "eslint:recommended",
77
"parserOptions": {
8-
"ecmaVersion": 8,
8+
"ecmaVersion": 2019,
99
"sourceType": "module"
1010
},
1111
"rules": {

src/librustdoc/html/static/js/externs.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ let ParserState;
4141
* foundElems: number,
4242
* totalElems: number,
4343
* literalSearch: boolean,
44-
* corrections: Array<{from: string, to: integer}>,
44+
* corrections: Array<{from: string, to: integer}> | null,
4545
* typeFingerprint: Uint32Array,
46+
* error: Array<string> | null,
4647
* }}
4748
*/
4849
let ParsedQuery;

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

+85-71
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../";
8989
// of permutations we need to check.
9090
const UNBOXING_LIMIT = 5;
9191

92+
// used for search query verification
93+
const REGEX_IDENT = /\p{ID_Start}\p{ID_Continue}*|_\p{ID_Continue}+/uy;
94+
const REGEX_INVALID_TYPE_FILTER = /[^a-z]/ui;
95+
9296
// In the search display, allows to switch between tabs.
9397
function printTab(nb) {
9498
let iter = 0;
@@ -410,18 +414,21 @@ function initSearch(rawSearchIndex) {
410414
}
411415

412416
/**
413-
* Returns `true` if the given `c` character is valid for an ident.
417+
* If the current parser position is at the beginning of an identifier,
418+
* move the position to the end of it and return `true`. Otherwise, return `false`.
414419
*
415-
* @param {string} c
420+
* @param {ParserState} parserState
416421
*
417422
* @return {boolean}
418423
*/
419-
function isIdentCharacter(c) {
420-
return (
421-
c === "_" ||
422-
(c >= "0" && c <= "9") ||
423-
(c >= "a" && c <= "z") ||
424-
(c >= "A" && c <= "Z"));
424+
function consumeIdent(parserState) {
425+
REGEX_IDENT.lastIndex = parserState.pos;
426+
const match = parserState.userQuery.match(REGEX_IDENT);
427+
if (match) {
428+
parserState.pos += match[0].length;
429+
return true;
430+
}
431+
return false;
425432
}
426433

427434
/**
@@ -618,70 +625,62 @@ function initSearch(rawSearchIndex) {
618625
* @return {integer}
619626
*/
620627
function getIdentEndPosition(parserState) {
621-
const start = parserState.pos;
628+
let afterIdent = consumeIdent(parserState);
622629
let end = parserState.pos;
623-
let foundExclamation = -1;
630+
let macroExclamation = -1;
624631
while (parserState.pos < parserState.length) {
625632
const c = parserState.userQuery[parserState.pos];
626-
if (!isIdentCharacter(c)) {
627-
if (c === "!") {
628-
if (foundExclamation !== -1) {
629-
throw ["Cannot have more than one ", "!", " in an ident"];
630-
} else if (parserState.pos + 1 < parserState.length &&
631-
isIdentCharacter(parserState.userQuery[parserState.pos + 1])
632-
) {
633+
if (c === "!") {
634+
if (macroExclamation !== -1) {
635+
throw ["Cannot have more than one ", "!", " in an ident"];
636+
} else if (parserState.pos + 1 < parserState.length) {
637+
const pos = parserState.pos;
638+
parserState.pos++;
639+
const beforeIdent = consumeIdent(parserState);
640+
parserState.pos = pos;
641+
if (beforeIdent) {
633642
throw ["Unexpected ", "!", ": it can only be at the end of an ident"];
634643
}
635-
foundExclamation = parserState.pos;
636-
} else if (isPathSeparator(c)) {
637-
if (c === ":") {
638-
if (!isPathStart(parserState)) {
644+
}
645+
if (afterIdent) macroExclamation = parserState.pos;
646+
} else if (isPathSeparator(c)) {
647+
if (c === ":") {
648+
if (!isPathStart(parserState)) {
649+
break;
650+
}
651+
// Skip current ":".
652+
parserState.pos += 1;
653+
} else {
654+
while (parserState.pos + 1 < parserState.length) {
655+
const next_c = parserState.userQuery[parserState.pos + 1];
656+
if (next_c !== " ") {
639657
break;
640658
}
641-
// Skip current ":".
642659
parserState.pos += 1;
643-
} else {
644-
while (parserState.pos + 1 < parserState.length) {
645-
const next_c = parserState.userQuery[parserState.pos + 1];
646-
if (next_c !== " ") {
647-
break;
648-
}
649-
parserState.pos += 1;
650-
}
651660
}
652-
if (foundExclamation !== -1) {
653-
if (foundExclamation !== start &&
654-
isIdentCharacter(parserState.userQuery[foundExclamation - 1])
655-
) {
656-
throw ["Cannot have associated items in macros"];
657-
} else {
658-
// while the never type has no associated macros, we still
659-
// can parse a path like that
660-
foundExclamation = -1;
661-
}
662-
}
663-
} else if (
664-
c === "[" ||
665-
c === "(" ||
666-
isEndCharacter(c) ||
667-
isSpecialStartCharacter(c) ||
668-
isSeparatorCharacter(c)
669-
) {
670-
break;
671-
} else if (parserState.pos > 0) {
672-
throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1]];
673-
} else {
674-
throw ["Unexpected ", c];
675661
}
662+
if (macroExclamation !== -1) {
663+
throw ["Cannot have associated items in macros"];
664+
}
665+
} else if (
666+
c === "[" ||
667+
c === "(" ||
668+
isEndCharacter(c) ||
669+
isSpecialStartCharacter(c) ||
670+
isSeparatorCharacter(c)
671+
) {
672+
break;
673+
} else if (parserState.pos > 0) {
674+
throw ["Unexpected ", c, " after ", parserState.userQuery[parserState.pos - 1],
675+
" (not a valid identifier)"];
676+
} else {
677+
throw ["Unexpected ", c, " (not a valid identifier)"];
676678
}
677679
parserState.pos += 1;
680+
afterIdent = consumeIdent(parserState);
678681
end = parserState.pos;
679682
}
680-
// if start == end - 1, we got the never type
681-
if (foundExclamation !== -1 &&
682-
foundExclamation !== start &&
683-
isIdentCharacter(parserState.userQuery[foundExclamation - 1])
684-
) {
683+
if (macroExclamation !== -1) {
685684
if (parserState.typeFilter === null) {
686685
parserState.typeFilter = "macro";
687686
} else if (parserState.typeFilter !== "macro") {
@@ -693,7 +692,7 @@ function initSearch(rawSearchIndex) {
693692
" both specified",
694693
];
695694
}
696-
end = foundExclamation;
695+
end = macroExclamation;
697696
}
698697
return end;
699698
}
@@ -1071,16 +1070,15 @@ function initSearch(rawSearchIndex) {
10711070
function checkExtraTypeFilterCharacters(start, parserState) {
10721071
const query = parserState.userQuery.slice(start, parserState.pos).trim();
10731072

1074-
for (const c in query) {
1075-
if (!isIdentCharacter(query[c])) {
1076-
throw [
1077-
"Unexpected ",
1078-
query[c],
1079-
" in type filter (before ",
1080-
":",
1081-
")",
1082-
];
1083-
}
1073+
const match = query.match(REGEX_INVALID_TYPE_FILTER);
1074+
if (match) {
1075+
throw [
1076+
"Unexpected ",
1077+
match[0],
1078+
" in type filter (before ",
1079+
":",
1080+
")",
1081+
];
10841082
}
10851083
}
10861084

@@ -2127,7 +2125,7 @@ function initSearch(rawSearchIndex) {
21272125
};
21282126
}
21292127

2130-
function handleAliases(ret, query, filterCrates, currentCrate) {
2128+
async function handleAliases(ret, query, filterCrates, currentCrate) {
21312129
const lowerQuery = query.toLowerCase();
21322130
// We separate aliases and crate aliases because we want to have current crate
21332131
// aliases to be before the others in the displayed results.
@@ -2163,6 +2161,15 @@ function initSearch(rawSearchIndex) {
21632161
crateAliases.sort(sortFunc);
21642162
aliases.sort(sortFunc);
21652163

2164+
const fetchDesc = alias => {
2165+
return searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex) ?
2166+
"" : searchState.loadDesc(alias);
2167+
};
2168+
const [crateDescs, descs] = await Promise.all([
2169+
Promise.all(crateAliases.map(fetchDesc)),
2170+
Promise.all(aliases.map(fetchDesc)),
2171+
]);
2172+
21662173
const pushFunc = alias => {
21672174
alias.alias = query;
21682175
const res = buildHrefAndPath(alias);
@@ -2176,7 +2183,13 @@ function initSearch(rawSearchIndex) {
21762183
}
21772184
};
21782185

2186+
aliases.forEach((alias, i) => {
2187+
alias.desc = descs[i];
2188+
});
21792189
aliases.forEach(pushFunc);
2190+
crateAliases.forEach((alias, i) => {
2191+
alias.desc = crateDescs[i];
2192+
});
21802193
crateAliases.forEach(pushFunc);
21812194
}
21822195

@@ -2538,7 +2551,8 @@ function initSearch(rawSearchIndex) {
25382551
sorted_returned,
25392552
sorted_others,
25402553
parsedQuery);
2541-
handleAliases(ret, parsedQuery.original.replace(/"/g, ""), filterCrates, currentCrate);
2554+
await handleAliases(ret, parsedQuery.original.replace(/"/g, ""),
2555+
filterCrates, currentCrate);
25422556
await Promise.all([ret.others, ret.returned, ret.in_args].map(async list => {
25432557
const descs = await Promise.all(list.map(result => {
25442558
return searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex) ?

src/tools/rustdoc-gui/.eslintrc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module.exports = {
66
},
77
"extends": "eslint:recommended",
88
"parserOptions": {
9-
"ecmaVersion": 2018,
9+
"ecmaVersion": 2019,
1010
"sourceType": "module"
1111
},
1212
"rules": {

src/tools/rustdoc-js/.eslintrc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module.exports = {
66
},
77
"extends": "eslint:recommended",
88
"parserOptions": {
9-
"ecmaVersion": 8,
9+
"ecmaVersion": 2019,
1010
"sourceType": "module"
1111
},
1212
"rules": {

tests/rustdoc-js-std/parser-errors.js

+16-7
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const PARSED = [
2424
original: "-> *",
2525
returned: [],
2626
userQuery: "-> *",
27-
error: "Unexpected `*` after ` `",
27+
error: "Unexpected `*` after ` ` (not a valid identifier)",
2828
},
2929
{
3030
query: 'a<"P">',
@@ -204,16 +204,25 @@ const PARSED = [
204204
original: "_:",
205205
returned: [],
206206
userQuery: "_:",
207-
error: "Unexpected `:` (expected path after type filter `_:`)",
207+
error: "Unexpected `_` (not a valid identifier)",
208208
},
209209
{
210-
query: "_:a",
210+
query: "ab:",
211211
elems: [],
212212
foundElems: 0,
213-
original: "_:a",
213+
original: "ab:",
214214
returned: [],
215-
userQuery: "_:a",
216-
error: "Unknown type filter `_`",
215+
userQuery: "ab:",
216+
error: "Unexpected `:` (expected path after type filter `ab:`)",
217+
},
218+
{
219+
query: "a:b",
220+
elems: [],
221+
foundElems: 0,
222+
original: "a:b",
223+
returned: [],
224+
userQuery: "a:b",
225+
error: "Unknown type filter `a`",
217226
},
218227
{
219228
query: "a-bb",
@@ -240,7 +249,7 @@ const PARSED = [
240249
original: "ab'",
241250
returned: [],
242251
userQuery: "ab'",
243-
error: "Unexpected `'` after `b`",
252+
error: "Unexpected `'` after `b` (not a valid identifier)",
244253
},
245254
{
246255
query: "a->",

tests/rustdoc-js/basic.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const EXPECTED = {
22
'query': 'Fo',
33
'others': [
4-
{ 'path': 'basic', 'name': 'Foo' },
4+
{ 'path': 'basic', 'name': 'Foo', 'desc': 'Docs for Foo' },
55
],
66
};

0 commit comments

Comments
 (0)