Files
rust/src/librustdoc/formats/renderer.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

132 lines
4.7 KiB
Rust
Raw Normal View History

2024-11-21 15:16:36 +01:00
use rustc_data_structures::profiling::SelfProfilerRef;
2021-01-22 21:17:32 +01:00
use rustc_middle::ty::TyCtxt;
use crate::clean;
use crate::config::RenderOptions;
use crate::error::Error;
2021-01-12 23:36:04 +01:00
use crate::formats::cache::Cache;
2020-07-27 17:34:17 -05:00
/// Allows for different backends to rustdoc to be used with the `run_format()` function. Each
2020-06-29 18:22:58 -05:00
/// backend renderer has hooks for initialization, documenting an item, entering and exiting a
/// module, and cleanup/finalizing output.
pub(crate) trait FormatRenderer<'tcx>: Sized {
/// Gives a description of the renderer. Used for performance profiling.
fn descr() -> &'static str;
/// Whether to call `item` recursively for modules
///
/// This is true for html, and false for json. See #80664
const RUN_ON_MODULE: bool;
/// This associated type is the type where the current module information is stored.
///
/// For each module, we go through their items by calling for each item:
///
/// 1. save_module_data
/// 2. item
/// 3. set_back_info
///
/// However,the `item` method might update information in `self` (for example if the child is
/// a module). To prevent it to impact the other children of the current module, we need to
/// reset the information between each call to `item` by using `set_back_info`.
type ModuleData;
2020-06-29 18:22:58 -05:00
/// Sets up any state required for the renderer. When this is called the cache has already been
2020-06-26 08:18:20 -05:00
/// populated.
fn init(
krate: clean::Crate,
options: RenderOptions,
2021-01-12 23:36:04 +01:00
cache: Cache,
2021-01-22 21:17:32 +01:00
tcx: TyCtxt<'tcx>,
2020-06-29 18:22:58 -05:00
) -> Result<(Self, clean::Crate), Error>;
/// This method is called right before call [`Self::item`]. This method returns a type
/// containing information that needs to be reset after the [`Self::item`] method has been
/// called with the [`Self::set_back_info`] method.
///
/// In short it goes like this:
///
/// ```ignore (not valid code)
/// let reset_data = type.save_module_data();
/// type.item(item)?;
/// type.set_back_info(reset_data);
/// ```
fn save_module_data(&mut self) -> Self::ModuleData;
/// Used to reset current module's information.
fn set_back_info(&mut self, info: Self::ModuleData);
/// Renders a single non-module item. This means no recursive sub-item rendering is required.
2021-01-12 23:36:04 +01:00
fn item(&mut self, item: clean::Item) -> Result<(), Error>;
2020-06-29 18:22:58 -05:00
/// Renders a module (should not handle recursing into children).
fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error>;
/// Runs after recursively rendering all sub-items of a module.
fn mod_item_out(&mut self) -> Result<(), Error> {
Ok(())
}
/// Post processing hook for cleanup and dumping output to files.
fn after_krate(&mut self) -> Result<(), Error>;
2021-01-12 23:36:04 +01:00
fn cache(&self) -> &Cache;
}
2024-11-21 15:16:36 +01:00
fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
cx: &mut T,
item: clean::Item,
prof: &SelfProfilerRef,
) -> Result<(), Error> {
if item.is_mod() && T::RUN_ON_MODULE {
// modules are special because they add a namespace. We also need to
// recurse into the items of the module as well.
let _timer =
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
cx.mod_item_in(&item)?;
let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
item.inner.kind
else {
unreachable!()
};
for it in module.items {
let info = cx.save_module_data();
2024-11-21 15:16:36 +01:00
run_format_inner(cx, it, prof)?;
cx.set_back_info(info);
}
cx.mod_item_out()?;
// FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
// cases. Use an explicit match instead.
} else if let Some(item_name) = item.name
&& !item.is_extern_crate()
{
prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
}
Ok(())
}
2020-07-27 17:34:17 -05:00
/// Main method for rendering a crate.
pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
2020-07-27 17:34:17 -05:00
krate: clean::Crate,
options: RenderOptions,
cache: Cache,
2020-12-31 23:25:30 -05:00
tcx: TyCtxt<'tcx>,
2020-07-27 17:34:17 -05:00
) -> Result<(), Error> {
let prof = &tcx.sess.prof;
let emit_crate = options.should_emit_crate();
let (mut format_renderer, krate) = prof
Remove `-Ztime` option. The compiler currently has `-Ztime` and `-Ztime-passes`. I've used `-Ztime-passes` for years but only recently learned about `-Ztime`. What's the difference? Let's look at the `-Zhelp` output: ``` -Z time=val -- measure time of rustc processes (default: no) -Z time-passes=val -- measure time of each rustc pass (default: no) ``` The `-Ztime-passes` description is clear, but the `-Ztime` one is less so. Sounds like it measures the time for the entire process? No. The real difference is that `-Ztime-passes` prints out info about passes, and `-Ztime` does the same, but only for a subset of those passes. More specifically, there is a distinction in the profiling code between a "verbose generic activity" and an "extra verbose generic activity". `-Ztime-passes` prints both kinds, while `-Ztime` only prints the first one. (It took me a close reading of the source code to determine this difference.) In practice this distinction has low value. Perhaps in the past the "extra verbose" output was more voluminous, but now that we only print stats for a pass if it exceeds 5ms or alters the RSS, `-Ztime-passes` is less spammy. Also, a lot of the "extra verbose" cases are for individual lint passes, and you need to also use `-Zno-interleave-lints` to see those anyway. Therefore, this commit removes `-Ztime` and the associated machinery. One thing to note is that the existing "extra verbose" activities all have an extra string argument, so the commit adds the ability to accept an extra argument to the "verbose" activities.
2022-10-06 14:51:45 +11:00
.verbose_generic_activity_with_arg("create_renderer", T::descr())
.run(|| T::init(krate, options, cache, tcx))?;
2020-07-27 17:34:17 -05:00
if !emit_crate {
return Ok(());
}
2020-07-27 17:34:17 -05:00
// Render the crate documentation
2024-11-21 15:16:36 +01:00
run_format_inner(&mut format_renderer, krate.module, prof)?;
Remove `-Ztime` option. The compiler currently has `-Ztime` and `-Ztime-passes`. I've used `-Ztime-passes` for years but only recently learned about `-Ztime`. What's the difference? Let's look at the `-Zhelp` output: ``` -Z time=val -- measure time of rustc processes (default: no) -Z time-passes=val -- measure time of each rustc pass (default: no) ``` The `-Ztime-passes` description is clear, but the `-Ztime` one is less so. Sounds like it measures the time for the entire process? No. The real difference is that `-Ztime-passes` prints out info about passes, and `-Ztime` does the same, but only for a subset of those passes. More specifically, there is a distinction in the profiling code between a "verbose generic activity" and an "extra verbose generic activity". `-Ztime-passes` prints both kinds, while `-Ztime` only prints the first one. (It took me a close reading of the source code to determine this difference.) In practice this distinction has low value. Perhaps in the past the "extra verbose" output was more voluminous, but now that we only print stats for a pass if it exceeds 5ms or alters the RSS, `-Ztime-passes` is less spammy. Also, a lot of the "extra verbose" cases are for individual lint passes, and you need to also use `-Zno-interleave-lints` to see those anyway. Therefore, this commit removes `-Ztime` and the associated machinery. One thing to note is that the existing "extra verbose" activities all have an extra string argument, so the commit adds the ability to accept an extra argument to the "verbose" activities.
2022-10-06 14:51:45 +11:00
prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
.run(|| format_renderer.after_krate())
}