mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 03:38:29 +00:00
Auto merge of #91948 - nnethercote:rustdoc-more-Symbols, r=GuillaumeGomez
rustdoc: avoid many `Symbol` to `String` conversions. Particularly when constructing file paths and fully qualified paths. This avoids a lot of allocations, speeding things up on almost all examples. r? `@GuillaumeGomez`
This commit is contained in:
commit
b0ec3e09a9
@ -567,6 +567,7 @@ symbols! {
|
|||||||
doc_spotlight,
|
doc_spotlight,
|
||||||
doctest,
|
doctest,
|
||||||
document_private_items,
|
document_private_items,
|
||||||
|
dotdot: "..",
|
||||||
dotdot_in_tuple_patterns,
|
dotdot_in_tuple_patterns,
|
||||||
dotdoteq_in_patterns,
|
dotdoteq_in_patterns,
|
||||||
dreg,
|
dreg,
|
||||||
|
@ -9,7 +9,6 @@ use rustc_data_structures::thin_vec::ThinVec;
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::definitions::DefPathData;
|
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::Mutability;
|
||||||
use rustc_metadata::creader::{CStore, LoadedMacro};
|
use rustc_metadata::creader::{CStore, LoadedMacro};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
@ -164,12 +163,10 @@ crate fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> Attrs<'hir> {
|
|||||||
/// These names are used later on by HTML rendering to generate things like
|
/// These names are used later on by HTML rendering to generate things like
|
||||||
/// source links back to the original item.
|
/// source links back to the original item.
|
||||||
crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType) {
|
crate fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType) {
|
||||||
let crate_name = cx.tcx.crate_name(did.krate).to_string();
|
let crate_name = cx.tcx.crate_name(did.krate);
|
||||||
|
|
||||||
let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
|
let relative =
|
||||||
// Filter out extern blocks
|
cx.tcx.def_path(did).data.into_iter().filter_map(|elem| elem.data.get_opt_name());
|
||||||
(elem.data != DefPathData::ForeignMod).then(|| elem.data.to_string())
|
|
||||||
});
|
|
||||||
let fqn = if let ItemType::Macro = kind {
|
let fqn = if let ItemType::Macro = kind {
|
||||||
// Check to see if it is a macro 2.0 or built-in macro
|
// Check to see if it is a macro 2.0 or built-in macro
|
||||||
if matches!(
|
if matches!(
|
||||||
|
@ -4,13 +4,14 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
|||||||
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
|
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
|
||||||
use rustc_middle::middle::privacy::AccessLevels;
|
use rustc_middle::middle::privacy::AccessLevels;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::{sym, Symbol};
|
||||||
|
|
||||||
use crate::clean::{self, types::ExternalLocation, ExternalCrate, ItemId, PrimitiveType};
|
use crate::clean::{self, types::ExternalLocation, ExternalCrate, ItemId, PrimitiveType};
|
||||||
use crate::core::DocContext;
|
use crate::core::DocContext;
|
||||||
use crate::fold::DocFolder;
|
use crate::fold::DocFolder;
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
use crate::formats::Impl;
|
use crate::formats::Impl;
|
||||||
|
use crate::html::format::join_with_double_colon;
|
||||||
use crate::html::markdown::short_markdown_summary;
|
use crate::html::markdown::short_markdown_summary;
|
||||||
use crate::html::render::search_index::get_function_type_for_search;
|
use crate::html::render::search_index::get_function_type_for_search;
|
||||||
use crate::html::render::IndexItem;
|
use crate::html::render::IndexItem;
|
||||||
@ -39,11 +40,11 @@ crate struct Cache {
|
|||||||
/// URLs when a type is being linked to. External paths are not located in
|
/// URLs when a type is being linked to. External paths are not located in
|
||||||
/// this map because the `External` type itself has all the information
|
/// this map because the `External` type itself has all the information
|
||||||
/// necessary.
|
/// necessary.
|
||||||
crate paths: FxHashMap<DefId, (Vec<String>, ItemType)>,
|
crate paths: FxHashMap<DefId, (Vec<Symbol>, ItemType)>,
|
||||||
|
|
||||||
/// Similar to `paths`, but only holds external paths. This is only used for
|
/// Similar to `paths`, but only holds external paths. This is only used for
|
||||||
/// generating explicit hyperlinks to other crates.
|
/// generating explicit hyperlinks to other crates.
|
||||||
crate external_paths: FxHashMap<DefId, (Vec<String>, ItemType)>,
|
crate external_paths: FxHashMap<DefId, (Vec<Symbol>, ItemType)>,
|
||||||
|
|
||||||
/// Maps local `DefId`s of exported types to fully qualified paths.
|
/// Maps local `DefId`s of exported types to fully qualified paths.
|
||||||
/// Unlike 'paths', this mapping ignores any renames that occur
|
/// Unlike 'paths', this mapping ignores any renames that occur
|
||||||
@ -55,7 +56,7 @@ crate struct Cache {
|
|||||||
/// to the path used if the corresponding type is inlined. By
|
/// to the path used if the corresponding type is inlined. By
|
||||||
/// doing this, we can detect duplicate impls on a trait page, and only display
|
/// doing this, we can detect duplicate impls on a trait page, and only display
|
||||||
/// the impl for the inlined type.
|
/// the impl for the inlined type.
|
||||||
crate exact_paths: FxHashMap<DefId, Vec<String>>,
|
crate exact_paths: FxHashMap<DefId, Vec<Symbol>>,
|
||||||
|
|
||||||
/// This map contains information about all known traits of this crate.
|
/// This map contains information about all known traits of this crate.
|
||||||
/// Implementations of a crate should inherit the documentation of the
|
/// Implementations of a crate should inherit the documentation of the
|
||||||
@ -92,7 +93,7 @@ crate struct Cache {
|
|||||||
crate masked_crates: FxHashSet<CrateNum>,
|
crate masked_crates: FxHashSet<CrateNum>,
|
||||||
|
|
||||||
// Private fields only used when initially crawling a crate to build a cache
|
// Private fields only used when initially crawling a crate to build a cache
|
||||||
stack: Vec<String>,
|
stack: Vec<Symbol>,
|
||||||
parent_stack: Vec<DefId>,
|
parent_stack: Vec<DefId>,
|
||||||
parent_is_trait_impl: bool,
|
parent_is_trait_impl: bool,
|
||||||
stripped_mod: bool,
|
stripped_mod: bool,
|
||||||
@ -155,7 +156,7 @@ impl Cache {
|
|||||||
let dst = &render_options.output;
|
let dst = &render_options.output;
|
||||||
let location = e.location(extern_url, extern_url_takes_precedence, dst, tcx);
|
let location = e.location(extern_url, extern_url_takes_precedence, dst, tcx);
|
||||||
cx.cache.extern_locations.insert(e.crate_num, location);
|
cx.cache.extern_locations.insert(e.crate_num, location);
|
||||||
cx.cache.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module));
|
cx.cache.external_paths.insert(e.def_id(), (vec![name], ItemType::Module));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: avoid this clone (requires implementing Default manually)
|
// FIXME: avoid this clone (requires implementing Default manually)
|
||||||
@ -164,10 +165,9 @@ impl Cache {
|
|||||||
let crate_name = tcx.crate_name(def_id.krate);
|
let crate_name = tcx.crate_name(def_id.krate);
|
||||||
// Recall that we only allow primitive modules to be at the root-level of the crate.
|
// Recall that we only allow primitive modules to be at the root-level of the crate.
|
||||||
// If that restriction is ever lifted, this will have to include the relative paths instead.
|
// If that restriction is ever lifted, this will have to include the relative paths instead.
|
||||||
cx.cache.external_paths.insert(
|
cx.cache
|
||||||
def_id,
|
.external_paths
|
||||||
(vec![crate_name.to_string(), prim.as_sym().to_string()], ItemType::Primitive),
|
.insert(def_id, (vec![crate_name, prim.as_sym()], ItemType::Primitive));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
krate = CacheBuilder { tcx, cache: &mut cx.cache }.fold_crate(krate);
|
krate = CacheBuilder { tcx, cache: &mut cx.cache }.fold_crate(krate);
|
||||||
@ -299,7 +299,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
|||||||
self.cache.search_index.push(IndexItem {
|
self.cache.search_index.push(IndexItem {
|
||||||
ty: item.type_(),
|
ty: item.type_(),
|
||||||
name: s.to_string(),
|
name: s.to_string(),
|
||||||
path: path.join("::"),
|
path: join_with_double_colon(path),
|
||||||
desc,
|
desc,
|
||||||
parent,
|
parent,
|
||||||
parent_idx: None,
|
parent_idx: None,
|
||||||
@ -320,7 +320,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
|||||||
// Keep track of the fully qualified path for this item.
|
// Keep track of the fully qualified path for this item.
|
||||||
let pushed = match item.name {
|
let pushed = match item.name {
|
||||||
Some(n) if !n.is_empty() => {
|
Some(n) if !n.is_empty() => {
|
||||||
self.cache.stack.push(n.to_string());
|
self.cache.stack.push(n);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -19,6 +19,7 @@ use rustc_middle::ty;
|
|||||||
use rustc_middle::ty::DefIdTree;
|
use rustc_middle::ty::DefIdTree;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::def_id::CRATE_DEF_INDEX;
|
use rustc_span::def_id::CRATE_DEF_INDEX;
|
||||||
|
use rustc_span::{sym, Symbol};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use crate::clean::{
|
use crate::clean::{
|
||||||
@ -29,6 +30,7 @@ use crate::formats::item_type::ItemType;
|
|||||||
use crate::html::escape::Escape;
|
use crate::html::escape::Escape;
|
||||||
use crate::html::render::Context;
|
use crate::html::render::Context;
|
||||||
|
|
||||||
|
use super::url_parts_builder::estimate_item_path_byte_length;
|
||||||
use super::url_parts_builder::UrlPartsBuilder;
|
use super::url_parts_builder::UrlPartsBuilder;
|
||||||
|
|
||||||
crate trait Print {
|
crate trait Print {
|
||||||
@ -502,11 +504,22 @@ crate enum HrefError {
|
|||||||
NotInExternalCache,
|
NotInExternalCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Panics if `syms` is empty.
|
||||||
|
crate fn join_with_double_colon(syms: &[Symbol]) -> String {
|
||||||
|
let mut s = String::with_capacity(estimate_item_path_byte_length(syms.len()));
|
||||||
|
s.push_str(&syms[0].as_str());
|
||||||
|
for sym in &syms[1..] {
|
||||||
|
s.push_str("::");
|
||||||
|
s.push_str(&sym.as_str());
|
||||||
|
}
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
crate fn href_with_root_path(
|
crate fn href_with_root_path(
|
||||||
did: DefId,
|
did: DefId,
|
||||||
cx: &Context<'_>,
|
cx: &Context<'_>,
|
||||||
root_path: Option<&str>,
|
root_path: Option<&str>,
|
||||||
) -> Result<(String, ItemType, Vec<String>), HrefError> {
|
) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
|
||||||
let tcx = cx.tcx();
|
let tcx = cx.tcx();
|
||||||
let def_kind = tcx.def_kind(did);
|
let def_kind = tcx.def_kind(did);
|
||||||
let did = match def_kind {
|
let did = match def_kind {
|
||||||
@ -518,7 +531,7 @@ crate fn href_with_root_path(
|
|||||||
};
|
};
|
||||||
let cache = cx.cache();
|
let cache = cx.cache();
|
||||||
let relative_to = &cx.current;
|
let relative_to = &cx.current;
|
||||||
fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
|
fn to_module_fqp(shortty: ItemType, fqp: &[Symbol]) -> &[Symbol] {
|
||||||
if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] }
|
if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,9 +546,9 @@ crate fn href_with_root_path(
|
|||||||
let mut is_remote = false;
|
let mut is_remote = false;
|
||||||
let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
|
let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
|
||||||
Some(&(ref fqp, shortty)) => (fqp, shortty, {
|
Some(&(ref fqp, shortty)) => (fqp, shortty, {
|
||||||
let module_fqp = to_module_fqp(shortty, fqp);
|
let module_fqp = to_module_fqp(shortty, fqp.as_slice());
|
||||||
debug!(?fqp, ?shortty, ?module_fqp);
|
debug!(?fqp, ?shortty, ?module_fqp);
|
||||||
href_relative_parts(module_fqp, relative_to)
|
href_relative_parts(module_fqp, relative_to).collect()
|
||||||
}),
|
}),
|
||||||
None => {
|
None => {
|
||||||
if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) {
|
if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) {
|
||||||
@ -548,10 +561,12 @@ crate fn href_with_root_path(
|
|||||||
is_remote = true;
|
is_remote = true;
|
||||||
let s = s.trim_end_matches('/');
|
let s = s.trim_end_matches('/');
|
||||||
let mut builder = UrlPartsBuilder::singleton(s);
|
let mut builder = UrlPartsBuilder::singleton(s);
|
||||||
builder.extend(module_fqp.iter().map(String::as_str));
|
builder.extend(module_fqp.iter().copied());
|
||||||
builder
|
builder
|
||||||
}
|
}
|
||||||
ExternalLocation::Local => href_relative_parts(module_fqp, relative_to),
|
ExternalLocation::Local => {
|
||||||
|
href_relative_parts(module_fqp, relative_to).collect()
|
||||||
|
}
|
||||||
ExternalLocation::Unknown => return Err(HrefError::DocumentationNotBuilt),
|
ExternalLocation::Unknown => return Err(HrefError::DocumentationNotBuilt),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -567,45 +582,50 @@ crate fn href_with_root_path(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug!(?url_parts);
|
debug!(?url_parts);
|
||||||
let last = &fqp.last().unwrap()[..];
|
|
||||||
match shortty {
|
match shortty {
|
||||||
ItemType::Module => {
|
ItemType::Module => {
|
||||||
url_parts.push("index.html");
|
url_parts.push("index.html");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let filename = format!("{}.{}.html", shortty.as_str(), last);
|
let prefix = shortty.as_str();
|
||||||
url_parts.push(&filename);
|
let last = fqp.last().unwrap();
|
||||||
|
url_parts.push_fmt(format_args!("{}.{}.html", prefix, last));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((url_parts.finish(), shortty, fqp.to_vec()))
|
Ok((url_parts.finish(), shortty, fqp.to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<String>), HrefError> {
|
crate fn href(did: DefId, cx: &Context<'_>) -> Result<(String, ItemType, Vec<Symbol>), HrefError> {
|
||||||
href_with_root_path(did, cx, None)
|
href_with_root_path(did, cx, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Both paths should only be modules.
|
/// Both paths should only be modules.
|
||||||
/// This is because modules get their own directories; that is, `std::vec` and `std::vec::Vec` will
|
/// This is because modules get their own directories; that is, `std::vec` and `std::vec::Vec` will
|
||||||
/// both need `../iter/trait.Iterator.html` to get at the iterator trait.
|
/// both need `../iter/trait.Iterator.html` to get at the iterator trait.
|
||||||
crate fn href_relative_parts(fqp: &[String], relative_to_fqp: &[String]) -> UrlPartsBuilder {
|
crate fn href_relative_parts<'fqp>(
|
||||||
|
fqp: &'fqp [Symbol],
|
||||||
|
relative_to_fqp: &[Symbol],
|
||||||
|
) -> Box<dyn Iterator<Item = Symbol> + 'fqp> {
|
||||||
for (i, (f, r)) in fqp.iter().zip(relative_to_fqp.iter()).enumerate() {
|
for (i, (f, r)) in fqp.iter().zip(relative_to_fqp.iter()).enumerate() {
|
||||||
// e.g. linking to std::iter from std::vec (`dissimilar_part_count` will be 1)
|
// e.g. linking to std::iter from std::vec (`dissimilar_part_count` will be 1)
|
||||||
if f != r {
|
if f != r {
|
||||||
let dissimilar_part_count = relative_to_fqp.len() - i;
|
let dissimilar_part_count = relative_to_fqp.len() - i;
|
||||||
let fqp_module = fqp[i..fqp.len()].iter().map(String::as_str);
|
let fqp_module = &fqp[i..fqp.len()];
|
||||||
return iter::repeat("..").take(dissimilar_part_count).chain(fqp_module).collect();
|
return box iter::repeat(sym::dotdot)
|
||||||
|
.take(dissimilar_part_count)
|
||||||
|
.chain(fqp_module.iter().copied());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// e.g. linking to std::sync::atomic from std::sync
|
// e.g. linking to std::sync::atomic from std::sync
|
||||||
if relative_to_fqp.len() < fqp.len() {
|
if relative_to_fqp.len() < fqp.len() {
|
||||||
fqp[relative_to_fqp.len()..fqp.len()].iter().map(String::as_str).collect()
|
box fqp[relative_to_fqp.len()..fqp.len()].iter().copied()
|
||||||
// e.g. linking to std::sync from std::sync::atomic
|
// e.g. linking to std::sync from std::sync::atomic
|
||||||
} else if fqp.len() < relative_to_fqp.len() {
|
} else if fqp.len() < relative_to_fqp.len() {
|
||||||
let dissimilar_part_count = relative_to_fqp.len() - fqp.len();
|
let dissimilar_part_count = relative_to_fqp.len() - fqp.len();
|
||||||
iter::repeat("..").take(dissimilar_part_count).collect()
|
box iter::repeat(sym::dotdot).take(dissimilar_part_count)
|
||||||
// linking to the same module
|
// linking to the same module
|
||||||
} else {
|
} else {
|
||||||
UrlPartsBuilder::new()
|
box iter::empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,14 +652,14 @@ fn resolved_path<'cx>(
|
|||||||
if let Ok((_, _, fqp)) = href(did, cx) {
|
if let Ok((_, _, fqp)) = href(did, cx) {
|
||||||
format!(
|
format!(
|
||||||
"{}::{}",
|
"{}::{}",
|
||||||
fqp[..fqp.len() - 1].join("::"),
|
join_with_double_colon(&fqp[..fqp.len() - 1]),
|
||||||
anchor(did, fqp.last().unwrap(), cx)
|
anchor(did, *fqp.last().unwrap(), cx)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
last.name.to_string()
|
last.name.to_string()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
anchor(did, last.name.as_str(), cx).to_string()
|
anchor(did, last.name, cx).to_string()
|
||||||
};
|
};
|
||||||
write!(w, "{}{}", path, last.args.print(cx))?;
|
write!(w, "{}{}", path, last.args.print(cx))?;
|
||||||
}
|
}
|
||||||
@ -668,30 +688,31 @@ fn primitive_link(
|
|||||||
needs_termination = true;
|
needs_termination = true;
|
||||||
}
|
}
|
||||||
Some(&def_id) => {
|
Some(&def_id) => {
|
||||||
let cname_sym;
|
|
||||||
let loc = match m.extern_locations[&def_id.krate] {
|
let loc = match m.extern_locations[&def_id.krate] {
|
||||||
ExternalLocation::Remote(ref s) => {
|
ExternalLocation::Remote(ref s) => {
|
||||||
cname_sym = ExternalCrate { crate_num: def_id.krate }.name(cx.tcx());
|
let cname_sym = ExternalCrate { crate_num: def_id.krate }.name(cx.tcx());
|
||||||
Some(vec![s.trim_end_matches('/'), cname_sym.as_str()])
|
let builder: UrlPartsBuilder =
|
||||||
|
[s.as_str().trim_end_matches('/'), cname_sym.as_str()]
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
Some(builder)
|
||||||
}
|
}
|
||||||
ExternalLocation::Local => {
|
ExternalLocation::Local => {
|
||||||
cname_sym = ExternalCrate { crate_num: def_id.krate }.name(cx.tcx());
|
let cname_sym = ExternalCrate { crate_num: def_id.krate }.name(cx.tcx());
|
||||||
Some(if cx.current.first().map(|x| &x[..]) == Some(cname_sym.as_str()) {
|
Some(if cx.current.first() == Some(&cname_sym) {
|
||||||
iter::repeat("..").take(cx.current.len() - 1).collect()
|
iter::repeat(sym::dotdot).take(cx.current.len() - 1).collect()
|
||||||
} else {
|
} else {
|
||||||
let cname = iter::once(cname_sym.as_str());
|
iter::repeat(sym::dotdot)
|
||||||
iter::repeat("..").take(cx.current.len()).chain(cname).collect()
|
.take(cx.current.len())
|
||||||
|
.chain(iter::once(cname_sym))
|
||||||
|
.collect()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ExternalLocation::Unknown => None,
|
ExternalLocation::Unknown => None,
|
||||||
};
|
};
|
||||||
if let Some(loc) = loc {
|
if let Some(mut loc) = loc {
|
||||||
write!(
|
loc.push_fmt(format_args!("primitive.{}.html", prim.as_sym()));
|
||||||
f,
|
write!(f, "<a class=\"primitive\" href=\"{}\">", loc.finish())?;
|
||||||
"<a class=\"primitive\" href=\"{}/primitive.{}.html\">",
|
|
||||||
loc.join("/"),
|
|
||||||
prim.as_sym()
|
|
||||||
)?;
|
|
||||||
needs_termination = true;
|
needs_termination = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -730,7 +751,7 @@ fn tybounds<'a, 'tcx: 'a>(
|
|||||||
|
|
||||||
crate fn anchor<'a, 'cx: 'a>(
|
crate fn anchor<'a, 'cx: 'a>(
|
||||||
did: DefId,
|
did: DefId,
|
||||||
text: &'a str,
|
text: Symbol,
|
||||||
cx: &'cx Context<'_>,
|
cx: &'cx Context<'_>,
|
||||||
) -> impl fmt::Display + 'a {
|
) -> impl fmt::Display + 'a {
|
||||||
let parts = href(did, cx);
|
let parts = href(did, cx);
|
||||||
@ -742,8 +763,8 @@ crate fn anchor<'a, 'cx: 'a>(
|
|||||||
short_ty,
|
short_ty,
|
||||||
url,
|
url,
|
||||||
short_ty,
|
short_ty,
|
||||||
fqp.join("::"),
|
join_with_double_colon(&fqp),
|
||||||
text
|
text.as_str()
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{}", text)
|
write!(f, "{}", text)
|
||||||
@ -960,7 +981,7 @@ fn fmt_type<'cx>(
|
|||||||
url = url,
|
url = url,
|
||||||
shortty = ItemType::AssocType,
|
shortty = ItemType::AssocType,
|
||||||
name = name,
|
name = name,
|
||||||
path = path.join("::")
|
path = join_with_double_colon(path),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
_ => write!(f, "{}", name)?,
|
_ => write!(f, "{}", name)?,
|
||||||
@ -1270,7 +1291,7 @@ impl clean::Visibility {
|
|||||||
debug!("path={:?}", path);
|
debug!("path={:?}", path);
|
||||||
// modified from `resolved_path()` to work with `DefPathData`
|
// modified from `resolved_path()` to work with `DefPathData`
|
||||||
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
|
let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
|
||||||
let anchor = anchor(vis_did, last_name.as_str(), cx).to_string();
|
let anchor = anchor(vis_did, last_name, cx).to_string();
|
||||||
|
|
||||||
let mut s = "pub(in ".to_owned();
|
let mut s = "pub(in ".to_owned();
|
||||||
for seg in &path.data[..path.data.len() - 1] {
|
for seg in &path.data[..path.data.len() - 1] {
|
||||||
|
@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt;
|
|||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::source_map::FileName;
|
use rustc_span::source_map::FileName;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::{sym, Symbol};
|
||||||
|
|
||||||
use super::print_item::{full_path, item_path, print_item};
|
use super::print_item::{full_path, item_path, print_item};
|
||||||
use super::search_index::build_index;
|
use super::search_index::build_index;
|
||||||
@ -29,7 +29,7 @@ use crate::formats::cache::Cache;
|
|||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
use crate::formats::FormatRenderer;
|
use crate::formats::FormatRenderer;
|
||||||
use crate::html::escape::Escape;
|
use crate::html::escape::Escape;
|
||||||
use crate::html::format::Buffer;
|
use crate::html::format::{join_with_double_colon, Buffer};
|
||||||
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
|
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
|
||||||
use crate::html::{layout, sources};
|
use crate::html::{layout, sources};
|
||||||
use crate::scrape_examples::AllCallLocations;
|
use crate::scrape_examples::AllCallLocations;
|
||||||
@ -45,7 +45,7 @@ use crate::try_err;
|
|||||||
crate struct Context<'tcx> {
|
crate struct Context<'tcx> {
|
||||||
/// Current hierarchy of components leading down to what's currently being
|
/// Current hierarchy of components leading down to what's currently being
|
||||||
/// rendered
|
/// rendered
|
||||||
pub(crate) current: Vec<String>,
|
pub(crate) current: Vec<Symbol>,
|
||||||
/// The current destination folder of where HTML artifacts should be placed.
|
/// The current destination folder of where HTML artifacts should be placed.
|
||||||
/// This changes as the context descends into the module hierarchy.
|
/// This changes as the context descends into the module hierarchy.
|
||||||
crate dst: PathBuf,
|
crate dst: PathBuf,
|
||||||
@ -176,7 +176,7 @@ impl<'tcx> Context<'tcx> {
|
|||||||
title.push_str(" in ");
|
title.push_str(" in ");
|
||||||
}
|
}
|
||||||
// No need to include the namespace for primitive types and keywords
|
// No need to include the namespace for primitive types and keywords
|
||||||
title.push_str(&self.current.join("::"));
|
title.push_str(&join_with_double_colon(&self.current));
|
||||||
};
|
};
|
||||||
title.push_str(" - Rust");
|
title.push_str(" - Rust");
|
||||||
let tyname = it.type_();
|
let tyname = it.type_();
|
||||||
@ -225,18 +225,18 @@ impl<'tcx> Context<'tcx> {
|
|||||||
if let Some(&(ref names, ty)) = self.cache().paths.get(&it.def_id.expect_def_id()) {
|
if let Some(&(ref names, ty)) = self.cache().paths.get(&it.def_id.expect_def_id()) {
|
||||||
let mut path = String::new();
|
let mut path = String::new();
|
||||||
for name in &names[..names.len() - 1] {
|
for name in &names[..names.len() - 1] {
|
||||||
path.push_str(name);
|
path.push_str(&name.as_str());
|
||||||
path.push('/');
|
path.push('/');
|
||||||
}
|
}
|
||||||
path.push_str(&item_path(ty, names.last().unwrap()));
|
path.push_str(&item_path(ty, &names.last().unwrap().as_str()));
|
||||||
match self.shared.redirections {
|
match self.shared.redirections {
|
||||||
Some(ref redirections) => {
|
Some(ref redirections) => {
|
||||||
let mut current_path = String::new();
|
let mut current_path = String::new();
|
||||||
for name in &self.current {
|
for name in &self.current {
|
||||||
current_path.push_str(name);
|
current_path.push_str(&name.as_str());
|
||||||
current_path.push('/');
|
current_path.push('/');
|
||||||
}
|
}
|
||||||
current_path.push_str(&item_path(ty, names.last().unwrap()));
|
current_path.push_str(&item_path(ty, &names.last().unwrap().as_str()));
|
||||||
redirections.borrow_mut().insert(current_path, path);
|
redirections.borrow_mut().insert(current_path, path);
|
||||||
}
|
}
|
||||||
None => return layout::redirect(&format!("{}{}", self.root_path(), path)),
|
None => return layout::redirect(&format!("{}{}", self.root_path(), path)),
|
||||||
@ -634,8 +634,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
|||||||
self.render_redirect_pages = item.is_stripped();
|
self.render_redirect_pages = item.is_stripped();
|
||||||
}
|
}
|
||||||
let scx = &self.shared;
|
let scx = &self.shared;
|
||||||
let item_name = item.name.as_ref().unwrap().to_string();
|
let item_name = item.name.unwrap();
|
||||||
self.dst.push(&item_name);
|
self.dst.push(&*item_name.as_str());
|
||||||
self.current.push(item_name);
|
self.current.push(item_name);
|
||||||
|
|
||||||
info!("Recursing into {}", self.dst.display());
|
info!("Recursing into {}", self.dst.display());
|
||||||
|
@ -69,8 +69,9 @@ use crate::formats::item_type::ItemType;
|
|||||||
use crate::formats::{AssocItemRender, Impl, RenderMode};
|
use crate::formats::{AssocItemRender, Impl, RenderMode};
|
||||||
use crate::html::escape::Escape;
|
use crate::html::escape::Escape;
|
||||||
use crate::html::format::{
|
use crate::html::format::{
|
||||||
href, print_abi_with_space, print_constness_with_space, print_default_space,
|
href, join_with_double_colon, print_abi_with_space, print_constness_with_space,
|
||||||
print_generic_bounds, print_where_clause, Buffer, HrefError, PrintWithSpace,
|
print_default_space, print_generic_bounds, print_where_clause, Buffer, HrefError,
|
||||||
|
PrintWithSpace,
|
||||||
};
|
};
|
||||||
use crate::html::highlight;
|
use crate::html::highlight;
|
||||||
use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
|
use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
|
||||||
@ -2515,7 +2516,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
|
|||||||
let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern);
|
let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern);
|
||||||
|
|
||||||
if let Some(path) = fqp {
|
if let Some(path) = fqp {
|
||||||
out.push(path.join("::"));
|
out.push(join_with_double_colon(&path));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,11 +26,13 @@ use crate::formats::item_type::ItemType;
|
|||||||
use crate::formats::{AssocItemRender, Impl, RenderMode};
|
use crate::formats::{AssocItemRender, Impl, RenderMode};
|
||||||
use crate::html::escape::Escape;
|
use crate::html::escape::Escape;
|
||||||
use crate::html::format::{
|
use crate::html::format::{
|
||||||
print_abi_with_space, print_constness_with_space, print_where_clause, Buffer, PrintWithSpace,
|
join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause,
|
||||||
|
Buffer, PrintWithSpace,
|
||||||
};
|
};
|
||||||
use crate::html::highlight;
|
use crate::html::highlight;
|
||||||
use crate::html::layout::Page;
|
use crate::html::layout::Page;
|
||||||
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
|
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
|
||||||
|
use crate::html::url_parts_builder::UrlPartsBuilder;
|
||||||
|
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
|
|
||||||
@ -40,9 +42,9 @@ const ITEM_TABLE_ROW_OPEN: &str = "<div class=\"item-row\">";
|
|||||||
const ITEM_TABLE_ROW_CLOSE: &str = "</div>";
|
const ITEM_TABLE_ROW_CLOSE: &str = "</div>";
|
||||||
|
|
||||||
// A component in a `use` path, like `string` in std::string::ToString
|
// A component in a `use` path, like `string` in std::string::ToString
|
||||||
struct PathComponent<'a> {
|
struct PathComponent {
|
||||||
path: String,
|
path: String,
|
||||||
name: &'a str,
|
name: Symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
@ -53,7 +55,7 @@ struct ItemVars<'a> {
|
|||||||
typ: &'a str,
|
typ: &'a str,
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
item_type: &'a str,
|
item_type: &'a str,
|
||||||
path_components: Vec<PathComponent<'a>>,
|
path_components: Vec<PathComponent>,
|
||||||
stability_since_raw: &'a str,
|
stability_since_raw: &'a str,
|
||||||
src_href: Option<&'a str>,
|
src_href: Option<&'a str>,
|
||||||
}
|
}
|
||||||
@ -121,7 +123,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer,
|
|||||||
.take(amt)
|
.take(amt)
|
||||||
.map(|(i, component)| PathComponent {
|
.map(|(i, component)| PathComponent {
|
||||||
path: "../".repeat(cur.len() - i - 1),
|
path: "../".repeat(cur.len() - i - 1),
|
||||||
name: component,
|
name: *component,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
@ -262,7 +264,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
|||||||
indices.dedup_by_key(|i| {
|
indices.dedup_by_key(|i| {
|
||||||
(
|
(
|
||||||
items[*i].def_id,
|
items[*i].def_id,
|
||||||
if items[*i].name.as_ref().is_some() { Some(full_path(cx, &items[*i])) } else { None },
|
if items[*i].name.is_some() { Some(full_path(cx, &items[*i])) } else { None },
|
||||||
items[*i].type_(),
|
items[*i].type_(),
|
||||||
if items[*i].is_import() { *i } else { 0 },
|
if items[*i].is_import() { *i } else { 0 },
|
||||||
)
|
)
|
||||||
@ -304,22 +306,18 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
|||||||
|
|
||||||
w.write_str(ITEM_TABLE_ROW_OPEN);
|
w.write_str(ITEM_TABLE_ROW_OPEN);
|
||||||
match *src {
|
match *src {
|
||||||
Some(ref src) => write!(
|
Some(src) => write!(
|
||||||
w,
|
w,
|
||||||
"<div class=\"item-left\"><code>{}extern crate {} as {};",
|
"<div class=\"item-left\"><code>{}extern crate {} as {};",
|
||||||
myitem.visibility.print_with_space(myitem.def_id, cx),
|
myitem.visibility.print_with_space(myitem.def_id, cx),
|
||||||
anchor(myitem.def_id.expect_def_id(), src.as_str(), cx),
|
anchor(myitem.def_id.expect_def_id(), src, cx),
|
||||||
myitem.name.as_ref().unwrap(),
|
myitem.name.unwrap(),
|
||||||
),
|
),
|
||||||
None => write!(
|
None => write!(
|
||||||
w,
|
w,
|
||||||
"<div class=\"item-left\"><code>{}extern crate {};",
|
"<div class=\"item-left\"><code>{}extern crate {};",
|
||||||
myitem.visibility.print_with_space(myitem.def_id, cx),
|
myitem.visibility.print_with_space(myitem.def_id, cx),
|
||||||
anchor(
|
anchor(myitem.def_id.expect_def_id(), myitem.name.unwrap(), cx),
|
||||||
myitem.def_id.expect_def_id(),
|
|
||||||
myitem.name.as_ref().unwrap().as_str(),
|
|
||||||
cx
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
w.write_str("</code></div>");
|
w.write_str("</code></div>");
|
||||||
@ -391,7 +389,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
|
|||||||
{stab_tags}\
|
{stab_tags}\
|
||||||
</div>\
|
</div>\
|
||||||
<div class=\"item-right docblock-short\">{docs}</div>",
|
<div class=\"item-right docblock-short\">{docs}</div>",
|
||||||
name = *myitem.name.as_ref().unwrap(),
|
name = myitem.name.unwrap(),
|
||||||
stab_tags = extra_info_tags(myitem, item, cx.tcx()),
|
stab_tags = extra_info_tags(myitem, item, cx.tcx()),
|
||||||
docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string(),
|
docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string(),
|
||||||
class = myitem.type_(),
|
class = myitem.type_(),
|
||||||
@ -463,7 +461,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
|
|||||||
let asyncness = f.header.asyncness.print_with_space();
|
let asyncness = f.header.asyncness.print_with_space();
|
||||||
let unsafety = f.header.unsafety.print_with_space();
|
let unsafety = f.header.unsafety.print_with_space();
|
||||||
let abi = print_abi_with_space(f.header.abi).to_string();
|
let abi = print_abi_with_space(f.header.abi).to_string();
|
||||||
let name = it.name.as_ref().unwrap();
|
let name = it.name.unwrap();
|
||||||
|
|
||||||
let generics_len = format!("{:#}", f.generics.print(cx)).len();
|
let generics_len = format!("{:#}", f.generics.print(cx)).len();
|
||||||
let header_len = "fn ".len()
|
let header_len = "fn ".len()
|
||||||
@ -519,7 +517,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
|
|||||||
it.visibility.print_with_space(it.def_id, cx),
|
it.visibility.print_with_space(it.def_id, cx),
|
||||||
t.unsafety.print_with_space(),
|
t.unsafety.print_with_space(),
|
||||||
if t.is_auto { "auto " } else { "" },
|
if t.is_auto { "auto " } else { "" },
|
||||||
it.name.as_ref().unwrap(),
|
it.name.unwrap(),
|
||||||
t.generics.print(cx),
|
t.generics.print(cx),
|
||||||
bounds
|
bounds
|
||||||
);
|
);
|
||||||
@ -660,7 +658,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) {
|
fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) {
|
||||||
let name = m.name.as_ref().unwrap();
|
let name = m.name.unwrap();
|
||||||
info!("Documenting {} on {:?}", name, t.name);
|
info!("Documenting {} on {:?}", name, t.name);
|
||||||
let item_type = m.type_();
|
let item_type = m.type_();
|
||||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||||
@ -857,20 +855,21 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(
|
let mut js_src_path: UrlPartsBuilder = std::iter::repeat("..")
|
||||||
w,
|
.take(cx.current.len())
|
||||||
"<script type=\"text/javascript\" \
|
.chain(std::iter::once("implementors"))
|
||||||
src=\"{root_path}/implementors/{path}/{ty}.{name}.js\" async>\
|
.collect();
|
||||||
</script>",
|
if it.def_id.is_local() {
|
||||||
root_path = vec![".."; cx.current.len()].join("/"),
|
js_src_path.extend(cx.current.iter().copied());
|
||||||
path = if it.def_id.is_local() {
|
|
||||||
cx.current.join("/")
|
|
||||||
} else {
|
} else {
|
||||||
let (ref path, _) = cache.external_paths[&it.def_id.expect_def_id()];
|
let (ref path, _) = cache.external_paths[&it.def_id.expect_def_id()];
|
||||||
path[..path.len() - 1].join("/")
|
js_src_path.extend(path[..path.len() - 1].iter().copied());
|
||||||
},
|
}
|
||||||
ty = it.type_(),
|
js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap()));
|
||||||
name = *it.name.as_ref().unwrap()
|
write!(
|
||||||
|
w,
|
||||||
|
"<script type=\"text/javascript\" src=\"{src}\" async></script>",
|
||||||
|
src = js_src_path.finish(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,7 +880,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
|
|||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"trait {}{}{} = {};",
|
"trait {}{}{} = {};",
|
||||||
it.name.as_ref().unwrap(),
|
it.name.unwrap(),
|
||||||
t.generics.print(cx),
|
t.generics.print(cx),
|
||||||
print_where_clause(&t.generics, cx, 0, true),
|
print_where_clause(&t.generics, cx, 0, true),
|
||||||
bounds(&t.bounds, true, cx)
|
bounds(&t.bounds, true, cx)
|
||||||
@ -905,7 +904,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
|
|||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"type {}{}{where_clause} = impl {bounds};",
|
"type {}{}{where_clause} = impl {bounds};",
|
||||||
it.name.as_ref().unwrap(),
|
it.name.unwrap(),
|
||||||
t.generics.print(cx),
|
t.generics.print(cx),
|
||||||
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
||||||
bounds = bounds(&t.bounds, false, cx),
|
bounds = bounds(&t.bounds, false, cx),
|
||||||
@ -944,7 +943,7 @@ fn item_typedef(
|
|||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"type {}{}{where_clause} = {type_};",
|
"type {}{}{where_clause} = {type_};",
|
||||||
it.name.as_ref().unwrap(),
|
it.name.unwrap(),
|
||||||
t.generics.print(cx),
|
t.generics.print(cx),
|
||||||
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
||||||
type_ = t.type_.print(cx),
|
type_ = t.type_.print(cx),
|
||||||
@ -997,7 +996,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
|
|||||||
Fields<a href=\"#fields\" class=\"anchor\"></a></h2>"
|
Fields<a href=\"#fields\" class=\"anchor\"></a></h2>"
|
||||||
);
|
);
|
||||||
for (field, ty) in fields {
|
for (field, ty) in fields {
|
||||||
let name = field.name.as_ref().expect("union field name");
|
let name = field.name.expect("union field name");
|
||||||
let id = format!("{}.{}", ItemType::StructField, name);
|
let id = format!("{}.{}", ItemType::StructField, name);
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
@ -1042,7 +1041,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
|||||||
w,
|
w,
|
||||||
"{}enum {}{}{}",
|
"{}enum {}{}{}",
|
||||||
it.visibility.print_with_space(it.def_id, cx),
|
it.visibility.print_with_space(it.def_id, cx),
|
||||||
it.name.as_ref().unwrap(),
|
it.name.unwrap(),
|
||||||
e.generics.print(cx),
|
e.generics.print(cx),
|
||||||
print_where_clause(&e.generics, cx, 0, true),
|
print_where_clause(&e.generics, cx, 0, true),
|
||||||
);
|
);
|
||||||
@ -1057,7 +1056,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
|||||||
}
|
}
|
||||||
for v in &e.variants {
|
for v in &e.variants {
|
||||||
w.write_str(" ");
|
w.write_str(" ");
|
||||||
let name = v.name.as_ref().unwrap();
|
let name = v.name.unwrap();
|
||||||
match *v.kind {
|
match *v.kind {
|
||||||
clean::VariantItem(ref var) => match var {
|
clean::VariantItem(ref var) => match var {
|
||||||
clean::Variant::CLike => write!(w, "{}", name),
|
clean::Variant::CLike => write!(w, "{}", name),
|
||||||
@ -1106,15 +1105,14 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
|||||||
);
|
);
|
||||||
document_non_exhaustive(w, it);
|
document_non_exhaustive(w, it);
|
||||||
for variant in &e.variants {
|
for variant in &e.variants {
|
||||||
let id =
|
let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap()));
|
||||||
cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.as_ref().unwrap()));
|
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"<h3 id=\"{id}\" class=\"variant small-section-header\">\
|
"<h3 id=\"{id}\" class=\"variant small-section-header\">\
|
||||||
<a href=\"#{id}\" class=\"anchor field\"></a>\
|
<a href=\"#{id}\" class=\"anchor field\"></a>\
|
||||||
<code>{name}",
|
<code>{name}",
|
||||||
id = id,
|
id = id,
|
||||||
name = variant.name.as_ref().unwrap()
|
name = variant.name.unwrap()
|
||||||
);
|
);
|
||||||
if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind {
|
if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind {
|
||||||
w.write_str("(");
|
w.write_str("(");
|
||||||
@ -1140,11 +1138,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some((heading, fields)) = heading_and_fields {
|
if let Some((heading, fields)) = heading_and_fields {
|
||||||
let variant_id = cx.derive_id(format!(
|
let variant_id =
|
||||||
"{}.{}.fields",
|
cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.unwrap()));
|
||||||
ItemType::Variant,
|
|
||||||
variant.name.as_ref().unwrap()
|
|
||||||
));
|
|
||||||
write!(w, "<div class=\"sub-variant\" id=\"{id}\">", id = variant_id);
|
write!(w, "<div class=\"sub-variant\" id=\"{id}\">", id = variant_id);
|
||||||
write!(w, "<h4>{heading}</h4>", heading = heading);
|
write!(w, "<h4>{heading}</h4>", heading = heading);
|
||||||
document_non_exhaustive(w, variant);
|
document_non_exhaustive(w, variant);
|
||||||
@ -1154,8 +1149,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
|||||||
clean::StructFieldItem(ref ty) => {
|
clean::StructFieldItem(ref ty) => {
|
||||||
let id = cx.derive_id(format!(
|
let id = cx.derive_id(format!(
|
||||||
"variant.{}.field.{}",
|
"variant.{}.field.{}",
|
||||||
variant.name.as_ref().unwrap(),
|
variant.name.unwrap(),
|
||||||
field.name.as_ref().unwrap()
|
field.name.unwrap()
|
||||||
));
|
));
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
@ -1165,7 +1160,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
|
|||||||
<code>{f}: {t}</code>\
|
<code>{f}: {t}</code>\
|
||||||
</span>",
|
</span>",
|
||||||
id = id,
|
id = id,
|
||||||
f = field.name.as_ref().unwrap(),
|
f = field.name.unwrap(),
|
||||||
t = ty.print(cx)
|
t = ty.print(cx)
|
||||||
);
|
);
|
||||||
document(w, cx, field, Some(variant), HeadingOffset::H5);
|
document(w, cx, field, Some(variant), HeadingOffset::H5);
|
||||||
@ -1204,7 +1199,7 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac
|
|||||||
|
|
||||||
fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
|
fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
|
||||||
wrap_into_docblock(w, |w| {
|
wrap_into_docblock(w, |w| {
|
||||||
let name = it.name.as_ref().expect("proc-macros always have names");
|
let name = it.name.expect("proc-macros always have names");
|
||||||
match m.kind {
|
match m.kind {
|
||||||
MacroKind::Bang => {
|
MacroKind::Bang => {
|
||||||
wrap_item(w, "macro", |w| {
|
wrap_item(w, "macro", |w| {
|
||||||
@ -1248,7 +1243,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
|
|||||||
w,
|
w,
|
||||||
"{vis}const {name}: {typ}",
|
"{vis}const {name}: {typ}",
|
||||||
vis = it.visibility.print_with_space(it.def_id, cx),
|
vis = it.visibility.print_with_space(it.def_id, cx),
|
||||||
name = it.name.as_ref().unwrap(),
|
name = it.name.unwrap(),
|
||||||
typ = c.type_.print(cx),
|
typ = c.type_.print(cx),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1341,7 +1336,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
|
|||||||
"{vis}static {mutability}{name}: {typ}",
|
"{vis}static {mutability}{name}: {typ}",
|
||||||
vis = it.visibility.print_with_space(it.def_id, cx),
|
vis = it.visibility.print_with_space(it.def_id, cx),
|
||||||
mutability = s.mutability.print_with_space(),
|
mutability = s.mutability.print_with_space(),
|
||||||
name = it.name.as_ref().unwrap(),
|
name = it.name.unwrap(),
|
||||||
typ = s.type_.print(cx)
|
typ = s.type_.print(cx)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -1358,7 +1353,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
|
|||||||
w,
|
w,
|
||||||
" {}type {};\n}}",
|
" {}type {};\n}}",
|
||||||
it.visibility.print_with_space(it.def_id, cx),
|
it.visibility.print_with_space(it.def_id, cx),
|
||||||
it.name.as_ref().unwrap(),
|
it.name.unwrap(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1410,7 +1405,7 @@ crate fn compare_names(mut lhs: &str, mut rhs: &str) -> Ordering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
|
pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
|
||||||
let mut s = cx.current.join("::");
|
let mut s = join_with_double_colon(&cx.current);
|
||||||
s.push_str("::");
|
s.push_str("::");
|
||||||
s.push_str(item.name.unwrap().as_str());
|
s.push_str(item.name.unwrap().as_str());
|
||||||
s
|
s
|
||||||
@ -1526,12 +1521,7 @@ fn render_union(
|
|||||||
tab: &str,
|
tab: &str,
|
||||||
cx: &Context<'_>,
|
cx: &Context<'_>,
|
||||||
) {
|
) {
|
||||||
write!(
|
write!(w, "{}union {}", it.visibility.print_with_space(it.def_id, cx), it.name.unwrap());
|
||||||
w,
|
|
||||||
"{}union {}",
|
|
||||||
it.visibility.print_with_space(it.def_id, cx),
|
|
||||||
it.name.as_ref().unwrap()
|
|
||||||
);
|
|
||||||
if let Some(g) = g {
|
if let Some(g) = g {
|
||||||
write!(w, "{}", g.print(cx));
|
write!(w, "{}", g.print(cx));
|
||||||
write!(w, "{}", print_where_clause(g, cx, 0, true));
|
write!(w, "{}", print_where_clause(g, cx, 0, true));
|
||||||
@ -1551,7 +1541,7 @@ fn render_union(
|
|||||||
w,
|
w,
|
||||||
" {}{}: {},\n{}",
|
" {}{}: {},\n{}",
|
||||||
field.visibility.print_with_space(field.def_id, cx),
|
field.visibility.print_with_space(field.def_id, cx),
|
||||||
field.name.as_ref().unwrap(),
|
field.name.unwrap(),
|
||||||
ty.print(cx),
|
ty.print(cx),
|
||||||
tab
|
tab
|
||||||
);
|
);
|
||||||
@ -1582,7 +1572,7 @@ fn render_struct(
|
|||||||
"{}{}{}",
|
"{}{}{}",
|
||||||
it.visibility.print_with_space(it.def_id, cx),
|
it.visibility.print_with_space(it.def_id, cx),
|
||||||
if structhead { "struct " } else { "" },
|
if structhead { "struct " } else { "" },
|
||||||
it.name.as_ref().unwrap()
|
it.name.unwrap()
|
||||||
);
|
);
|
||||||
if let Some(g) = g {
|
if let Some(g) = g {
|
||||||
write!(w, "{}", g.print(cx))
|
write!(w, "{}", g.print(cx))
|
||||||
@ -1607,7 +1597,7 @@ fn render_struct(
|
|||||||
"\n{} {}{}: {},",
|
"\n{} {}{}: {},",
|
||||||
tab,
|
tab,
|
||||||
field.visibility.print_with_space(field.def_id, cx),
|
field.visibility.print_with_space(field.def_id, cx),
|
||||||
field.name.as_ref().unwrap(),
|
field.name.unwrap(),
|
||||||
ty.print(cx),
|
ty.print(cx),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ use crate::clean;
|
|||||||
use crate::clean::types::{FnRetTy, Function, GenericBound, Generics, Type, WherePredicate};
|
use crate::clean::types::{FnRetTy, Function, GenericBound, Generics, Type, WherePredicate};
|
||||||
use crate::formats::cache::Cache;
|
use crate::formats::cache::Cache;
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
|
use crate::html::format::join_with_double_colon;
|
||||||
use crate::html::markdown::short_markdown_summary;
|
use crate::html::markdown::short_markdown_summary;
|
||||||
use crate::html::render::{IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
|
use crate::html::render::{IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
|
|||||||
cache.search_index.push(IndexItem {
|
cache.search_index.push(IndexItem {
|
||||||
ty: item.type_(),
|
ty: item.type_(),
|
||||||
name: item.name.unwrap().to_string(),
|
name: item.name.unwrap().to_string(),
|
||||||
path: fqp[..fqp.len() - 1].join("::"),
|
path: join_with_double_colon(&fqp[..fqp.len() - 1]),
|
||||||
desc,
|
desc,
|
||||||
parent: Some(did),
|
parent: Some(did),
|
||||||
parent_idx: None,
|
parent_idx: None,
|
||||||
@ -102,7 +103,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
|
|||||||
struct CrateData<'a> {
|
struct CrateData<'a> {
|
||||||
doc: String,
|
doc: String,
|
||||||
items: Vec<&'a IndexItem>,
|
items: Vec<&'a IndexItem>,
|
||||||
paths: Vec<(ItemType, String)>,
|
paths: Vec<(ItemType, Symbol)>,
|
||||||
// The String is alias name and the vec is the list of the elements with this alias.
|
// The String is alias name and the vec is the list of the elements with this alias.
|
||||||
//
|
//
|
||||||
// To be noted: the `usize` elements are indexes to `items`.
|
// To be noted: the `usize` elements are indexes to `items`.
|
||||||
@ -154,7 +155,10 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
|
|||||||
"f",
|
"f",
|
||||||
&self.items.iter().map(|item| &item.search_type).collect::<Vec<_>>(),
|
&self.items.iter().map(|item| &item.search_type).collect::<Vec<_>>(),
|
||||||
)?;
|
)?;
|
||||||
crate_data.serialize_field("p", &self.paths)?;
|
crate_data.serialize_field(
|
||||||
|
"p",
|
||||||
|
&self.paths.iter().map(|(it, s)| (it, s.to_string())).collect::<Vec<_>>(),
|
||||||
|
)?;
|
||||||
if has_aliases {
|
if has_aliases {
|
||||||
crate_data.serialize_field("a", &self.aliases)?;
|
crate_data.serialize_field("a", &self.aliases)?;
|
||||||
}
|
}
|
||||||
|
@ -562,7 +562,7 @@ pub(super) fn write_shared(
|
|||||||
|
|
||||||
let mut mydst = dst.clone();
|
let mut mydst = dst.clone();
|
||||||
for part in &remote_path[..remote_path.len() - 1] {
|
for part in &remote_path[..remote_path.len() - 1] {
|
||||||
mydst.push(part);
|
mydst.push(part.to_string());
|
||||||
}
|
}
|
||||||
cx.shared.ensure_dir(&mydst)?;
|
cx.shared.ensure_dir(&mydst)?;
|
||||||
mydst.push(&format!("{}.{}.js", remote_item_type, remote_path[remote_path.len() - 1]));
|
mydst.push(&format!("{}.{}.js", remote_item_type, remote_path[remote_path.len() - 1]));
|
||||||
|
@ -1,44 +1,50 @@
|
|||||||
use crate::html::format::href_relative_parts;
|
use crate::html::format::href_relative_parts;
|
||||||
|
use rustc_span::{sym, Symbol};
|
||||||
|
|
||||||
fn assert_relative_path(expected: &str, relative_to_fqp: &[&str], fqp: &[&str]) {
|
fn assert_relative_path(expected: &[Symbol], relative_to_fqp: &[Symbol], fqp: &[Symbol]) {
|
||||||
let relative_to_fqp: Vec<String> = relative_to_fqp.iter().copied().map(String::from).collect();
|
// No `create_default_session_globals_then` call is needed here because all
|
||||||
let fqp: Vec<String> = fqp.iter().copied().map(String::from).collect();
|
// the symbols used are static, and no `Symbol::intern` calls occur.
|
||||||
assert_eq!(expected, href_relative_parts(&fqp, &relative_to_fqp).finish());
|
assert_eq!(expected, href_relative_parts(&fqp, &relative_to_fqp).collect::<Vec<_>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn href_relative_parts_basic() {
|
fn href_relative_parts_basic() {
|
||||||
let relative_to_fqp = &["std", "vec"];
|
let relative_to_fqp = &[sym::std, sym::vec];
|
||||||
let fqp = &["std", "iter"];
|
let fqp = &[sym::std, sym::iter];
|
||||||
assert_relative_path("../iter", relative_to_fqp, fqp);
|
assert_relative_path(&[sym::dotdot, sym::iter], relative_to_fqp, fqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn href_relative_parts_parent_module() {
|
fn href_relative_parts_parent_module() {
|
||||||
let relative_to_fqp = &["std", "vec"];
|
let relative_to_fqp = &[sym::std, sym::vec];
|
||||||
let fqp = &["std"];
|
let fqp = &[sym::std];
|
||||||
assert_relative_path("..", relative_to_fqp, fqp);
|
assert_relative_path(&[sym::dotdot], relative_to_fqp, fqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn href_relative_parts_different_crate() {
|
fn href_relative_parts_different_crate() {
|
||||||
let relative_to_fqp = &["std", "vec"];
|
let relative_to_fqp = &[sym::std, sym::vec];
|
||||||
let fqp = &["core", "iter"];
|
let fqp = &[sym::core, sym::iter];
|
||||||
assert_relative_path("../../core/iter", relative_to_fqp, fqp);
|
assert_relative_path(&[sym::dotdot, sym::dotdot, sym::core, sym::iter], relative_to_fqp, fqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn href_relative_parts_same_module() {
|
fn href_relative_parts_same_module() {
|
||||||
let relative_to_fqp = &["std", "vec"];
|
let relative_to_fqp = &[sym::std, sym::vec];
|
||||||
let fqp = &["std", "vec"];
|
let fqp = &[sym::std, sym::vec];
|
||||||
assert_relative_path("", relative_to_fqp, fqp);
|
assert_relative_path(&[], relative_to_fqp, fqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn href_relative_parts_child_module() {
|
fn href_relative_parts_child_module() {
|
||||||
let relative_to_fqp = &["std"];
|
let relative_to_fqp = &[sym::std];
|
||||||
let fqp = &["std", "vec"];
|
let fqp = &[sym::std, sym::vec];
|
||||||
assert_relative_path("vec", relative_to_fqp, fqp);
|
assert_relative_path(&[sym::vec], relative_to_fqp, fqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn href_relative_parts_root() {
|
fn href_relative_parts_root() {
|
||||||
let relative_to_fqp = &[];
|
let relative_to_fqp = &[];
|
||||||
let fqp = &["std"];
|
let fqp = &[sym::std];
|
||||||
assert_relative_path("std", relative_to_fqp, fqp);
|
assert_relative_path(&[sym::std], relative_to_fqp, fqp);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
use std::fmt::{self, Write};
|
||||||
|
|
||||||
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
/// A builder that allows efficiently and easily constructing the part of a URL
|
/// A builder that allows efficiently and easily constructing the part of a URL
|
||||||
/// after the domain: `nightly/core/str/struct.Bytes.html`.
|
/// after the domain: `nightly/core/str/struct.Bytes.html`.
|
||||||
///
|
///
|
||||||
@ -10,6 +14,7 @@ crate struct UrlPartsBuilder {
|
|||||||
|
|
||||||
impl UrlPartsBuilder {
|
impl UrlPartsBuilder {
|
||||||
/// Create an empty buffer.
|
/// Create an empty buffer.
|
||||||
|
#[allow(dead_code)]
|
||||||
crate fn new() -> Self {
|
crate fn new() -> Self {
|
||||||
Self { buf: String::new() }
|
Self { buf: String::new() }
|
||||||
}
|
}
|
||||||
@ -62,6 +67,26 @@ impl UrlPartsBuilder {
|
|||||||
self.buf.push_str(part);
|
self.buf.push_str(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Push a component onto the buffer, using [`format!`]'s formatting syntax.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage (equivalent to the example for [`UrlPartsBuilder::push`]):
|
||||||
|
///
|
||||||
|
/// ```ignore (private-type)
|
||||||
|
/// let mut builder = UrlPartsBuilder::new();
|
||||||
|
/// builder.push("core");
|
||||||
|
/// builder.push("str");
|
||||||
|
/// builder.push_fmt(format_args!("{}.{}.html", "struct", "Bytes"));
|
||||||
|
/// assert_eq!(builder.finish(), "core/str/struct.Bytes.html");
|
||||||
|
/// ```
|
||||||
|
crate fn push_fmt(&mut self, args: fmt::Arguments<'_>) {
|
||||||
|
if !self.buf.is_empty() {
|
||||||
|
self.buf.push('/');
|
||||||
|
}
|
||||||
|
self.buf.write_fmt(args).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Push a component onto the front of the buffer.
|
/// Push a component onto the front of the buffer.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -93,10 +118,25 @@ impl UrlPartsBuilder {
|
|||||||
|
|
||||||
/// This is just a guess at the average length of a URL part,
|
/// This is just a guess at the average length of a URL part,
|
||||||
/// used for [`String::with_capacity`] calls in the [`FromIterator`]
|
/// used for [`String::with_capacity`] calls in the [`FromIterator`]
|
||||||
/// and [`Extend`] impls.
|
/// and [`Extend`] impls, and for [estimating item path lengths].
|
||||||
///
|
///
|
||||||
/// This is intentionally on the lower end to avoid overallocating.
|
/// The value `8` was chosen for two main reasons:
|
||||||
const AVG_PART_LENGTH: usize = 5;
|
///
|
||||||
|
/// * It seems like a good guess for the average part length.
|
||||||
|
/// * 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.
|
||||||
|
crate const fn estimate_item_path_byte_length(segment_count: usize) -> usize {
|
||||||
|
AVG_PART_LENGTH * segment_count
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> FromIterator<&'a str> for UrlPartsBuilder {
|
impl<'a> FromIterator<&'a str> for UrlPartsBuilder {
|
||||||
fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
|
fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
|
||||||
@ -115,5 +155,26 @@ impl<'a> Extend<&'a str> for UrlPartsBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromIterator<Symbol> for UrlPartsBuilder {
|
||||||
|
fn from_iter<T: IntoIterator<Item = Symbol>>(iter: T) -> Self {
|
||||||
|
// This code has to be duplicated from the `&str` impl because of
|
||||||
|
// `Symbol::as_str`'s lifetimes.
|
||||||
|
let iter = iter.into_iter();
|
||||||
|
let mut builder = Self::with_capacity_bytes(AVG_PART_LENGTH * iter.size_hint().0);
|
||||||
|
iter.for_each(|part| builder.push(part.as_str()));
|
||||||
|
builder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Extend<Symbol> for UrlPartsBuilder {
|
||||||
|
fn extend<T: IntoIterator<Item = Symbol>>(&mut self, iter: T) {
|
||||||
|
// This code has to be duplicated from the `&str` impl because of
|
||||||
|
// `Symbol::as_str`'s lifetimes.
|
||||||
|
let iter = iter.into_iter();
|
||||||
|
self.buf.reserve(AVG_PART_LENGTH * iter.size_hint().0);
|
||||||
|
iter.for_each(|part| self.push(part.as_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -40,6 +40,16 @@ fn push_front_non_empty() {
|
|||||||
t(builder, "nightly/core/str/struct.Bytes.html");
|
t(builder, "nightly/core/str/struct.Bytes.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn push_fmt() {
|
||||||
|
let mut builder = UrlPartsBuilder::new();
|
||||||
|
builder.push_fmt(format_args!("{}", "core"));
|
||||||
|
builder.push("str");
|
||||||
|
builder.push_front("nightly");
|
||||||
|
builder.push_fmt(format_args!("{}.{}.html", "struct", "Bytes"));
|
||||||
|
t(builder, "nightly/core/str/struct.Bytes.html");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn collect() {
|
fn collect() {
|
||||||
t(["core", "str"].into_iter().collect(), "core/str");
|
t(["core", "str"].into_iter().collect(), "core/str");
|
||||||
|
@ -120,7 +120,7 @@ impl<'tcx> JsonRenderer<'tcx> {
|
|||||||
})
|
})
|
||||||
.0
|
.0
|
||||||
.last()
|
.last()
|
||||||
.map(Clone::clone),
|
.map(|s| s.to_string()),
|
||||||
visibility: types::Visibility::Public,
|
visibility: types::Visibility::Public,
|
||||||
inner: types::ItemEnum::Trait(trait_item.clone().into_tcx(self.tcx)),
|
inner: types::ItemEnum::Trait(trait_item.clone().into_tcx(self.tcx)),
|
||||||
span: None,
|
span: None,
|
||||||
@ -230,7 +230,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||||||
from_item_id(k.into()),
|
from_item_id(k.into()),
|
||||||
types::ItemSummary {
|
types::ItemSummary {
|
||||||
crate_id: k.krate.as_u32(),
|
crate_id: k.krate.as_u32(),
|
||||||
path,
|
path: path.iter().map(|s| s.to_string()).collect(),
|
||||||
kind: kind.into_tcx(self.tcx),
|
kind: kind.into_tcx(self.tcx),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -5,7 +5,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::definitions::DefPathData;
|
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
use rustc_hir::CRATE_HIR_ID;
|
use rustc_hir::CRATE_HIR_ID;
|
||||||
use rustc_middle::middle::privacy::AccessLevel;
|
use rustc_middle::middle::privacy::AccessLevel;
|
||||||
@ -43,12 +42,9 @@ impl Module<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Should this be replaced with tcx.def_path_str?
|
// FIXME: Should this be replaced with tcx.def_path_str?
|
||||||
fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<String> {
|
fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<Symbol> {
|
||||||
let crate_name = tcx.crate_name(did.krate).to_string();
|
let crate_name = tcx.crate_name(did.krate);
|
||||||
let relative = tcx.def_path(did).data.into_iter().filter_map(|elem| {
|
let relative = tcx.def_path(did).data.into_iter().filter_map(|elem| elem.data.get_opt_name());
|
||||||
// Filter out extern blocks
|
|
||||||
(elem.data != DefPathData::ForeignMod).then(|| elem.data.to_string())
|
|
||||||
});
|
|
||||||
std::iter::once(crate_name).chain(relative).collect()
|
std::iter::once(crate_name).chain(relative).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +67,7 @@ crate struct RustdocVisitor<'a, 'tcx> {
|
|||||||
inlining: bool,
|
inlining: bool,
|
||||||
/// Are the current module and all of its parents public?
|
/// Are the current module and all of its parents public?
|
||||||
inside_public_path: bool,
|
inside_public_path: bool,
|
||||||
exact_paths: FxHashMap<DefId, Vec<String>>,
|
exact_paths: FxHashMap<DefId, Vec<Symbol>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
|
Loading…
Reference in New Issue
Block a user