Skip to content

Commit f43ebdf

Browse files
committed
---
yaml --- r: 11379 b: refs/heads/master c: 57be673 h: refs/heads/master i: 11377: f1c2ec6 11375: 3515529 v: v3
1 parent 343fb48 commit f43ebdf

File tree

4 files changed

+303
-2
lines changed

4 files changed

+303
-2
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 102896897067960341c17dae75958e955c6d7cb2
2+
refs/heads/master: 57be673025556516747f50117672cb293864a5a5
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
55
refs/heads/try: 2898dcc5d97da9427ac367542382b6239d9c0bbf

trunk/src/rustdoc/reexport_pass.rs

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
#[doc = "Finds docs for reexported items and duplicates them"];
2+
3+
import std::map;
4+
import rustc::syntax::ast;
5+
import rustc::syntax::ast_util;
6+
import rustc::util::common;
7+
8+
export mk_pass;
9+
10+
fn mk_pass() -> pass {
11+
run
12+
}
13+
14+
type def_set = map::set<ast::def_id>;
15+
type def_map = map::hashmap<ast::def_id, doc::itemtag>;
16+
type path_map = map::hashmap<str, [(str, doc::itemtag)]>;
17+
18+
fn run(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc {
19+
20+
// First gather the set of defs that are used as reexports
21+
let def_set = build_reexport_def_set(srv);
22+
23+
// Now find the docs that go with those defs
24+
let def_map = build_reexport_def_map(srv, doc, def_set);
25+
26+
// Now create a map that tells us where to insert the duplicated
27+
// docs into the existing doc tree
28+
let path_map = build_reexport_path_map(srv, def_map);
29+
30+
// Finally update the doc tree
31+
merge_reexports(doc, path_map)
32+
}
33+
34+
fn build_reexport_def_set(srv: astsrv::srv) -> def_set {
35+
astsrv::exec(srv) {|ctxt|
36+
let def_set = common::new_def_hash();
37+
ctxt.exp_map.items {|_path, defs|
38+
for def in *defs {
39+
let def_id = ast_util::def_id_of_def(def);
40+
def_set.insert(def_id, ());
41+
}
42+
}
43+
def_set
44+
}
45+
}
46+
47+
fn build_reexport_def_map(
48+
srv: astsrv::srv,
49+
doc: doc::cratedoc,
50+
def_set: def_set
51+
) -> def_map {
52+
53+
type ctxt = {
54+
srv: astsrv::srv,
55+
def_set: def_set,
56+
def_map: def_map
57+
};
58+
59+
let ctxt = {
60+
srv: srv,
61+
def_set: def_set,
62+
def_map: common::new_def_hash()
63+
};
64+
65+
let fold = fold::fold({
66+
fold_mod: fold_mod
67+
with *fold::default_seq_fold(ctxt)
68+
});
69+
70+
fold.fold_crate(fold, doc);
71+
72+
ret ctxt.def_map;
73+
74+
fn fold_mod(fold: fold::fold<ctxt>, doc: doc::moddoc) -> doc::moddoc {
75+
let doc = fold::default_seq_fold_mod(fold, doc);
76+
77+
for item in *doc.items {
78+
let def_id = ast_util::local_def(item.id());
79+
if fold.ctxt.def_set.contains_key(def_id) {
80+
fold.ctxt.def_map.insert(def_id, item);
81+
}
82+
}
83+
84+
ret doc;
85+
}
86+
}
87+
88+
fn to_assoc_list<V:copy>(
89+
map: map::hashmap<ast::def_id, V>
90+
) -> [(ast::def_id, V)] {
91+
92+
let vec = [];
93+
map.items {|k, v|
94+
vec += [(k, v)];
95+
}
96+
ret vec;
97+
}
98+
99+
fn from_assoc_list<V:copy>(
100+
list: [(ast::def_id, V)]
101+
) -> map::hashmap<ast::def_id, V> {
102+
103+
let map = common::new_def_hash();
104+
vec::iter(list) {|elt|
105+
let (k, v) = elt;
106+
map.insert(k, v);
107+
}
108+
ret map;
109+
}
110+
111+
fn build_reexport_path_map(srv: astsrv::srv, -def_map: def_map) -> path_map {
112+
113+
// This is real unfortunate. Lots of copying going on here
114+
let def_assoc_list = to_assoc_list(def_map);
115+
#debug("def_map: %?", def_assoc_list);
116+
117+
astsrv::exec(srv) {|ctxt|
118+
119+
let def_map = from_assoc_list(def_assoc_list);
120+
let path_map = map::new_str_hash();
121+
122+
ctxt.exp_map.items {|path, defs|
123+
124+
let path = str::split_str(path, "::");
125+
let modpath = str::connect(vec::init(path), "::");
126+
let name = option::get(vec::last(path));
127+
128+
let reexportdocs = [];
129+
130+
for def in *defs {
131+
let def_id = ast_util::def_id_of_def(def);
132+
alt def_map.find(def_id) {
133+
some(itemtag) {
134+
reexportdocs += [(name, itemtag)];
135+
}
136+
none { }
137+
}
138+
}
139+
140+
if vec::is_not_empty(reexportdocs) {
141+
let prevdocs = alt path_map.find(modpath) {
142+
some(docs) { docs }
143+
none { [] }
144+
};
145+
let reexportdocs = prevdocs + reexportdocs;
146+
path_map.insert(modpath, reexportdocs);
147+
#debug("path_map entry: %? - %?",
148+
modpath, (name, reexportdocs));
149+
}
150+
}
151+
152+
path_map
153+
}
154+
}
155+
156+
fn merge_reexports(
157+
doc: doc::cratedoc,
158+
path_map: path_map
159+
) -> doc::cratedoc {
160+
161+
let fold = fold::fold({
162+
fold_mod: fold_mod
163+
with *fold::default_seq_fold(path_map)
164+
});
165+
166+
ret fold.fold_crate(fold, doc);
167+
168+
fn fold_mod(fold: fold::fold<path_map>, doc: doc::moddoc) -> doc::moddoc {
169+
let doc = fold::default_seq_fold_mod(fold, doc);
170+
171+
let path = doc.path() + [doc.name()];
172+
let new_items = get_new_items(path, fold.ctxt);
173+
#debug("merging into %?: %?", path, new_items);
174+
175+
{
176+
items: ~(*doc.items + new_items)
177+
with doc
178+
}
179+
}
180+
181+
fn get_new_items(path: [str], path_map: path_map) -> [doc::itemtag] {
182+
#debug("looking for reexports in path %?", path);
183+
alt path_map.find(str::connect(path, "::")) {
184+
some(name_docs) {
185+
vec::foldl([], name_docs) {|v, name_doc|
186+
let (name, doc) = name_doc;
187+
v + [rename_doc(doc, name)]
188+
}
189+
}
190+
none { [] }
191+
}
192+
}
193+
194+
fn rename_doc(doc: doc::itemtag, name: str) -> doc::itemtag {
195+
alt doc {
196+
doc::modtag(doc @ {item, _}) {
197+
doc::modtag({
198+
item: rename(item, name)
199+
with doc
200+
})
201+
}
202+
doc::consttag(doc @ {item, _}) {
203+
doc::consttag({
204+
item: rename(item, name)
205+
with doc
206+
})
207+
}
208+
doc::fntag(doc @ {item, _}) {
209+
doc::fntag({
210+
item: rename(item, name)
211+
with doc
212+
})
213+
}
214+
doc::enumtag(doc @ {item, _}) {
215+
doc::enumtag({
216+
item: rename(item, name)
217+
with doc
218+
})
219+
}
220+
doc::restag(doc @ {item, _}) {
221+
doc::restag({
222+
item: rename(item, name)
223+
with doc
224+
})
225+
}
226+
doc::ifacetag(doc @ {item, _}) {
227+
doc::ifacetag({
228+
item: rename(item, name)
229+
with doc
230+
})
231+
}
232+
doc::impltag(doc @ {item, _}) {
233+
doc::impltag({
234+
item: rename(item, name)
235+
with doc
236+
})
237+
}
238+
doc::tytag(doc @ {item, _}) {
239+
doc::tytag({
240+
item: rename(item, name)
241+
with doc
242+
})
243+
}
244+
}
245+
}
246+
247+
fn rename(doc: doc::itemdoc, name: str) -> doc::itemdoc {
248+
{
249+
name: name
250+
with doc
251+
}
252+
}
253+
}
254+
255+
#[test]
256+
fn should_duplicate_reexported_items() {
257+
let source = "mod a { export b; fn b() { } } \
258+
mod c { import a::b; export b; }";
259+
let doc = test::mk_doc(source);
260+
assert doc.topmod.mods()[1].fns()[0].name() == "b";
261+
}
262+
263+
#[test]
264+
fn should_duplicate_multiple_reexported_items() {
265+
let source = "mod a { \
266+
export b; export c; \
267+
fn b() { } fn c() { } \
268+
} \
269+
mod d { \
270+
import a::b; import a::c; \
271+
export b; export c; \
272+
}";
273+
let srv = astsrv::mk_srv_from_str(source);
274+
let doc = extract::from_srv(srv, "");
275+
let doc = path_pass::mk_pass()(srv, doc);
276+
let doc = run(srv, doc);
277+
// Reexports may not be in any specific order
278+
let doc = sort_item_name_pass::mk_pass()(srv, doc);
279+
assert doc.topmod.mods()[1].fns()[0].name() == "b";
280+
assert doc.topmod.mods()[1].fns()[1].name() == "c";
281+
}
282+
283+
#[test]
284+
fn should_rename_items_reexported_with_different_names() {
285+
let source = "mod a { export b; fn b() { } } \
286+
mod c { import x = a::b; export x; }";
287+
let doc = test::mk_doc(source);
288+
assert doc.topmod.mods()[1].fns()[0].name() == "x";
289+
}
290+
291+
#[cfg(test)]
292+
mod test {
293+
fn mk_doc(source: str) -> doc::cratedoc {
294+
let srv = astsrv::mk_srv_from_str(source);
295+
let doc = extract::from_srv(srv, "");
296+
let doc = path_pass::mk_pass()(srv, doc);
297+
run(srv, doc)
298+
}
299+
}

trunk/src/rustdoc/rustdoc.rc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@ mod astsrv;
3232
mod demo;
3333
mod sort_pass;
3434
mod sort_item_name_pass;
35-
mod sort_item_type_pass;
35+
mod sort_item_type_pass;
36+
mod reexport_pass;

trunk/src/rustdoc/rustdoc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ fn run(source_file: str) {
106106
desc_to_brief_pass::mk_pass(),
107107
trim_pass::mk_pass(),
108108
unindent_pass::mk_pass(),
109+
reexport_pass::mk_pass(),
109110
sort_item_name_pass::mk_pass(),
110111
sort_item_type_pass::mk_pass(),
111112
markdown_pass::mk_pass {|f| f(std::io:: stdout()) }

0 commit comments

Comments
 (0)