Skip to content

Commit 5a9bbba

Browse files
committed
rustdoc: Add DocVisitor
`DocFolder` allows transforming the docs, accomplished by making its methods take and return types by-value. However, several of the rustdoc `DocFolder` impls only *visit* the docs; they don't change anything. Passing around types by-value is thus unnecessary, confusing, and potentially inefficient for those impls. `DocVisitor` is very similar to `DocFolder`, except that its methods take shared references and return nothing (i.e., the unit type). This should both be more efficient and make the code clearer. There is an additional reason to add `DocVisitor`, too. As part of my cleanup of `external_traits`, I'm planning to add a `fn cache(&mut self) -> &mut Cache` method to `DocFolder` so that `external_traits` can be retrieved explicitly from the `Cache`, rather than implicitly via `Crate.external_traits` (which is an `Rc<RefCell<...>>`). However, some of the `DocFolder` impls that could be turned into `DocVisitor` impls only have a shared reference to the `Cache`, because they are used during rendering. (They have to access the `Cache` via `html::render::Context.shared.cache`, which involves an `Rc`.) Since `DocVisitor` does not mutate any of the types it's visiting, its equivalent `cache()` method will only need a shared reference to the `Cache`, avoiding the problem described above.
1 parent 705dec1 commit 5a9bbba

File tree

3 files changed

+66
-15
lines changed

3 files changed

+66
-15
lines changed

src/librustdoc/fold.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,21 @@ crate trait DocFolder: Sized {
4646
i.items = i.items.into_iter().filter_map(|x| self.fold_item(x)).collect();
4747
ImplItem(i)
4848
}
49-
VariantItem(i) => {
50-
match i {
51-
Variant::Struct(mut j) => {
52-
let num_fields = j.fields.len();
53-
j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
54-
j.fields_stripped |= num_fields != j.fields.len()
55-
|| j.fields.iter().any(|f| f.is_stripped());
56-
VariantItem(Variant::Struct(j))
57-
}
58-
Variant::Tuple(fields) => {
59-
let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
60-
VariantItem(Variant::Tuple(fields))
61-
}
62-
Variant::CLike => VariantItem(Variant::CLike),
49+
VariantItem(i) => match i {
50+
Variant::Struct(mut j) => {
51+
let num_fields = j.fields.len();
52+
j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
53+
j.fields_stripped |=
54+
num_fields != j.fields.len() || j.fields.iter().any(|f| f.is_stripped());
55+
VariantItem(Variant::Struct(j))
6356
}
64-
}
57+
Variant::Tuple(fields) => {
58+
let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
59+
VariantItem(Variant::Tuple(fields))
60+
}
61+
Variant::CLike => VariantItem(Variant::CLike),
62+
},
63+
// FIXME: list all cases explicitly
6564
x => x,
6665
}
6766
}

src/librustdoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ mod markdown;
121121
mod passes;
122122
mod scrape_examples;
123123
mod theme;
124+
mod visit;
124125
mod visit_ast;
125126
mod visit_lib;
126127

src/librustdoc/visit.rs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use crate::clean::*;
2+
3+
crate trait DocVisitor: Sized {
4+
fn visit_item(&mut self, item: &Item) {
5+
self.visit_item_recur(item)
6+
}
7+
8+
/// don't override!
9+
fn visit_inner_recur(&mut self, kind: &ItemKind) {
10+
match kind {
11+
StrippedItem(..) => unreachable!(),
12+
ModuleItem(i) => {
13+
self.visit_mod(i);
14+
return;
15+
}
16+
StructItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
17+
UnionItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
18+
EnumItem(i) => i.variants.iter().for_each(|x| self.visit_item(x)),
19+
TraitItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
20+
ImplItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
21+
VariantItem(i) => match i {
22+
Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
23+
Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
24+
Variant::CLike => {}
25+
},
26+
// FIXME: list all cases explicitly
27+
_ => return,
28+
}
29+
}
30+
31+
/// don't override!
32+
fn visit_item_recur(&mut self, item: &Item) {
33+
match &*item.kind {
34+
StrippedItem(i) => self.visit_inner_recur(i),
35+
_ => self.visit_inner_recur(&item.kind),
36+
}
37+
}
38+
39+
fn visit_mod(&mut self, m: &Module) {
40+
m.items.iter().for_each(|i| self.visit_item(i))
41+
}
42+
43+
fn visit_crate(&mut self, c: &Crate) {
44+
self.visit_item(&c.module);
45+
46+
let external_traits = c.external_traits.borrow();
47+
for v in external_traits.values() {
48+
v.trait_.items.iter().for_each(|i| self.visit_item(i))
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)