mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-28 19:27:30 +03:00
* Greatly improve the rustdoc search parser source code
* Move all functions outside parseQuery
This commit is contained in:
@@ -8,7 +8,6 @@ function initSearch(searchIndex){}
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* isExact: boolean,
|
||||
* name: string,
|
||||
* fullPath: Array<string>,
|
||||
* pathWithoutLast: Array<string>,
|
||||
@@ -18,20 +17,25 @@ function initSearch(searchIndex){}
|
||||
*/
|
||||
var QueryElement;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* pos: number,
|
||||
* totalElems: number,
|
||||
* typeFilter: (null|string),
|
||||
* userQuery: string,
|
||||
* }}
|
||||
*/
|
||||
var ParserState;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* original: string,
|
||||
* userQuery: string,
|
||||
* length: number,
|
||||
* pos: number,
|
||||
* typeFilter: number,
|
||||
* elems: Array<QueryElement>,
|
||||
* elemName: (string|null),
|
||||
* args: Array<QueryElement>,
|
||||
* returned: Array<QueryElement>,
|
||||
* foundElems: number,
|
||||
* id: string,
|
||||
* nameSplit: (string|null),
|
||||
* }}
|
||||
*/
|
||||
var ParsedQuery;
|
||||
@@ -50,3 +54,31 @@ var ParsedQuery;
|
||||
* }}
|
||||
*/
|
||||
var Row;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* in_args: Array<Object>,
|
||||
* returned: Array<Object>,
|
||||
* others: Array<Object>,
|
||||
* query: ParsedQuery,
|
||||
* }}
|
||||
*/
|
||||
var ResultsTable;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* crate: "std"
|
||||
* desc: string,
|
||||
* displayPath: string,
|
||||
* fullPath: string,
|
||||
* href: string,
|
||||
* id: number,
|
||||
* lev: number,
|
||||
* name: string,
|
||||
* normalizedName: string,
|
||||
* parent: (Object|undefined),
|
||||
* path: string,
|
||||
* ty: number,
|
||||
* }}
|
||||
*/
|
||||
var Results;
|
||||
|
||||
@@ -124,6 +124,302 @@ window.initSearch = function(rawSearchIndex) {
|
||||
searchState.input.value = params.search || "";
|
||||
}
|
||||
|
||||
function isWhitespace(c) {
|
||||
return " \t\n\r".indexOf(c) !== -1;
|
||||
}
|
||||
|
||||
function isSpecialStartCharacter(c) {
|
||||
return "(<\"".indexOf(c) !== -1;
|
||||
}
|
||||
|
||||
function isStopCharacter(c) {
|
||||
return isWhitespace(c) || "),>-=".indexOf(c) !== -1;
|
||||
}
|
||||
|
||||
function removeEmptyStringsFromArray(arr) {
|
||||
for (var i = 0, len = arr.length; i < len; ++i) {
|
||||
if (arr[i] === "") {
|
||||
arr.splice(i, 1);
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function itemTypeFromName(typename) {
|
||||
for (var i = 0, len = itemTypes.length; i < len; ++i) {
|
||||
if (itemTypes[i] === typename) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return NO_TYPE_FILTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we encounter a `"`, then we try to extract the string from it until we find another `"`.
|
||||
*
|
||||
* This function will throw an error in the following cases:
|
||||
* * There is already another string element.
|
||||
* * We are parsing a generic argument.
|
||||
* * There is more than one element.
|
||||
* * There is no closing `"`.
|
||||
*
|
||||
* @param {ParsedQuery} query
|
||||
* @param {ParserState} parserState
|
||||
* @param {boolean} isInGenerics
|
||||
*/
|
||||
function getStringElem(query, parserState, isInGenerics) {
|
||||
if (isInGenerics) {
|
||||
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) {
|
||||
throw new Error("Cannot use literal search when there is more than one element");
|
||||
}
|
||||
parserState.pos += 1;
|
||||
while (parserState.pos < parserState.length &&
|
||||
parserState.userQuery[parserState.pos] !== "\"")
|
||||
{
|
||||
parserState.pos += 1;
|
||||
}
|
||||
if (parserState.pos >= parserState.length) {
|
||||
throw new Error("Unclosed `\"`");
|
||||
}
|
||||
// To skip the quote at the end.
|
||||
parserState.pos += 1;
|
||||
query.literalSearch = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the parser position as long as the character is a whitespace. This check is
|
||||
* performed with the `isWhitespace` function.
|
||||
*
|
||||
* @param {ParserState} parserState
|
||||
*/
|
||||
function skipWhitespaces(parserState) {
|
||||
while (parserState.pos < parserState.length) {
|
||||
var c = parserState.userQuery[parserState.pos];
|
||||
if (!isWhitespace(c)) {
|
||||
break;
|
||||
}
|
||||
parserState.pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the current parser position is starting with "::".
|
||||
*
|
||||
* @param {ParserState} parserState
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isPathStart(parserState) {
|
||||
return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) == '::';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the current parser position is starting with "->".
|
||||
*
|
||||
* @param {ParserState} parserState
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isReturnArrow(parserState) {
|
||||
return parserState.userQuery.slice(parserState.pos, parserState.pos + 2) == '->';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ParsedQuery} query
|
||||
* @param {ParserState} parserState
|
||||
* @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added.
|
||||
* @param {string} name - Name of the query element.
|
||||
* @param {Array<QueryElement>} generics - List of generics of this query element.
|
||||
*/
|
||||
function createQueryElement(query, parserState, elems, name, generics) {
|
||||
removeEmptyStringsFromArray(generics);
|
||||
if (name === '*' || (name.length === 0 && generics.length === 0)) {
|
||||
return;
|
||||
}
|
||||
if (query.literalSearch && parserState.totalElems > 0) {
|
||||
throw new Error("You cannot have more than one element if you use quotes");
|
||||
}
|
||||
var pathSegments = name.split("::");
|
||||
removeEmptyStringsFromArray(pathSegments);
|
||||
// In case we only have something like `<p>`, there is no name but it remains valid.
|
||||
if (pathSegments.length === 0) {
|
||||
pathSegments = [""];
|
||||
}
|
||||
elems.push({
|
||||
name: name,
|
||||
fullPath: pathSegments,
|
||||
pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1),
|
||||
pathLast: pathSegments[pathSegments.length - 1],
|
||||
generics: generics,
|
||||
});
|
||||
parserState.totalElems += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ParsedQuery} query
|
||||
* @param {ParserState} parserState
|
||||
* @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added.
|
||||
* @param {boolean} isInGenerics
|
||||
*/
|
||||
function getNextElem(query, parserState, elems, isInGenerics) {
|
||||
var generics = [];
|
||||
|
||||
var start = parserState.pos;
|
||||
var end = start;
|
||||
// We handle the strings on their own mostly to make code easier to follow.
|
||||
if (parserState.userQuery[parserState.pos] === "\"") {
|
||||
start += 1;
|
||||
getStringElem(query, parserState, isInGenerics);
|
||||
end = parserState.pos - 1;
|
||||
skipWhitespaces(parserState);
|
||||
} else {
|
||||
while (parserState.pos < parserState.length) {
|
||||
var c = parserState.userQuery[parserState.pos];
|
||||
if (isStopCharacter(c) || isSpecialStartCharacter(c)) {
|
||||
break;
|
||||
}
|
||||
// If we allow paths ("str::string" for example).
|
||||
else if (c === ":") {
|
||||
if (!isPathStart(parserState)) {
|
||||
break;
|
||||
}
|
||||
// Skip current ":".
|
||||
parserState.pos += 1;
|
||||
}
|
||||
parserState.pos += 1;
|
||||
end = parserState.pos;
|
||||
skipWhitespaces(parserState);
|
||||
}
|
||||
}
|
||||
if (parserState.pos < parserState.length &&
|
||||
parserState.userQuery[parserState.pos] === "<")
|
||||
{
|
||||
parserState.pos += 1;
|
||||
getItemsBefore(query, parserState, generics, ">");
|
||||
}
|
||||
if (start >= end && generics.length === 0) {
|
||||
return;
|
||||
}
|
||||
createQueryElement(
|
||||
query,
|
||||
parserState,
|
||||
elems,
|
||||
parserState.userQuery.slice(start, end),
|
||||
generics);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ParsedQuery} query
|
||||
* @param {ParserState} parserState
|
||||
* @param {Array<QueryElement>} elems - This is where the new {QueryElement} will be added.
|
||||
* @param {string} limit - This function will stop when it'll encounter this
|
||||
* character.
|
||||
*/
|
||||
function getItemsBefore(query, parserState, elems, limit) {
|
||||
while (parserState.pos < parserState.length) {
|
||||
var c = parserState.userQuery[parserState.pos];
|
||||
if (c === limit) {
|
||||
break;
|
||||
} else if (c === '(' || c === ":") {
|
||||
// Something weird is going on in here. Ignoring it!
|
||||
parserState.pos += 1;
|
||||
continue;
|
||||
}
|
||||
var posBefore = parserState.pos;
|
||||
getNextElem(query, parserState, elems, limit === ">");
|
||||
if (posBefore === parserState.pos) {
|
||||
parserState.pos += 1;
|
||||
}
|
||||
}
|
||||
// We skip the "limit".
|
||||
parserState.pos += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ParsedQuery} query
|
||||
* @param {ParserState} parserState
|
||||
*/
|
||||
function parseInput(query, parserState) {
|
||||
var c, before;
|
||||
|
||||
while (parserState.pos < parserState.length) {
|
||||
c = parserState.userQuery[parserState.pos];
|
||||
if (isStopCharacter(c)) {
|
||||
if (c === "," || c === " ") {
|
||||
parserState.pos += 1;
|
||||
continue;
|
||||
} else if (c === "-" && isReturnArrow(parserState)) {
|
||||
break;
|
||||
}
|
||||
} else if (c == "(") {
|
||||
break;
|
||||
} else if (c === ":" &&
|
||||
parserState.typeFilter === null &&
|
||||
!isPathStart(parserState) &&
|
||||
query.elems.length === 1)
|
||||
{
|
||||
if (query.literalSearch) {
|
||||
throw new Error("You cannot use quotes on type filter");
|
||||
}
|
||||
// The type filter doesn't count as an element since it's a modifier.
|
||||
parserState.typeFilter = query.elems.pop().name;
|
||||
parserState.pos += 1;
|
||||
parserState.totalElems = 0;
|
||||
query.literalSearch = false;
|
||||
continue;
|
||||
}
|
||||
before = query.elems.length;
|
||||
getNextElem(query, parserState, query.elems, false);
|
||||
if (query.elems.length === before) {
|
||||
// Nothing was added, let's check it's not because of a solo ":"!
|
||||
if (parserState.pos >= parserState.length ||
|
||||
parserState.userQuery[parserState.pos] !== ":")
|
||||
{
|
||||
break;
|
||||
}
|
||||
parserState.pos += 1;
|
||||
}
|
||||
}
|
||||
while (parserState.pos < parserState.length) {
|
||||
c = parserState.userQuery[parserState.pos];
|
||||
if (query.args.length === 0 && c === "(") {
|
||||
parserState.pos += 1;
|
||||
// Check for function/method arguments.
|
||||
getItemsBefore(query, parserState, query.args, ")");
|
||||
} else if (isReturnArrow(parserState)) {
|
||||
parserState.pos += 2;
|
||||
// Get returned elements.
|
||||
getItemsBefore(query, parserState, query.returned, "");
|
||||
// Nothing can come afterward!
|
||||
break;
|
||||
} else {
|
||||
parserState.pos += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the user search input and returns an empty `ParsedQuery`.
|
||||
*
|
||||
* @param {string} userQuery
|
||||
* @return {ParsedQuery}
|
||||
*/
|
||||
function newParsedQuery(userQuery) {
|
||||
return {
|
||||
original: userQuery,
|
||||
userQuery: userQuery.toLowerCase(),
|
||||
typeFilter: NO_TYPE_FILTER,
|
||||
elems: [],
|
||||
args: [],
|
||||
returned: [],
|
||||
// Total number of "top" elements (does not include generics).
|
||||
foundElems: 0,
|
||||
literalSearch: false,
|
||||
error: null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an URL with search parameters.
|
||||
*
|
||||
@@ -158,7 +454,7 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the query and builds an index of results
|
||||
* Parses the query.
|
||||
*
|
||||
* The supported syntax by this parser is as follow:
|
||||
*
|
||||
@@ -222,274 +518,39 @@ window.initSearch = function(rawSearchIndex) {
|
||||
* @return {ParsedQuery} - The parsed query
|
||||
*/
|
||||
function parseQuery(userQuery) {
|
||||
function isWhitespace(c) {
|
||||
return " \t\n\r".indexOf(c) !== -1;
|
||||
}
|
||||
function isSpecialStartCharacter(c) {
|
||||
return "(<\"".indexOf(c) !== -1;
|
||||
}
|
||||
function isStopCharacter(c) {
|
||||
return isWhitespace(c) || "),>-=".indexOf(c) !== -1;
|
||||
}
|
||||
function getStringElem(query, isInGenerics) {
|
||||
if (isInGenerics) {
|
||||
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 (query.totalElems !== 0) {
|
||||
throw new Error("Cannot use literal search when there is more than one element");
|
||||
}
|
||||
query.pos += 1;
|
||||
while (query.pos < query.length && query.userQuery[query.pos] !== "\"") {
|
||||
if (query.userQuery[query.pos] === "\\") {
|
||||
// We ignore the next coming character.
|
||||
query.pos += 1;
|
||||
}
|
||||
query.pos += 1;
|
||||
}
|
||||
if (query.pos >= query.length) {
|
||||
throw new Error("Unclosed `\"`");
|
||||
}
|
||||
// To skip the quote at the end.
|
||||
query.pos += 1;
|
||||
query.literalSearch = true;
|
||||
}
|
||||
function skipWhitespaces(query) {
|
||||
while (query.pos < query.length) {
|
||||
var c = query.userQuery[query.pos];
|
||||
if (!isWhitespace(c)) {
|
||||
break;
|
||||
}
|
||||
query.pos += 1;
|
||||
}
|
||||
}
|
||||
function skipStopCharacters(query) {
|
||||
while (query.pos < query.length) {
|
||||
var c = query.userQuery[query.pos];
|
||||
if (!isStopCharacter(c)) {
|
||||
break;
|
||||
}
|
||||
query.pos += 1;
|
||||
}
|
||||
}
|
||||
function isPathStart(query) {
|
||||
var pos = query.pos;
|
||||
return pos + 1 < query.length && query.userQuery[pos] === ':' &&
|
||||
query.userQuery[pos + 1] === ':';
|
||||
}
|
||||
function isReturnArrow(query) {
|
||||
var pos = query.pos;
|
||||
return pos + 1 < query.length && query.userQuery[pos] === '-' &&
|
||||
query.userQuery[pos + 1] === '>';
|
||||
}
|
||||
function removeEmptyStringsFromArray(x) {
|
||||
for (var i = 0, len = x.length; i < len; ++i) {
|
||||
if (x[i] === "") {
|
||||
x.splice(i, 1);
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
function createQueryElement(query, elems, name, generics) {
|
||||
removeEmptyStringsFromArray(generics);
|
||||
if (name === '*' || (name.length === 0 && generics.length === 0)) {
|
||||
return;
|
||||
}
|
||||
if (query.literalSearch && query.totalElems > 0) {
|
||||
throw new Error("You cannot have more than one element if you use quotes");
|
||||
}
|
||||
var paths = name.split("::");
|
||||
removeEmptyStringsFromArray(paths);
|
||||
// In case we only have something like `<p>`, there is no name but it remains valid.
|
||||
if (paths.length === 0) {
|
||||
paths = [""];
|
||||
}
|
||||
elems.push({
|
||||
name: name,
|
||||
fullPath: paths,
|
||||
pathWithoutLast: paths.slice(0, paths.length - 1),
|
||||
pathLast: paths[paths.length - 1],
|
||||
generics: generics,
|
||||
});
|
||||
query.totalElems += 1;
|
||||
}
|
||||
function getNextElem(query, elems, isInGenerics) {
|
||||
var generics = [];
|
||||
|
||||
skipStopCharacters(query);
|
||||
var start = query.pos;
|
||||
var end = start;
|
||||
// We handle the strings on their own mostly to make code easier to follow.
|
||||
if (query.userQuery[query.pos] === "\"") {
|
||||
start += 1;
|
||||
getStringElem(query, isInGenerics);
|
||||
end = query.pos - 1;
|
||||
skipWhitespaces(query);
|
||||
} else {
|
||||
while (query.pos < query.length) {
|
||||
var c = query.userQuery[query.pos];
|
||||
if (isStopCharacter(c) || isSpecialStartCharacter(c)) {
|
||||
break;
|
||||
}
|
||||
// If we allow paths ("str::string" for example).
|
||||
else if (c === ":") {
|
||||
if (!isPathStart(query)) {
|
||||
break;
|
||||
}
|
||||
// Skip current ":".
|
||||
query.pos += 1;
|
||||
}
|
||||
query.pos += 1;
|
||||
end = query.pos;
|
||||
skipWhitespaces(query);
|
||||
}
|
||||
}
|
||||
if (query.pos < query.length && query.userQuery[query.pos] === "<") {
|
||||
getItemsBefore(query, generics, ">");
|
||||
}
|
||||
if (start >= end && generics.length === 0) {
|
||||
return;
|
||||
}
|
||||
createQueryElement(query, elems, query.userQuery.slice(start, end), generics);
|
||||
}
|
||||
function getItemsBefore(query, elems, limit) {
|
||||
while (query.pos < query.length) {
|
||||
var c = query.userQuery[query.pos];
|
||||
if (c === limit) {
|
||||
break;
|
||||
} else if (isSpecialStartCharacter(c) || c === ":") {
|
||||
// Something weird is going on in here. Ignoring it!
|
||||
query.pos += 1;
|
||||
}
|
||||
getNextElem(query, elems, limit === ">");
|
||||
}
|
||||
// We skip the "limit".
|
||||
query.pos += 1;
|
||||
}
|
||||
function parseInput(query) {
|
||||
var c, before;
|
||||
|
||||
while (query.pos < query.length) {
|
||||
c = query.userQuery[query.pos];
|
||||
if (isStopCharacter(c)) {
|
||||
if (c === ",") {
|
||||
query.pos += 1;
|
||||
continue;
|
||||
} else if (c === "-" && isReturnArrow(query)) {
|
||||
break;
|
||||
}
|
||||
} else if (c == "(") {
|
||||
break;
|
||||
} else if (c === ":" && query.typeFilter === null && !isPathStart(query) &&
|
||||
query.elems.length === 1)
|
||||
{
|
||||
if (query.literalSearch) {
|
||||
throw new Error("You cannot use quotes on type filter");
|
||||
}
|
||||
// The type filter doesn't count as an element since it's a modifier.
|
||||
query.typeFilter = query.elems.pop().name;
|
||||
query.pos += 1;
|
||||
query.totalElems = 0;
|
||||
query.literalSearch = false;
|
||||
continue;
|
||||
}
|
||||
before = query.elems.length;
|
||||
getNextElem(query, query.elems, false);
|
||||
if (query.elems.length === before) {
|
||||
// Nothing was added, let's check it's not because of a solo ":"!
|
||||
if (query.pos >= query.length || query.userQuery[query.pos] !== ":") {
|
||||
break;
|
||||
}
|
||||
query.pos += 1;
|
||||
}
|
||||
}
|
||||
while (query.pos < query.length) {
|
||||
c = query.userQuery[query.pos];
|
||||
if (query.args.length === 0 && c === "(") {
|
||||
if (query.elemName === null && query.elems.length === 1) {
|
||||
query.elemName = query.elems.pop();
|
||||
}
|
||||
// Check for function/method arguments.
|
||||
getItemsBefore(query, query.args, ")");
|
||||
} else if (isReturnArrow(query)) {
|
||||
// Get returned elements.
|
||||
getItemsBefore(query, query.returned, "");
|
||||
// Nothing can come afterward!
|
||||
break;
|
||||
} else {
|
||||
query.pos += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
function itemTypeFromName(typename) {
|
||||
for (var i = 0, len = itemTypes.length; i < len; ++i) {
|
||||
if (itemTypes[i] === typename) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return NO_TYPE_FILTER;
|
||||
}
|
||||
|
||||
userQuery = userQuery.trim();
|
||||
var query = {
|
||||
original: userQuery,
|
||||
userQuery: userQuery.toLowerCase(),
|
||||
var parserState = {
|
||||
length: userQuery.length,
|
||||
pos: 0,
|
||||
typeFilter: null,
|
||||
elems: [],
|
||||
elemName: null,
|
||||
args: [],
|
||||
returned: [],
|
||||
// Total number of elements (includes generics).
|
||||
totalElems: 0,
|
||||
// Total number of "top" elements (does not include generics).
|
||||
foundElems: 0,
|
||||
// This field is used to check if it's needed to re-run a search or not.
|
||||
id: "",
|
||||
// This field is used in `sortResults`.
|
||||
nameSplit: null,
|
||||
literalSearch: false,
|
||||
error: null,
|
||||
typeFilter: null,
|
||||
userQuery: userQuery.toLowerCase(),
|
||||
};
|
||||
query.id = userQuery;
|
||||
var query = newParsedQuery(userQuery);
|
||||
|
||||
try {
|
||||
parseInput(query);
|
||||
parseInput(query, parserState);
|
||||
} catch (err) {
|
||||
query = newParsedQuery(userQuery);
|
||||
query.error = err.message;
|
||||
query.elems = [];
|
||||
query.returned = [];
|
||||
query.args = [];
|
||||
return query;
|
||||
}
|
||||
query.foundElems = query.elems.length + query.args.length + query.returned.length;
|
||||
|
||||
if (!query.literalSearch) {
|
||||
// If there is more than one element in the query, we switch to literalSearch in any
|
||||
// case.
|
||||
query.literalSearch = query.totalElems > 1;
|
||||
query.literalSearch = parserState.totalElems > 1;
|
||||
}
|
||||
if (query.elemName !== null) {
|
||||
query.foundElems += 1;
|
||||
}
|
||||
if (query.foundElems === 0 && userQuery.length !== 0) {
|
||||
query.foundElems = query.elems.length + query.args.length + query.returned.length;
|
||||
if (query.foundElems === 0 && parserState.length !== 0) {
|
||||
// In this case, we'll simply keep whatever was entered by the user...
|
||||
createQueryElement(query, query.elems, userQuery, []);
|
||||
createQueryElement(query, parserState, query.elems, userQuery, []);
|
||||
query.foundElems += 1;
|
||||
}
|
||||
if (query.typeFilter !== null) {
|
||||
query.typeFilter = query.typeFilter.replace(/^const$/, "constant");
|
||||
query.typeFilter = itemTypeFromName(query.typeFilter);
|
||||
} else {
|
||||
query.typeFilter = NO_TYPE_FILTER;
|
||||
}
|
||||
// In case we only have one argument, we move it back to `elems` to keep things simple.
|
||||
if (query.foundElems === 1 && query.elemName !== null) {
|
||||
query.elems.push(query.elemName);
|
||||
query.elemName = null;
|
||||
}
|
||||
if (query.elemName !== null || query.elems.length === 1) {
|
||||
userQuery = query.elemName || query.elems[0];
|
||||
query.nameSplit = typeof userQuery.path === "undefined" ? null : userQuery.path;
|
||||
if (parserState.typeFilter !== null) {
|
||||
var typeFilter = parserState.typeFilter.replace(/^const$/, "constant");
|
||||
query.typeFilter = itemTypeFromName(typeFilter);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
@@ -497,32 +558,32 @@ window.initSearch = function(rawSearchIndex) {
|
||||
/**
|
||||
* Creates the query results.
|
||||
*
|
||||
* @param {Array<Object>} results_in_args
|
||||
* @param {Array<Object>} results_returned
|
||||
* @param {Array<Object>} results_in_args
|
||||
* @param {ParsedQuery} queryInfo
|
||||
* @return {Object} - A search index of results
|
||||
* @param {Array<Result>} results_in_args
|
||||
* @param {Array<Result>} results_returned
|
||||
* @param {Array<Result>} results_in_args
|
||||
* @param {ParsedQuery} parsedQuery
|
||||
* @return {ResultsTable}
|
||||
*/
|
||||
function createQueryResults(results_in_args, results_returned, results_others, queryInfo) {
|
||||
function createQueryResults(results_in_args, results_returned, results_others, parsedQuery) {
|
||||
return {
|
||||
"in_args": results_in_args,
|
||||
"returned": results_returned,
|
||||
"others": results_others,
|
||||
"query": queryInfo,
|
||||
"query": parsedQuery,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the query and builds an index of results
|
||||
* Executes the parsed query and builds a {ResultsTable}.
|
||||
*
|
||||
* @param {ParsedQuery} query - The user query
|
||||
* @param {Object} searchWords - The list of search words to query against
|
||||
* @param {Object} filterCrates - Crate to search in if defined
|
||||
* @return {Object} - A search index of results
|
||||
* @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
|
||||
* @return {ResultsTable}
|
||||
*/
|
||||
function execQuery(queryInfo, searchWords, filterCrates) {
|
||||
if (queryInfo.error !== null) {
|
||||
createQueryResults([], [], [], queryInfo);
|
||||
function execQuery(parsedQuery, searchWords, filterCrates) {
|
||||
if (parsedQuery.error !== null) {
|
||||
createQueryResults([], [], [], parsedQuery);
|
||||
}
|
||||
var results_others = {}, results_in_args = {}, results_returned = {};
|
||||
|
||||
@@ -558,8 +619,12 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
|
||||
function sortResults(results, isType) {
|
||||
var nameSplit = queryInfo.nameSplit;
|
||||
var query = queryInfo.userQuery;
|
||||
var nameSplit = null;
|
||||
if (parsedQuery.elems.length === 1) {
|
||||
var hasPath = typeof parsedQuery.elems[0].path === "undefined";
|
||||
nameSplit = hasPath ? null : parsedQuery.elems[0].path;
|
||||
}
|
||||
var query = parsedQuery.userQuery;
|
||||
var ar = [];
|
||||
for (var entry in results) {
|
||||
if (hasOwnPropertyRustdoc(results, entry)) {
|
||||
@@ -661,26 +726,26 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks if the object (`obj`) generics match the given type (`val`)
|
||||
* generics. If there are no generics on `obj`, `defaultLev` is returned.
|
||||
* This function checks if the object (`row`) generics match the given type (`elem`)
|
||||
* generics. If there are no generics on `row`, `defaultLev` is returned.
|
||||
*
|
||||
* @param {Row} obj - The object to check.
|
||||
* @param {QueryElement} val - The element from the parsed query.
|
||||
* @param {Row} row - The object to check.
|
||||
* @param {QueryElement} elem - The element from the parsed query.
|
||||
* @param {integer} defaultLev - This is the value to return in case there are no generics.
|
||||
*
|
||||
* @return {integer} - Returns the best match (if any) or `MAX_LEV_DISTANCE + 1`.
|
||||
*/
|
||||
function checkGenerics(obj, val, defaultLev) {
|
||||
if (obj.length <= GENERICS_DATA || obj[GENERICS_DATA].length === 0) {
|
||||
return val.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
|
||||
function checkGenerics(row, elem, defaultLev) {
|
||||
if (row.length <= GENERICS_DATA || row[GENERICS_DATA].length === 0) {
|
||||
return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
|
||||
}
|
||||
// The names match, but we need to be sure that all generics kinda
|
||||
// match as well.
|
||||
var elem_name;
|
||||
if (val.generics.length > 0 && obj[GENERICS_DATA].length >= val.generics.length) {
|
||||
if (elem.generics.length > 0 && row[GENERICS_DATA].length >= elem.generics.length) {
|
||||
var elems = {};
|
||||
for (var x = 0, length = obj[GENERICS_DATA].length; x < length; ++x) {
|
||||
elem_name = obj[GENERICS_DATA][x][NAME];
|
||||
for (var x = 0, length = row[GENERICS_DATA].length; x < length; ++x) {
|
||||
elem_name = row[GENERICS_DATA][x][NAME];
|
||||
if (!elems[elem_name]) {
|
||||
elems[elem_name] = 0;
|
||||
}
|
||||
@@ -688,8 +753,8 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
// We need to find the type that matches the most to remove it in order
|
||||
// to move forward.
|
||||
for (x = 0, length = val.generics.length; x < length; ++x) {
|
||||
var generic = val.generics[x];
|
||||
for (x = 0, length = elem.generics.length; x < length; ++x) {
|
||||
var generic = elem.generics[x];
|
||||
var match = null;
|
||||
if (elems[generic.name]) {
|
||||
match = generic.name;
|
||||
@@ -718,19 +783,19 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks if the object (`obj`) matches the given type (`val`) and its
|
||||
* This function checks if the object (`row`) matches the given type (`elem`) and its
|
||||
* generics (if any).
|
||||
*
|
||||
* @param {Row} obj
|
||||
* @param {QueryElement} val - The element from the parsed query.
|
||||
* @param {Row} row
|
||||
* @param {QueryElement} elem - The element from the parsed query.
|
||||
*
|
||||
* @return {integer} - Returns a Levenshtein distance to the best match.
|
||||
*/
|
||||
function checkIfInGenerics(obj, val) {
|
||||
function checkIfInGenerics(row, elem) {
|
||||
var lev = MAX_LEV_DISTANCE + 1;
|
||||
for (var x = 0, length = obj[GENERICS_DATA].length; x < length && lev !== 0; ++x) {
|
||||
for (var x = 0, length = row[GENERICS_DATA].length; x < length && lev !== 0; ++x) {
|
||||
lev = Math.min(
|
||||
checkType(obj[GENERICS_DATA][x], val, true),
|
||||
checkType(row[GENERICS_DATA][x], elem, true),
|
||||
lev
|
||||
);
|
||||
}
|
||||
@@ -738,51 +803,51 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks if the object (`obj`) matches the given type (`val`) and its
|
||||
* This function checks if the object (`row`) matches the given type (`elem`) and its
|
||||
* generics (if any).
|
||||
*
|
||||
* @param {Row} obj
|
||||
* @param {QueryElement} val - The element from the parsed query.
|
||||
* @param {Row} row
|
||||
* @param {QueryElement} elem - The element from the parsed query.
|
||||
* @param {boolean} literalSearch
|
||||
*
|
||||
* @return {integer} - Returns a Levenshtein distance to the best match. If there is
|
||||
* no match, returns `MAX_LEV_DISTANCE + 1`.
|
||||
*/
|
||||
function checkType(obj, val, literalSearch) {
|
||||
if (val.name.length === 0 || obj[NAME].length === 0) {
|
||||
function checkType(row, elem, literalSearch) {
|
||||
if (elem.name.length === 0 || row[NAME].length === 0) {
|
||||
// This is a pure "generic" search, no need to run other checks.
|
||||
if (obj.length > GENERICS_DATA) {
|
||||
return checkIfInGenerics(obj, val);
|
||||
if (row.length > GENERICS_DATA) {
|
||||
return checkIfInGenerics(row, elem);
|
||||
}
|
||||
return MAX_LEV_DISTANCE + 1;
|
||||
}
|
||||
|
||||
var lev = levenshtein(obj[NAME], val.name);
|
||||
var lev = levenshtein(row[NAME], elem.name);
|
||||
if (literalSearch) {
|
||||
if (lev !== 0) {
|
||||
// The name didn't match, let's try to check if the generics do.
|
||||
if (val.generics.length === 0) {
|
||||
var checkGeneric = (obj.length > GENERICS_DATA &&
|
||||
obj[GENERICS_DATA].length > 0);
|
||||
if (checkGeneric && obj[GENERICS_DATA].findIndex(function(elem) {
|
||||
return elem[NAME] === val.name;
|
||||
if (elem.generics.length === 0) {
|
||||
var checkGeneric = (row.length > GENERICS_DATA &&
|
||||
row[GENERICS_DATA].length > 0);
|
||||
if (checkGeneric && row[GENERICS_DATA].findIndex(function(tmp_elem) {
|
||||
return tmp_elem[NAME] === elem.name;
|
||||
}) !== -1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return MAX_LEV_DISTANCE + 1;
|
||||
} else if (val.generics.length > 0) {
|
||||
return checkGenerics(obj, val, MAX_LEV_DISTANCE + 1);
|
||||
} else if (elem.generics.length > 0) {
|
||||
return checkGenerics(row, elem, MAX_LEV_DISTANCE + 1);
|
||||
}
|
||||
return 0;
|
||||
} else if (obj.length > GENERICS_DATA) {
|
||||
if (val.generics.length === 0) {
|
||||
} else if (row.length > GENERICS_DATA) {
|
||||
if (elem.generics.length === 0) {
|
||||
if (lev === 0) {
|
||||
return 0;
|
||||
}
|
||||
// The name didn't match so we now check if the type we're looking for is inside
|
||||
// the generics!
|
||||
lev = checkIfInGenerics(obj, val);
|
||||
lev = checkIfInGenerics(row, elem);
|
||||
// Now whatever happens, the returned distance is "less good" so we should mark
|
||||
// it as such, and so we add 0.5 to the distance to make it "less good".
|
||||
return lev + 0.5;
|
||||
@@ -791,18 +856,18 @@ window.initSearch = function(rawSearchIndex) {
|
||||
//
|
||||
// Maybe it's present in a sub generic? For example "f<A<B<C>>>()", if we're
|
||||
// looking for "B<C>", we'll need to go down.
|
||||
return checkIfInGenerics(obj, val);
|
||||
return checkIfInGenerics(row, elem);
|
||||
} else {
|
||||
// At this point, the name kinda match and we have generics to check, so
|
||||
// let's go!
|
||||
var tmp_lev = checkGenerics(obj, val, lev);
|
||||
var tmp_lev = checkGenerics(row, elem, lev);
|
||||
if (tmp_lev > MAX_LEV_DISTANCE) {
|
||||
return MAX_LEV_DISTANCE + 1;
|
||||
}
|
||||
// We compute the median value of both checks and return it.
|
||||
return (tmp_lev + lev) / 2;
|
||||
}
|
||||
} else if (val.generics.length > 0) {
|
||||
} else if (elem.generics.length > 0) {
|
||||
// In this case, we were expecting generics but there isn't so we simply reject this
|
||||
// one.
|
||||
return MAX_LEV_DISTANCE + 1;
|
||||
@@ -813,64 +878,62 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks if the object (`obj`) has an argument with the given type (`val`).
|
||||
* This function checks if the object (`row`) has an argument with the given type (`elem`).
|
||||
*
|
||||
* @param {Row} obj
|
||||
* @param {QueryElement} val - The element from the parsed query.
|
||||
* @param {Row} row
|
||||
* @param {QueryElement} elem - The element from the parsed query.
|
||||
* @param {integer} typeFilter
|
||||
*
|
||||
* @return {integer} - Returns a Levenshtein distance to the best match. If there is no
|
||||
* match, returns `MAX_LEV_DISTANCE + 1`.
|
||||
*/
|
||||
function findArg(obj, val, typeFilter) {
|
||||
function findArg(row, elem, typeFilter) {
|
||||
var lev = MAX_LEV_DISTANCE + 1;
|
||||
var tmp;
|
||||
|
||||
if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
|
||||
var length = obj.type[INPUTS_DATA].length;
|
||||
if (row && row.type && row.type[INPUTS_DATA] && row.type[INPUTS_DATA].length > 0) {
|
||||
var length = row.type[INPUTS_DATA].length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
tmp = obj.type[INPUTS_DATA][i];
|
||||
var tmp = row.type[INPUTS_DATA][i];
|
||||
if (!typePassesFilter(typeFilter, tmp[1])) {
|
||||
continue;
|
||||
}
|
||||
lev = Math.min(lev, checkType(tmp, val, queryInfo.literalSearch));
|
||||
lev = Math.min(lev, checkType(tmp, elem, parsedQuery.literalSearch));
|
||||
if (lev === 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return queryInfo.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
|
||||
return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Row} obj
|
||||
* @param {QueryElement} val - The element from the parsed query.
|
||||
* @param {Row} row
|
||||
* @param {QueryElement} elem - The element from the parsed query.
|
||||
* @param {integer} typeFilter
|
||||
*
|
||||
* @return {integer} - Returns a Levenshtein distance to the best match. If there is no
|
||||
* match, returns `MAX_LEV_DISTANCE + 1`.
|
||||
*/
|
||||
function checkReturned(obj, val, typeFilter) {
|
||||
function checkReturned(row, elem, typeFilter) {
|
||||
var lev = MAX_LEV_DISTANCE + 1;
|
||||
var tmp;
|
||||
|
||||
if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
|
||||
var ret = obj.type[OUTPUT_DATA];
|
||||
if (row && row.type && row.type.length > OUTPUT_DATA) {
|
||||
var ret = row.type[OUTPUT_DATA];
|
||||
if (typeof ret[0] === "string") {
|
||||
ret = [ret];
|
||||
}
|
||||
for (var x = 0, len = ret.length; x < len; ++x) {
|
||||
tmp = ret[x];
|
||||
var tmp = ret[x];
|
||||
if (!typePassesFilter(typeFilter, tmp[1])) {
|
||||
continue;
|
||||
}
|
||||
lev = Math.min(lev, checkType(tmp, val, queryInfo.literalSearch));
|
||||
lev = Math.min(lev, checkType(tmp, elem, parsedQuery.literalSearch));
|
||||
if (lev === 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return queryInfo.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
|
||||
return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
|
||||
}
|
||||
|
||||
function checkPath(contains, lastElem, ty) {
|
||||
@@ -945,13 +1008,14 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
|
||||
function handleAliases(ret, query, filterCrates) {
|
||||
var lowerQuery = query.toLowerCase();
|
||||
// We separate aliases and crate aliases because we want to have current crate
|
||||
// aliases to be before the others in the displayed results.
|
||||
var aliases = [];
|
||||
var crateAliases = [];
|
||||
if (filterCrates !== null) {
|
||||
if (ALIASES[filterCrates] && ALIASES[filterCrates][query]) {
|
||||
var query_aliases = ALIASES[filterCrates][query];
|
||||
if (ALIASES[filterCrates] && ALIASES[filterCrates][lowerQuery]) {
|
||||
var query_aliases = ALIASES[filterCrates][lowerQuery];
|
||||
var len = query_aliases.length;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
|
||||
@@ -959,9 +1023,9 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
} else {
|
||||
Object.keys(ALIASES).forEach(function(crate) {
|
||||
if (ALIASES[crate][query]) {
|
||||
if (ALIASES[crate][lowerQuery]) {
|
||||
var pushTo = crate === window.currentCrate ? crateAliases : aliases;
|
||||
var query_aliases = ALIASES[crate][query];
|
||||
var query_aliases = ALIASES[crate][lowerQuery];
|
||||
var len = query_aliases.length;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
|
||||
@@ -998,37 +1062,37 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This function adds the given result into the provided `res` map if it matches the
|
||||
* This function adds the given result into the provided `results` map if it matches the
|
||||
* following condition:
|
||||
*
|
||||
* * If it is a "literal search" (`queryInfo.literalSearch`), then `lev` must be 0.
|
||||
* * If it is a "literal search" (`parsedQuery.literalSearch`), then `lev` must be 0.
|
||||
* * If it is not a "literal search", `lev` must be <= `MAX_LEV_DISTANCE`.
|
||||
*
|
||||
* The `res` 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 `res` 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.
|
||||
* * `index` is an `integer`` used to sort by the position of the word in the item's name.
|
||||
* * `lev` is the main metric used to sort the search results.
|
||||
*
|
||||
* @param {Object} res
|
||||
* @param {Object} results
|
||||
* @param {string} fullId
|
||||
* @param {integer} id
|
||||
* @param {integer} index
|
||||
* @param {integer} lev
|
||||
*/
|
||||
function addIntoResults(res, fullId, id, index, lev) {
|
||||
if (lev === 0 || (!queryInfo.literalSearch && lev <= MAX_LEV_DISTANCE)) {
|
||||
if (res[fullId] !== undefined) {
|
||||
var result = res[fullId];
|
||||
function addIntoResults(results, fullId, id, index, lev) {
|
||||
if (lev === 0 || (!parsedQuery.literalSearch && lev <= MAX_LEV_DISTANCE)) {
|
||||
if (results[fullId] !== undefined) {
|
||||
var result = results[fullId];
|
||||
if (result.dontValidate || result.lev <= lev) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
res[fullId] = {
|
||||
results[fullId] = {
|
||||
id: id,
|
||||
index: index,
|
||||
dontValidate: queryInfo.literalSearch,
|
||||
dontValidate: parsedQuery.literalSearch,
|
||||
lev: lev,
|
||||
};
|
||||
}
|
||||
@@ -1037,29 +1101,29 @@ window.initSearch = function(rawSearchIndex) {
|
||||
/**
|
||||
* This function is called in case the query is only one element (with or without generics).
|
||||
*
|
||||
* @param {Row} ty
|
||||
* @param {Row} row
|
||||
* @param {integer} pos - Position in the `searchIndex`.
|
||||
* @param {QueryElement} elem - The element from the parsed query.
|
||||
*/
|
||||
function handleSingleArg(ty, pos, elem) {
|
||||
if (!ty || (filterCrates !== null && ty.crate !== filterCrates)) {
|
||||
function handleSingleArg(row, pos, elem) {
|
||||
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
|
||||
return;
|
||||
}
|
||||
var lev, lev_add = 0, index = -1;
|
||||
var fullId = ty.id;
|
||||
var fullId = row.id;
|
||||
|
||||
var in_args = findArg(ty, elem, queryInfo.typeFilter);
|
||||
var returned = checkReturned(ty, elem, queryInfo.typeFilter);
|
||||
var in_args = findArg(row, elem, parsedQuery.typeFilter);
|
||||
var returned = checkReturned(row, elem, parsedQuery.typeFilter);
|
||||
|
||||
addIntoResults(results_in_args, fullId, pos, index, in_args);
|
||||
addIntoResults(results_returned, fullId, pos, index, returned);
|
||||
|
||||
if (!typePassesFilter(queryInfo.typeFilter, ty.ty)) {
|
||||
if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) {
|
||||
return;
|
||||
}
|
||||
var searchWord = searchWords[pos];
|
||||
|
||||
if (queryInfo.literalSearch) {
|
||||
if (parsedQuery.literalSearch) {
|
||||
if (searchWord === elem.name) {
|
||||
addIntoResults(results_others, fullId, pos, -1, 0);
|
||||
}
|
||||
@@ -1068,16 +1132,16 @@ window.initSearch = function(rawSearchIndex) {
|
||||
|
||||
// No need to check anything else if it's a "pure" generics search.
|
||||
if (elem.name.length === 0) {
|
||||
if (ty.type !== null) {
|
||||
lev = checkGenerics(ty.type, elem, MAX_LEV_DISTANCE + 1);
|
||||
if (row.type !== null) {
|
||||
lev = checkGenerics(row.type, elem, MAX_LEV_DISTANCE + 1);
|
||||
addIntoResults(results_others, fullId, pos, index, lev);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (elem.fullPath.length > 1) {
|
||||
lev = checkPath(elem.pathWithoutLast, elem.pathLast, ty);
|
||||
if (lev > MAX_LEV_DISTANCE || (queryInfo.literalSearch && lev !== 0)) {
|
||||
lev = checkPath(elem.pathWithoutLast, elem.pathLast, row);
|
||||
if (lev > MAX_LEV_DISTANCE || (parsedQuery.literalSearch && lev !== 0)) {
|
||||
return;
|
||||
} else if (lev > 0) {
|
||||
lev_add = lev / 10;
|
||||
@@ -1085,16 +1149,16 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
|
||||
if (searchWord.indexOf(elem.pathLast) > -1 ||
|
||||
ty.normalizedName.indexOf(elem.pathLast) > -1)
|
||||
row.normalizedName.indexOf(elem.pathLast) > -1)
|
||||
{
|
||||
// filter type: ... queries
|
||||
if (!results_others[fullId] !== undefined) {
|
||||
index = ty.normalizedName.indexOf(elem.pathLast);
|
||||
index = row.normalizedName.indexOf(elem.pathLast);
|
||||
}
|
||||
}
|
||||
lev = levenshtein(searchWord, elem.pathLast);
|
||||
lev += lev_add;
|
||||
if (lev > 0 && elem.pathLast.length > 3 && searchWord.indexOf(elem.pathLast) > -1)
|
||||
if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1)
|
||||
{
|
||||
if (elem.pathLast.length < 6) {
|
||||
lev = 1;
|
||||
@@ -1116,27 +1180,25 @@ window.initSearch = function(rawSearchIndex) {
|
||||
/**
|
||||
* This function is called in case the query has more than one element.
|
||||
*
|
||||
* @param {Object} ty
|
||||
* @param {integer} pos - Position in the `searchIndex`.
|
||||
* @param {Object} elem - The element from the parsed query.
|
||||
* @param {Row} row
|
||||
* @param {integer} pos - Position in the `searchIndex`.
|
||||
* @param {Object} results
|
||||
*/
|
||||
function handleArgs(ty, pos, results) {
|
||||
if (!ty || (filterCrates !== null && ty.crate !== filterCrates)) {
|
||||
function handleArgs(row, pos, results) {
|
||||
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var totalLev = 0;
|
||||
var nbLev = 0;
|
||||
var lev;
|
||||
var i, len;
|
||||
var el;
|
||||
|
||||
// If the result is too "bad", we return false and it ends this search.
|
||||
function checkArgs(args, callback) {
|
||||
for (i = 0, len = args.length; i < len; ++i) {
|
||||
el = args[i];
|
||||
function checkArgs(elems, callback) {
|
||||
for (var i = 0, len = elems.length; i < len; ++i) {
|
||||
var elem = elems[i];
|
||||
// There is more than one parameter to the query so all checks should be "exact"
|
||||
lev = callback(ty, el, NO_TYPE_FILTER);
|
||||
lev = callback(row, elem, NO_TYPE_FILTER);
|
||||
if (lev <= 1) {
|
||||
nbLev += 1;
|
||||
totalLev += lev;
|
||||
@@ -1146,13 +1208,13 @@ window.initSearch = function(rawSearchIndex) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!checkArgs(queryInfo.elems, findArg)) {
|
||||
if (!checkArgs(parsedQuery.elems, findArg)) {
|
||||
return;
|
||||
}
|
||||
if (!checkArgs(queryInfo.args, findArg)) {
|
||||
if (!checkArgs(parsedQuery.args, findArg)) {
|
||||
return;
|
||||
}
|
||||
if (!checkArgs(queryInfo.returned, checkReturned)) {
|
||||
if (!checkArgs(parsedQuery.returned, checkReturned)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1160,43 +1222,43 @@ window.initSearch = function(rawSearchIndex) {
|
||||
return;
|
||||
}
|
||||
lev = Math.round(totalLev / nbLev);
|
||||
addIntoResults(results, ty.id, pos, 0, lev);
|
||||
addIntoResults(results, row.id, pos, 0, lev);
|
||||
}
|
||||
|
||||
function innerRunQuery() {
|
||||
var elem, i, nSearchWords, in_args, in_returned, ty;
|
||||
var elem, i, nSearchWords, in_args, in_returned, row;
|
||||
|
||||
if (queryInfo.foundElems === 1) {
|
||||
if (queryInfo.elems.length === 1) {
|
||||
elem = queryInfo.elems[0];
|
||||
if (parsedQuery.foundElems === 1) {
|
||||
if (parsedQuery.elems.length === 1) {
|
||||
elem = parsedQuery.elems[0];
|
||||
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
|
||||
// It means we want to check for this element everywhere (in names, args and
|
||||
// returned).
|
||||
handleSingleArg(searchIndex[i], i, elem);
|
||||
}
|
||||
} else if (queryInfo.args.length === 1) {
|
||||
} else if (parsedQuery.args.length === 1) {
|
||||
// We received one argument to check, so looking into args.
|
||||
elem = queryInfo.args[0];
|
||||
elem = parsedQuery.args[0];
|
||||
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
|
||||
ty = searchIndex[i];
|
||||
in_args = findArg(ty, elem, queryInfo.typeFilter);
|
||||
addIntoResults(results_in_args, ty.id, i, -1, in_args);
|
||||
row = searchIndex[i];
|
||||
in_args = findArg(row, elem, parsedQuery.typeFilter);
|
||||
addIntoResults(results_in_args, row.id, i, -1, in_args);
|
||||
}
|
||||
} else if (queryInfo.returned.length === 1) {
|
||||
} else if (parsedQuery.returned.length === 1) {
|
||||
// We received one returned argument to check, so looking into returned values.
|
||||
elem = queryInfo.returned[0];
|
||||
elem = parsedQuery.returned[0];
|
||||
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
|
||||
ty = searchIndex[i];
|
||||
in_returned = checkReturned(ty, elem, queryInfo.typeFilter);
|
||||
addIntoResults(results_returned, ty.id, i, -1, in_returned);
|
||||
row = searchIndex[i];
|
||||
in_returned = checkReturned(row, elem, parsedQuery.typeFilter);
|
||||
addIntoResults(results_returned, row.id, i, -1, in_returned);
|
||||
}
|
||||
}
|
||||
} else if (queryInfo.foundElems > 0) {
|
||||
} else if (parsedQuery.foundElems > 0) {
|
||||
var container = results_others;
|
||||
// In the special case where only a "returned" information is available, we want to
|
||||
// put the information into the "results_returned" dict.
|
||||
if (queryInfo.returned.length !== 0 && queryInfo.elemName === null &&
|
||||
queryInfo.args.length === 0 && queryInfo.elems.length === 0)
|
||||
if (parsedQuery.returned.length !== 0 && parsedQuery.args.length === 0 &&
|
||||
parsedQuery.elems.length === 0)
|
||||
{
|
||||
container = results_returned;
|
||||
}
|
||||
@@ -1211,8 +1273,8 @@ window.initSearch = function(rawSearchIndex) {
|
||||
sortResults(results_in_args, true),
|
||||
sortResults(results_returned, true),
|
||||
sortResults(results_others, false),
|
||||
queryInfo);
|
||||
handleAliases(ret, queryInfo.original.replace(/"/g, "").toLowerCase(), filterCrates);
|
||||
parsedQuery);
|
||||
handleAliases(ret, parsedQuery.original.replace(/"/g, ""), filterCrates);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1434,6 +1496,11 @@ window.initSearch = function(rawSearchIndex) {
|
||||
return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ResultsTable} results
|
||||
* @param {boolean} go_to_first
|
||||
* @param {string} filterCrates
|
||||
*/
|
||||
function showResults(results, go_to_first, filterCrates) {
|
||||
var search = searchState.outputElement();
|
||||
if (go_to_first || (results.others.length === 1
|
||||
@@ -1455,7 +1522,7 @@ window.initSearch = function(rawSearchIndex) {
|
||||
results.query = parseQuery(searchState.input.value);
|
||||
}
|
||||
|
||||
currentResults = results.query.id;
|
||||
currentResults = results.query.userQuery;
|
||||
|
||||
var ret_others = addTab(results.others, results.query, true);
|
||||
var ret_in_args = addTab(results.in_args, results.query, false);
|
||||
@@ -1535,7 +1602,7 @@ window.initSearch = function(rawSearchIndex) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (!forced && query.id === currentResults) {
|
||||
if (!forced && query.userQuery === currentResults) {
|
||||
if (query.userQuery.length > 0) {
|
||||
putBackSearch();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// The goal of this test is to ensure the color of the text is the one expected.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html?search=cook
|
||||
goto: file://|DOC_PATH|/test_docs/index.html?search=coo
|
||||
|
||||
// This is needed so that the text color is computed.
|
||||
show-text: true
|
||||
|
||||
@@ -3,66 +3,51 @@ const QUERY = ['<"P">', '"P" "P"', 'P "P"', '"p" p', '"const": p'];
|
||||
const PARSED = [
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 0,
|
||||
id: "<\"P\">",
|
||||
nameSplit: null,
|
||||
original: "<\"P\">",
|
||||
returned: [],
|
||||
typeFilter: null,
|
||||
typeFilter: -1,
|
||||
userQuery: "<\"p\">",
|
||||
error: "`\"` cannot be used in generics",
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 0,
|
||||
id: "\"P\" \"P\"",
|
||||
nameSplit: null,
|
||||
original: "\"P\" \"P\"",
|
||||
returned: [],
|
||||
typeFilter: null,
|
||||
typeFilter: -1,
|
||||
userQuery: "\"p\" \"p\"",
|
||||
error: "Cannot have more than one literal search element",
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 0,
|
||||
id: "P \"P\"",
|
||||
nameSplit: null,
|
||||
original: "P \"P\"",
|
||||
returned: [],
|
||||
typeFilter: null,
|
||||
typeFilter: -1,
|
||||
userQuery: "p \"p\"",
|
||||
error: "Cannot use literal search when there is more than one element",
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 0,
|
||||
id: "\"p\" p",
|
||||
nameSplit: null,
|
||||
original: "\"p\" p",
|
||||
returned: [],
|
||||
typeFilter: null,
|
||||
typeFilter: -1,
|
||||
userQuery: "\"p\" p",
|
||||
error: "You cannot have more than one element if you use quotes",
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 0,
|
||||
id: "\"const\": p",
|
||||
nameSplit: null,
|
||||
original: "\"const\": p",
|
||||
returned: [],
|
||||
typeFilter: null,
|
||||
typeFilter: -1,
|
||||
userQuery: "\"const\": p",
|
||||
error: "You cannot use quotes on type filter",
|
||||
},
|
||||
|
||||
@@ -3,7 +3,6 @@ const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo'];
|
||||
const PARSED = [
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [{
|
||||
name: "foo",
|
||||
fullPath: ["foo"],
|
||||
@@ -12,8 +11,6 @@ const PARSED = [
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
id: "fn:foo",
|
||||
nameSplit: null,
|
||||
original: "fn:foo",
|
||||
returned: [],
|
||||
typeFilter: 5,
|
||||
@@ -22,7 +19,6 @@ const PARSED = [
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [{
|
||||
name: "foo",
|
||||
fullPath: ["foo"],
|
||||
@@ -31,8 +27,6 @@ const PARSED = [
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
id: "enum : foo",
|
||||
nameSplit: null,
|
||||
original: "enum : foo",
|
||||
returned: [],
|
||||
typeFilter: 4,
|
||||
@@ -41,7 +35,6 @@ const PARSED = [
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [{
|
||||
name: "foo",
|
||||
fullPath: ["foo"],
|
||||
@@ -50,8 +43,6 @@ const PARSED = [
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
id: "macro<f>:foo",
|
||||
nameSplit: null,
|
||||
original: "macro<f>:foo",
|
||||
returned: [],
|
||||
typeFilter: 14,
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const QUERY = ['<P>', 'A<B<C<D>, E>'];
|
||||
const QUERY = ['<P>', 'A<B<C<D>, E>', 'p<> u8'];
|
||||
|
||||
const PARSED = [
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [{
|
||||
name: "",
|
||||
fullPath: [""],
|
||||
@@ -20,8 +19,6 @@ const PARSED = [
|
||||
],
|
||||
}],
|
||||
foundElems: 1,
|
||||
id: "<P>",
|
||||
nameSplit: null,
|
||||
original: "<P>",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
@@ -30,7 +27,6 @@ const PARSED = [
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [{
|
||||
name: "a",
|
||||
fullPath: ["a"],
|
||||
@@ -70,12 +66,35 @@ const PARSED = [
|
||||
],
|
||||
}],
|
||||
foundElems: 1,
|
||||
id: 'A<B<C<D>, E>',
|
||||
nameSplit: null,
|
||||
original: 'A<B<C<D>, E>',
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
userQuery: 'a<b<c<d>, e>',
|
||||
error: null,
|
||||
}
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elems: [
|
||||
{
|
||||
name: "p",
|
||||
fullPath: ["p"],
|
||||
pathWithoutLast: [],
|
||||
pathLast: "p",
|
||||
generics: [],
|
||||
},
|
||||
{
|
||||
name: "u8",
|
||||
fullPath: ["u8"],
|
||||
pathWithoutLast: [],
|
||||
pathLast: "u8",
|
||||
generics: [],
|
||||
},
|
||||
],
|
||||
foundElems: 2,
|
||||
original: "p<> u8",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
userQuery: "p<> u8",
|
||||
error: null,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -9,11 +9,8 @@ const PARSED = [
|
||||
pathLast: "whatever",
|
||||
generics: [],
|
||||
}],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 1,
|
||||
id: "(whatever)",
|
||||
nameSplit: null,
|
||||
original: "(whatever)",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
@@ -36,11 +33,8 @@ const PARSED = [
|
||||
},
|
||||
],
|
||||
}],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 1,
|
||||
id: "(<P>)",
|
||||
nameSplit: null,
|
||||
original: "(<P>)",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
|
||||
@@ -6,11 +6,8 @@ const QUERY = ['-> <P> (p2)', '(p -> p2', 'a b', 'a,b(c)'];
|
||||
const PARSED = [
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 2,
|
||||
id: "-> <P> (p2)",
|
||||
nameSplit: null,
|
||||
original: "-> <P> (p2)",
|
||||
returned: [
|
||||
{
|
||||
@@ -57,11 +54,8 @@ const PARSED = [
|
||||
generics: [],
|
||||
},
|
||||
],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 2,
|
||||
id: "(p -> p2",
|
||||
nameSplit: null,
|
||||
original: "(p -> p2",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
@@ -70,7 +64,6 @@ const PARSED = [
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [
|
||||
{
|
||||
name: "a b",
|
||||
@@ -81,8 +74,6 @@ const PARSED = [
|
||||
},
|
||||
],
|
||||
foundElems: 1,
|
||||
id: "a b",
|
||||
nameSplit: null,
|
||||
original: "a b",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
@@ -99,7 +90,6 @@ const PARSED = [
|
||||
generics: [],
|
||||
},
|
||||
],
|
||||
elemName: null,
|
||||
elems: [
|
||||
{
|
||||
name: "a",
|
||||
@@ -117,8 +107,6 @@ const PARSED = [
|
||||
},
|
||||
],
|
||||
foundElems: 3,
|
||||
id: "a,b(c)",
|
||||
nameSplit: null,
|
||||
original: "a,b(c)",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
|
||||
@@ -3,7 +3,6 @@ const QUERY = ['R<P>'];
|
||||
const PARSED = [
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [{
|
||||
name: "r",
|
||||
fullPath: ["r"],
|
||||
@@ -20,8 +19,6 @@ const PARSED = [
|
||||
],
|
||||
}],
|
||||
foundElems: 1,
|
||||
id: "R<P>",
|
||||
nameSplit: null,
|
||||
original: "R<P>",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
|
||||
@@ -3,7 +3,6 @@ const QUERY = ['A::B', '::A::B', 'A::B::,C', 'A::B::<f>,C'];
|
||||
const PARSED = [
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [{
|
||||
name: "a::b",
|
||||
fullPath: ["a", "b"],
|
||||
@@ -12,8 +11,6 @@ const PARSED = [
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
id: "A::B",
|
||||
nameSplit: null,
|
||||
original: "A::B",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
@@ -22,7 +19,6 @@ const PARSED = [
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [{
|
||||
name: "::a::b",
|
||||
fullPath: ["a", "b"],
|
||||
@@ -31,8 +27,6 @@ const PARSED = [
|
||||
generics: [],
|
||||
}],
|
||||
foundElems: 1,
|
||||
id: '::A::B',
|
||||
nameSplit: null,
|
||||
original: '::A::B',
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
@@ -41,7 +35,6 @@ const PARSED = [
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [
|
||||
{
|
||||
name: "a::b::",
|
||||
@@ -59,8 +52,6 @@ const PARSED = [
|
||||
},
|
||||
],
|
||||
foundElems: 2,
|
||||
id: 'A::B::,C',
|
||||
nameSplit: null,
|
||||
original: 'A::B::,C',
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
@@ -69,7 +60,6 @@ const PARSED = [
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [
|
||||
{
|
||||
name: "a::b::",
|
||||
@@ -95,8 +85,6 @@ const PARSED = [
|
||||
},
|
||||
],
|
||||
foundElems: 2,
|
||||
id: 'A::B::<f>,C',
|
||||
nameSplit: null,
|
||||
original: 'A::B::<f>,C',
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
|
||||
@@ -3,11 +3,8 @@ const QUERY = ['-> "p"', '("p")'];
|
||||
const PARSED = [
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 1,
|
||||
id: "-> \"p\"",
|
||||
nameSplit: null,
|
||||
original: "-> \"p\"",
|
||||
returned: [{
|
||||
name: "p",
|
||||
@@ -28,11 +25,8 @@ const PARSED = [
|
||||
pathLast: "p",
|
||||
generics: [],
|
||||
}],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 1,
|
||||
id: "(\"p\")",
|
||||
nameSplit: null,
|
||||
original: "(\"p\")",
|
||||
returned: [],
|
||||
typeFilter: -1,
|
||||
|
||||
@@ -3,11 +3,8 @@ const QUERY = ['-> <P>', '-> P'];
|
||||
const PARSED = [
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 1,
|
||||
id: "-> <P>",
|
||||
nameSplit: null,
|
||||
original: "-> <P>",
|
||||
returned: [{
|
||||
name: "",
|
||||
@@ -30,11 +27,8 @@ const PARSED = [
|
||||
},
|
||||
{
|
||||
args: [],
|
||||
elemName: null,
|
||||
elems: [],
|
||||
foundElems: 1,
|
||||
id: "-> P",
|
||||
nameSplit: null,
|
||||
original: "-> P",
|
||||
returned: [{
|
||||
name: "p",
|
||||
|
||||
@@ -4,6 +4,6 @@ const EXPECTED = {
|
||||
'others': [
|
||||
{ 'path': 'std::vec::Vec', 'name': 'new' },
|
||||
{ 'path': 'std::vec::Vec', 'name': 'ne' },
|
||||
{ 'path': 'std::rc::Rc', 'name': 'ne' },
|
||||
{ 'path': 'alloc::vec::Vec', 'name': 'ne' },
|
||||
],
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias_whitespace',
|
||||
'name': 'Struct',
|
||||
'alias': 'demon lord',
|
||||
'alias': 'Demon Lord',
|
||||
'href': '../doc_alias_whitespace/struct.Struct.html',
|
||||
'is_alias': true
|
||||
},
|
||||
|
||||
@@ -32,7 +32,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'Struct',
|
||||
'alias': 'structitem',
|
||||
'alias': 'StructItem',
|
||||
'href': '../doc_alias/struct.Struct.html',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -44,7 +44,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Struct',
|
||||
'name': 'field',
|
||||
'alias': 'structfielditem',
|
||||
'alias': 'StructFieldItem',
|
||||
'href': '../doc_alias/struct.Struct.html#structfield.field',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -56,7 +56,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Struct',
|
||||
'name': 'method',
|
||||
'alias': 'structmethoditem',
|
||||
'alias': 'StructMethodItem',
|
||||
'href': '../doc_alias/struct.Struct.html#method.method',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -72,7 +72,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Struct',
|
||||
'name': 'ImplConstItem',
|
||||
'alias': 'structimplconstitem',
|
||||
'alias': 'StructImplConstItem',
|
||||
'href': '../doc_alias/struct.Struct.html#associatedconstant.ImplConstItem',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -84,7 +84,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Struct',
|
||||
'name': 'function',
|
||||
'alias': 'impltraitfunction',
|
||||
'alias': 'ImplTraitFunction',
|
||||
'href': '../doc_alias/struct.Struct.html#method.function',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -96,7 +96,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'Enum',
|
||||
'alias': 'enumitem',
|
||||
'alias': 'EnumItem',
|
||||
'href': '../doc_alias/enum.Enum.html',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -108,7 +108,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Enum',
|
||||
'name': 'Variant',
|
||||
'alias': 'variantitem',
|
||||
'alias': 'VariantItem',
|
||||
'href': '../doc_alias/enum.Enum.html#variant.Variant',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -120,7 +120,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Enum',
|
||||
'name': 'method',
|
||||
'alias': 'enummethoditem',
|
||||
'alias': 'EnumMethodItem',
|
||||
'href': '../doc_alias/enum.Enum.html#method.method',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -132,7 +132,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'Typedef',
|
||||
'alias': 'typedefitem',
|
||||
'alias': 'TypedefItem',
|
||||
'href': '../doc_alias/type.Typedef.html',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -144,7 +144,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'Trait',
|
||||
'alias': 'traititem',
|
||||
'alias': 'TraitItem',
|
||||
'href': '../doc_alias/trait.Trait.html',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -156,7 +156,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Trait',
|
||||
'name': 'Target',
|
||||
'alias': 'traittypeitem',
|
||||
'alias': 'TraitTypeItem',
|
||||
'href': '../doc_alias/trait.Trait.html#associatedtype.Target',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -168,7 +168,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Trait',
|
||||
'name': 'AssociatedConst',
|
||||
'alias': 'associatedconstitem',
|
||||
'alias': 'AssociatedConstItem',
|
||||
'href': '../doc_alias/trait.Trait.html#associatedconstant.AssociatedConst',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -180,7 +180,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Trait',
|
||||
'name': 'function',
|
||||
'alias': 'traitfunctionitem',
|
||||
'alias': 'TraitFunctionItem',
|
||||
'href': '../doc_alias/trait.Trait.html#tymethod.function',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -192,7 +192,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'function',
|
||||
'alias': 'functionitem',
|
||||
'alias': 'FunctionItem',
|
||||
'href': '../doc_alias/fn.function.html',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -204,7 +204,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'Module',
|
||||
'alias': 'moduleitem',
|
||||
'alias': 'ModuleItem',
|
||||
'href': '../doc_alias/Module/index.html',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -216,7 +216,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'Const',
|
||||
'alias': 'constitem',
|
||||
'alias': 'ConstItem',
|
||||
'href': '../doc_alias/constant.Const.html',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -232,7 +232,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'Static',
|
||||
'alias': 'staticitem',
|
||||
'alias': 'StaticItem',
|
||||
'href': '../doc_alias/static.Static.html',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -244,7 +244,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'Union',
|
||||
'alias': 'unionitem',
|
||||
'alias': 'UnionItem',
|
||||
'href': '../doc_alias/union.Union.html',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -262,7 +262,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Union',
|
||||
'name': 'union_item',
|
||||
'alias': 'unionfielditem',
|
||||
'alias': 'UnionFieldItem',
|
||||
'href': '../doc_alias/union.Union.html#structfield.union_item',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -274,7 +274,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias::Union',
|
||||
'name': 'method',
|
||||
'alias': 'unionmethoditem',
|
||||
'alias': 'UnionMethodItem',
|
||||
'href': '../doc_alias/union.Union.html#method.method',
|
||||
'is_alias': true
|
||||
},
|
||||
@@ -286,7 +286,7 @@ const EXPECTED = [
|
||||
{
|
||||
'path': 'doc_alias',
|
||||
'name': 'Macro',
|
||||
'alias': 'macroitem',
|
||||
'alias': 'MacroItem',
|
||||
'href': '../doc_alias/macro.Macro.html',
|
||||
'is_alias': true
|
||||
},
|
||||
|
||||
@@ -270,7 +270,12 @@ function loadSearchJsAndIndex(searchJs, searchIndex, storageJs, crate) {
|
||||
// execQuery last parameter is built in buildIndex.
|
||||
// buildIndex requires the hashmap from search-index.
|
||||
var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult",
|
||||
"buildIndex", "execQuery", "parseQuery", "createQueryResults"];
|
||||
"buildIndex", "execQuery", "parseQuery", "createQueryResults",
|
||||
"isWhitespace", "isSpecialStartCharacter", "isStopCharacter",
|
||||
"removeEmptyStringsFromArray", "parseInput", "getItemsBefore",
|
||||
"getNextElem", "createQueryElement", "isReturnArrow", "isPathStart",
|
||||
"skipWhitespaces", "getStringElem", "itemTypeFromName",
|
||||
"newParsedQuery"];
|
||||
|
||||
const functions = ["hasOwnPropertyRustdoc", "onEach"];
|
||||
ALIASES = {};
|
||||
@@ -286,13 +291,12 @@ function loadSearchJsAndIndex(searchJs, searchIndex, storageJs, crate) {
|
||||
return [loaded, index];
|
||||
}
|
||||
|
||||
function checkFieldNeededFields(fullPath, expected, error_text, queryName, position) {
|
||||
// This function checks if `expected` has all the required fields needed for the checks.
|
||||
function checkNeededFields(fullPath, expected, error_text, queryName, position) {
|
||||
let fieldsToCheck;
|
||||
if (fullPath.length === 0) {
|
||||
fieldsToCheck = [
|
||||
"foundElems",
|
||||
"id",
|
||||
"nameSplit",
|
||||
"original",
|
||||
"returned",
|
||||
"typeFilter",
|
||||
@@ -328,7 +332,7 @@ function checkFieldNeededFields(fullPath, expected, error_text, queryName, posit
|
||||
function valueCheck(fullPath, expected, result, error_text, queryName) {
|
||||
if (Array.isArray(expected)) {
|
||||
for (var i = 0; i < expected.length; ++i) {
|
||||
checkFieldNeededFields(fullPath, expected[i], error_text, queryName, i);
|
||||
checkNeededFields(fullPath, expected[i], error_text, queryName, i);
|
||||
if (i >= result.length) {
|
||||
error_text.push(`${queryName}==> EXPECTED has extra value in array from field ` +
|
||||
`\`${fullPath}\` (position ${i}): \`${JSON.stringify(expected[i])}\``);
|
||||
@@ -367,7 +371,7 @@ function valueCheck(fullPath, expected, result, error_text, queryName) {
|
||||
|
||||
function runParser(query, expected, loaded, loadedFile, queryName) {
|
||||
var error_text = [];
|
||||
checkFieldNeededFields("", expected, error_text, queryName, null);
|
||||
checkNeededFields("", expected, error_text, queryName, null);
|
||||
if (error_text.length === 0) {
|
||||
valueCheck('', expected, loaded.parseQuery(query), error_text, queryName);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user