diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index a47e89fb94885..fda6b8359f111 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -352,6 +352,7 @@
function initSearch(rawSearchIndex) {
var currentResults, index, searchIndex;
var MAX_LEV_DISTANCE = 3;
+ var MAX_RESULTS = 200;
var params = getQueryStringParams();
// Populate search bar with query string search term when provided,
@@ -374,7 +375,7 @@
var valLower = query.query.toLowerCase(),
val = valLower,
typeFilter = itemTypeFromName(query.type),
- results = {},
+ results = {}, results_in_args = {}, results_returned = {},
split = valLower.split("::");
for (var z = 0; z < split.length; ++z) {
@@ -384,6 +385,126 @@
}
}
+ function transformResults(results, isType) {
+ var out = [];
+ for (i = 0; i < results.length; ++i) {
+ if (results[i].id > -1) {
+ var obj = searchIndex[results[i].id];
+ obj.lev = results[i].lev;
+ if (isType !== true || obj.type) {
+ out.push(obj);
+ }
+ }
+ if (out.length >= MAX_RESULTS) {
+ break;
+ }
+ }
+ return out;
+ }
+
+ function sortResults(results, isType) {
+ var ar = [];
+ for (var entry in results) {
+ if (results.hasOwnProperty(entry)) {
+ ar.push(results[entry]);
+ }
+ }
+ results = ar;
+ var nresults = results.length;
+ for (var i = 0; i < nresults; ++i) {
+ results[i].word = searchWords[results[i].id];
+ results[i].item = searchIndex[results[i].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 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 exact match (mismatch goes later)
+ a = (aaa.word !== valLower);
+ b = (bbb.word !== valLower);
+ 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 pages
+ if ((aaa.item.ty === TY_PRIMITIVE) && (bbb.item.ty !== TY_PRIMITIVE)) {
+ return -1;
+ }
+ if ((bbb.item.ty === TY_PRIMITIVE) && (aaa.item.ty !== TY_PRIMITIVE)) {
+ 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 (var i = 0; i < results.length; ++i) {
+ var 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 !== true &&
+ validateResult(name, path, split, parent) === false)
+ {
+ result.id = -1;
+ }
+ }
+ return transformResults(results);
+ }
+
function extractGenerics(val) {
val = val.toLowerCase();
if (val.indexOf('<') !== -1) {
@@ -404,11 +525,13 @@
// match as well.
var lev_distance = MAX_LEV_DISTANCE + 1;
if (val.generics.length > 0) {
- if (obj.generics &&
- obj.generics.length >= val.generics.length) {
+ if (obj.generics && obj.generics.length >= val.generics.length) {
var elems = obj.generics.slice(0);
+ var total = 0;
+ var done = 0;
+ // We need to find the type that matches the most to remove it in order
+ // to move forward.
for (var y = 0; y < val.generics.length; ++y) {
- // The point here is to find the type that matches the most.
var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1};
for (var x = 0; x < elems.length; ++x) {
var tmp_lev = levenshtein(elems[x], val.generics[y]);
@@ -420,14 +543,14 @@
if (lev.pos !== -1) {
elems.splice(lev.pos, 1);
lev_distance = Math.min(lev.lev, lev_distance);
+ total += lev.lev;
+ done += 1;
} else {
return MAX_LEV_DISTANCE + 1;
}
}
- return lev_distance;
+ return lev_distance;//Math.ceil(total / done);
}
- } else {
- return 0;
}
return MAX_LEV_DISTANCE + 1;
}
@@ -463,9 +586,13 @@
}
// 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.
- var tmp_lev = checkGenerics(obj, val);
- if (tmp_lev <= MAX_LEV_DISTANCE) {
- return tmp_lev;
+ if (obj.generics && obj.generics.length !== 0) {
+ var tmp_lev = checkGenerics(obj, val);
+ if (tmp_lev <= MAX_LEV_DISTANCE) {
+ return tmp_lev;
+ }
+ } else {
+ return 0;
}
}
// Names didn't match so let's check if one of the generic types could.
@@ -479,12 +606,11 @@
}
return false;
}
- var new_lev = levenshtein(obj.name, val.name);
- if (new_lev < lev_distance) {
- if ((lev = checkGenerics(obj, val)) <= MAX_LEV_DISTANCE) {
- lev_distance = Math.min(Math.min(new_lev, lev), lev_distance);
- }
+ var lev_distance = Math.min(levenshtein(obj.name, val.name), lev_distance);
+ if (lev_distance <= MAX_LEV_DISTANCE) {
+ lev_distance = Math.min(checkGenerics(obj, val), lev_distance);
} else if (obj.generics && obj.generics.length > 0) {
+ // We can check if the type we're looking for is inside the generics!
for (var x = 0; x < obj.generics.length; ++x) {
lev_distance = Math.min(levenshtein(obj.generics[x], val.name),
lev_distance);
@@ -599,7 +725,6 @@
if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
val.charAt(val.length - 1) === val.charAt(0))
{
- var results_length = 0;
val = extractGenerics(val.substr(1, val.length - 2));
for (var i = 0; i < nSearchWords; ++i) {
var in_args = findArg(searchIndex[i], val, true);
@@ -613,31 +738,32 @@
results[fullId] === undefined)
{
results[fullId] = {id: i, index: -1};
- results_length += 1;
}
} else if ((in_args === true || returned === true) &&
typePassesFilter(typeFilter, searchIndex[i].ty)) {
- if (results[fullId] === undefined) {
+ if (in_args === true || returned === true) {
+ if (in_args === true) {
+ results_in_args[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ if (returned === true) {
+ results_returned[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ } else {
results[fullId] = {
id: i,
index: -1,
dontValidate: true,
- in_args: in_args,
- returned: returned,
};
- results_length += 1;
- } else {
- if (in_args === true) {
- results[fullId].in_args = true;
- }
- if (returned === true) {
- results[fullId].returned = true;
- }
}
}
- if (results_length === max) {
- break;
- }
}
query.inputs = [val];
query.output = val;
@@ -678,23 +804,26 @@
}
in_args = allFound;
}
- if (in_args === true || returned === true || module === true) {
- if (results[fullId] !== undefined) {
- if (returned === true) {
- results[fullId].returned = true;
- }
- if (in_args === true) {
- results[fullId].in_args = true;
- }
- } else {
- results[fullId] = {
- id: i,
- index: -1,
- dontValidate: true,
- returned: returned,
- in_args: in_args,
- };
- }
+ if (in_args === true) {
+ results_in_args[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ if (returned === true) {
+ results_returned[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
+ }
+ if (module === true) {
+ results[fullId] = {
+ id: i,
+ index: -1,
+ dontValidate: true,
+ };
}
}
}
@@ -709,7 +838,6 @@
// gather matching search results up to a certain maximum
val = val.replace(/\_/g, "");
- var results_length = 0;
var valGenerics = extractGenerics(val);
var paths = valLower.split("::");
@@ -739,177 +867,84 @@
}
}
- var returned = false;
- var in_args = false;
+ var returned = MAX_LEV_DISTANCE + 1;
+ var in_args = MAX_LEV_DISTANCE + 1;
var index = -1;
// we want lev results to go lower than others
var lev = MAX_LEV_DISTANCE + 1;
var fullId = itemTypes[ty.ty] + ty.path + ty.name;
- if (searchWords[j].indexOf(val) > -1 ||
+ if (searchWords[j].indexOf(split[i]) > -1 ||
+ searchWords[j].indexOf(val) > -1 ||
searchWords[j].replace(/_/g, "").indexOf(val) > -1)
{
// filter type: ... queries
- if (typePassesFilter(typeFilter, ty) &&
- results[fullId] === undefined) {
+ if (typePassesFilter(typeFilter, ty) && results[fullId] === undefined) {
index = searchWords[j].replace(/_/g, "").indexOf(val);
}
}
- if ((lev_distance = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
- if (typePassesFilter(typeFilter, ty) &&
- (results[fullId] === undefined ||
- results[fullId].lev > lev_distance)) {
- lev = Math.min(lev, lev_distance);
- index = Math.max(0, index);
+ if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
+ if (typePassesFilter(typeFilter, ty) === false) {
+ lev = MAX_LEV_DISTANCE + 1;
+ } else {
+ lev += 1;
}
}
- if ((lev_distance = findArg(searchIndex[j], valGenerics))
- <= MAX_LEV_DISTANCE) {
- if (typePassesFilter(typeFilter, ty) &&
- (results[fullId] === undefined ||
- results[fullId].lev > lev_distance)) {
- in_args = true;
- lev = Math.min(lev_distance, lev);
- index = Math.max(0, index);
+ if ((in_args = findArg(ty, valGenerics)) <= MAX_LEV_DISTANCE) {
+ if (typePassesFilter(typeFilter, ty) === false) {
+ in_args = MAX_LEV_DISTANCE + 1;
}
}
- if ((lev_distance = checkReturned(searchIndex[j], valGenerics)) <=
- MAX_LEV_DISTANCE) {
- if (typePassesFilter(typeFilter, ty) &&
- (results[fullId] === undefined ||
- results[fullId].lev > lev_distance)) {
- returned = true;
- lev = Math.min(lev_distance, lev);
- index = Math.max(0, index);
+ if ((returned = checkReturned(ty, valGenerics)) <= MAX_LEV_DISTANCE) {
+ if (typePassesFilter(typeFilter, ty) === false) {
+ returned = MAX_LEV_DISTANCE + 1;
}
}
+
lev += lev_add;
- if (index !== -1) {
+ if (in_args <= MAX_LEV_DISTANCE) {
+ if (results_in_args[fullId] === undefined) {
+ results_in_args[fullId] = {
+ id: j,
+ index: index,
+ lev: in_args,
+ };
+ }
+ results_in_args[fullId].lev =
+ Math.min(results_in_args[fullId].lev, in_args);
+ }
+ if (returned <= MAX_LEV_DISTANCE) {
+ if (results_returned[fullId] === undefined) {
+ results_returned[fullId] = {
+ id: j,
+ index: index,
+ lev: returned,
+ };
+ }
+ results_returned[fullId].lev =
+ Math.min(results_returned[fullId].lev, returned);
+ }
+ if (index !== -1 || lev <= MAX_LEV_DISTANCE) {
+ if (index !== -1) {
+ lev = 0;
+ }
if (results[fullId] === undefined) {
results[fullId] = {
id: j,
index: index,
lev: lev,
- in_args: in_args,
- returned: returned,
};
- results_length += 1;
- } else {
- if (results[fullId].lev > lev) {
- results[fullId].lev = lev;
- }
- if (in_args === true) {
- results[fullId].in_args = true;
- }
- if (returned === true) {
- results[fullId].returned = true;
- }
}
- }
- if (results_length === max) {
- break;
+ results[fullId].lev = Math.min(results[fullId].lev, lev);
}
}
}
- var ar = [];
- for (var entry in results) {
- if (results.hasOwnProperty(entry)) {
- ar.push(results[entry]);
- }
- }
- results = ar;
- var nresults = results.length;
- for (var i = 0; i < nresults; ++i) {
- results[i].word = searchWords[results[i].id];
- results[i].item = searchIndex[results[i].id] || {};
- }
- // if there are no results then return to default and fail
- if (results.length === 0) {
- return [];
- }
-
- results.sort(function sortResults(aaa, bbb) {
- var 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 exact match (mismatch goes later)
- a = (aaa.word !== valLower);
- b = (bbb.word !== valLower);
- 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 pages
- if ((aaa.item.ty === TY_PRIMITIVE) && (bbb.item.ty !== TY_PRIMITIVE)) {
- return -1;
- }
- if ((bbb.item.ty === TY_PRIMITIVE) && (aaa.item.ty !== TY_PRIMITIVE)) {
- 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 (var i = 0; i < results.length; ++i) {
- var result = results[i];
-
- // this validation does not make sense when searching by types
- if (result.dontValidate || result.returned === true && result.param === true) {
- continue;
- }
- var name = result.item.name.toLowerCase(),
- path = result.item.path.toLowerCase(),
- parent = result.item.parent;
-
- if (validateResult(name, path, split, parent) === false) {
- result.id = -1;
- }
- }
- return results;
+ return {
+ 'in_args': sortResults(results_in_args, true),
+ 'returned': sortResults(results_returned, true),
+ 'others': sortResults(results),
+ };
}
/**
@@ -1187,10 +1222,8 @@
function search(e) {
var query,
- filterdata = [],
obj, i, len,
results = {"in_args": [], "returned": [], "others": []},
- maxResults = 200,
resultIndex;
var params = getQueryStringParams();
@@ -1216,40 +1249,7 @@
}
}
- resultIndex = execQuery(query, 20000, index);
- len = resultIndex.length;
- for (i = 0; i < len; ++i) {
- if (resultIndex[i].id > -1) {
- var added = false;
- obj = searchIndex[resultIndex[i].id];
- filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
- if (obj.type) {
- if (results['returned'].length < maxResults &&
- resultIndex[i].returned === true)
- {
- results['returned'].push(obj);
- added = true;
- }
- if (results['in_args'].length < maxResults &&
- resultIndex[i].in_args === true)
- {
- results['in_args'].push(obj);
- added = true;
- }
- }
- if (results['others'].length < maxResults &&
- (added === false ||
- (query.search && obj.name.indexOf(query.search) !== -1))) {
- results['others'].push(obj);
- }
- }
- if (results['others'].length >= maxResults &&
- results['in_args'].length >= maxResults &&
- results['returned'].length >= maxResults) {
- break;
- }
- }
-
+ results = execQuery(query, 20000, index);
showResults(results);
}