diff options
Diffstat (limited to 'src/librustdoc/html')
| -rw-r--r-- | src/librustdoc/html/format.rs | 35 | ||||
| -rw-r--r-- | src/librustdoc/html/highlight.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/html/layout.rs | 1 | ||||
| -rw-r--r-- | src/librustdoc/html/markdown.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/html/render/context.rs | 88 | ||||
| -rw-r--r-- | src/librustdoc/html/render/mod.rs | 56 | ||||
| -rw-r--r-- | src/librustdoc/html/render/ordered_json.rs | 2 | ||||
| -rw-r--r-- | src/librustdoc/html/render/print_item.rs | 92 | ||||
| -rw-r--r-- | src/librustdoc/html/render/search_index.rs | 16 | ||||
| -rw-r--r-- | src/librustdoc/html/render/sidebar.rs | 2 | ||||
| -rw-r--r-- | src/librustdoc/html/render/sorted_template.rs | 3 | ||||
| -rw-r--r-- | src/librustdoc/html/render/write_shared.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/html/static/js/rustdoc.d.ts | 7 | ||||
| -rw-r--r-- | src/librustdoc/html/static/js/search.js | 150 | ||||
| -rw-r--r-- | src/librustdoc/html/url_parts_builder.rs | 12 |
15 files changed, 226 insertions, 250 deletions
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index bcb3e57c844..be8a2d511e9 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -14,6 +14,7 @@ use std::slice; use itertools::{Either, Itertools}; use rustc_abi::ExternAbi; +use rustc_ast::join_path_syms; use rustc_attr_data_structures::{ConstStability, StabilityLevel, StableSince}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; @@ -25,7 +26,7 @@ use rustc_span::symbol::kw; use rustc_span::{Symbol, sym}; use tracing::{debug, trace}; -use super::url_parts_builder::{UrlPartsBuilder, estimate_item_path_byte_length}; +use super::url_parts_builder::UrlPartsBuilder; use crate::clean::types::ExternalLocation; use crate::clean::utils::find_nearest_parent_module; use crate::clean::{self, ExternalCrate, PrimitiveType}; @@ -113,9 +114,9 @@ impl clean::Generics { let real_params = fmt::from_fn(|f| real_params.clone().map(|g| g.print(cx)).joined(", ", f)); if f.alternate() { - write!(f, "<{:#}>", real_params) + write!(f, "<{real_params:#}>") } else { - write!(f, "<{}>", real_params) + write!(f, "<{real_params}>") } }) } @@ -369,18 +370,6 @@ pub(crate) enum HrefError { NotInExternalCache, } -// Panics if `syms` is empty. -pub(crate) fn join_with_double_colon(syms: &[Symbol]) -> String { - let mut s = String::with_capacity(estimate_item_path_byte_length(syms.len())); - // NOTE: using `Joined::joined` here causes a noticeable perf regression - s.push_str(syms[0].as_str()); - for sym in &syms[1..] { - s.push_str("::"); - s.push_str(sym.as_str()); - } - s -} - /// This function is to get the external macro path because they are not in the cache used in /// `href_with_root_path`. fn generate_macro_def_id_path( @@ -605,7 +594,7 @@ pub(crate) fn href_with_root_path( } } }; - let url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote); + let url_parts = make_href(root_path, shortty, url_parts, fqp, is_remote); Ok((url_parts, shortty, fqp.clone())) } @@ -672,7 +661,7 @@ pub(crate) fn link_tooltip( write!(f, "{}", cx.tcx().item_name(id))?; } else if !fqp.is_empty() { write!(f, "{shortty} ")?; - fqp.iter().joined("::", f)?; + write!(f, "{}", join_path_syms(fqp))?; } Ok(()) }) @@ -703,7 +692,7 @@ fn resolved_path( write!( f, "{path}::{anchor}", - path = join_with_double_colon(&fqp[..fqp.len() - 1]), + path = join_path_syms(&fqp[..fqp.len() - 1]), anchor = print_anchor(did, *fqp.last().unwrap(), cx) ) } else { @@ -835,7 +824,7 @@ pub(crate) fn print_anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl D write!( f, r#"<a class="{short_ty}" href="{url}" title="{short_ty} {path}">{text}</a>"#, - path = join_with_double_colon(&fqp), + path = join_path_syms(fqp), text = EscapeBodyText(text.as_str()), ) } else { @@ -1095,7 +1084,7 @@ impl clean::QPathData { title=\"type {path}::{name}\">{name}</a>", shortty = ItemType::AssocType, name = assoc.name, - path = join_with_double_colon(&path), + path = join_path_syms(path), ) } else { write!(f, "{}", assoc.name) @@ -1126,7 +1115,7 @@ impl clean::Impl { { let last = ty.last(); if f.alternate() { - write!(f, "{}<", last)?; + write!(f, "{last}<")?; self.print_type(inner_type, f, use_absolute, cx)?; write!(f, ">")?; } else { @@ -1230,7 +1219,7 @@ pub(crate) fn print_params(params: &[clean::Parameter], cx: &Context<'_>) -> imp .map(|param| { fmt::from_fn(|f| { if let Some(name) = param.name { - write!(f, "{}: ", name)?; + write!(f, "{name}: ")?; } param.type_.print(cx).fmt(f) }) @@ -1352,7 +1341,7 @@ impl clean::FnDecl { write!(f, "const ")?; } if let Some(name) = param.name { - write!(f, "{}: ", name)?; + write!(f, "{name}: ")?; } param.type_.print(cx).fmt(f)?; } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index b2feee36c93..272180fb990 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -547,7 +547,7 @@ impl<'a> Iterator for TokenIter<'a> { fn get_real_ident_class(text: &str, allow_path_keywords: bool) -> Option<Class> { let ignore: &[&str] = if allow_path_keywords { &["self", "Self", "super", "crate"] } else { &["self", "Self"] }; - if ignore.iter().any(|k| *k == text) { + if ignore.contains(&text) { return None; } Some(match text { @@ -1159,7 +1159,7 @@ fn string_without_closing_tag<T: Display>( return Some("</a>"); } if !open_tag { - write!(out, "{}", text_s).unwrap(); + out.write_str(&text_s).unwrap(); return None; } let klass_s = klass.as_html(); diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 50320cb231d..1f92c521d46 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -132,6 +132,5 @@ pub(crate) fn redirect(url: &str) -> String { <script>location.replace("{url}" + location.search + location.hash);</script> </body> </html>"##, - url = url, ) } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index e41435de29c..4addf2c3c96 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -251,7 +251,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> { if !parse_result.rust { let added_classes = parse_result.added_classes; let lang_string = if let Some(lang) = parse_result.unknown.first() { - format!("language-{}", lang) + format!("language-{lang}") } else { String::new() }; @@ -999,7 +999,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { if let Some((_, c)) = self.inner.next() { if c != '=' { - self.emit_error(format!("expected `=`, found `{}`", c)); + self.emit_error(format!("expected `=`, found `{c}`")); return None; } } else { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 3b4dae841ee..5ceb1fc988d 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -6,6 +6,7 @@ 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; @@ -27,7 +28,6 @@ use crate::formats::FormatRenderer; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; -use crate::html::format::join_with_double_colon; 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; @@ -193,14 +193,12 @@ impl<'tcx> Context<'tcx> { 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)) { - if 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; - } + // 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 { @@ -211,7 +209,7 @@ impl<'tcx> Context<'tcx> { title.push_str(" in "); } // No need to include the namespace for primitive types and keywords - title.push_str(&join_with_double_colon(&self.current)); + title.push_str(&join_path_syms(&self.current)); }; title.push_str(" - Rust"); let tyname = it.type_(); @@ -254,40 +252,36 @@ impl<'tcx> Context<'tcx> { &self.shared.style_files, ) } else { - if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) { - if 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() - )); + 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())); } } } @@ -762,11 +756,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // 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::new(io::ErrorKind::Other, "I/O error"), "")) - } else { - Ok(()) - } + 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> { @@ -842,7 +832,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { self.info.render_redirect_pages = item.is_stripped(); } - let buf = self.render_item(&item, false); + 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(); @@ -853,7 +843,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { 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); + 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). diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 70f3f54e4c0..872dbbcd19e 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -49,6 +49,7 @@ use std::{fs, str}; use askama::Template; use itertools::Either; +use rustc_ast::join_path_syms; use rustc_attr_data_structures::{ ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince, }; @@ -74,9 +75,9 @@ use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; use crate::html::format::{ - Ending, HrefError, PrintWithSpace, href, join_with_double_colon, print_abi_with_space, - print_constness_with_space, print_default_space, print_generic_bounds, print_where_clause, - visibility_print_with_space, write_str, + Ending, HrefError, PrintWithSpace, href, print_abi_with_space, print_constness_with_space, + print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space, + write_str, }; use crate::html::markdown::{ HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine, @@ -1109,7 +1110,7 @@ fn since_to_string(since: &StableSince) -> Option<String> { match since { StableSince::Version(since) => Some(since.to_string()), StableSince::Current => Some(RustcVersion::CURRENT.to_string()), - StableSince::Err => None, + StableSince::Err(_) => None, } } @@ -1191,7 +1192,7 @@ fn render_assoc_item( // a whitespace prefix and newline. fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display { fmt::from_fn(move |f| { - for a in it.attributes(cx.tcx(), cx.cache(), false) { + for a in it.attributes(cx.tcx(), cx.cache()) { writeln!(f, "{prefix}{a}")?; } Ok(()) @@ -1207,7 +1208,7 @@ fn render_code_attribute(code_attr: CodeAttribute, w: &mut impl fmt::Write) { // When an attribute is rendered inside a <code> tag, it is formatted using // a div to produce a newline after it. fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) { - for attr in it.attributes(cx.tcx(), cx.cache(), false) { + for attr in it.attributes(cx.tcx(), cx.cache()) { render_code_attribute(CodeAttribute(attr), w); } } @@ -1219,7 +1220,7 @@ fn render_repr_attributes_in_code( def_id: DefId, item_type: ItemType, ) { - if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type, false) { + if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) { render_code_attribute(CodeAttribute(repr), w); } } @@ -1482,10 +1483,10 @@ fn render_deref_methods( } } render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); - } else if let Some(prim) = target.primitive_type() { - if let Some(&did) = cache.primitive_locations.get(&prim) { - render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); - } + } else if let Some(prim) = target.primitive_type() + && let Some(&did) = cache.primitive_locations.get(&prim) + { + render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); } } @@ -2057,21 +2058,20 @@ fn render_impl( // default items which weren't overridden in the implementation block. // We don't emit documentation for default items if they appear in the // Implementations on Foreign Types or Implementors sections. - if rendering_params.show_default_items { - if let Some(t) = trait_ - && !impl_.is_negative_trait_impl() - { - render_default_items( - &mut default_impl_items, - &mut impl_items, - cx, - t, - impl_, - &i.impl_item, - render_mode, - rendering_params, - )?; - } + if rendering_params.show_default_items + && let Some(t) = trait_ + && !impl_.is_negative_trait_impl() + { + render_default_items( + &mut default_impl_items, + &mut impl_items, + cx, + t, + impl_, + &i.impl_item, + render_mode, + rendering_params, + )?; } if render_mode == RenderMode::Normal { let toggled = !(impl_items.is_empty() && default_impl_items.is_empty()); @@ -2555,7 +2555,7 @@ fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec<String> let fqp = cache.exact_paths.get(&did).or_else(get_extern); if let Some(path) = fqp { - out.push(join_with_double_colon(path)); + out.push(join_path_syms(path)); } }; @@ -2569,7 +2569,7 @@ fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec<String> match ty { clean::Type::Path { path } => process_path(path.def_id()), clean::Type::Tuple(tys) => { - work.extend(tys.into_iter()); + work.extend(tys.iter()); } clean::Type::Slice(ty) => { work.push_back(ty); diff --git a/src/librustdoc/html/render/ordered_json.rs b/src/librustdoc/html/render/ordered_json.rs index d1dddfebc83..be51dad1c2b 100644 --- a/src/librustdoc/html/render/ordered_json.rs +++ b/src/librustdoc/html/render/ordered_json.rs @@ -25,7 +25,7 @@ impl OrderedJson { .into_iter() .sorted_unstable_by(|a, b| a.borrow().cmp(b.borrow())) .format_with(",", |item, f| f(item.borrow())); - Self(format!("[{}]", items)) + Self(format!("[{items}]")) } pub(crate) fn array_unsorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I) -> Self { diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index e33bdc0db32..02ee34aaac6 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -4,6 +4,7 @@ use std::iter; use askama::Template; use rustc_abi::VariantIdx; +use rustc_ast::join_path_syms; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; @@ -30,8 +31,8 @@ use crate::formats::Impl; use crate::formats::item_type::ItemType; use crate::html::escape::{Escape, EscapeBodyTextWithWbr}; use crate::html::format::{ - Ending, PrintWithSpace, join_with_double_colon, print_abi_with_space, - print_constness_with_space, print_where_clause, visibility_print_with_space, + Ending, PrintWithSpace, print_abi_with_space, print_constness_with_space, print_where_clause, + visibility_print_with_space, }; use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use crate::html::render::{document_full, document_item_info}; @@ -1424,7 +1425,7 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> iter::repeat_n("..", cx.current.len()).chain(iter::once("type.impl")).collect(); js_src_path.extend(target_fqp[..target_fqp.len() - 1].iter().copied()); js_src_path.push_fmt(format_args!("{target_type}.{}.js", target_fqp.last().unwrap())); - let self_path = fmt::from_fn(|f| self_fqp.iter().joined("::", f)); + let self_path = join_path_syms(self_fqp); write!( w, "<script src=\"{src}\" data-self-path=\"{self_path}\" async></script>", @@ -1450,7 +1451,7 @@ item_template!( impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { fn render_union(&self) -> impl Display { - render_union(self.it, Some(&self.generics), &self.fields, self.cx) + render_union(self.it, Some(self.generics), self.fields, self.cx) } fn document_field(&self, field: &'a clean::Item) -> impl Display { @@ -1487,12 +1488,11 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { self.cx.cache(), self.def_id, ItemType::Union, - false, ) { writeln!(f, "{repr}")?; }; } else { - for a in self.it.attributes(self.cx.tcx(), self.cx.cache(), false) { + for a in self.it.attributes(self.cx.tcx(), self.cx.cache()) { writeln!(f, "{a}")?; } } @@ -1982,16 +1982,14 @@ fn item_constant( w.write_str(";")?; } - if !is_literal { - if let Some(value) = &value { - let value_lowercase = value.to_lowercase(); - let expr_lowercase = expr.to_lowercase(); + if !is_literal && let Some(value) = &value { + let value_lowercase = value.to_lowercase(); + let expr_lowercase = expr.to_lowercase(); - if value_lowercase != expr_lowercase - && value_lowercase.trim_end_matches("i32") != expr_lowercase - { - write!(w, " // {value}", value = Escape(value))?; - } + if value_lowercase != expr_lowercase + && value_lowercase.trim_end_matches("i32") != expr_lowercase + { + write!(w, " // {value}", value = Escape(value))?; } } Ok::<(), fmt::Error>(()) @@ -2071,41 +2069,39 @@ fn item_fields( _ => None, }) .peekable(); - if let None | Some(CtorKind::Fn) = ctor_kind { - if fields.peek().is_some() { - let title = format!( - "{}{}", - if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, - document_non_exhaustive_header(it), - ); + if let None | Some(CtorKind::Fn) = ctor_kind + && fields.peek().is_some() + { + let title = format!( + "{}{}", + if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, + document_non_exhaustive_header(it), + ); + write!( + w, + "{}", + write_section_heading( + &title, + "fields", + Some("fields"), + document_non_exhaustive(it) + ) + )?; + for (index, (field, ty)) in fields.enumerate() { + let field_name = + field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); + let id = cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField)); write!( w, - "{}", - write_section_heading( - &title, - "fields", - Some("fields"), - document_non_exhaustive(it) - ) + "<span id=\"{id}\" class=\"{item_type} section-header\">\ + <a href=\"#{id}\" class=\"anchor field\">§</a>\ + <code>{field_name}: {ty}</code>\ + </span>\ + {doc}", + item_type = ItemType::StructField, + ty = ty.print(cx), + doc = document(cx, field, Some(it), HeadingOffset::H3), )?; - for (index, (field, ty)) in fields.enumerate() { - let field_name = field - .name - .map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); - let id = - cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField)); - write!( - w, - "<span id=\"{id}\" class=\"{item_type} section-header\">\ - <a href=\"#{id}\" class=\"anchor field\">§</a>\ - <code>{field_name}: {ty}</code>\ - </span>\ - {doc}", - item_type = ItemType::StructField, - ty = ty.print(cx), - doc = document(cx, field, Some(it), HeadingOffset::H3), - )?; - } } } Ok(()) @@ -2257,7 +2253,7 @@ pub(crate) fn compare_names(left: &str, right: &str) -> Ordering { } pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String { - let mut s = join_with_double_colon(&cx.current); + let mut s = join_path_syms(&cx.current); s.push_str("::"); s.push_str(item.name.unwrap().as_str()); s diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index aff8684ee3a..3c9be29ccc3 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -4,6 +4,7 @@ use std::collections::hash_map::Entry; use std::collections::{BTreeMap, VecDeque}; use encode::{bitmap_to_string, write_vlqhex_to_string}; +use rustc_ast::join_path_syms; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; @@ -17,7 +18,6 @@ use crate::clean::types::{Function, Generics, ItemId, Type, WherePredicate}; use crate::clean::{self, utils}; use crate::formats::cache::{Cache, OrphanImplItem}; use crate::formats::item_type::ItemType; -use crate::html::format::join_with_double_colon; use crate::html::markdown::short_markdown_summary; use crate::html::render::ordered_json::OrderedJson; use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, RenderTypeId}; @@ -78,7 +78,7 @@ pub(crate) fn build_index( ty: item.type_(), defid: item.item_id.as_def_id(), name: item.name.unwrap(), - path: join_with_double_colon(&fqp[..fqp.len() - 1]), + path: join_path_syms(&fqp[..fqp.len() - 1]), desc, parent: Some(parent), parent_idx: None, @@ -116,7 +116,7 @@ pub(crate) fn build_index( // Set up alias indexes. for (i, item) in cache.search_index.iter().enumerate() { for alias in &item.aliases[..] { - aliases.entry(alias.as_str().to_lowercase()).or_default().push(i); + aliases.entry(alias.to_string()).or_default().push(i); } } @@ -416,7 +416,7 @@ pub(crate) fn build_index( if fqp.len() < 2 { return None; } - join_with_double_colon(&fqp[..fqp.len() - 1]) + join_path_syms(&fqp[..fqp.len() - 1]) }; if path == item.path { return None; @@ -427,10 +427,10 @@ pub(crate) fn build_index( let i = <isize as TryInto<usize>>::try_into(parent_idx).unwrap(); item.path = { let p = &crate_paths[i].1; - join_with_double_colon(&p[..p.len() - 1]) + join_path_syms(&p[..p.len() - 1]) }; item.exact_path = - crate_paths[i].2.as_ref().map(|xp| join_with_double_colon(&xp[..xp.len() - 1])); + crate_paths[i].2.as_ref().map(|xp| join_path_syms(&xp[..xp.len() - 1])); } // Omit the parent path if it is same to that of the prior item. @@ -549,11 +549,11 @@ pub(crate) fn build_index( }); continue; } - let full_path = join_with_double_colon(&path[..path.len() - 1]); + let full_path = join_path_syms(&path[..path.len() - 1]); let full_exact_path = exact .as_ref() .filter(|exact| exact.last() == path.last() && exact.len() >= 2) - .map(|exact| join_with_double_colon(&exact[..exact.len() - 1])); + .map(|exact| join_path_syms(&exact[..exact.len() - 1])); let exact_path = extra_paths.len() + self.items.len(); let exact_path = full_exact_path.as_ref().map(|full_exact_path| match extra_paths .entry(full_exact_path.clone()) diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 91540e06e33..b9f5ada417c 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -541,7 +541,7 @@ fn sidebar_deref_methods<'a>( .iter() .filter(|i| { i.inner_impl().trait_.is_none() - && real_target.is_doc_subtype_of(&i.inner_impl().for_, &c) + && real_target.is_doc_subtype_of(&i.inner_impl().for_, c) }) .flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx())) .collect::<Vec<_>>(); diff --git a/src/librustdoc/html/render/sorted_template.rs b/src/librustdoc/html/render/sorted_template.rs index a7b954ab70b..659c5e6093b 100644 --- a/src/librustdoc/html/render/sorted_template.rs +++ b/src/librustdoc/html/render/sorted_template.rs @@ -63,7 +63,8 @@ impl<F: FileFormat> fmt::Display for SortedTemplate<F> { for (p, fragment) in self.fragments.iter().with_position() { let mut f = DeltaWriter { inner: &mut f, delta: 0 }; let sep = if matches!(p, Position::First | Position::Only) { "" } else { F::SEPARATOR }; - write!(f, "{}{}", sep, fragment)?; + f.write_str(sep)?; + f.write_str(fragment)?; fragment_lengths.push(f.delta); } let offset = Offset { start: self.before.len(), fragment_lengths }; diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 0078671fcc5..1f691392b17 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -26,6 +26,7 @@ use std::{fmt, fs}; use indexmap::IndexMap; use regex::Regex; +use rustc_ast::join_path_syms; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_middle::ty::TyCtxt; @@ -43,7 +44,6 @@ use crate::docfs::PathError; use crate::error::Error; use crate::formats::Impl; use crate::formats::item_type::ItemType; -use crate::html::format::join_with_double_colon; use crate::html::layout; use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; use crate::html::render::search_index::{SerializedSearchIndex, build_index}; @@ -608,7 +608,7 @@ impl TypeAliasPart { for &(type_alias_fqp, type_alias_item) in type_aliases { cx.id_map.borrow_mut().clear(); cx.deref_id_map.borrow_mut().clear(); - let type_alias_fqp = join_with_double_colon(&type_alias_fqp); + let type_alias_fqp = join_path_syms(type_alias_fqp); if let Some(ret) = &mut ret { ret.aliases.push(type_alias_fqp); } else { diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index ca2512e5ab6..a9589764547 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -219,6 +219,8 @@ declare namespace rustdoc { crate: string, descShard: SearchDescShard, id: number, + // This is the name of the item. For doc aliases, if you want the name of the aliased + // item, take a look at `Row.original.name`. name: string, normalizedName: string, word: string, @@ -227,6 +229,11 @@ declare namespace rustdoc { path: string, ty: number, type: FunctionSearchType | null, + descIndex: number, + bitIndex: number, + implDisambiguator: String | null, + is_alias?: boolean, + original?: Row, } /** diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 15cad31f555..2caf214ff73 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -830,7 +830,7 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) { */ function makePrimitiveElement(name, extra) { return Object.assign({ - name: name, + name, id: null, fullPath: [name], pathWithoutLast: [], @@ -1483,6 +1483,7 @@ class DocSearch { */ this.assocTypeIdNameMap = new Map(); this.ALIASES = new Map(); + this.FOUND_ALIASES = new Set(); this.rootPath = rootPath; this.searchState = searchState; @@ -2030,6 +2031,8 @@ class DocSearch { // normalized names, type signature objects and fingerprints, and aliases. id = 0; + /** @type {Array<[string, { [key: string]: Array<number> }, number]>} */ + const allAliases = []; for (const [crate, crateCorpus] of rawSearchIndex) { // a string representing the lengths of each description shard // a string representing the list of function types @@ -2178,10 +2181,10 @@ class DocSearch { paths[i] = { ty, name, path, exactPath, unboxFlag }; } - // convert `item*` into an object form, and construct word indices. + // Convert `item*` into an object form, and construct word indices. // - // before any analysis is performed lets gather the search terms to - // search against apart from the rest of the data. This is a quick + // Before any analysis is performed, let's gather the search terms to + // search against apart from the rest of the data. This is a quick // operation that is cached for the life of the page state so that // all other search operations have access to this cached data for // faster analysis operations @@ -2269,29 +2272,58 @@ class DocSearch { } if (aliases) { - const currentCrateAliases = new Map(); - this.ALIASES.set(crate, currentCrateAliases); - for (const alias_name in aliases) { - if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) { - continue; - } - - /** @type{number[]} */ - let currentNameAliases; - if (currentCrateAliases.has(alias_name)) { - currentNameAliases = currentCrateAliases.get(alias_name); - } else { - currentNameAliases = []; - currentCrateAliases.set(alias_name, currentNameAliases); - } - for (const local_alias of aliases[alias_name]) { - currentNameAliases.push(local_alias + currentIndex); - } - } + // We need to add the aliases in `searchIndex` after we finished filling it + // to not mess up indexes. + allAliases.push([crate, aliases, currentIndex]); } currentIndex += itemTypes.length; this.searchState.descShards.set(crate, descShardList); } + + for (const [crate, aliases, index] of allAliases) { + for (const [alias_name, alias_refs] of Object.entries(aliases)) { + if (!this.ALIASES.has(crate)) { + this.ALIASES.set(crate, new Map()); + } + const word = alias_name.toLowerCase(); + const crate_alias_map = this.ALIASES.get(crate); + if (!crate_alias_map.has(word)) { + crate_alias_map.set(word, []); + } + const aliases_map = crate_alias_map.get(word); + + const normalizedName = word.indexOf("_") === -1 ? word : word.replace(/_/g, ""); + for (const alias of alias_refs) { + const originalIndex = alias + index; + const original = searchIndex[originalIndex]; + /** @type {rustdoc.Row} */ + const row = { + crate, + name: alias_name, + normalizedName, + is_alias: true, + ty: original.ty, + type: original.type, + paramNames: [], + word, + id, + parent: undefined, + original, + path: "", + implDisambiguator: original.implDisambiguator, + // Needed to load the description of the original item. + // @ts-ignore + descShard: original.descShard, + descIndex: original.descIndex, + bitIndex: original.bitIndex, + }; + aliases_map.push(row); + this.nameTrie.insert(normalizedName, id, this.tailTable); + id += 1; + searchIndex.push(row); + } + } + } // Drop the (rather large) hash table used for reusing function items this.TYPES_POOL = new Map(); return searchIndex; @@ -2536,6 +2568,8 @@ class DocSearch { parsedQuery.elems.reduce((acc, next) => acc + next.pathLast.length, 0) + parsedQuery.returned.reduce((acc, next) => acc + next.pathLast.length, 0); const maxEditDistance = Math.floor(queryLen / 3); + // We reinitialize the `FOUND_ALIASES` map. + this.FOUND_ALIASES.clear(); /** * @type {Map<string, number>} @@ -2695,6 +2729,10 @@ class DocSearch { const buildHrefAndPath = item => { let displayPath; let href; + if (item.is_alias) { + this.FOUND_ALIASES.add(item.word); + item = item.original; + } const type = itemTypes[item.ty]; const name = item.name; let path = item.path; @@ -3198,8 +3236,7 @@ class DocSearch { result.item = this.searchIndex[result.id]; result.word = this.searchIndex[result.id].word; if (isReturnTypeQuery) { - // we are doing a return-type based search, - // deprioritize "clone-like" results, + // We are doing a return-type based search, deprioritize "clone-like" results, // ie. functions that also take the queried type as an argument. const resultItemType = result.item && result.item.type; if (!resultItemType) { @@ -4259,28 +4296,13 @@ class DocSearch { return false; } - // this does not yet have a type in `rustdoc.d.ts`. - // @ts-expect-error - function createAliasFromItem(item) { - return { - crate: item.crate, - name: item.name, - path: item.path, - descShard: item.descShard, - descIndex: item.descIndex, - exactPath: item.exactPath, - ty: item.ty, - parent: item.parent, - type: item.type, - is_alias: true, - bitIndex: item.bitIndex, - implDisambiguator: item.implDisambiguator, - }; - } - // @ts-expect-error const handleAliases = async(ret, query, filterCrates, currentCrate) => { const lowerQuery = query.toLowerCase(); + if (this.FOUND_ALIASES.has(lowerQuery)) { + return; + } + this.FOUND_ALIASES.add(lowerQuery); // We separate aliases and crate aliases because we want to have current crate // aliases to be before the others in the displayed results. // @ts-expect-error @@ -4292,7 +4314,7 @@ class DocSearch { && this.ALIASES.get(filterCrates).has(lowerQuery)) { const query_aliases = this.ALIASES.get(filterCrates).get(lowerQuery); for (const alias of query_aliases) { - aliases.push(createAliasFromItem(this.searchIndex[alias])); + aliases.push(alias); } } } else { @@ -4302,7 +4324,7 @@ class DocSearch { const pushTo = crate === currentCrate ? crateAliases : aliases; const query_aliases = crateAliasesIndex.get(lowerQuery); for (const alias of query_aliases) { - pushTo.push(createAliasFromItem(this.searchIndex[alias])); + pushTo.push(alias); } } } @@ -4310,9 +4332,9 @@ class DocSearch { // @ts-expect-error const sortFunc = (aaa, bbb) => { - if (aaa.path < bbb.path) { + if (aaa.original.path < bbb.original.path) { return 1; - } else if (aaa.path === bbb.path) { + } else if (aaa.original.path === bbb.original.path) { return 0; } return -1; @@ -4322,20 +4344,9 @@ class DocSearch { aliases.sort(sortFunc); // @ts-expect-error - const fetchDesc = alias => { - // @ts-expect-error - return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex) ? - "" : this.searchState.loadDesc(alias); - }; - const [crateDescs, descs] = await Promise.all([ - // @ts-expect-error - Promise.all(crateAliases.map(fetchDesc)), - Promise.all(aliases.map(fetchDesc)), - ]); - - // @ts-expect-error const pushFunc = alias => { - alias.alias = query; + // Cloning `alias` to prevent its fields to be updated. + alias = {...alias}; const res = buildHrefAndPath(alias); alias.displayPath = pathSplitter(res[0]); alias.fullPath = alias.displayPath + alias.name; @@ -4347,16 +4358,8 @@ class DocSearch { } }; - aliases.forEach((alias, i) => { - // @ts-expect-error - alias.desc = descs[i]; - }); aliases.forEach(pushFunc); // @ts-expect-error - crateAliases.forEach((alias, i) => { - alias.desc = crateDescs[i]; - }); - // @ts-expect-error crateAliases.forEach(pushFunc); }; @@ -4802,7 +4805,7 @@ async function addTab(array, query, display) { output.className = "search-results " + extraClass; const lis = Promise.all(array.map(async item => { - const name = item.name; + const name = item.is_alias ? item.original.name : item.name; const type = itemTypes[item.ty]; const longType = longItemTypes[item.ty]; const typeName = longType.length !== 0 ? `${longType}` : "?"; @@ -4822,7 +4825,7 @@ async function addTab(array, query, display) { let alias = " "; if (item.is_alias) { alias = ` <div class="alias">\ -<b>${item.alias}</b><i class="grey"> - see </i>\ +<b>${item.name}</b><i class="grey"> - see </i>\ </div>`; } resultName.insertAdjacentHTML( @@ -5201,6 +5204,7 @@ function registerSearchEvents() { if (searchState.input.value.length === 0) { searchState.hideResults(); } else { + // @ts-ignore searchState.timeout = setTimeout(search, 500); } }; @@ -5842,8 +5846,8 @@ Lev1TParametricDescription.prototype.offsetIncrs3 = /*2 bits per value */ new In // be called ONLY when the whole file has been parsed and loaded. // @ts-expect-error -function initSearch(searchIndx) { - rawSearchIndex = searchIndx; +function initSearch(searchIndex) { + rawSearchIndex = searchIndex; if (typeof window !== "undefined") { // @ts-expect-error docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState); diff --git a/src/librustdoc/html/url_parts_builder.rs b/src/librustdoc/html/url_parts_builder.rs index 9a533827441..705fa498e8d 100644 --- a/src/librustdoc/html/url_parts_builder.rs +++ b/src/librustdoc/html/url_parts_builder.rs @@ -117,7 +117,7 @@ impl UrlPartsBuilder { /// This is just a guess at the average length of a URL part, /// used for [`String::with_capacity`] calls in the [`FromIterator`] -/// and [`Extend`] impls, and for [estimating item path lengths]. +/// and [`Extend`] impls. /// /// The value `8` was chosen for two main reasons: /// @@ -125,18 +125,8 @@ impl UrlPartsBuilder { /// * jemalloc's size classes are all multiples of eight, /// which means that the amount of memory it allocates will often match /// the amount requested, avoiding wasted bytes. -/// -/// [estimating item path lengths]: estimate_item_path_byte_length const AVG_PART_LENGTH: usize = 8; -/// Estimate the number of bytes in an item's path, based on how many segments it has. -/// -/// **Note:** This is only to be used with, e.g., [`String::with_capacity()`]; -/// the return value is just a rough estimate. -pub(crate) const fn estimate_item_path_byte_length(segment_count: usize) -> usize { - AVG_PART_LENGTH * segment_count -} - impl<'a> FromIterator<&'a str> for UrlPartsBuilder { fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self { let iter = iter.into_iter(); |
