Skip to content

Commit 651aeea

Browse files
committed
rustdoc: Document impl reexports
1 parent f3ed738 commit 651aeea

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

src/rustdoc/reexport_pass.rs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
import std::map;
44
import std::map::hashmap;
5+
import std::list;
56
import rustc::syntax::ast;
67
import rustc::syntax::ast_util;
78
import rustc::util::common;
89
import rustc::middle::ast_map;
10+
import rustc::syntax::visit;
11+
import rustc::syntax::codemap;
912

1013
export mk_pass;
1114

@@ -84,12 +87,63 @@ fn build_reexport_def_set(srv: astsrv::srv) -> def_set {
8487
}
8588
}
8689
}
90+
for def in find_reexport_impls(ctxt) {
91+
def_set.insert(def, ());
92+
}
8793
to_assoc_list(def_set)
8894
};
8995

9096
from_def_assoc_list(assoc_list)
9197
}
9298

99+
fn find_reexport_impls(ctxt: astsrv::ctxt) -> [ast::def_id] {
100+
let defs = @mut [];
101+
let visitor = @{
102+
visit_mod: bind visit_mod(ctxt, defs, _, _, _)
103+
with *visit::default_simple_visitor()
104+
};
105+
let visitor = visit::mk_simple_visitor(visitor);
106+
visit::visit_crate(*ctxt.ast, (), visitor);
107+
ret *defs;
108+
109+
fn visit_mod(
110+
ctxt: astsrv::ctxt,
111+
defs: @mut [ast::def_id],
112+
m: ast::_mod,
113+
_sp: codemap::span,
114+
mod_id: ast::node_id
115+
) {
116+
let all_impls = all_impls(m);
117+
alt check ctxt.impl_map.get(mod_id) {
118+
list::cons(impls, @list::nil) {
119+
for i in *impls {
120+
// This impl is not an item in the current mod
121+
if !all_impls.contains_key(i.did) {
122+
// Ignore external impls because I don't
123+
// know what to do with them yet
124+
if i.did.crate == ast::local_crate {
125+
*defs += [i.did]
126+
}
127+
}
128+
}
129+
}
130+
}
131+
}
132+
}
133+
134+
fn all_impls(m: ast::_mod) -> map::set<ast::def_id> {
135+
let all_impls = common::new_def_hash();
136+
for item in m.items {
137+
alt item.node {
138+
ast::item_impl(_, _, _, _) {
139+
all_impls.insert(ast_util::local_def(item.id), ());
140+
}
141+
_ { }
142+
}
143+
}
144+
ret all_impls;
145+
}
146+
93147
fn build_reexport_def_map(
94148
srv: astsrv::srv,
95149
doc: doc::doc,
@@ -191,12 +245,77 @@ fn build_reexport_path_map(srv: astsrv::srv, -def_map: def_map) -> path_map {
191245
}
192246
}
193247

248+
for (path, doc) in find_reexport_impl_docs(ctxt, def_map) {
249+
let docs = alt path_map.find(path) {
250+
some(docs) { docs + [(doc)] }
251+
none { [doc] }
252+
};
253+
path_map.insert(path, docs);
254+
}
255+
194256
to_assoc_list(path_map)
195257
};
196258

197259
from_str_assoc_list(assoc_list)
198260
}
199261

262+
fn find_reexport_impl_docs(
263+
ctxt: astsrv::ctxt,
264+
def_map: def_map
265+
) -> [(str, (str, doc::itemtag))] {
266+
let docs = @mut [];
267+
let visitor = @{
268+
visit_mod: bind visit_mod(ctxt, def_map, docs, _, _, _)
269+
with *visit::default_simple_visitor()
270+
};
271+
let visitor = visit::mk_simple_visitor(visitor);
272+
visit::visit_crate(*ctxt.ast, (), visitor);
273+
ret *docs;
274+
275+
fn visit_mod(
276+
ctxt: astsrv::ctxt,
277+
def_map: def_map,
278+
docs: @mut [(str, (str, doc::itemtag))],
279+
m: ast::_mod,
280+
_sp: codemap::span,
281+
mod_id: ast::node_id
282+
) {
283+
let all_impls = all_impls(m);
284+
alt check ctxt.impl_map.get(mod_id) {
285+
list::cons(impls, @list::nil) {
286+
for i in *impls {
287+
// This impl is not an item in the current mod
288+
if !all_impls.contains_key(i.did) {
289+
// Ignore external impls because I don't
290+
// know what to do with them yet
291+
if i.did.crate == ast::local_crate {
292+
let path = alt ctxt.ast_map.find(mod_id) {
293+
some(ast_map::node_item(item, path)) {
294+
let path = ast_map::path_to_str(*path);
295+
if str::is_empty(path) {
296+
item.ident
297+
} else {
298+
path + "::" + item.ident
299+
}
300+
}
301+
_ {
302+
assert mod_id == ast::crate_node_id;
303+
""
304+
}
305+
};
306+
let ident = i.ident;
307+
let doc = alt check def_map.find(i.did) {
308+
some(doc) { doc }
309+
};
310+
*docs += [(path, (ident, doc))];
311+
}
312+
}
313+
}
314+
}
315+
}
316+
}
317+
}
318+
200319
fn merge_reexports(
201320
doc: doc::doc,
202321
path_map: path_map
@@ -323,6 +442,30 @@ fn should_mark_reepxorts_as_such() {
323442
assert doc.cratemod().mods()[1].fns()[0].item.reexport == true;
324443
}
325444

445+
#[test]
446+
fn should_duplicate_reexported_impls() {
447+
let source = "mod a { impl b for int { fn c() { } } } \
448+
mod d { import a::b; export b; }";
449+
let doc = test::mk_doc(source);
450+
assert doc.cratemod().mods()[1].impls()[0].name() == "b";
451+
}
452+
453+
#[test]
454+
fn should_duplicate_reexported_impls_deep() {
455+
let source = "mod a { impl b for int { fn c() { } } } \
456+
mod d { mod e { import a::b; export b; } }";
457+
let doc = test::mk_doc(source);
458+
assert doc.cratemod().mods()[1].mods()[0].impls()[0].name() == "b";
459+
}
460+
461+
#[test]
462+
fn should_duplicate_reexported_impls_crate() {
463+
let source = "import a::b; export b; \
464+
mod a { impl b for int { fn c() { } } }";
465+
let doc = test::mk_doc(source);
466+
assert doc.cratemod().impls()[0].name() == "b";
467+
}
468+
326469
#[test]
327470
fn should_duplicate_reexported_native_fns() {
328471
let source = "native mod a { fn b(); } \

0 commit comments

Comments
 (0)