mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
rustdoc-search: remove parallel searchWords array
This might have made sense if the algorithm could use `searchWords` to skip having to look at `searchIndex`, but since it always does a substring check on both the stock word and the normalizedName, it doesn't seem to help performance anyway.
This commit is contained in:
parent
e6707df0de
commit
6b69ebcae0
@ -499,6 +499,7 @@ function initSearch(rawSearchIndex) {
|
|||||||
fullPath: ["never"],
|
fullPath: ["never"],
|
||||||
pathWithoutLast: [],
|
pathWithoutLast: [],
|
||||||
pathLast: "never",
|
pathLast: "never",
|
||||||
|
normalizedPathLast: "never",
|
||||||
generics: [],
|
generics: [],
|
||||||
bindings: new Map(),
|
bindings: new Map(),
|
||||||
typeFilter: "primitive",
|
typeFilter: "primitive",
|
||||||
@ -537,12 +538,14 @@ function initSearch(rawSearchIndex) {
|
|||||||
const bindingName = parserState.isInBinding;
|
const bindingName = parserState.isInBinding;
|
||||||
parserState.isInBinding = null;
|
parserState.isInBinding = null;
|
||||||
const bindings = new Map();
|
const bindings = new Map();
|
||||||
|
const pathLast = pathSegments[pathSegments.length - 1];
|
||||||
return {
|
return {
|
||||||
name: name.trim(),
|
name: name.trim(),
|
||||||
id: null,
|
id: null,
|
||||||
fullPath: pathSegments,
|
fullPath: pathSegments,
|
||||||
pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1),
|
pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1),
|
||||||
pathLast: pathSegments[pathSegments.length - 1],
|
pathLast,
|
||||||
|
normalizedPathLast: pathLast.replace(/_/g, ""),
|
||||||
generics: generics.filter(gen => {
|
generics: generics.filter(gen => {
|
||||||
// Syntactically, bindings are parsed as generics,
|
// Syntactically, bindings are parsed as generics,
|
||||||
// but the query engine treats them differently.
|
// but the query engine treats them differently.
|
||||||
@ -689,6 +692,7 @@ function initSearch(rawSearchIndex) {
|
|||||||
fullPath: ["[]"],
|
fullPath: ["[]"],
|
||||||
pathWithoutLast: [],
|
pathWithoutLast: [],
|
||||||
pathLast: "[]",
|
pathLast: "[]",
|
||||||
|
normalizedPathLast: "[]",
|
||||||
generics,
|
generics,
|
||||||
typeFilter: "primitive",
|
typeFilter: "primitive",
|
||||||
bindingName: isInBinding,
|
bindingName: isInBinding,
|
||||||
@ -1168,13 +1172,12 @@ function initSearch(rawSearchIndex) {
|
|||||||
* Executes the parsed query and builds a {ResultsTable}.
|
* Executes the parsed query and builds a {ResultsTable}.
|
||||||
*
|
*
|
||||||
* @param {ParsedQuery} parsedQuery - The parsed user query
|
* @param {ParsedQuery} parsedQuery - The parsed user query
|
||||||
* @param {Object} searchWords - The list of search words to query against
|
|
||||||
* @param {Object} [filterCrates] - Crate to search in if defined
|
* @param {Object} [filterCrates] - Crate to search in if defined
|
||||||
* @param {Object} [currentCrate] - Current crate, to rank results from this crate higher
|
* @param {Object} [currentCrate] - Current crate, to rank results from this crate higher
|
||||||
*
|
*
|
||||||
* @return {ResultsTable}
|
* @return {ResultsTable}
|
||||||
*/
|
*/
|
||||||
function execQuery(parsedQuery, searchWords, filterCrates, currentCrate) {
|
function execQuery(parsedQuery, filterCrates, currentCrate) {
|
||||||
const results_others = new Map(), results_in_args = new Map(),
|
const results_others = new Map(), results_in_args = new Map(),
|
||||||
results_returned = new Map();
|
results_returned = new Map();
|
||||||
|
|
||||||
@ -1232,8 +1235,8 @@ function initSearch(rawSearchIndex) {
|
|||||||
const userQuery = parsedQuery.userQuery;
|
const userQuery = parsedQuery.userQuery;
|
||||||
const result_list = [];
|
const result_list = [];
|
||||||
for (const result of results.values()) {
|
for (const result of results.values()) {
|
||||||
result.word = searchWords[result.id];
|
result.item = searchIndex[result.id];
|
||||||
result.item = searchIndex[result.id] || {};
|
result.word = searchIndex[result.id].word;
|
||||||
result_list.push(result);
|
result_list.push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1928,7 +1931,7 @@ function initSearch(rawSearchIndex) {
|
|||||||
* The `results` map contains information which will be used to sort the search results:
|
* The `results` map contains information which will be used to sort the search results:
|
||||||
*
|
*
|
||||||
* * `fullId` is a `string`` used as the key of the object we use for the `results` map.
|
* * `fullId` is a `string`` used as the key of the object we use for the `results` map.
|
||||||
* * `id` is the index in both `searchWords` and `searchIndex` arrays for this element.
|
* * `id` is the index in the `searchIndex` array for this element.
|
||||||
* * `index` is an `integer`` used to sort by the position of the word in the item's name.
|
* * `index` is an `integer`` used to sort by the position of the word in the item's name.
|
||||||
* * `dist` is the main metric used to sort the search results.
|
* * `dist` is the main metric used to sort the search results.
|
||||||
* * `path_dist` is zero if a single-component search query is used, otherwise it's the
|
* * `path_dist` is zero if a single-component search query is used, otherwise it's the
|
||||||
@ -1986,9 +1989,8 @@ function initSearch(rawSearchIndex) {
|
|||||||
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
|
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let index = -1, path_dist = 0;
|
let path_dist = 0;
|
||||||
const fullId = row.id;
|
const fullId = row.id;
|
||||||
const searchWord = searchWords[pos];
|
|
||||||
|
|
||||||
// fpDist is a minimum possible type distance, where "type distance" is the number of
|
// fpDist is a minimum possible type distance, where "type distance" is the number of
|
||||||
// atoms in the function not present in the query
|
// atoms in the function not present in the query
|
||||||
@ -2021,19 +2023,10 @@ function initSearch(rawSearchIndex) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const row_index = row.normalizedName.indexOf(elem.pathLast);
|
let index = row.word.indexOf(elem.pathLast);
|
||||||
const word_index = searchWord.indexOf(elem.pathLast);
|
const normalizedIndex = row.normalizedName.indexOf(elem.pathLast);
|
||||||
|
if (index === -1 || (index > normalizedIndex && normalizedIndex !== -1)) {
|
||||||
// lower indexes are "better" matches
|
index = normalizedIndex;
|
||||||
// rank based on the "best" match
|
|
||||||
if (row_index === -1) {
|
|
||||||
index = word_index;
|
|
||||||
} else if (word_index === -1) {
|
|
||||||
index = row_index;
|
|
||||||
} else if (word_index < row_index) {
|
|
||||||
index = word_index;
|
|
||||||
} else {
|
|
||||||
index = row_index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elem.fullPath.length > 1) {
|
if (elem.fullPath.length > 1) {
|
||||||
@ -2044,13 +2037,13 @@ function initSearch(rawSearchIndex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (parsedQuery.literalSearch) {
|
if (parsedQuery.literalSearch) {
|
||||||
if (searchWord === elem.name) {
|
if (row.word === elem.pathLast) {
|
||||||
addIntoResults(results_others, fullId, pos, index, 0, path_dist);
|
addIntoResults(results_others, fullId, pos, index, 0, path_dist);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dist = editDistance(searchWord, elem.pathLast, maxEditDistance);
|
const dist = editDistance(row.normalizedName, elem.normalizedPathLast, maxEditDistance);
|
||||||
|
|
||||||
if (index === -1 && dist + path_dist > maxEditDistance) {
|
if (index === -1 && dist + path_dist > maxEditDistance) {
|
||||||
return;
|
return;
|
||||||
@ -2135,15 +2128,15 @@ function initSearch(rawSearchIndex) {
|
|||||||
* @param {boolean} isAssocType
|
* @param {boolean} isAssocType
|
||||||
*/
|
*/
|
||||||
function convertNameToId(elem, isAssocType) {
|
function convertNameToId(elem, isAssocType) {
|
||||||
if (typeNameIdMap.has(elem.pathLast) &&
|
if (typeNameIdMap.has(elem.normalizedPathLast) &&
|
||||||
(isAssocType || !typeNameIdMap.get(elem.pathLast).assocOnly)) {
|
(isAssocType || !typeNameIdMap.get(elem.normalizedPathLast).assocOnly)) {
|
||||||
elem.id = typeNameIdMap.get(elem.pathLast).id;
|
elem.id = typeNameIdMap.get(elem.normalizedPathLast).id;
|
||||||
} else if (!parsedQuery.literalSearch) {
|
} else if (!parsedQuery.literalSearch) {
|
||||||
let match = null;
|
let match = null;
|
||||||
let matchDist = maxEditDistance + 1;
|
let matchDist = maxEditDistance + 1;
|
||||||
let matchName = "";
|
let matchName = "";
|
||||||
for (const [name, {id, assocOnly}] of typeNameIdMap) {
|
for (const [name, {id, assocOnly}] of typeNameIdMap) {
|
||||||
const dist = editDistance(name, elem.pathLast, maxEditDistance);
|
const dist = editDistance(name, elem.normalizedPathLast, maxEditDistance);
|
||||||
if (dist <= matchDist && dist <= maxEditDistance &&
|
if (dist <= matchDist && dist <= maxEditDistance &&
|
||||||
(isAssocType || !assocOnly)) {
|
(isAssocType || !assocOnly)) {
|
||||||
if (dist === matchDist && matchName > name) {
|
if (dist === matchDist && matchName > name) {
|
||||||
@ -2236,7 +2229,7 @@ function initSearch(rawSearchIndex) {
|
|||||||
if (parsedQuery.foundElems === 1 && parsedQuery.returned.length === 0) {
|
if (parsedQuery.foundElems === 1 && parsedQuery.returned.length === 0) {
|
||||||
if (parsedQuery.elems.length === 1) {
|
if (parsedQuery.elems.length === 1) {
|
||||||
const elem = parsedQuery.elems[0];
|
const elem = parsedQuery.elems[0];
|
||||||
for (let i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
|
for (let i = 0, nSearchIndex = searchIndex.length; i < nSearchIndex; ++i) {
|
||||||
// It means we want to check for this element everywhere (in names, args and
|
// It means we want to check for this element everywhere (in names, args and
|
||||||
// returned).
|
// returned).
|
||||||
handleSingleArg(
|
handleSingleArg(
|
||||||
@ -2267,7 +2260,7 @@ function initSearch(rawSearchIndex) {
|
|||||||
};
|
};
|
||||||
parsedQuery.elems.sort(sortQ);
|
parsedQuery.elems.sort(sortQ);
|
||||||
parsedQuery.returned.sort(sortQ);
|
parsedQuery.returned.sort(sortQ);
|
||||||
for (let i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
|
for (let i = 0, nSearchIndex = searchIndex.length; i < nSearchIndex; ++i) {
|
||||||
handleArgs(searchIndex[i], i, results_others);
|
handleArgs(searchIndex[i], i, results_others);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2651,7 +2644,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
updateSearchHistory(buildUrl(query.original, filterCrates));
|
updateSearchHistory(buildUrl(query.original, filterCrates));
|
||||||
|
|
||||||
showResults(
|
showResults(
|
||||||
execQuery(query, searchWords, filterCrates, window.currentCrate),
|
execQuery(query, filterCrates, window.currentCrate),
|
||||||
params.go_to_first,
|
params.go_to_first,
|
||||||
filterCrates);
|
filterCrates);
|
||||||
}
|
}
|
||||||
@ -2920,12 +2913,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
|
|
||||||
function buildIndex(rawSearchIndex) {
|
function buildIndex(rawSearchIndex) {
|
||||||
searchIndex = [];
|
searchIndex = [];
|
||||||
/**
|
|
||||||
* List of normalized search words (ASCII lowercased, and undescores removed).
|
|
||||||
*
|
|
||||||
* @type {Array<string>}
|
|
||||||
*/
|
|
||||||
const searchWords = [];
|
|
||||||
typeNameIdMap = new Map();
|
typeNameIdMap = new Map();
|
||||||
const charA = "A".charCodeAt(0);
|
const charA = "A".charCodeAt(0);
|
||||||
let currentIndex = 0;
|
let currentIndex = 0;
|
||||||
@ -3004,7 +2991,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
for (const [crate, crateCorpus] of rawSearchIndex) {
|
for (const [crate, crateCorpus] of rawSearchIndex) {
|
||||||
searchWords.push(crate);
|
|
||||||
// This object should have exactly the same set of fields as the "row"
|
// This object should have exactly the same set of fields as the "row"
|
||||||
// object defined below. Your JavaScript runtime will thank you.
|
// object defined below. Your JavaScript runtime will thank you.
|
||||||
// https://mathiasbynens.be/notes/shapes-ics
|
// https://mathiasbynens.be/notes/shapes-ics
|
||||||
@ -3017,6 +3003,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
parent: undefined,
|
parent: undefined,
|
||||||
type: null,
|
type: null,
|
||||||
id: id,
|
id: id,
|
||||||
|
word: crate,
|
||||||
normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""),
|
normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""),
|
||||||
deprecated: null,
|
deprecated: null,
|
||||||
implDisambiguator: null,
|
implDisambiguator: null,
|
||||||
@ -3084,12 +3071,9 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
len = itemTypes.length;
|
len = itemTypes.length;
|
||||||
for (let i = 0; i < len; ++i) {
|
for (let i = 0; i < len; ++i) {
|
||||||
let word = "";
|
let word = "";
|
||||||
// This object should have exactly the same set of fields as the "crateRow"
|
|
||||||
// object defined above.
|
|
||||||
if (typeof itemNames[i] === "string") {
|
if (typeof itemNames[i] === "string") {
|
||||||
word = itemNames[i].toLowerCase();
|
word = itemNames[i].toLowerCase();
|
||||||
}
|
}
|
||||||
searchWords.push(word);
|
|
||||||
const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath;
|
const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath;
|
||||||
let type = null;
|
let type = null;
|
||||||
if (itemFunctionSearchTypes[i] !== 0) {
|
if (itemFunctionSearchTypes[i] !== 0) {
|
||||||
@ -3113,6 +3097,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// This object should have exactly the same set of fields as the "crateRow"
|
||||||
|
// object defined above.
|
||||||
const row = {
|
const row = {
|
||||||
crate: crate,
|
crate: crate,
|
||||||
ty: itemTypes.charCodeAt(i) - charA,
|
ty: itemTypes.charCodeAt(i) - charA,
|
||||||
@ -3122,6 +3108,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
|
parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
|
||||||
type,
|
type,
|
||||||
id: id,
|
id: id,
|
||||||
|
word,
|
||||||
normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
|
normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
|
||||||
deprecated: deprecatedItems.has(i),
|
deprecated: deprecatedItems.has(i),
|
||||||
implDisambiguator: implDisambiguator.has(i) ? implDisambiguator.get(i) : null,
|
implDisambiguator: implDisambiguator.has(i) ? implDisambiguator.get(i) : null,
|
||||||
@ -3153,7 +3140,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
}
|
}
|
||||||
currentIndex += itemTypes.length;
|
currentIndex += itemTypes.length;
|
||||||
}
|
}
|
||||||
return searchWords;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3332,10 +3318,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
search(true);
|
search(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
buildIndex(rawSearchIndex);
|
||||||
* @type {Array<string>}
|
|
||||||
*/
|
|
||||||
const searchWords = buildIndex(rawSearchIndex);
|
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
registerSearchEvents();
|
registerSearchEvents();
|
||||||
// If there's a search term in the URL, execute the search now.
|
// If there's a search term in the URL, execute the search now.
|
||||||
@ -3349,7 +3332,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
|||||||
exports.execQuery = execQuery;
|
exports.execQuery = execQuery;
|
||||||
exports.parseQuery = parseQuery;
|
exports.parseQuery = parseQuery;
|
||||||
}
|
}
|
||||||
return searchWords;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
|
@ -396,16 +396,16 @@ function loadSearchJS(doc_folder, resource_suffix) {
|
|||||||
const staticFiles = path.join(doc_folder, "static.files");
|
const staticFiles = path.join(doc_folder, "static.files");
|
||||||
const searchJs = fs.readdirSync(staticFiles).find(f => f.match(/search.*\.js$/));
|
const searchJs = fs.readdirSync(staticFiles).find(f => f.match(/search.*\.js$/));
|
||||||
const searchModule = require(path.join(staticFiles, searchJs));
|
const searchModule = require(path.join(staticFiles, searchJs));
|
||||||
const searchWords = searchModule.initSearch(searchIndex.searchIndex);
|
searchModule.initSearch(searchIndex.searchIndex);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
doSearch: function(queryStr, filterCrate, currentCrate) {
|
doSearch: function(queryStr, filterCrate, currentCrate) {
|
||||||
return searchModule.execQuery(searchModule.parseQuery(queryStr), searchWords,
|
return searchModule.execQuery(searchModule.parseQuery(queryStr),
|
||||||
filterCrate, currentCrate);
|
filterCrate, currentCrate);
|
||||||
},
|
},
|
||||||
getCorrections: function(queryStr, filterCrate, currentCrate) {
|
getCorrections: function(queryStr, filterCrate, currentCrate) {
|
||||||
const parsedQuery = searchModule.parseQuery(queryStr);
|
const parsedQuery = searchModule.parseQuery(queryStr);
|
||||||
searchModule.execQuery(parsedQuery, searchWords, filterCrate, currentCrate);
|
searchModule.execQuery(parsedQuery, filterCrate, currentCrate);
|
||||||
return parsedQuery.correction;
|
return parsedQuery.correction;
|
||||||
},
|
},
|
||||||
parseQuery: searchModule.parseQuery,
|
parseQuery: searchModule.parseQuery,
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
const EXPECTED = {
|
const EXPECTED = [
|
||||||
|
{
|
||||||
'query': 'waker_from',
|
'query': 'waker_from',
|
||||||
'others': [
|
'others': [
|
||||||
{ 'path': 'substring::SuperWaker', 'name': 'local_waker_from_nonlocal' },
|
{ 'path': 'substring::SuperWaker', 'name': 'local_waker_from_nonlocal' },
|
||||||
{ 'path': 'substring::SuperWakerTask', 'name': 'local_waker_from_nonlocal' },
|
{ 'path': 'substring::SuperWakerTask', 'name': 'local_waker_from_nonlocal' },
|
||||||
],
|
],
|
||||||
};
|
},
|
||||||
|
{
|
||||||
|
'query': 'my',
|
||||||
|
'others': [
|
||||||
|
{ 'path': 'substring', 'name': 'm_y_substringmatching' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
@ -19,3 +19,5 @@ impl SuperWakerTask {
|
|||||||
pub fn waker_non_local() {}
|
pub fn waker_non_local() {}
|
||||||
pub fn from_non_local() {}
|
pub fn from_non_local() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn m_y_substringmatching() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user