Skip to content

Commit afee241

Browse files
committed
rustdoc-search: add support for nested generics
1 parent 276fa29 commit afee241

File tree

4 files changed

+184
-13
lines changed

4 files changed

+184
-13
lines changed

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

+10-11
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,7 @@ function initSearch(rawSearchIndex) {
461461
if (parserState.pos < parserState.length &&
462462
parserState.userQuery[parserState.pos] === "<"
463463
) {
464-
if (isInGenerics) {
465-
throw ["Unexpected ", "<", " after ", "<"];
466-
} else if (start >= end) {
464+
if (start >= end) {
467465
throw ["Found generics without a path"];
468466
}
469467
parserState.pos += 1;
@@ -765,13 +763,10 @@ function initSearch(rawSearchIndex) {
765763
* ident = *(ALPHA / DIGIT / "_")
766764
* path = ident *(DOUBLE-COLON ident) [!]
767765
* arg = [type-filter *WS COLON *WS] path [generics]
768-
* arg-without-generic = [type-filter *WS COLON *WS] path
769766
* type-sep = COMMA/WS *(COMMA/WS)
770767
* nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep)
771-
* nonempty-arg-list-without-generics = *(type-sep) arg-without-generic
772-
* *(type-sep arg-without-generic) *(type-sep)
773-
* generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list-without-generics ] *(type-sep)
774-
* CLOSE-ANGLE-BRACKET/EOF
768+
* generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list ] *(type-sep)
769+
* CLOSE-ANGLE-BRACKET
775770
* return-args = RETURN-ARROW *(type-sep) nonempty-arg-list
776771
*
777772
* exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ]
@@ -1127,7 +1122,7 @@ function initSearch(rawSearchIndex) {
11271122
currentEntryElems = [];
11281123
elems.set(entry.name, currentEntryElems);
11291124
}
1130-
currentEntryElems.push(entry.ty);
1125+
currentEntryElems.push(entry);
11311126
}
11321127
// We need to find the type that matches the most to remove it in order
11331128
// to move forward.
@@ -1136,8 +1131,12 @@ function initSearch(rawSearchIndex) {
11361131
return false;
11371132
}
11381133
const matchElems = elems.get(generic.name);
1139-
const matchIdx = matchElems.findIndex(tmp_elem =>
1140-
typePassesFilter(generic.typeFilter, tmp_elem));
1134+
const matchIdx = matchElems.findIndex(tmp_elem => {
1135+
if (checkGenerics(tmp_elem, generic, 0, maxEditDistance) !== 0) {
1136+
return false;
1137+
}
1138+
return typePassesFilter(generic.typeFilter, tmp_elem.ty);
1139+
});
11411140
if (matchIdx === -1) {
11421141
return false;
11431142
}

tests/rustdoc-js-std/parser-generics.js

+122-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
const QUERY = ['A<B<C<D>, E>', 'p<> u8', '"p"<a>'];
1+
const QUERY = [
2+
'A<B<C<D>, E>',
3+
'p<> u8',
4+
'"p"<a>',
5+
'p<u<x>>',
6+
'p<u<x>, r>',
7+
'p<u<x, r>>',
8+
];
29

310
const PARSED = [
411
{
@@ -7,7 +14,7 @@ const PARSED = [
714
original: 'A<B<C<D>, E>',
815
returned: [],
916
userQuery: 'a<b<c<d>, e>',
10-
error: 'Unexpected `<` after `<`',
17+
error: 'Unclosed `<`',
1118
},
1219
{
1320
elems: [
@@ -59,4 +66,117 @@ const PARSED = [
5966
userQuery: '"p"<a>',
6067
error: null,
6168
},
69+
{
70+
elems: [
71+
{
72+
name: "p",
73+
fullPath: ["p"],
74+
pathWithoutLast: [],
75+
pathLast: "p",
76+
generics: [
77+
{
78+
name: "u",
79+
fullPath: ["u"],
80+
pathWithoutLast: [],
81+
pathLast: "u",
82+
generics: [
83+
{
84+
name: "x",
85+
fullPath: ["x"],
86+
pathWithoutLast: [],
87+
pathLast: "x",
88+
generics: [],
89+
},
90+
],
91+
},
92+
],
93+
typeFilter: -1,
94+
},
95+
],
96+
foundElems: 1,
97+
original: 'p<u<x>>',
98+
returned: [],
99+
userQuery: 'p<u<x>>',
100+
error: null,
101+
},
102+
{
103+
elems: [
104+
{
105+
name: "p",
106+
fullPath: ["p"],
107+
pathWithoutLast: [],
108+
pathLast: "p",
109+
generics: [
110+
{
111+
name: "u",
112+
fullPath: ["u"],
113+
pathWithoutLast: [],
114+
pathLast: "u",
115+
generics: [
116+
{
117+
name: "x",
118+
fullPath: ["x"],
119+
pathWithoutLast: [],
120+
pathLast: "x",
121+
generics: [],
122+
},
123+
],
124+
},
125+
{
126+
name: "r",
127+
fullPath: ["r"],
128+
pathWithoutLast: [],
129+
pathLast: "r",
130+
generics: [],
131+
},
132+
],
133+
typeFilter: -1,
134+
},
135+
],
136+
foundElems: 1,
137+
original: 'p<u<x>, r>',
138+
returned: [],
139+
userQuery: 'p<u<x>, r>',
140+
error: null,
141+
},
142+
{
143+
elems: [
144+
{
145+
name: "p",
146+
fullPath: ["p"],
147+
pathWithoutLast: [],
148+
pathLast: "p",
149+
generics: [
150+
{
151+
name: "u",
152+
fullPath: ["u"],
153+
pathWithoutLast: [],
154+
pathLast: "u",
155+
generics: [
156+
{
157+
name: "x",
158+
fullPath: ["x"],
159+
pathWithoutLast: [],
160+
pathLast: "x",
161+
generics: [],
162+
},
163+
{
164+
name: "r",
165+
fullPath: ["r"],
166+
pathWithoutLast: [],
167+
pathLast: "r",
168+
generics: [],
169+
},
170+
],
171+
},
172+
],
173+
typeFilter: -1,
174+
},
175+
],
176+
foundElems: 1,
177+
original: 'p<u<x, r>>',
178+
returned: [],
179+
userQuery: 'p<u<x, r>>',
180+
error: null,
181+
},
62182
];

tests/rustdoc-js/generics-nested.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// exact-check
2+
3+
const QUERY = [
4+
'-> Out<First<Second>>',
5+
'-> Out<Second<First>>',
6+
'-> Out<First, Second>',
7+
'-> Out<Second, First>',
8+
];
9+
10+
const EXPECTED = [
11+
{
12+
// -> Out<First<Second>>
13+
'others': [
14+
{ 'path': 'generics_nested', 'name': 'alef' },
15+
],
16+
},
17+
{
18+
// -> Out<Second<First>>
19+
'others': [],
20+
},
21+
{
22+
// -> Out<First, Second>
23+
'others': [
24+
{ 'path': 'generics_nested', 'name': 'bet' },
25+
],
26+
},
27+
{
28+
// -> Out<Second, First>
29+
'others': [
30+
{ 'path': 'generics_nested', 'name': 'bet' },
31+
],
32+
},
33+
];

tests/rustdoc-js/generics-nested.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
pub struct Out<A, B = ()> {
2+
a: A,
3+
b: B,
4+
}
5+
6+
pub struct First<In = ()> {
7+
in_: In,
8+
}
9+
10+
pub struct Second;
11+
12+
// Out<First<Second>>
13+
pub fn alef() -> Out<First<Second>> {
14+
loop {}
15+
}
16+
17+
pub fn bet() -> Out<First, Second> {
18+
loop {}
19+
}

0 commit comments

Comments
 (0)