]>
Commit | Line | Data |
---|---|---|
5869c6ff | 1 | use rustc_middle::ty::TyCtxt; |
cdc7bbd5 | 2 | use rustc_span::Symbol; |
3dfed10e XL |
3 | |
4 | use crate::clean; | |
6a06907d | 5 | use crate::config::RenderOptions; |
3dfed10e | 6 | use crate::error::Error; |
5869c6ff | 7 | use crate::formats::cache::Cache; |
3dfed10e XL |
8 | |
9 | /// Allows for different backends to rustdoc to be used with the `run_format()` function. Each | |
10 | /// backend renderer has hooks for initialization, documenting an item, entering and exiting a | |
11 | /// module, and cleanup/finalizing output. | |
923072b8 | 12 | pub(crate) trait FormatRenderer<'tcx>: Sized { |
5869c6ff XL |
13 | /// Gives a description of the renderer. Used for performance profiling. |
14 | fn descr() -> &'static str; | |
15 | ||
5e7ed085 | 16 | /// Whether to call `item` recursively for modules |
cdc7bbd5 XL |
17 | /// |
18 | /// This is true for html, and false for json. See #80664 | |
19 | const RUN_ON_MODULE: bool; | |
20 | ||
3dfed10e XL |
21 | /// Sets up any state required for the renderer. When this is called the cache has already been |
22 | /// populated. | |
23 | fn init( | |
24 | krate: clean::Crate, | |
25 | options: RenderOptions, | |
5869c6ff XL |
26 | cache: Cache, |
27 | tcx: TyCtxt<'tcx>, | |
3dfed10e XL |
28 | ) -> Result<(Self, clean::Crate), Error>; |
29 | ||
6a06907d XL |
30 | /// Make a new renderer to render a child of the item currently being rendered. |
31 | fn make_child_renderer(&self) -> Self; | |
32 | ||
3dfed10e | 33 | /// Renders a single non-module item. This means no recursive sub-item rendering is required. |
5869c6ff | 34 | fn item(&mut self, item: clean::Item) -> Result<(), Error>; |
3dfed10e XL |
35 | |
36 | /// Renders a module (should not handle recursing into children). | |
cdc7bbd5 | 37 | fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error>; |
3dfed10e XL |
38 | |
39 | /// Runs after recursively rendering all sub-items of a module. | |
cdc7bbd5 XL |
40 | fn mod_item_out(&mut self) -> Result<(), Error> { |
41 | Ok(()) | |
42 | } | |
3dfed10e XL |
43 | |
44 | /// Post processing hook for cleanup and dumping output to files. | |
cdc7bbd5 | 45 | fn after_krate(&mut self) -> Result<(), Error>; |
3dfed10e | 46 | |
5869c6ff | 47 | fn cache(&self) -> &Cache; |
3dfed10e XL |
48 | } |
49 | ||
50 | /// Main method for rendering a crate. | |
923072b8 | 51 | pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( |
3dfed10e XL |
52 | krate: clean::Crate, |
53 | options: RenderOptions, | |
6a06907d | 54 | cache: Cache, |
5869c6ff | 55 | tcx: TyCtxt<'tcx>, |
3dfed10e | 56 | ) -> Result<(), Error> { |
5869c6ff XL |
57 | let prof = &tcx.sess.prof; |
58 | ||
cdc7bbd5 XL |
59 | let emit_crate = options.should_emit_crate(); |
60 | let (mut format_renderer, krate) = prof | |
2b03887a | 61 | .verbose_generic_activity_with_arg("create_renderer", T::descr()) |
cdc7bbd5 | 62 | .run(|| T::init(krate, options, cache, tcx))?; |
3dfed10e | 63 | |
cdc7bbd5 XL |
64 | if !emit_crate { |
65 | return Ok(()); | |
66 | } | |
3dfed10e XL |
67 | |
68 | // Render the crate documentation | |
cdc7bbd5 | 69 | let mut work = vec![(format_renderer.make_child_renderer(), krate.module)]; |
3dfed10e | 70 | |
cdc7bbd5 | 71 | let unknown = Symbol::intern("<unknown item>"); |
3dfed10e | 72 | while let Some((mut cx, item)) = work.pop() { |
cdc7bbd5 | 73 | if item.is_mod() && T::RUN_ON_MODULE { |
3dfed10e XL |
74 | // modules are special because they add a namespace. We also need to |
75 | // recurse into the items of the module as well. | |
cdc7bbd5 XL |
76 | let _timer = |
77 | prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string()); | |
3dfed10e | 78 | |
cdc7bbd5 | 79 | cx.mod_item_in(&item)?; |
5e7ed085 FG |
80 | let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = *item.kind |
81 | else { unreachable!() }; | |
3dfed10e XL |
82 | for it in module.items { |
83 | debug!("Adding {:?} to worklist", it.name); | |
6a06907d | 84 | work.push((cx.make_child_renderer(), it)); |
3dfed10e XL |
85 | } |
86 | ||
cdc7bbd5 | 87 | cx.mod_item_out()?; |
6a06907d XL |
88 | // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special |
89 | // cases. Use an explicit match instead. | |
90 | } else if item.name.is_some() && !item.is_extern_crate() { | |
a2a8927a | 91 | prof.generic_activity_with_arg("render_item", item.name.unwrap_or(unknown).as_str()) |
5869c6ff | 92 | .run(|| cx.item(item))?; |
3dfed10e XL |
93 | } |
94 | } | |
2b03887a | 95 | prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr()) |
cdc7bbd5 | 96 | .run(|| format_renderer.after_krate()) |
3dfed10e | 97 | } |