Skip to content

Commit 272afbe

Browse files
authored
Rollup merge of #109331 - notriddle:notriddle/search-bag-semantics, r=GuillaumeGomez
rustdoc: implement bag semantics for function parameter search This tweak to the function signature search engine makes things so that, if a type is repeated in the search query, it'll only match if the function actually includes it that many times.
2 parents 4f61ce2 + 5451fe7 commit 272afbe

File tree

3 files changed

+94
-26
lines changed

3 files changed

+94
-26
lines changed

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

+70-26
Original file line numberDiff line numberDiff line change
@@ -1202,28 +1202,42 @@ function initSearch(rawSearchIndex) {
12021202
* @param {Row} row
12031203
* @param {QueryElement} elem - The element from the parsed query.
12041204
* @param {integer} typeFilter
1205+
* @param {Array<integer>} skipPositions - Do not return one of these positions.
12051206
*
1206-
* @return {integer} - Returns an edit distance to the best match. If there is no
1207-
* match, returns `maxEditDistance + 1`.
1207+
* @return {dist: integer, position: integer} - Returns an edit distance to the best match.
1208+
* If there is no match, returns
1209+
* `maxEditDistance + 1` and position: -1.
12081210
*/
1209-
function findArg(row, elem, typeFilter, maxEditDistance) {
1211+
function findArg(row, elem, typeFilter, maxEditDistance, skipPositions) {
12101212
let dist = maxEditDistance + 1;
1213+
let position = -1;
12111214

12121215
if (row && row.type && row.type.inputs && row.type.inputs.length > 0) {
1216+
let i = 0;
12131217
for (const input of row.type.inputs) {
1214-
if (!typePassesFilter(typeFilter, input.ty)) {
1218+
if (!typePassesFilter(typeFilter, input.ty) ||
1219+
skipPositions.indexOf(i) !== -1) {
1220+
i += 1;
12151221
continue;
12161222
}
1217-
dist = Math.min(
1218-
dist,
1219-
checkType(input, elem, parsedQuery.literalSearch, maxEditDistance)
1223+
const typeDist = checkType(
1224+
input,
1225+
elem,
1226+
parsedQuery.literalSearch,
1227+
maxEditDistance
12201228
);
1221-
if (dist === 0) {
1222-
return 0;
1229+
if (typeDist === 0) {
1230+
return {dist: 0, position: i};
1231+
}
1232+
if (typeDist < dist) {
1233+
dist = typeDist;
1234+
position = i;
12231235
}
1236+
i += 1;
12241237
}
12251238
}
1226-
return parsedQuery.literalSearch ? maxEditDistance + 1 : dist;
1239+
dist = parsedQuery.literalSearch ? maxEditDistance + 1 : dist;
1240+
return {dist, position};
12271241
}
12281242

12291243
/**
@@ -1232,29 +1246,43 @@ function initSearch(rawSearchIndex) {
12321246
* @param {Row} row
12331247
* @param {QueryElement} elem - The element from the parsed query.
12341248
* @param {integer} typeFilter
1249+
* @param {Array<integer>} skipPositions - Do not return one of these positions.
12351250
*
1236-
* @return {integer} - Returns an edit distance to the best match. If there is no
1237-
* match, returns `maxEditDistance + 1`.
1251+
* @return {dist: integer, position: integer} - Returns an edit distance to the best match.
1252+
* If there is no match, returns
1253+
* `maxEditDistance + 1` and position: -1.
12381254
*/
1239-
function checkReturned(row, elem, typeFilter, maxEditDistance) {
1255+
function checkReturned(row, elem, typeFilter, maxEditDistance, skipPositions) {
12401256
let dist = maxEditDistance + 1;
1257+
let position = -1;
12411258

12421259
if (row && row.type && row.type.output.length > 0) {
12431260
const ret = row.type.output;
1261+
let i = 0;
12441262
for (const ret_ty of ret) {
1245-
if (!typePassesFilter(typeFilter, ret_ty.ty)) {
1263+
if (!typePassesFilter(typeFilter, ret_ty.ty) ||
1264+
skipPositions.indexOf(i) !== -1) {
1265+
i += 1;
12461266
continue;
12471267
}
1248-
dist = Math.min(
1249-
dist,
1250-
checkType(ret_ty, elem, parsedQuery.literalSearch, maxEditDistance)
1268+
const typeDist = checkType(
1269+
ret_ty,
1270+
elem,
1271+
parsedQuery.literalSearch,
1272+
maxEditDistance
12511273
);
1252-
if (dist === 0) {
1253-
return 0;
1274+
if (typeDist === 0) {
1275+
return {dist: 0, position: i};
12541276
}
1277+
if (typeDist < dist) {
1278+
dist = typeDist;
1279+
position = i;
1280+
}
1281+
i += 1;
12551282
}
12561283
}
1257-
return parsedQuery.literalSearch ? maxEditDistance + 1 : dist;
1284+
dist = parsedQuery.literalSearch ? maxEditDistance + 1 : dist;
1285+
return {dist, position};
12581286
}
12591287

12601288
function checkPath(contains, ty, maxEditDistance) {
@@ -1455,13 +1483,13 @@ function initSearch(rawSearchIndex) {
14551483
const fullId = row.id;
14561484
const searchWord = searchWords[pos];
14571485

1458-
const in_args = findArg(row, elem, parsedQuery.typeFilter, maxEditDistance);
1459-
const returned = checkReturned(row, elem, parsedQuery.typeFilter, maxEditDistance);
1486+
const in_args = findArg(row, elem, parsedQuery.typeFilter, maxEditDistance, []);
1487+
const returned = checkReturned(row, elem, parsedQuery.typeFilter, maxEditDistance, []);
14601488

14611489
// path_dist is 0 because no parent path information is currently stored
14621490
// in the search index
1463-
addIntoResults(results_in_args, fullId, pos, -1, in_args, 0, maxEditDistance);
1464-
addIntoResults(results_returned, fullId, pos, -1, returned, 0, maxEditDistance);
1491+
addIntoResults(results_in_args, fullId, pos, -1, in_args.dist, 0, maxEditDistance);
1492+
addIntoResults(results_returned, fullId, pos, -1, returned.dist, 0, maxEditDistance);
14651493

14661494
if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) {
14671495
return;
@@ -1534,12 +1562,20 @@ function initSearch(rawSearchIndex) {
15341562

15351563
// If the result is too "bad", we return false and it ends this search.
15361564
function checkArgs(elems, callback) {
1565+
const skipPositions = [];
15371566
for (const elem of elems) {
15381567
// There is more than one parameter to the query so all checks should be "exact"
1539-
const dist = callback(row, elem, NO_TYPE_FILTER, maxEditDistance);
1568+
const { dist, position } = callback(
1569+
row,
1570+
elem,
1571+
NO_TYPE_FILTER,
1572+
maxEditDistance,
1573+
skipPositions
1574+
);
15401575
if (dist <= 1) {
15411576
nbDist += 1;
15421577
totalDist += dist;
1578+
skipPositions.push(position);
15431579
} else {
15441580
return false;
15451581
}
@@ -1597,9 +1633,17 @@ function initSearch(rawSearchIndex) {
15971633
row,
15981634
elem,
15991635
parsedQuery.typeFilter,
1636+
maxEditDistance,
1637+
[]
1638+
);
1639+
addIntoResults(
1640+
results_others,
1641+
row.id,
1642+
i,
1643+
-1,
1644+
in_returned.dist,
16001645
maxEditDistance
16011646
);
1602-
addIntoResults(results_others, row.id, i, -1, in_returned, maxEditDistance);
16031647
}
16041648
}
16051649
} else if (parsedQuery.foundElems > 0) {
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// exact-check
2+
3+
const QUERY = [
4+
'P',
5+
'P, P',
6+
];
7+
8+
const EXPECTED = [
9+
{
10+
'in_args': [
11+
{ 'path': 'search_bag_semantics', 'name': 'alacazam' },
12+
{ 'path': 'search_bag_semantics', 'name': 'abracadabra' },
13+
],
14+
},
15+
{
16+
'others': [
17+
{ 'path': 'search_bag_semantics', 'name': 'abracadabra' },
18+
],
19+
},
20+
];
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pub struct P;
2+
3+
pub fn abracadabra(a: P, b: P) {}
4+
pub fn alacazam(a: P) {}

0 commit comments

Comments
 (0)