Skip to content

Commit f6f3d51

Browse files
committed
rustdoc: Split the pruning of undocumented branches into two passes
prune_undoc_details_pass strips arguments and return values that are undocumented. prune_undoc_items_pass prunes entire items.
1 parent e204aa2 commit f6f3d51

File tree

4 files changed

+187
-104
lines changed

4 files changed

+187
-104
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#[doc = "Prunes args, retvals of the document tree that \
2+
contain no documentation"];
3+
4+
export mk_pass;
5+
6+
fn mk_pass() -> pass {
7+
run
8+
}
9+
10+
fn run(
11+
_srv: astsrv::srv,
12+
doc: doc::cratedoc
13+
) -> doc::cratedoc {
14+
let fold = fold::fold({
15+
fold_fn: fold_fn,
16+
fold_res: fold_res,
17+
fold_iface: fold_iface,
18+
fold_impl: fold_impl
19+
with *fold::default_seq_fold(())
20+
});
21+
fold.fold_crate(fold, doc)
22+
}
23+
24+
fn fold_fn(
25+
fold: fold::fold<()>,
26+
doc: doc::fndoc
27+
) -> doc::fndoc {
28+
let doc = fold::default_seq_fold_fn(fold, doc);
29+
30+
{
31+
args: prune_args(doc.args),
32+
return: prune_return(doc.return)
33+
with doc
34+
}
35+
}
36+
37+
fn prune_args(docs: [doc::argdoc]) -> [doc::argdoc] {
38+
vec::filter_map(docs) {|doc|
39+
if option::is_some(doc.desc) {
40+
some(doc)
41+
} else {
42+
none
43+
}
44+
}
45+
}
46+
47+
fn prune_return(doc: doc::retdoc) -> doc::retdoc {
48+
{
49+
ty: if option::is_some(doc.desc) {
50+
doc.ty
51+
} else {
52+
none
53+
}
54+
with doc
55+
}
56+
}
57+
58+
#[test]
59+
fn should_elide_undocumented_arguments() {
60+
let doc = test::mk_doc("#[doc = \"hey\"] fn a(b: int) { }");
61+
assert vec::is_empty(doc.topmod.fns()[0].args);
62+
}
63+
64+
#[test]
65+
fn should_elide_undocumented_return_values() {
66+
let source = "#[doc = \"fonz\"] fn a() -> int { }";
67+
let srv = astsrv::mk_srv_from_str(source);
68+
let doc = extract::from_srv(srv, "");
69+
let doc = tystr_pass::mk_pass()(srv, doc);
70+
let doc = attr_pass::mk_pass()(srv, doc);
71+
let doc = run(srv, doc);
72+
assert doc.topmod.fns()[0].return.ty == none;
73+
}
74+
75+
fn fold_res(
76+
fold: fold::fold<()>,
77+
doc: doc::resdoc
78+
) -> doc::resdoc {
79+
let doc = fold::default_seq_fold_res(fold, doc);
80+
81+
{
82+
args: prune_args(doc.args)
83+
with doc
84+
}
85+
}
86+
87+
#[test]
88+
fn should_elide_undocumented_resource_args() {
89+
let doc = test::mk_doc("#[doc = \"drunk\"]\
90+
resource r(a: bool) { }");
91+
assert vec::is_empty(doc.topmod.resources()[0].args);
92+
}
93+
94+
fn fold_iface(
95+
fold: fold::fold<()>,
96+
doc: doc::ifacedoc
97+
) -> doc::ifacedoc {
98+
let doc = fold::default_seq_fold_iface(fold, doc);
99+
100+
{
101+
methods: prune_methods(doc.methods)
102+
with doc
103+
}
104+
}
105+
106+
fn prune_methods(docs: [doc::methoddoc]) -> [doc::methoddoc] {
107+
vec::map(docs) {|doc|
108+
{
109+
args: prune_args(doc.args),
110+
return: prune_return(doc.return)
111+
with doc
112+
}
113+
}
114+
}
115+
116+
#[test]
117+
fn should_elide_undocumented_iface_method_args() {
118+
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
119+
assert vec::is_empty(doc.topmod.ifaces()[0].methods[0].args);
120+
}
121+
122+
#[test]
123+
fn should_elide_undocumented_iface_method_return_values() {
124+
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a() -> int; }");
125+
assert doc.topmod.ifaces()[0].methods[0].return.ty == none;
126+
}
127+
128+
fn fold_impl(
129+
fold: fold::fold<()>,
130+
doc: doc::impldoc
131+
) -> doc::impldoc {
132+
let doc = fold::default_seq_fold_impl(fold, doc);
133+
134+
{
135+
methods: prune_methods(doc.methods)
136+
with doc
137+
}
138+
}
139+
140+
#[test]
141+
fn should_elide_undocumented_impl_method_args() {
142+
let doc = test::mk_doc(
143+
"#[doc = \"hey\"] impl i for int { fn a(b: bool) { } }");
144+
assert vec::is_empty(doc.topmod.impls()[0].methods[0].args);
145+
}
146+
147+
#[test]
148+
fn should_elide_undocumented_impl_method_return_values() {
149+
let doc = test::mk_doc(
150+
"#[doc = \"hey\"] impl i for int { fn a() -> int { } }");
151+
assert doc.topmod.impls()[0].methods[0].return.ty == none;
152+
}
153+
154+
#[cfg(test)]
155+
mod test {
156+
fn mk_doc(source: str) -> doc::cratedoc {
157+
let srv = astsrv::mk_srv_from_str(source);
158+
let doc = extract::from_srv(srv, "");
159+
let doc = attr_pass::mk_pass()(srv, doc);
160+
run(srv, doc)
161+
}
162+
}

src/rustdoc/prune_undoc_pass.rs renamed to src/rustdoc/prune_undoc_items_pass.rs

Lines changed: 21 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[doc = "Prunes branches of the document tree that contain no documentation"];
1+
#[doc = "Prunes items of the document tree that contain no documentation"];
22

33
export mk_pass;
44

@@ -109,46 +109,27 @@ fn fold_fn(
109109
fold: fold::fold<ctxt>,
110110
doc: doc::fndoc
111111
) -> doc::fndoc {
112-
let doc = {
113-
args: prune_args(doc.args),
114-
return: prune_return(doc.return)
115-
with doc
116-
};
112+
let doc = fold::default_seq_fold_fn(fold, doc);
117113

118114
fold.ctxt.have_docs =
119115
doc.brief != none
120116
|| doc.desc != none
121-
|| vec::is_not_empty(doc.args)
117+
|| args_have_docs(doc.args)
122118
|| doc.return.desc != none
123119
|| doc.failure != none;
124120
ret doc;
125121
}
126122

127-
fn prune_args(docs: [doc::argdoc]) -> [doc::argdoc] {
128-
vec::filter_map(docs) {|doc|
129-
if option::is_some(doc.desc) {
130-
some(doc)
131-
} else {
132-
none
133-
}
134-
}
135-
}
136-
137-
fn prune_return(doc: doc::retdoc) -> doc::retdoc {
138-
{
139-
ty: if option::is_some(doc.desc) {
140-
doc.ty
141-
} else {
142-
none
143-
}
144-
with doc
123+
fn args_have_docs(docs: [doc::argdoc]) -> bool {
124+
vec::foldl(false, docs) {|accum, doc|
125+
accum || doc.desc != none
145126
}
146127
}
147128

148129
#[test]
149-
fn should_elide_undocumented_arguments() {
150-
let doc = test::mk_doc("#[doc = \"hey\"] fn a(b: int) { }");
151-
assert vec::is_empty(doc.topmod.fns()[0].args);
130+
fn should_elide_fns_with_undocumented_arguments() {
131+
let doc = test::mk_doc("fn a(a: int) { }");
132+
assert vec::is_empty(doc.topmod.fns());
152133
}
153134

154135
#[test]
@@ -157,17 +138,6 @@ fn should_not_elide_fns_with_documented_arguments() {
157138
assert vec::is_not_empty(doc.topmod.fns());
158139
}
159140

160-
#[test]
161-
fn should_elide_undocumented_return_values() {
162-
let source = "#[doc = \"fonz\"] fn a() -> int { }";
163-
let srv = astsrv::mk_srv_from_str(source);
164-
let doc = extract::from_srv(srv, "");
165-
let doc = tystr_pass::mk_pass()(srv, doc);
166-
let doc = attr_pass::mk_pass()(srv, doc);
167-
let doc = run(srv, doc);
168-
assert doc.topmod.fns()[0].return.ty == none;
169-
}
170-
171141
#[test]
172142
fn should_not_elide_fns_with_documented_failure_conditions() {
173143
let doc = test::mk_doc("#[doc(failure = \"yup\")] fn a() { }");
@@ -252,20 +222,12 @@ fn should_not_elide_enums_with_documented_variants() {
252222
}
253223

254224
fn fold_res(fold: fold::fold<ctxt>, doc: doc::resdoc) -> doc::resdoc {
255-
let doc = {
256-
args: vec::filter_map(doc.args) {|arg|
257-
if arg.desc != none {
258-
some(arg)
259-
} else {
260-
none
261-
}
262-
}
263-
with fold::default_seq_fold_res(fold, doc)
264-
};
225+
let doc = fold::default_seq_fold_res(fold, doc);
226+
265227
fold.ctxt.have_docs =
266228
doc.brief != none
267229
|| doc.desc != none
268-
|| vec::is_not_empty(doc.args);
230+
|| args_have_docs(doc.args);
269231
ret doc;
270232
}
271233

@@ -275,13 +237,6 @@ fn should_elide_undocumented_resources() {
275237
assert vec::is_empty(doc.topmod.resources());
276238
}
277239

278-
#[test]
279-
fn should_elide_undocumented_resource_args() {
280-
let doc = test::mk_doc("#[doc = \"drunk\"]\
281-
resource r(a: bool) { }");
282-
assert vec::is_empty(doc.topmod.resources()[0].args);
283-
}
284-
285240
#[test]
286241
fn should_not_elide_resources_with_documented_args() {
287242
let doc = test::mk_doc("#[doc(args(a = \"drunk\"))]\
@@ -294,33 +249,20 @@ fn fold_iface(
294249
doc: doc::ifacedoc
295250
) -> doc::ifacedoc {
296251
let doc = fold::default_seq_fold_iface(fold, doc);
297-
let doc = {
298-
methods: prune_methods(doc.methods)
299-
with doc
300-
};
252+
301253
fold.ctxt.have_docs =
302254
doc.brief != none
303255
|| doc.desc != none
304256
|| methods_have_docs(doc.methods);
305257
ret doc;
306258
}
307259

308-
fn prune_methods(docs: [doc::methoddoc]) -> [doc::methoddoc] {
309-
vec::map(docs) {|doc|
310-
{
311-
args: prune_args(doc.args),
312-
return: prune_return(doc.return)
313-
with doc
314-
}
315-
}
316-
}
317-
318260
fn methods_have_docs(docs: [doc::methoddoc]) -> bool {
319261
vec::foldl(false, docs) {|accum, doc|
320262
accum
321263
|| doc.brief != none
322264
|| doc.desc != none
323-
|| vec::is_not_empty(doc.args)
265+
|| args_have_docs(doc.args)
324266
|| doc.return.desc != none
325267
|| doc.failure != none
326268
}
@@ -338,6 +280,12 @@ fn should_not_elide_documented_ifaces() {
338280
assert vec::is_not_empty(doc.topmod.ifaces());
339281
}
340282

283+
#[test]
284+
fn should_elide_ifaces_with_undocumented_args() {
285+
let doc = test::mk_doc("iface i { fn a(b: bool); }");
286+
assert vec::is_empty(doc.topmod.ifaces());
287+
}
288+
341289
#[test]
342290
fn should_not_elide_ifaces_with_documented_methods() {
343291
let doc = test::mk_doc("iface i { #[doc = \"hey\"] fn a(); }");
@@ -350,27 +298,12 @@ fn should_not_elide_undocumented_iface_methods() {
350298
assert vec::is_not_empty(doc.topmod.ifaces()[0].methods);
351299
}
352300

353-
#[test]
354-
fn should_elide_undocumented_iface_method_args() {
355-
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a(); }");
356-
assert vec::is_empty(doc.topmod.ifaces()[0].methods[0].args);
357-
}
358-
359-
#[test]
360-
fn should_elide_undocumented_iface_method_return_values() {
361-
let doc = test::mk_doc("#[doc = \"hey\"] iface i { fn a() -> int; }");
362-
assert doc.topmod.ifaces()[0].methods[0].return.ty == none;
363-
}
364-
365301
fn fold_impl(
366302
fold: fold::fold<ctxt>,
367303
doc: doc::impldoc
368304
) -> doc::impldoc {
369305
let doc = fold::default_seq_fold_impl(fold, doc);
370-
let doc = {
371-
methods: prune_methods(doc.methods)
372-
with doc
373-
};
306+
374307
fold.ctxt.have_docs =
375308
doc.brief != none
376309
|| doc.desc != none
@@ -402,20 +335,6 @@ fn should_not_elide_undocumented_impl_methods() {
402335
assert vec::is_not_empty(doc.topmod.impls()[0].methods);
403336
}
404337

405-
#[test]
406-
fn should_elide_undocumented_impl_method_args() {
407-
let doc = test::mk_doc(
408-
"#[doc = \"hey\"] impl i for int { fn a(b: bool) { } }");
409-
assert vec::is_empty(doc.topmod.impls()[0].methods[0].args);
410-
}
411-
412-
#[test]
413-
fn should_elide_undocumented_impl_method_return_values() {
414-
let doc = test::mk_doc(
415-
"#[doc = \"hey\"] impl i for int { fn a() -> int { } }");
416-
assert doc.topmod.impls()[0].methods[0].return.ty == none;
417-
}
418-
419338
#[cfg(test)]
420339
mod test {
421340
fn mk_doc(source: str) -> doc::cratedoc {

src/rustdoc/rustdoc.rc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ mod fold;
2121
mod path_pass;
2222
mod attr_pass;
2323
mod tystr_pass;
24-
mod prune_undoc_pass;
24+
mod prune_undoc_details_pass;
25+
mod prune_undoc_items_pass;
2526
mod prune_unexported_pass;
2627
mod desc_to_brief_pass;
2728
mod desc_pass;

src/rustdoc/rustdoc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,9 @@ fn run(source_file: str) {
100100
tystr_pass::mk_pass(),
101101
path_pass::mk_pass(),
102102
attr_pass::mk_pass(),
103+
prune_undoc_details_pass::mk_pass(),
103104
// FIXME: This pass should be optional
104-
prune_undoc_pass::mk_pass(),
105+
// prune_undoc_items_pass::mk_pass(),
105106
desc_to_brief_pass::mk_pass(),
106107
trim_pass::mk_pass(),
107108
unindent_pass::mk_pass(),

0 commit comments

Comments
 (0)