use std::cell::RefCell;
use std::collections::BTreeMap;
use std::fmt::{self, Write as _};
use std::io;
use std::path::{Path, PathBuf};
use std::sync::mpsc::{Receiver, channel};

use askama::Template;
use rustc_ast::join_path_syms;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_hir::Attribute;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::edition::Edition;
use rustc_span::{BytePos, FileName, RemapPathScopeComponents, Symbol};
use serde::ser::SerializeSeq;
use tracing::info;

use super::print_item::{full_path, print_item, print_item_path, print_ty_path};
use super::sidebar::{ModuleLike, Sidebar, print_sidebar, sidebar_module_like};
use super::{AllTypes, StylePath};
use crate::clean::types::ExternalLocation;
use crate::clean::utils::has_doc_flag;
use crate::clean::{self, ExternalCrate};
use crate::config::{EmitType, ModuleSorting, RenderOptions};
use crate::docfs::{DocFS, PathError};
use crate::error::Error;
use crate::formats::FormatRenderer;
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
use crate::html::escape::Escape;
use crate::html::macro_expansion::ExpandedCode;
use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary};
use crate::html::render::write_shared::write_shared;
use crate::html::span_map::{LinkFromSrc, Span, collect_spans_and_sources};
use crate::html::url_parts_builder::UrlPartsBuilder;
use crate::html::{layout, sources};
use crate::scrape_examples::AllCallLocations;
use crate::try_err;

/// Major driving force in all rustdoc rendering. This contains information
/// about where in the tree-like hierarchy rendering is occurring and controls
/// how the current page is being rendered.
///
/// It is intended that this context is a lightweight object which can be fairly
/// easily cloned because it is cloned per work-job (about once per item in the
/// rustdoc tree).
pub(crate) struct Context<'tcx> {
    /// Current hierarchy of components leading down to what's currently being
    /// rendered
    pub(crate) current: Vec<Symbol>,
    /// The current destination folder of where HTML artifacts should be placed.
    /// This changes as the context descends into the module hierarchy.
    pub(crate) dst: PathBuf,
    /// Tracks section IDs for `Deref` targets so they match in both the main
    /// body and the sidebar.
    pub(super) deref_id_map: RefCell<DefIdMap<String>>,
    /// The map used to ensure all generated 'id=' attributes are unique.
    pub(super) id_map: RefCell<IdMap>,
    /// Shared mutable state.
    ///
    /// Issue for improving the situation: [#82381][]
    ///
    /// [#82381]: https://github.com/rust-lang/rust/issues/82381
    pub(crate) shared: SharedContext<'tcx>,
    /// Collection of all types with notable traits referenced in the current module.
    pub(crate) types_with_notable_traits: RefCell<FxIndexSet<clean::Type>>,
    /// Contains information that needs to be saved and reset after rendering an item which is
    /// not a module.
    pub(crate) info: ContextInfo,
}

/// This struct contains the information that needs to be reset between each
/// [`FormatRenderer::item`] call.
///
/// When we enter a new module, we set these values for the whole module but they might be updated
/// in each child item (especially if it's a module). So to prevent these changes to impact other
/// items rendering in the same module, we need to reset them to the module's set values.
#[derive(Clone, Copy)]
pub(crate) struct ContextInfo {
    /// A flag, which when `true`, will render pages which redirect to the
    /// real location of an item. This is used to allow external links to
    /// publicly reused items to redirect to the right location.
    pub(super) render_redirect_pages: bool,
    /// This flag indicates whether source links should be generated or not. If
    /// the source files are present in the html rendering, then this will be
    /// `true`.
    pub(crate) include_sources: bool,
    /// Field used during rendering, to know if we're inside an inlined item.
    pub(crate) is_inside_inlined_module: bool,
}

impl ContextInfo {
    fn new(include_sources: bool) -> Self {
        Self { render_redirect_pages: false, include_sources, is_inside_inlined_module: false }
    }
}

/// Shared mutable state used in [`Context`] and elsewhere.
pub(crate) struct SharedContext<'tcx> {
    pub(crate) tcx: TyCtxt<'tcx>,
    /// The path to the crate root source minus the file name.
    /// Used for simplifying paths to the highlighted source code files.
    pub(crate) src_root: PathBuf,
    /// This describes the layout of each page, and is not modified after
    /// creation of the context (contains info like the favicon and added html).
    pub(crate) layout: layout::Layout,
    /// The local file sources we've emitted and their respective url-paths.
    pub(crate) local_sources: FxIndexMap<PathBuf, String>,
    /// Show the memory layout of types in the docs.
    pub(super) show_type_layout: bool,
    /// The base-URL of the issue tracker for when an item has been tagged with
    /// an issue number.
    pub(super) issue_tracker_base_url: Option<String>,
    /// The directories that have already been created in this doc run. Used to reduce the number
    /// of spurious `create_dir_all` calls.
    created_dirs: RefCell<FxHashSet<PathBuf>>,
    /// This flag indicates whether listings of modules (in the side bar and documentation itself)
    /// should be ordered alphabetically or in order of appearance (in the source code).
    pub(super) module_sorting: ModuleSorting,
    /// Additional CSS files to be added to the generated docs.
    pub(crate) style_files: Vec<StylePath>,
    /// Suffix to add on resource files (if suffix is "-v2" then "search-index.js" becomes
    /// "search-index-v2.js").
    pub(crate) resource_suffix: String,
    /// Optional path string to be used to load static files on output pages. If not set, uses
    /// combinations of `../` to reach the documentation root.
    pub(crate) static_root_path: Option<String>,
    /// The fs handle we are working with.
    pub(crate) fs: DocFS,
    pub(super) codes: ErrorCodes,
    pub(super) playground: Option<markdown::Playground>,
    all: RefCell<AllTypes>,
    /// Storage for the errors produced while generating documentation so they
    /// can be printed together at the end.
    errors: Receiver<String>,
    /// `None` by default, depends on the `generate-redirect-map` option flag. If this field is set
    /// to `Some(...)`, it'll store redirections and then generate a JSON file at the top level of
    /// the crate.
    redirections: Option<RefCell<FxHashMap<String, String>>>,

    /// Correspondence map used to link types used in the source code pages to allow to click on
    /// links to jump to the type's definition.
    pub(crate) span_correspondence_map: FxHashMap<Span, LinkFromSrc>,
    pub(crate) expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
    /// The [`Cache`] used during rendering.
    pub(crate) cache: Cache,
    pub(crate) call_locations: AllCallLocations,
}

impl SharedContext<'_> {
    pub(crate) fn ensure_dir(&self, dst: &Path) -> Result<(), Error> {
        let mut dirs = self.created_dirs.borrow_mut();
        if !dirs.contains(dst) {
            try_err!(self.fs.create_dir_all(dst), dst);
            dirs.insert(dst.to_path_buf());
        }

        Ok(())
    }

    pub(crate) fn edition(&self) -> Edition {
        self.tcx.sess.edition()
    }
}

struct SidebarItem {
    name: String,
    /// Bang macros can now be used as attribute/derive macros, making it tricky to correctly
    /// handle all their cases at once, which means that even if they are categorized as
    /// derive/attribute macros, they should still link to a "macro_rules" URL.
    is_macro_rules: bool,
}

impl serde::Serialize for SidebarItem {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        if self.is_macro_rules {
            let mut seq = serializer.serialize_seq(Some(2))?;
            seq.serialize_element(&self.name)?;
            seq.serialize_element(&1)?;
            seq.end()
        } else {
            serializer.serialize_some(&Some(&self.name))
        }
    }
}

impl<'tcx> Context<'tcx> {
    pub(crate) fn tcx(&self) -> TyCtxt<'tcx> {
        self.shared.tcx
    }

    pub(crate) fn cache(&self) -> &Cache {
        &self.shared.cache
    }

    pub(super) fn sess(&self) -> &'tcx Session {
        self.shared.tcx.sess
    }

    pub(super) fn derive_id<S: AsRef<str> + ToString>(&self, id: S) -> String {
        self.id_map.borrow_mut().derive(id)
    }

    /// String representation of how to get back to the root path of the 'doc/'
    /// folder in terms of a relative URL.
    pub(super) fn root_path(&self) -> String {
        "../".repeat(self.current.len())
    }

    fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
        let mut render_redirect_pages = self.info.render_redirect_pages;
        // If the item is stripped but inlined, links won't point to the item so no need to generate
        // a file for it.
        if it.is_stripped()
            && let Some(def_id) = it.def_id()
            && def_id.is_local()
            && (self.info.is_inside_inlined_module
                || self.shared.cache.inlined_items.contains(&def_id))
        {
            // For now we're forced to generate a redirect page for stripped items until
            // `record_extern_fqn` correctly points to external items.
            render_redirect_pages = true;
        }

        if !render_redirect_pages {
            let mut title = String::new();
            if !is_module {
                title.push_str(it.name.unwrap().as_str());
            }
            let short_title;
            let short_title = if is_module {
                let module_name = self.current.last().unwrap();
                short_title = if it.is_crate() {
                    format!("Crate {module_name}")
                } else {
                    format!("Module {module_name}")
                };
                &short_title[..]
            } else {
                it.name.as_ref().unwrap().as_str()
            };
            if !it.is_fake_item() {
                if !is_module {
                    title.push_str(" in ");
                }
                // No need to include the namespace for primitive types and keywords
                title.push_str(&join_path_syms(&self.current));
            };
            title.push_str(" - Rust");
            let tyname = it.type_();
            let desc = plain_text_summary(&it.doc_value(), &it.link_names(self.cache()));
            let desc = if !desc.is_empty() {
                desc
            } else if it.is_crate() {
                format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate)
            } else {
                format!(
                    "API documentation for the Rust `{name}` {tyname} in crate `{krate}`.",
                    name = it.name.as_ref().unwrap(),
                    krate = self.shared.layout.krate,
                )
            };

            let name;
            let tyname_s = if it.is_crate() {
                name = format!("{tyname} crate");
                name.as_str()
            } else {
                tyname.as_str()
            };

            let content = print_item(self, it);
            let page = layout::Page {
                css_class: tyname_s,
                root_path: &self.root_path(),
                static_root_path: self.shared.static_root_path.as_deref(),
                title: &title,
                short_title,
                description: &desc,
                resource_suffix: &self.shared.resource_suffix,
                rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), |d| {
                    d.rust_logo.is_some()
                }),
            };
            layout::render(
                &self.shared.layout,
                &page,
                fmt::from_fn(|f| print_sidebar(self, it, f)),
                content,
                &self.shared.style_files,
            )
        } else {
            if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id())
                && (self.current.len() + 1 != names.len()
                    || self.current.iter().zip(names.iter()).any(|(a, b)| a != b))
            {
                // We checked that the redirection isn't pointing to the current file,
                // preventing an infinite redirection loop in the generated
                // documentation.

                let path = fmt::from_fn(|f| {
                    for name in &names[..names.len() - 1] {
                        write!(f, "{name}/")?;
                    }
                    write!(f, "{}", print_ty_path(ty, names.last().unwrap().as_str()))
                });
                match self.shared.redirections {
                    Some(ref redirections) => {
                        let mut current_path = String::new();
                        for name in &self.current {
                            current_path.push_str(name.as_str());
                            current_path.push('/');
                        }
                        let _ = write!(
                            current_path,
                            "{}",
                            print_ty_path(ty, names.last().unwrap().as_str())
                        );
                        redirections.borrow_mut().insert(current_path, path.to_string());
                    }
                    None => {
                        return layout::redirect(&format!("{root}{path}", root = self.root_path()));
                    }
                }
            }
            String::new()
        }
    }

    /// Construct a map of items shown in the sidebar to a plain-text summary of their docs.
    fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<SidebarItem>> {
        // BTreeMap instead of HashMap to get a sorted output
        let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new();
        let mut inserted: FxHashMap<ItemType, FxHashSet<Symbol>> = FxHashMap::default();

        for item in &m.items {
            if item.is_stripped() {
                continue;
            }
            let name = match item.name {
                None => continue,
                Some(s) => s,
            };

            let is_macro_rules = item.is_decl_macro();
            for type_ in item.types() {
                if inserted.entry(type_).or_default().insert(name) {
                    let type_ = type_.to_string();
                    let name = name.to_string();
                    map.entry(type_).or_default().push(SidebarItem { name, is_macro_rules });
                }
            }
        }

        match self.shared.module_sorting {
            ModuleSorting::Alphabetical => {
                for items in map.values_mut() {
                    items.sort_by(|a, b| a.name.cmp(&b.name));
                }
            }
            ModuleSorting::DeclarationOrder => {}
        }
        map
    }

    /// Generates a url appropriate for an `href` attribute back to the source of
    /// this item.
    ///
    /// The url generated, when clicked, will redirect the browser back to the
    /// original source code.
    ///
    /// If `None` is returned, then a source link couldn't be generated. This
    /// may happen, for example, with externally inlined items where the source
    /// of their crate documentation isn't known.
    pub(super) fn src_href(&self, item: &clean::Item) -> Option<String> {
        self.href_from_span(item.span(self.tcx())?, true)
    }

    pub(crate) fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option<String> {
        let mut root = self.root_path();
        let mut path: String;
        let cnum = span.cnum(self.sess());

        // We can safely ignore synthetic `SourceFile`s.
        let file = match span.filename(self.sess()) {
            FileName::Real(ref path) => path
                .local_path()
                .unwrap_or(path.path(RemapPathScopeComponents::DOCUMENTATION))
                .to_path_buf(),
            _ => return None,
        };
        let file = &file;

        let krate_sym;
        let (krate, path) = if cnum == LOCAL_CRATE {
            if let Some(path) = self.shared.local_sources.get(file) {
                (self.shared.layout.krate.as_str(), path)
            } else {
                return None;
            }
        } else {
            let (krate, src_root) = match *self.cache().extern_locations.get(&cnum)? {
                ExternalLocation::Local => {
                    let e = ExternalCrate { crate_num: cnum };
                    (e.name(self.tcx()), e.src_root(self.tcx()))
                }
                ExternalLocation::Remote { ref url, .. } => {
                    // FIXME: relative extern URLs are not depth-adjusted for source pages
                    root = url.to_string();
                    let e = ExternalCrate { crate_num: cnum };
                    (e.name(self.tcx()), e.src_root(self.tcx()))
                }
                ExternalLocation::Unknown => return None,
            };

            let href = RefCell::new(PathBuf::new());
            sources::clean_path(
                &src_root,
                file,
                |component| {
                    href.borrow_mut().push(component);
                },
                || {
                    href.borrow_mut().pop();
                },
            );

            path = href.into_inner().to_string_lossy().into_owned();

            if let Some(c) = path.as_bytes().last()
                && *c != b'/'
            {
                path.push('/');
            }

            let mut fname = file.file_name().expect("source has no filename").to_os_string();
            fname.push(".html");
            path.push_str(&fname.to_string_lossy());
            krate_sym = krate;
            (krate_sym.as_str(), &path)
        };

        let anchor = if with_lines {
            let loline = span.lo(self.sess()).line;
            let hiline = span.hi(self.sess()).line;
            format!(
                "#{}",
                if loline == hiline { loline.to_string() } else { format!("{loline}-{hiline}") }
            )
        } else {
            "".to_string()
        };
        Some(format!(
            "{root}src/{krate}/{path}{anchor}",
            root = Escape(&root),
            krate = krate,
            path = path,
            anchor = anchor
        ))
    }

    pub(crate) fn href_from_span_relative(
        &self,
        span: clean::Span,
        relative_to: &str,
    ) -> Option<String> {
        self.href_from_span(span, false).map(|s| {
            let mut url = UrlPartsBuilder::new();
            let mut dest_href_parts = s.split('/');
            let mut cur_href_parts = relative_to.split('/');
            for (cur_href_part, dest_href_part) in (&mut cur_href_parts).zip(&mut dest_href_parts) {
                if cur_href_part != dest_href_part {
                    url.push(dest_href_part);
                    break;
                }
            }
            for dest_href_part in dest_href_parts {
                url.push(dest_href_part);
            }
            let loline = span.lo(self.sess()).line;
            let hiline = span.hi(self.sess()).line;
            format!(
                "{}{}#{}",
                "../".repeat(cur_href_parts.count()),
                url.finish(),
                if loline == hiline { loline.to_string() } else { format!("{loline}-{hiline}") }
            )
        })
    }
}

impl<'tcx> Context<'tcx> {
    pub(crate) fn init(
        krate: clean::Crate,
        options: RenderOptions,
        cache: Cache,
        tcx: TyCtxt<'tcx>,
        expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
    ) -> Result<(Self, clean::Crate), Error> {
        // need to save a copy of the options for rendering the index page
        let md_opts = options.clone();
        let RenderOptions {
            output,
            external_html,
            id_map,
            playground_url,
            module_sorting,
            themes: style_files,
            default_settings,
            extension_css,
            resource_suffix,
            static_root_path,
            generate_redirect_map,
            show_type_layout,
            emit,
            generate_link_to_definition,
            call_locations,
            no_emit_shared,
            html_no_source,
            ..
        } = options;

        let src_root = match krate.src(tcx) {
            FileName::Real(ref p) => {
                match p
                    .local_path()
                    .unwrap_or(p.path(RemapPathScopeComponents::DOCUMENTATION))
                    .parent()
                {
                    Some(p) => p.to_path_buf(),
                    None => PathBuf::new(),
                }
            }
            _ => PathBuf::new(),
        };
        // If user passed in `--playground-url` arg, we fill in crate name here
        let mut playground = None;
        if let Some(url) = playground_url {
            playground = Some(markdown::Playground { crate_name: Some(krate.name(tcx)), url });
        }
        let krate_version = cache.crate_version.as_deref().unwrap_or_default();
        let mut layout = layout::Layout {
            logo: String::new(),
            favicon: String::new(),
            external_html,
            default_settings,
            krate: krate.name(tcx).to_string(),
            krate_version: krate_version.to_string(),
            css_file_extension: extension_css,
            scrape_examples_extension: !call_locations.is_empty(),
        };
        let mut issue_tracker_base_url = None;
        let mut include_sources = !html_no_source;

        // Crawl the crate attributes looking for attributes which control how we're
        // going to emit HTML
        for attr in &krate.module.attrs.other_attrs {
            let Attribute::Parsed(AttributeKind::Doc(d)) = attr else { continue };
            if let Some((html_favicon_url, _)) = d.html_favicon_url {
                layout.favicon = html_favicon_url.to_string();
            }
            if let Some((html_logo_url, _)) = d.html_logo_url {
                layout.logo = html_logo_url.to_string();
            }
            if let Some((html_playground_url, _)) = d.html_playground_url {
                playground = Some(markdown::Playground {
                    crate_name: Some(krate.name(tcx)),
                    url: html_playground_url.to_string(),
                });
            }
            if let Some((s, _)) = d.issue_tracker_base_url {
                issue_tracker_base_url = Some(s.to_string());
            }
            if d.html_no_source.is_some() {
                include_sources = false;
            }
        }

        let (local_sources, matches) = collect_spans_and_sources(
            tcx,
            &krate,
            &src_root,
            include_sources,
            generate_link_to_definition,
        );

        let (sender, receiver) = channel();
        let scx = SharedContext {
            tcx,
            src_root,
            local_sources,
            issue_tracker_base_url,
            layout,
            created_dirs: Default::default(),
            module_sorting,
            style_files,
            resource_suffix,
            static_root_path,
            fs: DocFS::new(sender),
            codes: ErrorCodes::from(options.unstable_features.is_nightly_build()),
            playground,
            all: RefCell::new(AllTypes::new()),
            errors: receiver,
            redirections: if generate_redirect_map { Some(Default::default()) } else { None },
            show_type_layout,
            span_correspondence_map: matches,
            cache,
            call_locations,
            expanded_codes,
        };

        let dst = output;
        scx.ensure_dir(&dst)?;

        let mut cx = Context {
            current: Vec::new(),
            dst,
            id_map: RefCell::new(id_map),
            deref_id_map: Default::default(),
            shared: scx,
            types_with_notable_traits: RefCell::new(FxIndexSet::default()),
            info: ContextInfo::new(include_sources),
        };

        if emit.contains(&EmitType::HtmlNonStaticFiles) {
            sources::render(&mut cx, &krate)?;
        }

        if !no_emit_shared {
            write_shared(&mut cx, &krate, &md_opts, tcx)?;
        }

        Ok((cx, krate))
    }
}

/// Generates the documentation for `crate` into the directory `dst`
impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
    const DESCR: &'static str = "html";
    const RUN_ON_MODULE: bool = true;
    const NON_STATIC_FILE_EMIT_TYPE: EmitType = EmitType::HtmlNonStaticFiles;

    type ModuleData = ContextInfo;

    fn save_module_data(&mut self) -> Self::ModuleData {
        self.deref_id_map.borrow_mut().clear();
        self.id_map.borrow_mut().clear();
        self.types_with_notable_traits.borrow_mut().clear();
        self.info
    }

    fn restore_module_data(&mut self, info: Self::ModuleData) {
        self.info = info;
    }

    fn after_krate(mut self) -> Result<(), Error> {
        let crate_name = self.tcx().crate_name(LOCAL_CRATE);
        let final_file = self.dst.join(crate_name.as_str()).join("all.html");

        let shared = &self.shared;
        let page = layout::Page {
            title: "List of all items in this crate",
            short_title: "All",
            css_class: "mod sys",
            root_path: "../",
            static_root_path: shared.static_root_path.as_deref(),
            description: "List of all items in this crate",
            resource_suffix: &shared.resource_suffix,
            rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), |d| d.rust_logo.is_some()),
        };
        let all = shared.all.replace(AllTypes::new());
        let mut sidebar = String::new();

        // all.html is not customizable, so a blank id map is fine
        let blocks = sidebar_module_like(all.item_sections(), &mut IdMap::new(), ModuleLike::Crate);
        let bar = Sidebar {
            title_prefix: "",
            title: "",
            is_crate: false,
            is_mod: false,
            parent_is_crate: false,
            blocks: vec![blocks],
            path: String::new(),
        };

        bar.render_into(&mut sidebar).unwrap();

        let v = layout::render(&shared.layout, &page, sidebar, all.print(), &shared.style_files);
        shared.fs.write(final_file, v)?;

        if let Some(ref redirections) = shared.redirections
            && !redirections.borrow().is_empty()
        {
            let redirect_map_path = self.dst.join(crate_name.as_str()).join("redirect-map.json");
            let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
            shared.ensure_dir(&self.dst.join(crate_name.as_str()))?;
            shared.fs.write(redirect_map_path, paths)?;
        }

        // Flush pending errors.
        self.shared.fs.close();
        let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count();
        if nb_errors > 0 { Err(Error::new(io::Error::other("I/O error"), "")) } else { Ok(()) }
    }

    fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
        // Stripped modules survive the rustdoc passes (i.e., `strip-private`)
        // if they contain impls for public types. These modules can also
        // contain items such as publicly re-exported structures.
        //
        // External crates will provide links to these structures, so
        // these modules are recursed into, but not rendered normally
        // (a flag on the context).
        if !self.info.render_redirect_pages {
            self.info.render_redirect_pages = item.is_stripped();
        }
        let item_name = item.name.unwrap();
        self.dst.push(item_name.as_str());
        self.current.push(item_name);

        info!("Recursing into {}", self.dst.display());

        if !item.is_stripped() {
            let buf = self.render_item(item, true);
            // buf will be empty if the module is stripped and there is no redirect for it
            if !buf.is_empty() {
                self.shared.ensure_dir(&self.dst)?;
                let joint_dst = self.dst.join("index.html");
                self.shared.fs.write(joint_dst, buf)?;
            }
        }
        if !self.info.is_inside_inlined_module {
            if let Some(def_id) = item.def_id()
                && self.cache().inlined_items.contains(&def_id)
            {
                self.info.is_inside_inlined_module = true;
            }
        } else if !self.cache().document_hidden && item.is_doc_hidden() {
            // We're not inside an inlined module anymore since this one cannot be re-exported.
            self.info.is_inside_inlined_module = false;
        }

        // Render sidebar-items.js used throughout this module.
        if !self.info.render_redirect_pages {
            let (clean::StrippedItem(clean::ModuleItem(ref module))
            | clean::ModuleItem(ref module)) = item.kind
            else {
                unreachable!()
            };
            let items = self.build_sidebar_items(module);
            let js_dst = self.dst.join(format!("sidebar-items{}.js", self.shared.resource_suffix));
            let v = format!("window.SIDEBAR_ITEMS = {};", serde_json::to_string(&items).unwrap());
            self.shared.fs.write(js_dst, v)?;
        }
        Ok(())
    }

    fn mod_item_out(&mut self) -> Result<(), Error> {
        info!("Recursed; leaving {}", self.dst.display());

        // Go back to where we were at
        self.dst.pop();
        self.current.pop();
        Ok(())
    }

    fn item(&mut self, item: &clean::Item) -> Result<(), Error> {
        // Stripped modules survive the rustdoc passes (i.e., `strip-private`)
        // if they contain impls for public types. These modules can also
        // contain items such as publicly re-exported structures.
        //
        // External crates will provide links to these structures, so
        // these modules are recursed into, but not rendered normally
        // (a flag on the context).
        if !self.info.render_redirect_pages {
            self.info.render_redirect_pages = item.is_stripped();
        }

        let buf = self.render_item(item, false);
        // buf will be empty if the item is stripped and there is no redirect for it
        if !buf.is_empty() {
            if !self.info.render_redirect_pages {
                self.shared.all.borrow_mut().append(full_path(self, item), &item);
            }

            let file_name = print_item_path(item).to_string();
            self.shared.ensure_dir(&self.dst)?;
            let joint_dst = self.dst.join(&file_name);
            self.shared.fs.write(joint_dst, buf)?;
            // If the item is a macro, redirect from the old macro URL (with !)
            // to the new one (without).
            let item_type = item.type_();
            if item_type == ItemType::Macro {
                let name = item.name.as_ref().unwrap();
                let redir_name = format!("{item_type}.{name}!.html");
                if let Some(ref redirections) = self.shared.redirections {
                    let crate_name = &self.shared.layout.krate;
                    redirections.borrow_mut().insert(
                        format!("{crate_name}/{redir_name}"),
                        format!("{crate_name}/{file_name}"),
                    );
                } else {
                    let v = layout::redirect(&file_name);
                    let redir_dst = self.dst.join(redir_name);
                    self.shared.fs.write(redir_dst, v)?;
                }
            }
        }

        Ok(())
    }
}
