diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 7c55d10836c45..991e7ef15da39 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -151,467 +151,6 @@ window.initSearch = function(rawSearchIndex) {
removeEmptyStringsFromArray(split);
- function transformResults(results) {
- var out = [];
- for (var i = 0, len = results.length; i < len; ++i) {
- if (results[i].id > -1) {
- var obj = searchIndex[results[i].id];
- obj.lev = results[i].lev;
- var res = buildHrefAndPath(obj);
- obj.displayPath = pathSplitter(res[0]);
- obj.fullPath = obj.displayPath + obj.name;
- // To be sure than it some items aren't considered as duplicate.
- obj.fullPath += "|" + obj.ty;
- obj.href = res[1];
- out.push(obj);
- if (out.length >= MAX_RESULTS) {
- break;
- }
- }
- }
- return out;
- }
-
- function sortResults(results, isType) {
- var ar = [];
- for (var entry in results) {
- if (hasOwnPropertyRustdoc(results, entry)) {
- ar.push(results[entry]);
- }
- }
- results = ar;
- var i, len, result;
- for (i = 0, len = results.length; i < len; ++i) {
- result = results[i];
- result.word = searchWords[result.id];
- result.item = searchIndex[result.id] || {};
- }
- // if there are no results then return to default and fail
- if (results.length === 0) {
- return [];
- }
-
- results.sort(function(aaa, bbb) {
- var a, b;
-
- // sort by exact match with regard to the last word (mismatch goes later)
- a = (aaa.word !== val);
- b = (bbb.word !== val);
- if (a !== b) { return a - b; }
-
- // Sort by non levenshtein results and then levenshtein results by the distance
- // (less changes required to match means higher rankings)
- a = (aaa.lev);
- b = (bbb.lev);
- if (a !== b) { return a - b; }
-
- // sort by crate (non-current crate goes later)
- a = (aaa.item.crate !== window.currentCrate);
- b = (bbb.item.crate !== window.currentCrate);
- if (a !== b) { return a - b; }
-
- // sort by item name length (longer goes later)
- a = aaa.word.length;
- b = bbb.word.length;
- if (a !== b) { return a - b; }
-
- // sort by item name (lexicographically larger goes later)
- a = aaa.word;
- b = bbb.word;
- if (a !== b) { return (a > b ? +1 : -1); }
-
- // sort by index of keyword in item name (no literal occurrence goes later)
- a = (aaa.index < 0);
- b = (bbb.index < 0);
- if (a !== b) { return a - b; }
- // (later literal occurrence, if any, goes later)
- a = aaa.index;
- b = bbb.index;
- if (a !== b) { return a - b; }
-
- // special precedence for primitive and keyword pages
- if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
- (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
- return -1;
- }
- if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
- (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
- return 1;
- }
-
- // sort by description (no description goes later)
- a = (aaa.item.desc === "");
- b = (bbb.item.desc === "");
- if (a !== b) { return a - b; }
-
- // sort by type (later occurrence in `itemTypes` goes later)
- a = aaa.item.ty;
- b = bbb.item.ty;
- if (a !== b) { return a - b; }
-
- // sort by path (lexicographically larger goes later)
- a = aaa.item.path;
- b = bbb.item.path;
- if (a !== b) { return (a > b ? +1 : -1); }
-
- // que sera, sera
- return 0;
- });
-
- for (i = 0, len = results.length; i < len; ++i) {
- result = results[i];
-
- // this validation does not make sense when searching by types
- if (result.dontValidate) {
- continue;
- }
- var name = result.item.name.toLowerCase(),
- path = result.item.path.toLowerCase(),
- parent = result.item.parent;
-
- if (!isType && !validateResult(name, path, split, parent)) {
- result.id = -1;
- }
- }
- return transformResults(results);
- }
-
- function extractGenerics(val) {
- val = val.toLowerCase();
- if (val.indexOf("<") !== -1) {
- var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
- return {
- name: val.substring(0, val.indexOf("<")),
- generics: values.split(/\s*,\s*/),
- };
- }
- return {
- name: val,
- generics: [],
- };
- }
-
- function checkGenerics(obj, val) {
- // The names match, but we need to be sure that all generics kinda
- // match as well.
- var tmp_lev, elem_name;
- if (val.generics.length > 0) {
- if (obj.length > GENERICS_DATA &&
- obj[GENERICS_DATA].length >= val.generics.length) {
- var elems = Object.create(null);
- var elength = obj[GENERICS_DATA].length;
- for (var x = 0; x < elength; ++x) {
- if (!elems[obj[GENERICS_DATA][x][NAME]]) {
- elems[obj[GENERICS_DATA][x][NAME]] = 0;
- }
- elems[obj[GENERICS_DATA][x][NAME]] += 1;
- }
- var total = 0;
- var done = 0;
- // We need to find the type that matches the most to remove it in order
- // to move forward.
- var vlength = val.generics.length;
- for (x = 0; x < vlength; ++x) {
- var lev = MAX_LEV_DISTANCE + 1;
- var firstGeneric = val.generics[x];
- var match = null;
- if (elems[firstGeneric]) {
- match = firstGeneric;
- lev = 0;
- } else {
- for (elem_name in elems) {
- tmp_lev = levenshtein(elem_name, firstGeneric);
- if (tmp_lev < lev) {
- lev = tmp_lev;
- match = elem_name;
- }
- }
- }
- if (match !== null) {
- elems[match] -= 1;
- if (elems[match] == 0) {
- delete elems[match];
- }
- total += lev;
- done += 1;
- } else {
- return MAX_LEV_DISTANCE + 1;
- }
- }
- return Math.ceil(total / done);
- }
- }
- return MAX_LEV_DISTANCE + 1;
- }
-
- // Check for type name and type generics (if any).
- function checkType(obj, val, literalSearch) {
- var lev_distance = MAX_LEV_DISTANCE + 1;
- var tmp_lev = MAX_LEV_DISTANCE + 1;
- var len, x, firstGeneric;
- if (obj[NAME] === val.name) {
- if (literalSearch) {
- if (val.generics && val.generics.length !== 0) {
- if (obj.length > GENERICS_DATA &&
- obj[GENERICS_DATA].length > 0) {
- var elems = Object.create(null);
- len = obj[GENERICS_DATA].length;
- for (x = 0; x < len; ++x) {
- if (!elems[obj[GENERICS_DATA][x][NAME]]) {
- elems[obj[GENERICS_DATA][x][NAME]] = 0;
- }
- elems[obj[GENERICS_DATA][x][NAME]] += 1;
- }
-
- var allFound = true;
- len = val.generics.length;
- for (x = 0; x < len; ++x) {
- firstGeneric = val.generics[x];
- if (elems[firstGeneric]) {
- elems[firstGeneric] -= 1;
- } else {
- allFound = false;
- break;
- }
- }
- if (allFound) {
- return true;
- }
- }
- return false;
- }
- return true;
- } else {
- // If the type has generics but don't match, then it won't return at this point.
- // Otherwise, `checkGenerics` will return 0 and it'll return.
- if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
- tmp_lev = checkGenerics(obj, val);
- if (tmp_lev <= MAX_LEV_DISTANCE) {
- return tmp_lev;
- }
- }
- }
- } else if (literalSearch) {
- if ((!val.generics || val.generics.length === 0) &&
- obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
- return obj[GENERICS_DATA].some(
- function(gen) {
- return gen[NAME] === val.name;
- });
- }
- return false;
- }
- lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
- if (lev_distance <= MAX_LEV_DISTANCE) {
- // The generics didn't match but the name kinda did so we give it
- // a levenshtein distance value that isn't *this* good so it goes
- // into the search results but not too high.
- lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
- }
- if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
- // We can check if the type we're looking for is inside the generics!
- var olength = obj[GENERICS_DATA].length;
- for (x = 0; x < olength; ++x) {
- tmp_lev = Math.min(levenshtein(obj[GENERICS_DATA][x][NAME], val.name), tmp_lev);
- }
- if (tmp_lev !== 0) {
- // If we didn't find a good enough result, we go check inside the generics of
- // the generics.
- for (x = 0; x < olength && tmp_lev !== 0; ++x) {
- tmp_lev = Math.min(
- checkType(obj[GENERICS_DATA][x], val, literalSearch),
- tmp_lev
- );
- }
- }
- }
- // Now whatever happens, the returned distance is "less good" so we should mark it
- // as such, and so we add 1 to the distance to make it "less good".
- return Math.min(lev_distance, tmp_lev) + 1;
- }
-
- function findArg(obj, val, literalSearch, typeFilter) {
- var lev_distance = MAX_LEV_DISTANCE + 1;
-
- if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
- var length = obj.type[INPUTS_DATA].length;
- for (var i = 0; i < length; i++) {
- var tmp = obj.type[INPUTS_DATA][i];
- if (!typePassesFilter(typeFilter, tmp[1])) {
- continue;
- }
- tmp = checkType(tmp, val, literalSearch);
- if (literalSearch) {
- if (tmp) {
- return true;
- }
- continue;
- }
- lev_distance = Math.min(tmp, lev_distance);
- if (lev_distance === 0) {
- return 0;
- }
- }
- }
- return literalSearch ? false : lev_distance;
- }
-
- function checkReturned(obj, val, literalSearch, typeFilter) {
- var lev_distance = MAX_LEV_DISTANCE + 1;
-
- if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
- var ret = obj.type[OUTPUT_DATA];
- if (typeof ret[0] === "string") {
- ret = [ret];
- }
- for (var x = 0, len = ret.length; x < len; ++x) {
- var tmp = ret[x];
- if (!typePassesFilter(typeFilter, tmp[1])) {
- continue;
- }
- tmp = checkType(tmp, val, literalSearch);
- if (literalSearch) {
- if (tmp) {
- return true;
- }
- continue;
- }
- lev_distance = Math.min(tmp, lev_distance);
- if (lev_distance === 0) {
- return 0;
- }
- }
- }
- return literalSearch ? false : lev_distance;
- }
-
- function checkPath(contains, lastElem, ty) {
- if (contains.length === 0) {
- return 0;
- }
- var ret_lev = MAX_LEV_DISTANCE + 1;
- var path = ty.path.split("::");
-
- if (ty.parent && ty.parent.name) {
- path.push(ty.parent.name.toLowerCase());
- }
-
- var length = path.length;
- var clength = contains.length;
- if (clength > length) {
- return MAX_LEV_DISTANCE + 1;
- }
- for (var i = 0; i < length; ++i) {
- if (i + clength > length) {
- break;
- }
- var lev_total = 0;
- var aborted = false;
- for (var x = 0; x < clength; ++x) {
- var lev = levenshtein(path[i + x], contains[x]);
- if (lev > MAX_LEV_DISTANCE) {
- aborted = true;
- break;
- }
- lev_total += lev;
- }
- if (!aborted) {
- ret_lev = Math.min(ret_lev, Math.round(lev_total / clength));
- }
- }
- return ret_lev;
- }
-
- function typePassesFilter(filter, type) {
- // No filter
- if (filter <= NO_TYPE_FILTER) return true;
-
- // Exact match
- if (filter === type) return true;
-
- // Match related items
- var name = itemTypes[type];
- switch (itemTypes[filter]) {
- case "constant":
- return name === "associatedconstant";
- case "fn":
- return name === "method" || name === "tymethod";
- case "type":
- return name === "primitive" || name === "associatedtype";
- case "trait":
- return name === "traitalias";
- }
-
- // No match
- return false;
- }
-
- function createAliasFromItem(item) {
- return {
- crate: item.crate,
- name: item.name,
- path: item.path,
- desc: item.desc,
- ty: item.ty,
- parent: item.parent,
- type: item.type,
- is_alias: true,
- };
- }
-
- function handleAliases(ret, query, filterCrates) {
- // 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 !== undefined) {
- if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
- var query_aliases = ALIASES[filterCrates][query.search];
- var len = query_aliases.length;
- for (var i = 0; i < len; ++i) {
- aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
- }
- }
- } else {
- Object.keys(ALIASES).forEach(function(crate) {
- if (ALIASES[crate][query.search]) {
- var pushTo = crate === window.currentCrate ? crateAliases : aliases;
- var query_aliases = ALIASES[crate][query.search];
- var len = query_aliases.length;
- for (var i = 0; i < len; ++i) {
- pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
- }
- }
- });
- }
-
- var sortFunc = function(aaa, bbb) {
- if (aaa.path < bbb.path) {
- return 1;
- } else if (aaa.path === bbb.path) {
- return 0;
- }
- return -1;
- };
- crateAliases.sort(sortFunc);
- aliases.sort(sortFunc);
-
- var pushFunc = function(alias) {
- alias.alias = query.raw;
- var res = buildHrefAndPath(alias);
- alias.displayPath = pathSplitter(res[0]);
- alias.fullPath = alias.displayPath + alias.name;
- alias.href = res[1];
-
- ret.others.unshift(alias);
- if (ret.others.length > MAX_RESULTS) {
- ret.others.pop();
- }
- };
- onEach(aliases, pushFunc);
- onEach(crateAliases, pushFunc);
- }
-
// quoted values mean literal search
var nSearchWords = searchWords.length;
var i, it;
@@ -828,14 +367,476 @@ window.initSearch = function(rawSearchIndex) {
}
var ret = {
- "in_args": sortResults(results_in_args, true),
- "returned": sortResults(results_returned, true),
- "others": sortResults(results, false),
+ "in_args": sortResults(results_in_args, true, searchWords, searchIndex, val, split),
+ "returned": sortResults(results_returned, true, searchWords, searchIndex, val, split),
+ "others": sortResults(results, false, searchWords, searchIndex, val, split),
};
handleAliases(ret, query, filterCrates);
return ret;
}
+ function transformResults(results) {
+ var out = [];
+ for (var i = 0, len = results.length; i < len; ++i) {
+ if (results[i].id > -1) {
+ var obj = searchIndex[results[i].id];
+ obj.lev = results[i].lev;
+ var res = buildHrefAndPath(obj);
+ obj.displayPath = pathSplitter(res[0]);
+ obj.fullPath = obj.displayPath + obj.name;
+ // To be sure than it some items aren't considered as duplicate.
+ obj.fullPath += "|" + obj.ty;
+ obj.href = res[1];
+ out.push(obj);
+ if (out.length >= MAX_RESULTS) {
+ break;
+ }
+ }
+ }
+ return out;
+ }
+
+ function sortResults(results, isType, searchWords, searchIndex, val, split) {
+ var ar = [];
+ for (var entry in results) {
+ if (hasOwnPropertyRustdoc(results, entry)) {
+ ar.push(results[entry]);
+ }
+ }
+ results = ar;
+ var i, len, result;
+ for (i = 0, len = results.length; i < len; ++i) {
+ result = results[i];
+ result.word = searchWords[result.id];
+ result.item = searchIndex[result.id] || {};
+ }
+ // if there are no results then return to default and fail
+ if (results.length === 0) {
+ return [];
+ }
+
+ results.sort(function(aaa, bbb) {
+ var a, b;
+
+ // sort by exact match with regard to the last word (mismatch goes later)
+ a = (aaa.word !== val);
+ b = (bbb.word !== val);
+ if (a !== b) { return a - b; }
+
+ // Sort by non levenshtein results and then levenshtein results by the distance
+ // (less changes required to match means higher rankings)
+ a = (aaa.lev);
+ b = (bbb.lev);
+ if (a !== b) { return a - b; }
+
+ // sort by crate (non-current crate goes later)
+ a = (aaa.item.crate !== window.currentCrate);
+ b = (bbb.item.crate !== window.currentCrate);
+ if (a !== b) { return a - b; }
+
+ // sort by item name length (longer goes later)
+ a = aaa.word.length;
+ b = bbb.word.length;
+ if (a !== b) { return a - b; }
+
+ // sort by item name (lexicographically larger goes later)
+ a = aaa.word;
+ b = bbb.word;
+ if (a !== b) { return (a > b ? +1 : -1); }
+
+ // sort by index of keyword in item name (no literal occurrence goes later)
+ a = (aaa.index < 0);
+ b = (bbb.index < 0);
+ if (a !== b) { return a - b; }
+ // (later literal occurrence, if any, goes later)
+ a = aaa.index;
+ b = bbb.index;
+ if (a !== b) { return a - b; }
+
+ // special precedence for primitive and keyword pages
+ if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
+ (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
+ return -1;
+ }
+ if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
+ (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
+ return 1;
+ }
+
+ // sort by description (no description goes later)
+ a = (aaa.item.desc === "");
+ b = (bbb.item.desc === "");
+ if (a !== b) { return a - b; }
+
+ // sort by type (later occurrence in `itemTypes` goes later)
+ a = aaa.item.ty;
+ b = bbb.item.ty;
+ if (a !== b) { return a - b; }
+
+ // sort by path (lexicographically larger goes later)
+ a = aaa.item.path;
+ b = bbb.item.path;
+ if (a !== b) { return (a > b ? +1 : -1); }
+
+ // que sera, sera
+ return 0;
+ });
+
+ for (i = 0, len = results.length; i < len; ++i) {
+ result = results[i];
+
+ // this validation does not make sense when searching by types
+ if (result.dontValidate) {
+ continue;
+ }
+ var name = result.item.name.toLowerCase(),
+ path = result.item.path.toLowerCase(),
+ parent = result.item.parent;
+
+ if (!isType && !validateResult(name, path, split, parent)) {
+ result.id = -1;
+ }
+ }
+ return transformResults(results);
+ }
+
+ function extractGenerics(val) {
+ val = val.toLowerCase();
+ if (val.indexOf("<") !== -1) {
+ var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
+ return {
+ name: val.substring(0, val.indexOf("<")),
+ generics: values.split(/\s*,\s*/),
+ };
+ }
+ return {
+ name: val,
+ generics: [],
+ };
+ }
+
+ function checkGenerics(obj, val) {
+ // The names match, but we need to be sure that all generics kinda
+ // match as well.
+ var tmp_lev, elem_name;
+ if (val.generics.length > 0) {
+ if (obj.length > GENERICS_DATA &&
+ obj[GENERICS_DATA].length >= val.generics.length) {
+ var elems = Object.create(null);
+ var elength = obj[GENERICS_DATA].length;
+ for (var x = 0; x < elength; ++x) {
+ if (!elems[obj[GENERICS_DATA][x][NAME]]) {
+ elems[obj[GENERICS_DATA][x][NAME]] = 0;
+ }
+ elems[obj[GENERICS_DATA][x][NAME]] += 1;
+ }
+ var total = 0;
+ var done = 0;
+ // We need to find the type that matches the most to remove it in order
+ // to move forward.
+ var vlength = val.generics.length;
+ for (x = 0; x < vlength; ++x) {
+ var lev = MAX_LEV_DISTANCE + 1;
+ var firstGeneric = val.generics[x];
+ var match = null;
+ if (elems[firstGeneric]) {
+ match = firstGeneric;
+ lev = 0;
+ } else {
+ for (elem_name in elems) {
+ tmp_lev = levenshtein(elem_name, firstGeneric);
+ if (tmp_lev < lev) {
+ lev = tmp_lev;
+ match = elem_name;
+ }
+ }
+ }
+ if (match !== null) {
+ elems[match] -= 1;
+ if (elems[match] == 0) {
+ delete elems[match];
+ }
+ total += lev;
+ done += 1;
+ } else {
+ return MAX_LEV_DISTANCE + 1;
+ }
+ }
+ return Math.ceil(total / done);
+ }
+ }
+ return MAX_LEV_DISTANCE + 1;
+ }
+
+ // Check for type name and type generics (if any).
+ function checkType(obj, val, literalSearch) {
+ var lev_distance = MAX_LEV_DISTANCE + 1;
+ var tmp_lev = MAX_LEV_DISTANCE + 1;
+ var len, x, firstGeneric;
+ if (obj[NAME] === val.name) {
+ if (literalSearch) {
+ if (val.generics && val.generics.length !== 0) {
+ if (obj.length > GENERICS_DATA &&
+ obj[GENERICS_DATA].length > 0) {
+ var elems = Object.create(null);
+ len = obj[GENERICS_DATA].length;
+ for (x = 0; x < len; ++x) {
+ if (!elems[obj[GENERICS_DATA][x][NAME]]) {
+ elems[obj[GENERICS_DATA][x][NAME]] = 0;
+ }
+ elems[obj[GENERICS_DATA][x][NAME]] += 1;
+ }
+
+ var allFound = true;
+ len = val.generics.length;
+ for (x = 0; x < len; ++x) {
+ firstGeneric = val.generics[x];
+ if (elems[firstGeneric]) {
+ elems[firstGeneric] -= 1;
+ } else {
+ allFound = false;
+ break;
+ }
+ }
+ if (allFound) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
+ } else {
+ // If the type has generics but don't match, then it won't return at this point.
+ // Otherwise, `checkGenerics` will return 0 and it'll return.
+ if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
+ tmp_lev = checkGenerics(obj, val);
+ if (tmp_lev <= MAX_LEV_DISTANCE) {
+ return tmp_lev;
+ }
+ }
+ }
+ } else if (literalSearch) {
+ if ((!val.generics || val.generics.length === 0) &&
+ obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
+ return obj[GENERICS_DATA].some(
+ function(gen) {
+ return gen[NAME] === val.name;
+ });
+ }
+ return false;
+ }
+ lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
+ if (lev_distance <= MAX_LEV_DISTANCE) {
+ // The generics didn't match but the name kinda did so we give it
+ // a levenshtein distance value that isn't *this* good so it goes
+ // into the search results but not too high.
+ lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
+ }
+ if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
+ // We can check if the type we're looking for is inside the generics!
+ var olength = obj[GENERICS_DATA].length;
+ for (x = 0; x < olength; ++x) {
+ tmp_lev = Math.min(levenshtein(obj[GENERICS_DATA][x][NAME], val.name), tmp_lev);
+ }
+ if (tmp_lev !== 0) {
+ // If we didn't find a good enough result, we go check inside the generics of
+ // the generics.
+ for (x = 0; x < olength && tmp_lev !== 0; ++x) {
+ tmp_lev = Math.min(
+ checkType(obj[GENERICS_DATA][x], val, literalSearch),
+ tmp_lev
+ );
+ }
+ }
+ }
+ // Now whatever happens, the returned distance is "less good" so we should mark it
+ // as such, and so we add 1 to the distance to make it "less good".
+ return Math.min(lev_distance, tmp_lev) + 1;
+ }
+
+ function findArg(obj, val, literalSearch, typeFilter) {
+ var lev_distance = MAX_LEV_DISTANCE + 1;
+
+ if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
+ var length = obj.type[INPUTS_DATA].length;
+ for (var i = 0; i < length; i++) {
+ var tmp = obj.type[INPUTS_DATA][i];
+ if (!typePassesFilter(typeFilter, tmp[1])) {
+ continue;
+ }
+ tmp = checkType(tmp, val, literalSearch);
+ if (literalSearch) {
+ if (tmp) {
+ return true;
+ }
+ continue;
+ }
+ lev_distance = Math.min(tmp, lev_distance);
+ if (lev_distance === 0) {
+ return 0;
+ }
+ }
+ }
+ return literalSearch ? false : lev_distance;
+ }
+
+ function checkReturned(obj, val, literalSearch, typeFilter) {
+ var lev_distance = MAX_LEV_DISTANCE + 1;
+
+ if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
+ var ret = obj.type[OUTPUT_DATA];
+ if (typeof ret[0] === "string") {
+ ret = [ret];
+ }
+ for (var x = 0, len = ret.length; x < len; ++x) {
+ var tmp = ret[x];
+ if (!typePassesFilter(typeFilter, tmp[1])) {
+ continue;
+ }
+ tmp = checkType(tmp, val, literalSearch);
+ if (literalSearch) {
+ if (tmp) {
+ return true;
+ }
+ continue;
+ }
+ lev_distance = Math.min(tmp, lev_distance);
+ if (lev_distance === 0) {
+ return 0;
+ }
+ }
+ }
+ return literalSearch ? false : lev_distance;
+ }
+
+ function checkPath(contains, lastElem, ty) {
+ if (contains.length === 0) {
+ return 0;
+ }
+ var ret_lev = MAX_LEV_DISTANCE + 1;
+ var path = ty.path.split("::");
+
+ if (ty.parent && ty.parent.name) {
+ path.push(ty.parent.name.toLowerCase());
+ }
+
+ var length = path.length;
+ var clength = contains.length;
+ if (clength > length) {
+ return MAX_LEV_DISTANCE + 1;
+ }
+ for (var i = 0; i < length; ++i) {
+ if (i + clength > length) {
+ break;
+ }
+ var lev_total = 0;
+ var aborted = false;
+ for (var x = 0; x < clength; ++x) {
+ var lev = levenshtein(path[i + x], contains[x]);
+ if (lev > MAX_LEV_DISTANCE) {
+ aborted = true;
+ break;
+ }
+ lev_total += lev;
+ }
+ if (!aborted) {
+ ret_lev = Math.min(ret_lev, Math.round(lev_total / clength));
+ }
+ }
+ return ret_lev;
+ }
+
+ function typePassesFilter(filter, type) {
+ // No filter
+ if (filter <= NO_TYPE_FILTER) return true;
+
+ // Exact match
+ if (filter === type) return true;
+
+ // Match related items
+ var name = itemTypes[type];
+ switch (itemTypes[filter]) {
+ case "constant":
+ return name === "associatedconstant";
+ case "fn":
+ return name === "method" || name === "tymethod";
+ case "type":
+ return name === "primitive" || name === "associatedtype";
+ case "trait":
+ return name === "traitalias";
+ }
+
+ // No match
+ return false;
+ }
+
+ function createAliasFromItem(item) {
+ return {
+ crate: item.crate,
+ name: item.name,
+ path: item.path,
+ desc: item.desc,
+ ty: item.ty,
+ parent: item.parent,
+ type: item.type,
+ is_alias: true,
+ };
+ }
+
+ function handleAliases(ret, query, filterCrates) {
+ // 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 !== undefined) {
+ if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
+ var query_aliases = ALIASES[filterCrates][query.search];
+ var len = query_aliases.length;
+ for (var i = 0; i < len; ++i) {
+ aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
+ }
+ }
+ } else {
+ Object.keys(ALIASES).forEach(function(crate) {
+ if (ALIASES[crate][query.search]) {
+ var pushTo = crate === window.currentCrate ? crateAliases : aliases;
+ var query_aliases = ALIASES[crate][query.search];
+ var len = query_aliases.length;
+ for (var i = 0; i < len; ++i) {
+ pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
+ }
+ }
+ });
+ }
+
+ var sortFunc = function(aaa, bbb) {
+ if (aaa.path < bbb.path) {
+ return 1;
+ } else if (aaa.path === bbb.path) {
+ return 0;
+ }
+ return -1;
+ };
+ crateAliases.sort(sortFunc);
+ aliases.sort(sortFunc);
+
+ var pushFunc = function(alias) {
+ alias.alias = query.raw;
+ var res = buildHrefAndPath(alias);
+ alias.displayPath = pathSplitter(res[0]);
+ alias.fullPath = alias.displayPath + alias.name;
+ alias.href = res[1];
+
+ ret.others.unshift(alias);
+ if (ret.others.length > MAX_RESULTS) {
+ ret.others.pop();
+ }
+ };
+ onEach(aliases, pushFunc);
+ onEach(crateAliases, pushFunc);
+ }
+
+
/**
* Validate performs the following boolean logic. For example:
* "File::open" will give IF A PARENT EXISTS => ("file" && "open")
@@ -1136,87 +1137,6 @@ window.initSearch = function(rawSearchIndex) {
}
function execSearch(query, searchWords, filterCrates) {
- function getSmallest(arrays, positions, notDuplicates) {
- var start = null;
-
- for (var it = 0, len = positions.length; it < len; ++it) {
- if (arrays[it].length > positions[it] &&
- (start === null || start > arrays[it][positions[it]].lev) &&
- !notDuplicates[arrays[it][positions[it]].fullPath]) {
- start = arrays[it][positions[it]].lev;
- }
- }
- return start;
- }
-
- function mergeArrays(arrays) {
- var ret = [];
- var positions = [];
- var notDuplicates = {};
-
- for (var x = 0, arrays_len = arrays.length; x < arrays_len; ++x) {
- positions.push(0);
- }
- while (ret.length < MAX_RESULTS) {
- var smallest = getSmallest(arrays, positions, notDuplicates);
-
- if (smallest === null) {
- break;
- }
- for (x = 0; x < arrays_len && ret.length < MAX_RESULTS; ++x) {
- if (arrays[x].length > positions[x] &&
- arrays[x][positions[x]].lev === smallest &&
- !notDuplicates[arrays[x][positions[x]].fullPath]) {
- ret.push(arrays[x][positions[x]]);
- notDuplicates[arrays[x][positions[x]].fullPath] = true;
- positions[x] += 1;
- }
- }
- }
- return ret;
- }
-
- // Split search query by ",", while respecting angle bracket nesting.
- // Since "<" is an alias for the Ord family of traits, it also uses
- // lookahead to distinguish "<"-as-less-than from "<"-as-angle-bracket.
- //
- // tokenizeQuery("A, D") == ["A", "D"]
- // tokenizeQuery("A)/g;
- var ret = [];
- var start = 0;
- for (i = 0; i < l; ++i) {
- switch (raw[i]) {
- case "<":
- nextAngle.lastIndex = i + 1;
- matched = nextAngle.exec(raw);
- if (matched && matched[1] === '>') {
- depth += 1;
- }
- break;
- case ">":
- if (depth > 0) {
- depth -= 1;
- }
- break;
- case ",":
- if (depth === 0) {
- ret.push(raw.substring(start, i));
- start = i + 1;
- }
- break;
- }
- }
- if (start !== i) {
- ret.push(raw.substring(start, i));
- }
- return ret;
- }
-
var queries = tokenizeQuery(query.raw);
var results = {
"in_args": [],
@@ -1248,6 +1168,87 @@ window.initSearch = function(rawSearchIndex) {
};
}
+ function getSmallest(arrays, positions, notDuplicates) {
+ var start = null;
+
+ for (var it = 0, len = positions.length; it < len; ++it) {
+ if (arrays[it].length > positions[it] &&
+ (start === null || start > arrays[it][positions[it]].lev) &&
+ !notDuplicates[arrays[it][positions[it]].fullPath]) {
+ start = arrays[it][positions[it]].lev;
+ }
+ }
+ return start;
+ }
+
+ function mergeArrays(arrays) {
+ var ret = [];
+ var positions = [];
+ var notDuplicates = {};
+
+ for (var x = 0, arrays_len = arrays.length; x < arrays_len; ++x) {
+ positions.push(0);
+ }
+ while (ret.length < MAX_RESULTS) {
+ var smallest = getSmallest(arrays, positions, notDuplicates);
+
+ if (smallest === null) {
+ break;
+ }
+ for (x = 0; x < arrays_len && ret.length < MAX_RESULTS; ++x) {
+ if (arrays[x].length > positions[x] &&
+ arrays[x][positions[x]].lev === smallest &&
+ !notDuplicates[arrays[x][positions[x]].fullPath]) {
+ ret.push(arrays[x][positions[x]]);
+ notDuplicates[arrays[x][positions[x]].fullPath] = true;
+ positions[x] += 1;
+ }
+ }
+ }
+ return ret;
+ }
+
+ // Split search query by ",", while respecting angle bracket nesting.
+ // Since "<" is an alias for the Ord family of traits, it also uses
+ // lookahead to distinguish "<"-as-less-than from "<"-as-angle-bracket.
+ //
+ // tokenizeQuery("A, D") == ["A", "D"]
+ // tokenizeQuery("A)/g;
+ var ret = [];
+ var start = 0;
+ for (i = 0; i < l; ++i) {
+ switch (raw[i]) {
+ case "<":
+ nextAngle.lastIndex = i + 1;
+ matched = nextAngle.exec(raw);
+ if (matched && matched[1] === '>') {
+ depth += 1;
+ }
+ break;
+ case ">":
+ if (depth > 0) {
+ depth -= 1;
+ }
+ break;
+ case ",":
+ if (depth === 0) {
+ ret.push(raw.substring(start, i));
+ start = i + 1;
+ }
+ break;
+ }
+ }
+ if (start !== i) {
+ ret.push(raw.substring(start, i));
+ }
+ return ret;
+ }
+
function getFilterCrates() {
var elem = document.getElementById("crate-search");