mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Auto merge of #81398 - bugadani:rustdoc-perf, r=GuillaumeGomez
rustdoc tweaking * Reuse memory * simplify `next_def_id`, avoid multiple hashing and unnecessary lookups * remove `all_fake_def_ids`, use the global map instead (probably not a good step toward parallelization, though...) * convert `add_deref_target` to iterative implementation * use `ArrayVec` where we know the max number of elements * minor touchups here and there * avoid building temporary vectors that get appended to other vectors At most places I may or may not be doing the compiler's job is this PR.
This commit is contained in:
commit
0248c6f178
@ -4386,6 +4386,7 @@ dependencies = [
|
||||
name = "rustdoc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"expect-test",
|
||||
"itertools 0.9.0",
|
||||
"minifier",
|
||||
|
@ -8,6 +8,7 @@ edition = "2018"
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
arrayvec = { version = "0.5.1", default-features = false }
|
||||
pulldown-cmark = { version = "0.8", default-features = false }
|
||||
minifier = "0.0.33"
|
||||
rayon = { version = "0.3.0", package = "rustc-rayon" }
|
||||
|
@ -56,7 +56,7 @@ crate fn try_inline(
|
||||
let kind = match res {
|
||||
Res::Def(DefKind::Trait, did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Trait);
|
||||
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
|
||||
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
|
||||
clean::TraitItem(build_external_trait(cx, did))
|
||||
}
|
||||
Res::Def(DefKind::Fn, did) => {
|
||||
@ -65,27 +65,27 @@ crate fn try_inline(
|
||||
}
|
||||
Res::Def(DefKind::Struct, did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Struct);
|
||||
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
|
||||
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
|
||||
clean::StructItem(build_struct(cx, did))
|
||||
}
|
||||
Res::Def(DefKind::Union, did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Union);
|
||||
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
|
||||
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
|
||||
clean::UnionItem(build_union(cx, did))
|
||||
}
|
||||
Res::Def(DefKind::TyAlias, did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Typedef);
|
||||
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
|
||||
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
|
||||
clean::TypedefItem(build_type_alias(cx, did), false)
|
||||
}
|
||||
Res::Def(DefKind::Enum, did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Enum);
|
||||
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
|
||||
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
|
||||
clean::EnumItem(build_enum(cx, did))
|
||||
}
|
||||
Res::Def(DefKind::ForeignTy, did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Foreign);
|
||||
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
|
||||
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
|
||||
clean::ForeignTypeItem
|
||||
}
|
||||
// Never inline enum variants but leave them shown as re-exports.
|
||||
@ -133,10 +133,7 @@ crate fn try_inline_glob(
|
||||
res: Res,
|
||||
visited: &mut FxHashSet<DefId>,
|
||||
) -> Option<Vec<clean::Item>> {
|
||||
if res == Res::Err {
|
||||
return None;
|
||||
}
|
||||
let did = res.def_id();
|
||||
let did = res.opt_def_id()?;
|
||||
if did.is_local() {
|
||||
return None;
|
||||
}
|
||||
@ -280,16 +277,14 @@ crate fn build_impls(
|
||||
parent_module: Option<DefId>,
|
||||
did: DefId,
|
||||
attrs: Option<Attrs<'_>>,
|
||||
) -> Vec<clean::Item> {
|
||||
ret: &mut Vec<clean::Item>,
|
||||
) {
|
||||
let tcx = cx.tcx;
|
||||
let mut impls = Vec::new();
|
||||
|
||||
// for each implementation of an item represented by `did`, build the clean::Item for that impl
|
||||
for &did in tcx.inherent_impls(did).iter() {
|
||||
build_impl(cx, parent_module, did, attrs, &mut impls);
|
||||
build_impl(cx, parent_module, did, attrs, ret);
|
||||
}
|
||||
|
||||
impls
|
||||
}
|
||||
|
||||
/// `parent_module` refers to the parent of the re-export, not the original item
|
||||
|
@ -8,6 +8,7 @@ use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::{slice, vec};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use rustc_ast::attr;
|
||||
use rustc_ast::util::comments::beautify_doc_string;
|
||||
use rustc_ast::{self as ast, AttrStyle};
|
||||
@ -16,7 +17,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_feature::UnstableFeatures;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::Mutability;
|
||||
use rustc_index::vec::IndexVec;
|
||||
@ -28,7 +29,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr};
|
||||
use rustc_span::{self, FileName, Loc};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use crate::clean::cfg::Cfg;
|
||||
use crate::clean::external_path;
|
||||
@ -45,7 +45,7 @@ use self::ItemKind::*;
|
||||
use self::SelfTy::*;
|
||||
use self::Type::*;
|
||||
|
||||
thread_local!(crate static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
|
||||
thread_local!(crate static MAX_DEF_IDX: RefCell<FxHashMap<CrateNum, DefIndex>> = Default::default());
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
crate struct Crate {
|
||||
@ -293,8 +293,8 @@ impl Item {
|
||||
///
|
||||
/// [`next_def_id()`]: DocContext::next_def_id()
|
||||
crate fn is_fake(&self) -> bool {
|
||||
MAX_DEF_ID.with(|m| {
|
||||
m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
|
||||
MAX_DEF_IDX.with(|m| {
|
||||
m.borrow().get(&self.def_id.krate).map(|&idx| idx <= self.def_id.index).unwrap_or(false)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1539,12 +1539,12 @@ impl PrimitiveType {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
|
||||
crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<[DefId; 4]> {
|
||||
Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
|
||||
}
|
||||
|
||||
crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
|
||||
static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
|
||||
crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<[DefId; 4]>> {
|
||||
static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<[DefId; 4]>>> = OnceCell::new();
|
||||
|
||||
CELL.get_or_init(move || {
|
||||
use self::PrimitiveType::*;
|
||||
@ -1568,7 +1568,7 @@ impl PrimitiveType {
|
||||
}
|
||||
|
||||
let single = |a: Option<DefId>| a.into_iter().collect();
|
||||
let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
|
||||
let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_> {
|
||||
a.into_iter().chain(b).collect()
|
||||
};
|
||||
|
||||
@ -1601,8 +1601,8 @@ impl PrimitiveType {
|
||||
.collect()
|
||||
},
|
||||
Array => single(lang_items.array_impl()),
|
||||
Tuple => smallvec![],
|
||||
Unit => smallvec![],
|
||||
Tuple => ArrayVec::new(),
|
||||
Unit => ArrayVec::new(),
|
||||
RawPointer => {
|
||||
lang_items
|
||||
.const_ptr_impl()
|
||||
@ -1612,9 +1612,9 @@ impl PrimitiveType {
|
||||
.chain(lang_items.mut_slice_ptr_impl())
|
||||
.collect()
|
||||
},
|
||||
Reference => smallvec![],
|
||||
Fn => smallvec![],
|
||||
Never => smallvec![],
|
||||
Reference => ArrayVec::new(),
|
||||
Fn => ArrayVec::new(),
|
||||
Never => ArrayVec::new(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -322,21 +322,15 @@ crate fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut
|
||||
ItemKind::TypedefItem(ref t, true) => &t.type_,
|
||||
_ => continue,
|
||||
};
|
||||
let primitive = match *target {
|
||||
ResolvedPath { did, .. } if did.is_local() => continue,
|
||||
ResolvedPath { did, .. } => {
|
||||
ret.extend(inline::build_impls(cx, None, did, None));
|
||||
continue;
|
||||
}
|
||||
_ => match target.primitive_type() {
|
||||
Some(prim) => prim,
|
||||
None => continue,
|
||||
},
|
||||
};
|
||||
for &did in primitive.impls(tcx) {
|
||||
if !did.is_local() {
|
||||
|
||||
if let Some(prim) = target.primitive_type() {
|
||||
for &did in prim.impls(tcx).iter().filter(|did| !did.is_local()) {
|
||||
inline::build_impl(cx, None, did, None, ret);
|
||||
}
|
||||
} else if let ResolvedPath { did, .. } = *target {
|
||||
if !did.is_local() {
|
||||
inline::build_impls(cx, None, did, None, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -474,7 +474,7 @@ impl Options {
|
||||
};
|
||||
|
||||
let mut id_map = html::markdown::IdMap::new();
|
||||
id_map.populate(html::render::initial_ids());
|
||||
id_map.populate(&html::render::INITIAL_IDS);
|
||||
let external_html = match ExternalHtml::load(
|
||||
&matches.opt_strs("html-in-header"),
|
||||
&matches.opt_strs("html-before-content"),
|
||||
|
@ -24,12 +24,15 @@ use rustc_span::source_map;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
collections::hash_map::Entry,
|
||||
};
|
||||
|
||||
use crate::clean;
|
||||
use crate::clean::{AttributesExt, MAX_DEF_ID};
|
||||
use crate::clean::{AttributesExt, MAX_DEF_IDX};
|
||||
use crate::config::{Options as RustdocOptions, RenderOptions};
|
||||
use crate::config::{OutputFormat, RenderInfo};
|
||||
use crate::formats::cache::Cache;
|
||||
@ -63,8 +66,7 @@ crate struct DocContext<'tcx> {
|
||||
crate ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>,
|
||||
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
|
||||
crate impl_trait_bounds: RefCell<FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>>,
|
||||
crate fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
|
||||
crate all_fake_def_ids: RefCell<FxHashSet<DefId>>,
|
||||
crate fake_def_ids: RefCell<FxHashMap<CrateNum, DefIndex>>,
|
||||
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
|
||||
// FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set.
|
||||
crate generated_synthetics: RefCell<FxHashSet<(Ty<'tcx>, DefId)>>,
|
||||
@ -138,37 +140,38 @@ impl<'tcx> DocContext<'tcx> {
|
||||
/// [`Debug`]: std::fmt::Debug
|
||||
/// [`clean::Item`]: crate::clean::types::Item
|
||||
crate fn next_def_id(&self, crate_num: CrateNum) -> DefId {
|
||||
let start_def_id = {
|
||||
let num_def_ids = if crate_num == LOCAL_CRATE {
|
||||
self.tcx.hir().definitions().def_path_table().num_def_ids()
|
||||
} else {
|
||||
self.enter_resolver(|r| r.cstore().num_def_ids(crate_num))
|
||||
};
|
||||
|
||||
DefId { krate: crate_num, index: DefIndex::from_usize(num_def_ids) }
|
||||
};
|
||||
|
||||
let mut fake_ids = self.fake_def_ids.borrow_mut();
|
||||
|
||||
let def_id = *fake_ids.entry(crate_num).or_insert(start_def_id);
|
||||
fake_ids.insert(
|
||||
crate_num,
|
||||
DefId { krate: crate_num, index: DefIndex::from(def_id.index.index() + 1) },
|
||||
);
|
||||
let def_index = match fake_ids.entry(crate_num) {
|
||||
Entry::Vacant(e) => {
|
||||
let num_def_idx = {
|
||||
let num_def_idx = if crate_num == LOCAL_CRATE {
|
||||
self.tcx.hir().definitions().def_path_table().num_def_ids()
|
||||
} else {
|
||||
self.enter_resolver(|r| r.cstore().num_def_ids(crate_num))
|
||||
};
|
||||
|
||||
MAX_DEF_ID.with(|m| {
|
||||
m.borrow_mut().entry(def_id.krate).or_insert(start_def_id);
|
||||
});
|
||||
DefIndex::from_usize(num_def_idx)
|
||||
};
|
||||
|
||||
self.all_fake_def_ids.borrow_mut().insert(def_id);
|
||||
MAX_DEF_IDX.with(|m| {
|
||||
m.borrow_mut().insert(crate_num, num_def_idx);
|
||||
});
|
||||
e.insert(num_def_idx)
|
||||
}
|
||||
Entry::Occupied(e) => e.into_mut(),
|
||||
};
|
||||
*def_index = DefIndex::from(*def_index + 1);
|
||||
|
||||
def_id
|
||||
DefId { krate: crate_num, index: *def_index }
|
||||
}
|
||||
|
||||
/// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
|
||||
/// (This avoids a slice-index-out-of-bounds panic.)
|
||||
crate fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
|
||||
if self.all_fake_def_ids.borrow().contains(&def_id) {
|
||||
if MAX_DEF_IDX.with(|m| {
|
||||
m.borrow().get(&def_id.krate).map(|&idx| idx <= def_id.index).unwrap_or(false)
|
||||
}) {
|
||||
None
|
||||
} else {
|
||||
def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
|
||||
@ -517,7 +520,6 @@ crate fn run_global_ctxt(
|
||||
ct_substs: Default::default(),
|
||||
impl_trait_bounds: Default::default(),
|
||||
fake_def_ids: Default::default(),
|
||||
all_fake_def_ids: Default::default(),
|
||||
generated_synthetics: Default::default(),
|
||||
auto_traits: tcx
|
||||
.all_traits(LOCAL_CRATE)
|
||||
|
@ -158,6 +158,6 @@ impl ItemType {
|
||||
|
||||
impl fmt::Display for ItemType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
@ -16,23 +16,20 @@ impl<'a> fmt::Display for Escape<'a> {
|
||||
let Escape(s) = *self;
|
||||
let pile_o_bits = s;
|
||||
let mut last = 0;
|
||||
for (i, ch) in s.bytes().enumerate() {
|
||||
match ch as char {
|
||||
'<' | '>' | '&' | '\'' | '"' => {
|
||||
fmt.write_str(&pile_o_bits[last..i])?;
|
||||
let s = match ch as char {
|
||||
'>' => ">",
|
||||
'<' => "<",
|
||||
'&' => "&",
|
||||
'\'' => "'",
|
||||
'"' => """,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
fmt.write_str(s)?;
|
||||
last = i + 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
for (i, ch) in s.char_indices() {
|
||||
let s = match ch {
|
||||
'>' => ">",
|
||||
'<' => "<",
|
||||
'&' => "&",
|
||||
'\'' => "'",
|
||||
'"' => """,
|
||||
_ => continue,
|
||||
};
|
||||
fmt.write_str(&pile_o_bits[last..i])?;
|
||||
fmt.write_str(s)?;
|
||||
// NOTE: we only expect single byte characters here - which is fine as long as we
|
||||
// only match single byte characters
|
||||
last = i + 1;
|
||||
}
|
||||
|
||||
if last < s.len() {
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
use crate::html::escape::Escape;
|
||||
|
||||
use std::fmt::{Display, Write};
|
||||
use std::fmt::Display;
|
||||
use std::iter::Peekable;
|
||||
|
||||
use rustc_lexer::{LiteralKind, TokenKind};
|
||||
@ -15,16 +15,18 @@ use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::with_default_session_globals;
|
||||
|
||||
use super::format::Buffer;
|
||||
|
||||
/// Highlights `src`, returning the HTML output.
|
||||
crate fn render_with_highlighting(
|
||||
src: String,
|
||||
src: &str,
|
||||
out: &mut Buffer,
|
||||
class: Option<&str>,
|
||||
playground_button: Option<&str>,
|
||||
tooltip: Option<(Option<Edition>, &str)>,
|
||||
edition: Edition,
|
||||
) -> String {
|
||||
) {
|
||||
debug!("highlighting: ================\n{}\n==============", src);
|
||||
let mut out = String::with_capacity(src.len());
|
||||
if let Some((edition_info, class)) = tooltip {
|
||||
write!(
|
||||
out,
|
||||
@ -35,23 +37,19 @@ crate fn render_with_highlighting(
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
);
|
||||
}
|
||||
|
||||
write_header(&mut out, class);
|
||||
write_code(&mut out, &src, edition);
|
||||
write_footer(&mut out, playground_button);
|
||||
|
||||
out
|
||||
write_header(out, class);
|
||||
write_code(out, &src, edition);
|
||||
write_footer(out, playground_button);
|
||||
}
|
||||
|
||||
fn write_header(out: &mut String, class: Option<&str>) {
|
||||
write!(out, "<div class=\"example-wrap\"><pre class=\"rust {}\">\n", class.unwrap_or_default())
|
||||
.unwrap()
|
||||
fn write_header(out: &mut Buffer, class: Option<&str>) {
|
||||
write!(out, "<div class=\"example-wrap\"><pre class=\"rust {}\">\n", class.unwrap_or_default());
|
||||
}
|
||||
|
||||
fn write_code(out: &mut String, src: &str, edition: Edition) {
|
||||
fn write_code(out: &mut Buffer, src: &str, edition: Edition) {
|
||||
// This replace allows to fix how the code source with DOS backline characters is displayed.
|
||||
let src = src.replace("\r\n", "\n");
|
||||
Classifier::new(&src, edition).highlight(&mut |highlight| {
|
||||
@ -63,8 +61,8 @@ fn write_code(out: &mut String, src: &str, edition: Edition) {
|
||||
});
|
||||
}
|
||||
|
||||
fn write_footer(out: &mut String, playground_button: Option<&str>) {
|
||||
write!(out, "</pre>{}</div>\n", playground_button.unwrap_or_default()).unwrap()
|
||||
fn write_footer(out: &mut Buffer, playground_button: Option<&str>) {
|
||||
write!(out, "</pre>{}</div>\n", playground_button.unwrap_or_default());
|
||||
}
|
||||
|
||||
/// How a span of text is classified. Mostly corresponds to token kinds.
|
||||
@ -331,13 +329,13 @@ impl<'a> Classifier<'a> {
|
||||
|
||||
/// Called when we start processing a span of text that should be highlighted.
|
||||
/// The `Class` argument specifies how it should be highlighted.
|
||||
fn enter_span(out: &mut String, klass: Class) {
|
||||
write!(out, "<span class=\"{}\">", klass.as_html()).unwrap()
|
||||
fn enter_span(out: &mut Buffer, klass: Class) {
|
||||
write!(out, "<span class=\"{}\">", klass.as_html());
|
||||
}
|
||||
|
||||
/// Called at the end of a span of highlighted text.
|
||||
fn exit_span(out: &mut String) {
|
||||
write!(out, "</span>").unwrap()
|
||||
fn exit_span(out: &mut Buffer) {
|
||||
out.write_str("</span>");
|
||||
}
|
||||
|
||||
/// Called for a span of text. If the text should be highlighted differently
|
||||
@ -351,10 +349,10 @@ fn exit_span(out: &mut String) {
|
||||
/// ```
|
||||
/// The latter can be thought of as a shorthand for the former, which is more
|
||||
/// flexible.
|
||||
fn string<T: Display>(out: &mut String, text: T, klass: Option<Class>) {
|
||||
fn string<T: Display>(out: &mut Buffer, text: T, klass: Option<Class>) {
|
||||
match klass {
|
||||
None => write!(out, "{}", text).unwrap(),
|
||||
Some(klass) => write!(out, "<span class=\"{}\">{}</span>", klass.as_html(), text).unwrap(),
|
||||
None => write!(out, "{}", text),
|
||||
Some(klass) => write!(out, "<span class=\"{}\">{}</span>", klass.as_html(), text),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::write_code;
|
||||
use crate::html::format::Buffer;
|
||||
use expect_test::expect_file;
|
||||
use rustc_span::edition::Edition;
|
||||
|
||||
@ -18,9 +19,9 @@ const STYLE: &str = r#"
|
||||
fn test_html_highlighting() {
|
||||
let src = include_str!("fixtures/sample.rs");
|
||||
let html = {
|
||||
let mut out = String::new();
|
||||
let mut out = Buffer::new();
|
||||
write_code(&mut out, src, Edition::Edition2018);
|
||||
format!("{}<pre><code>{}</code></pre>\n", STYLE, out)
|
||||
format!("{}<pre><code>{}</code></pre>\n", STYLE, out.into_inner())
|
||||
};
|
||||
expect_file!["fixtures/sample.html"].assert_eq(&html);
|
||||
}
|
||||
@ -30,7 +31,7 @@ fn test_dos_backline() {
|
||||
let src = "pub fn foo() {\r\n\
|
||||
println!(\"foo\");\r\n\
|
||||
}\r\n";
|
||||
let mut html = String::new();
|
||||
let mut html = Buffer::new();
|
||||
write_code(&mut html, src, Edition::Edition2018);
|
||||
expect_file!["fixtures/dos_line.html"].assert_eq(&html);
|
||||
expect_file!["fixtures/dos_line.html"].assert_eq(&html.into_inner());
|
||||
}
|
||||
|
@ -114,7 +114,6 @@ crate fn render<T: Print, S: Print>(
|
||||
{after_content}\
|
||||
<div id=\"rustdoc-vars\" data-root-path=\"{root_path}\" data-current-crate=\"{krate}\"></div>
|
||||
<script src=\"{static_root_path}main{suffix}.js\"></script>\
|
||||
{static_extra_scripts}\
|
||||
{extra_scripts}\
|
||||
<script defer src=\"{root_path}search-index{suffix}.js\"></script>\
|
||||
</body>\
|
||||
@ -135,22 +134,23 @@ crate fn render<T: Print, S: Print>(
|
||||
root_path = page.root_path,
|
||||
css_class = page.css_class,
|
||||
logo = {
|
||||
let p = format!("{}{}", page.root_path, layout.krate);
|
||||
let p = ensure_trailing_slash(&p);
|
||||
if layout.logo.is_empty() {
|
||||
format!(
|
||||
"<a href='{path}index.html'>\
|
||||
"<a href='{root}{path}index.html'>\
|
||||
<div class='logo-container rust-logo'>\
|
||||
<img src='{static_root_path}rust-logo{suffix}.png' alt='logo'></div></a>",
|
||||
path = p,
|
||||
root = page.root_path,
|
||||
path = ensure_trailing_slash(&layout.krate),
|
||||
static_root_path = static_root_path,
|
||||
suffix = page.resource_suffix
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"<a href='{}index.html'>\
|
||||
<div class='logo-container'><img src='{}' alt='logo'></div></a>",
|
||||
p, layout.logo
|
||||
"<a href='{root}{path}index.html'>\
|
||||
<div class='logo-container'><img src='{logo}' alt='logo'></div></a>",
|
||||
root = page.root_path,
|
||||
path = ensure_trailing_slash(&layout.krate),
|
||||
logo = layout.logo
|
||||
)
|
||||
}
|
||||
},
|
||||
@ -194,7 +194,7 @@ crate fn render<T: Print, S: Print>(
|
||||
))
|
||||
.collect::<String>(),
|
||||
suffix = page.resource_suffix,
|
||||
static_extra_scripts = page
|
||||
extra_scripts = page
|
||||
.static_extra_scripts
|
||||
.iter()
|
||||
.map(|e| {
|
||||
@ -204,17 +204,13 @@ crate fn render<T: Print, S: Print>(
|
||||
extra_script = e
|
||||
)
|
||||
})
|
||||
.collect::<String>(),
|
||||
extra_scripts = page
|
||||
.extra_scripts
|
||||
.iter()
|
||||
.map(|e| {
|
||||
.chain(page.extra_scripts.iter().map(|e| {
|
||||
format!(
|
||||
"<script src=\"{root_path}{extra_script}.js\"></script>",
|
||||
root_path = page.root_path,
|
||||
extra_script = e
|
||||
)
|
||||
})
|
||||
}))
|
||||
.collect::<String>(),
|
||||
filter_crates = if layout.generate_search_filter {
|
||||
"<select id=\"crate-search\">\
|
||||
|
@ -41,6 +41,8 @@ use pulldown_cmark::{
|
||||
html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
|
||||
};
|
||||
|
||||
use super::format::Buffer;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@ -235,9 +237,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||
}
|
||||
let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
|
||||
let text = lines.collect::<Vec<Cow<'_, str>>>().join("\n");
|
||||
// insert newline to clearly separate it from the
|
||||
// previous block so we can shorten the html output
|
||||
let mut s = String::from("\n");
|
||||
|
||||
let playground_button = self.playground.as_ref().and_then(|playground| {
|
||||
let krate = &playground.crate_name;
|
||||
let url = &playground.url;
|
||||
@ -298,8 +298,13 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||
None
|
||||
};
|
||||
|
||||
s.push_str(&highlight::render_with_highlighting(
|
||||
text,
|
||||
// insert newline to clearly separate it from the
|
||||
// previous block so we can shorten the html output
|
||||
let mut s = Buffer::new();
|
||||
s.push_str("\n");
|
||||
highlight::render_with_highlighting(
|
||||
&text,
|
||||
&mut s,
|
||||
Some(&format!(
|
||||
"rust-example-rendered{}",
|
||||
if let Some((_, class)) = tooltip { format!(" {}", class) } else { String::new() }
|
||||
@ -307,8 +312,8 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
|
||||
playground_button.as_deref(),
|
||||
tooltip,
|
||||
edition,
|
||||
));
|
||||
Some(Event::Html(s.into()))
|
||||
);
|
||||
Some(Event::Html(s.into_inner().into()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1332,7 +1337,7 @@ impl IdMap {
|
||||
IdMap { map: init_id_map() }
|
||||
}
|
||||
|
||||
crate fn populate<I: IntoIterator<Item = String>>(&mut self, ids: I) {
|
||||
crate fn populate<I: IntoIterator<Item = S>, S: AsRef<str> + ToString>(&mut self, ids: I) {
|
||||
for id in ids {
|
||||
let _ = self.derive(id);
|
||||
}
|
||||
@ -1342,11 +1347,11 @@ impl IdMap {
|
||||
self.map = init_id_map();
|
||||
}
|
||||
|
||||
crate fn derive(&mut self, candidate: String) -> String {
|
||||
let id = match self.map.get_mut(&candidate) {
|
||||
None => candidate,
|
||||
crate fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
|
||||
let id = match self.map.get_mut(candidate.as_ref()) {
|
||||
None => candidate.to_string(),
|
||||
Some(a) => {
|
||||
let id = format!("{}-{}", candidate, *a);
|
||||
let id = format!("{}-{}", candidate.as_ref(), *a);
|
||||
*a += 1;
|
||||
id
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -86,7 +86,7 @@ impl SourceCollector<'_, '_> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut contents = match fs::read_to_string(&p) {
|
||||
let contents = match fs::read_to_string(&p) {
|
||||
Ok(contents) => contents,
|
||||
Err(e) => {
|
||||
return Err(Error::new(e, &p));
|
||||
@ -94,9 +94,7 @@ impl SourceCollector<'_, '_> {
|
||||
};
|
||||
|
||||
// Remove the utf-8 BOM if any
|
||||
if contents.starts_with('\u{feff}') {
|
||||
contents.drain(..3);
|
||||
}
|
||||
let contents = if contents.starts_with('\u{feff}') { &contents[3..] } else { &contents };
|
||||
|
||||
// Create the intermediate directories
|
||||
let mut cur = self.dst.clone();
|
||||
@ -171,7 +169,7 @@ where
|
||||
|
||||
/// Wrapper struct to render the source code of a file. This will do things like
|
||||
/// adding line numbers to the left-hand side.
|
||||
fn print_src(buf: &mut Buffer, s: String, edition: Edition) {
|
||||
fn print_src(buf: &mut Buffer, s: &str, edition: Edition) {
|
||||
let lines = s.lines().count();
|
||||
let mut cols = 0;
|
||||
let mut tmp = lines;
|
||||
@ -179,10 +177,10 @@ fn print_src(buf: &mut Buffer, s: String, edition: Edition) {
|
||||
cols += 1;
|
||||
tmp /= 10;
|
||||
}
|
||||
write!(buf, "<pre class=\"line-numbers\">");
|
||||
buf.write_str("<pre class=\"line-numbers\">");
|
||||
for i in 1..=lines {
|
||||
write!(buf, "<span id=\"{0}\">{0:1$}</span>\n", i, cols);
|
||||
}
|
||||
write!(buf, "</pre>");
|
||||
write!(buf, "{}", highlight::render_with_highlighting(s, None, None, None, edition));
|
||||
buf.write_str("</pre>");
|
||||
highlight::render_with_highlighting(s, buf, None, None, None, edition);
|
||||
}
|
||||
|
@ -56,12 +56,12 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
|
||||
|
||||
// `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
|
||||
// doesn't work with it anyway, so pull them from the HIR map instead
|
||||
let mut extra_attrs = Vec::new();
|
||||
for &trait_did in cx.tcx.all_traits(LOCAL_CRATE).iter() {
|
||||
for &impl_node in cx.tcx.hir().trait_impls(trait_did) {
|
||||
let impl_did = cx.tcx.hir().local_def_id(impl_node);
|
||||
let impl_did = cx.tcx.hir().local_def_id(impl_node).to_def_id();
|
||||
cx.tcx.sess.prof.generic_activity("build_local_trait_impl").run(|| {
|
||||
let mut extra_attrs = Vec::new();
|
||||
let mut parent = cx.tcx.parent(impl_did.to_def_id());
|
||||
let mut parent = cx.tcx.parent(impl_did);
|
||||
while let Some(did) = parent {
|
||||
extra_attrs.extend(
|
||||
cx.tcx
|
||||
@ -79,13 +79,8 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
|
||||
);
|
||||
parent = cx.tcx.parent(did);
|
||||
}
|
||||
inline::build_impl(
|
||||
cx,
|
||||
None,
|
||||
impl_did.to_def_id(),
|
||||
Some(&extra_attrs),
|
||||
&mut new_items,
|
||||
);
|
||||
inline::build_impl(cx, None, impl_did, Some(&extra_attrs), &mut new_items);
|
||||
extra_attrs.clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -137,25 +132,28 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
|
||||
}
|
||||
}
|
||||
|
||||
new_items.retain(|it| {
|
||||
if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
|
||||
cleaner.keep_impl(for_)
|
||||
|| trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t))
|
||||
|| blanket_impl.is_some()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(ref mut it) = krate.module {
|
||||
let items = if let Some(ref mut it) = krate.module {
|
||||
if let ModuleItem(Module { ref mut items, .. }) = *it.kind {
|
||||
items.extend(synth.impls);
|
||||
items.extend(new_items);
|
||||
items
|
||||
} else {
|
||||
panic!("collect-trait-impls can't run");
|
||||
}
|
||||
} else {
|
||||
panic!("collect-trait-impls can't run");
|
||||
};
|
||||
|
||||
items.extend(synth.impls);
|
||||
for it in new_items.drain(..) {
|
||||
if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
|
||||
if !(cleaner.keep_impl(for_)
|
||||
|| trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t))
|
||||
|| blanket_impl.is_some())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
items.push(it);
|
||||
}
|
||||
|
||||
krate
|
||||
|
Loading…
Reference in New Issue
Block a user