Skip to content

Commit 5bc9794

Browse files
committed
Refactor html backend to use generic interface
1 parent c692ed4 commit 5bc9794

File tree

3 files changed

+409
-313
lines changed

3 files changed

+409
-313
lines changed

src/librustdoc/formats/mod.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use std::cell::RefCell;
2+
use std::rc::Rc;
3+
4+
use rustc_span::edition::Edition;
5+
6+
use crate::clean;
7+
use crate::config::{RenderInfo, RenderOptions};
8+
use crate::error::Error;
9+
10+
pub trait FormatRenderer: Clone {
11+
type Output: FormatRenderer;
12+
13+
fn init(
14+
krate: clean::Crate,
15+
options: RenderOptions,
16+
renderinfo: RenderInfo,
17+
diag: &rustc_errors::Handler,
18+
edition: Edition,
19+
parent: Rc<RefCell<Renderer>>,
20+
) -> Result<(Self::Output, clean::Crate), Error>;
21+
22+
/// Renders a single non-module item. This means no recursive sub-item rendering is required.
23+
fn item(&mut self, item: clean::Item) -> Result<(), Error>;
24+
25+
/// Renders a module. Doesn't need to handle recursing into children, the driver does that
26+
/// automatically.
27+
fn mod_item_in(
28+
&mut self,
29+
item: &clean::Item,
30+
item_name: &str,
31+
module: &clean::Module,
32+
) -> Result<(), Error>;
33+
34+
/// Runs after recursively rendering all sub-items of a module.
35+
fn mod_item_out(&mut self) -> Result<(), Error>;
36+
37+
/// Post processing hook for cleanup and dumping output to files.
38+
fn after_krate(&mut self, krate: &clean::Crate) -> Result<(), Error>;
39+
40+
/// Called after everything else to write out errors.
41+
fn after_run(&mut self, diag: &rustc_errors::Handler) -> Result<(), Error>;
42+
}
43+
44+
#[derive(Clone)]
45+
pub struct Renderer;
46+
47+
impl Renderer {
48+
pub fn new() -> Renderer {
49+
Renderer
50+
}
51+
52+
/// Main method for rendering a crate.
53+
pub fn run<T: FormatRenderer + Clone>(
54+
self,
55+
krate: clean::Crate,
56+
options: RenderOptions,
57+
renderinfo: RenderInfo,
58+
diag: &rustc_errors::Handler,
59+
edition: Edition,
60+
) -> Result<(), Error> {
61+
let rself = Rc::new(RefCell::new(self));
62+
let (mut renderer, mut krate) =
63+
T::init(krate, options, renderinfo, diag, edition, rself.clone())?;
64+
let mut item = match krate.module.take() {
65+
Some(i) => i,
66+
None => return Ok(()),
67+
};
68+
69+
item.name = Some(krate.name.clone());
70+
71+
// Render the crate documentation
72+
let mut work = vec![(renderer.clone(), item)];
73+
74+
while let Some((mut cx, item)) = work.pop() {
75+
if item.is_mod() {
76+
// modules are special because they add a namespace. We also need to
77+
// recurse into the items of the module as well.
78+
let name = item.name.as_ref().unwrap().to_string();
79+
if name.is_empty() {
80+
panic!("Unexpected module with empty name");
81+
}
82+
83+
let module = match item.inner {
84+
clean::StrippedItem(box clean::ModuleItem(ref m))
85+
| clean::ModuleItem(ref m) => m,
86+
_ => unreachable!(),
87+
};
88+
cx.mod_item_in(&item, &name, module)?;
89+
let module = match item.inner {
90+
clean::StrippedItem(box clean::ModuleItem(m)) | clean::ModuleItem(m) => m,
91+
_ => unreachable!(),
92+
};
93+
for it in module.items {
94+
info!("Adding {:?} to worklist", it.name);
95+
work.push((cx.clone(), it));
96+
}
97+
98+
cx.mod_item_out()?;
99+
} else if item.name.is_some() {
100+
cx.item(item)?;
101+
}
102+
}
103+
104+
renderer.after_krate(&krate)?;
105+
renderer.after_run(diag)
106+
}
107+
}

0 commit comments

Comments
 (0)