1 use std::cell::RefCell;
4 use rustc_span::edition::Edition;
7 use crate::config::{RenderInfo, RenderOptions};
8 use crate::error::Error;
10 pub trait FormatRenderer: Clone {
11 type Output: FormatRenderer;
15 options: RenderOptions,
16 renderinfo: RenderInfo,
17 diag: &rustc_errors::Handler,
19 parent: Rc<RefCell<Renderer>>,
20 ) -> Result<(Self::Output, clean::Crate), Error>;
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>;
25 /// Renders a module. Doesn't need to handle recursing into children, the driver does that
31 module: &clean::Module,
32 ) -> Result<(), Error>;
34 /// Runs after recursively rendering all sub-items of a module.
35 fn mod_item_out(&mut self) -> Result<(), Error>;
37 /// Post processing hook for cleanup and dumping output to files.
38 fn after_krate(&mut self, krate: &clean::Crate) -> Result<(), Error>;
40 /// Called after everything else to write out errors.
41 fn after_run(&mut self, diag: &rustc_errors::Handler) -> Result<(), Error>;
48 pub fn new() -> Renderer {
52 /// Main method for rendering a crate.
53 pub fn run<T: FormatRenderer + Clone>(
56 options: RenderOptions,
57 renderinfo: RenderInfo,
58 diag: &rustc_errors::Handler,
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() {
66 None => return Ok(()),
69 item.name = Some(krate.name.clone());
71 // Render the crate documentation
72 let mut work = vec![(renderer.clone(), item)];
74 while let Some((mut cx, item)) = work.pop() {
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();
80 panic!("Unexpected module with empty name");
83 let module = match item.inner {
84 clean::StrippedItem(box clean::ModuleItem(ref m))
85 | clean::ModuleItem(ref m) => m,
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,
93 for it in module.items {
94 info!("Adding {:?} to worklist", it.name);
95 work.push((cx.clone(), it));
99 } else if item.name.is_some() {
104 renderer.after_krate(&krate)?;
105 renderer.after_run(diag)