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::def_id::{DefIdMap, LOCAL_CRATE};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::edition::Edition;
use rustc_span::{BytePos, FileName, Symbol, sym};
use tracing::info;

use super::print_item::{full_path, print_item, print_item_path};
use super::sidebar::{ModuleLike, Sidebar, print_sidebar, sidebar_module_like};
use super::{AllTypes, LinkFromSrc, StylePath, collect_spans_and_sources, scrape_examples_help};
use crate::clean::types::ExternalLocation;
use crate::clean::utils::has_doc_flag;
use crate::clean::{self, ExternalCrate};
use crate::config::{ModuleSorting, RenderOptions, ShouldMerge};
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::url_parts_builder::UrlPartsBuilder;
use crate::html::{layout, sources, static_files};
use crate::scrape_examples::AllCallLocations;
use crate::{DOC_RUST_LANG_ORG_VERSION, 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<rustc_span::Span, LinkFromSrc>,
    pub(crate) expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
    /// The [`Cache`] used during rendering.
    pub(crate) cache: Cache,
    pub(crate) call_locations: AllCallLocations,
    /// Controls whether we read / write to cci files in the doc root. Defaults read=true,
    /// write=true
    should_merge: ShouldMerge,
}

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()
    }
}

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;
        }
        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()
        };

        if !render_redirect_pages {
            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(), sym::rust_logo),
            };
            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_item_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_item_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<String>> {
        // 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 short = item.type_();
            let myname = match item.name {
                None => continue,
                Some(s) => s,
            };
            if inserted.entry(short).or_default().insert(myname) {
                let short = short.to_string();
                let myname = myname.to_string();
                map.entry(short).or_default().push(myname);
            }
        }

        match self.shared.module_sorting {
            ModuleSorting::Alphabetical => {
                for items in map.values_mut() {
                    items.sort();
                }
            }
            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_if_available().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 s) => {
                    root = s.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 emit_crate = options.should_emit_crate();
        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,
            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_if_available().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.lists(sym::doc) {
            match (attr.name(), attr.value_str()) {
                (Some(sym::html_favicon_url), Some(s)) => {
                    layout.favicon = s.to_string();
                }
                (Some(sym::html_logo_url), Some(s)) => {
                    layout.logo = s.to_string();
                }
                (Some(sym::html_playground_url), Some(s)) => {
                    playground = Some(markdown::Playground {
                        crate_name: Some(krate.name(tcx)),
                        url: s.to_string(),
                    });
                }
                (Some(sym::issue_tracker_base_url), Some(s)) => {
                    issue_tracker_base_url = Some(s.to_string());
                }
                (Some(sym::html_no_source), None) if attr.is_word() => {
                    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,
            should_merge: options.should_merge,
            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_crate {
            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> {
    fn descr() -> &'static str {
        "html"
    }

    const RUN_ON_MODULE: bool = true;
    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 settings_file = self.dst.join("settings.html");
        let help_file = self.dst.join("help.html");
        let scrape_examples_help_file = self.dst.join("scrape-examples-help.html");

        let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
        if !root_path.ends_with('/') {
            root_path.push('/');
        }
        let shared = &self.shared;
        let mut 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(), sym::rust_logo),
        };
        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 to avoid writing help, settings files to doc root unless we're on the final invocation
        if shared.should_merge.write_rendered_cci {
            // Generating settings page.
            page.title = "Settings";
            page.description = "Settings of Rustdoc";
            page.root_path = "./";
            page.rust_logo = true;

            let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
            let v = layout::render(
                &shared.layout,
                &page,
                sidebar,
                fmt::from_fn(|buf| {
                    write!(
                        buf,
                        "<div class=\"main-heading\">\
                         <h1>Rustdoc settings</h1>\
                         <span class=\"out-of-band\">\
                             <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
                                Back\
                            </a>\
                         </span>\
                         </div>\
                         <noscript>\
                            <section>\
                                You need to enable JavaScript be able to update your settings.\
                            </section>\
                         </noscript>\
                         <script defer src=\"{static_root_path}{settings_js}\"></script>",
                        static_root_path = page.get_static_root_path(),
                        settings_js = static_files::STATIC_FILES.settings_js,
                    )?;
                    // Pre-load all theme CSS files, so that switching feels seamless.
                    //
                    // When loading settings.html as a popover, the equivalent HTML is
                    // generated in main.js.
                    for file in &shared.style_files {
                        if let Ok(theme) = file.basename() {
                            write!(
                                buf,
                                "<link rel=\"preload\" href=\"{root_path}{theme}{suffix}.css\" \
                                    as=\"style\">",
                                root_path = page.static_root_path.unwrap_or(""),
                                suffix = page.resource_suffix,
                            )?;
                        }
                    }
                    Ok(())
                }),
                &shared.style_files,
            );
            shared.fs.write(settings_file, v)?;

            // Generating help page.
            page.title = "Help";
            page.description = "Documentation for Rustdoc";
            page.root_path = "./";
            page.rust_logo = true;

            let sidebar = "<h2 class=\"location\">Help</h2><div class=\"sidebar-elems\"></div>";
            let v = layout::render(
                &shared.layout,
                &page,
                sidebar,
                format_args!(
                    "<div class=\"main-heading\">\
                        <h1>Rustdoc help</h1>\
                        <span class=\"out-of-band\">\
                            <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
                            Back\
                        </a>\
                        </span>\
                        </div>\
                        <noscript>\
                        <section>\
                            <p>You need to enable JavaScript to use keyboard commands or search.</p>\
                            <p>For more information, browse the <a href=\"{DOC_RUST_LANG_ORG_VERSION}/rustdoc/\">rustdoc handbook</a>.</p>\
                        </section>\
                        </noscript>",
                ),
                &shared.style_files,
            );
            shared.fs.write(help_file, v)?;
        }

        // if to avoid writing files to doc root unless we're on the final invocation
        if shared.layout.scrape_examples_extension && shared.should_merge.write_rendered_cci {
            page.title = "About scraped examples";
            page.description = "How the scraped examples feature works in Rustdoc";
            let v = layout::render(
                &shared.layout,
                &page,
                "",
                scrape_examples_help(shared),
                &shared.style_files,
            );
            shared.fs.write(scrape_examples_help_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(box 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() {
            let name = item.name.as_ref().unwrap();
            let item_type = item.type_();
            let file_name = print_item_path(item_type, name.as_str()).to_string();
            self.shared.ensure_dir(&self.dst)?;
            let joint_dst = self.dst.join(&file_name);
            self.shared.fs.write(joint_dst, buf)?;

            if !self.info.render_redirect_pages {
                self.shared.all.borrow_mut().append(full_path(self, item), &item_type);
            }
            // If the item is a macro, redirect from the old macro URL (with !)
            // to the new one (without).
            if item_type == ItemType::Macro {
                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(())
    }
}
