Slim down rustdoc::html::render::Context
Like the comment on `Context` explains, `Context` is supposed to be lightweight, so we're putting everything that's immutable after creation of the Context behind an `Arc<SharedContext>`.
This commit is contained in:
parent
0ef85c1e6a
commit
95eb8a68aa
1 changed files with 47 additions and 40 deletions
|
@ -91,12 +91,20 @@ pub struct Context {
|
||||||
/// String representation of how to get back to the root path of the 'doc/'
|
/// String representation of how to get back to the root path of the 'doc/'
|
||||||
/// folder in terms of a relative URL.
|
/// folder in terms of a relative URL.
|
||||||
pub root_path: String,
|
pub root_path: String,
|
||||||
/// The path to the crate root source minus the file name.
|
|
||||||
/// Used for simplifying paths to the highlighted source code files.
|
|
||||||
pub src_root: PathBuf,
|
|
||||||
/// 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.
|
||||||
pub dst: PathBuf,
|
pub dst: PathBuf,
|
||||||
|
/// A flag, which when `true`, will render pages which redirect to the
|
||||||
|
/// real location of an item. This is used to allow external links to
|
||||||
|
/// publicly reused items to redirect to the right location.
|
||||||
|
pub render_redirect_pages: bool,
|
||||||
|
pub shared: Arc<SharedContext>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SharedContext {
|
||||||
|
/// The path to the crate root source minus the file name.
|
||||||
|
/// Used for simplifying paths to the highlighted source code files.
|
||||||
|
pub src_root: PathBuf,
|
||||||
/// This describes the layout of each page, and is not modified after
|
/// This describes the layout of each page, and is not modified after
|
||||||
/// creation of the context (contains info like the favicon and added html).
|
/// creation of the context (contains info like the favicon and added html).
|
||||||
pub layout: layout::Layout,
|
pub layout: layout::Layout,
|
||||||
|
@ -106,10 +114,6 @@ pub struct Context {
|
||||||
pub include_sources: bool,
|
pub include_sources: bool,
|
||||||
/// The local file sources we've emitted and their respective url-paths.
|
/// The local file sources we've emitted and their respective url-paths.
|
||||||
pub local_sources: HashMap<PathBuf, String>,
|
pub local_sources: HashMap<PathBuf, String>,
|
||||||
/// A flag, which when turned off, will render pages which redirect to the
|
|
||||||
/// real location of an item. This is used to allow external links to
|
|
||||||
/// publicly reused items to redirect to the right location.
|
|
||||||
pub render_redirect_pages: bool,
|
|
||||||
/// All the passes that were run on this crate.
|
/// All the passes that were run on this crate.
|
||||||
pub passes: HashSet<String>,
|
pub passes: HashSet<String>,
|
||||||
/// The base-URL of the issue tracker for when an item has been tagged with
|
/// The base-URL of the issue tracker for when an item has been tagged with
|
||||||
|
@ -259,7 +263,7 @@ pub struct Cache {
|
||||||
|
|
||||||
/// Helper struct to render all source code to HTML pages
|
/// Helper struct to render all source code to HTML pages
|
||||||
struct SourceCollector<'a> {
|
struct SourceCollector<'a> {
|
||||||
cx: &'a mut Context,
|
scx: &'a mut SharedContext,
|
||||||
|
|
||||||
/// Root destination to place all HTML output into
|
/// Root destination to place all HTML output into
|
||||||
dst: PathBuf,
|
dst: PathBuf,
|
||||||
|
@ -412,12 +416,12 @@ pub fn run(mut krate: clean::Crate,
|
||||||
Some(p) => p.to_path_buf(),
|
Some(p) => p.to_path_buf(),
|
||||||
None => PathBuf::new(),
|
None => PathBuf::new(),
|
||||||
};
|
};
|
||||||
let mut cx = Context {
|
let mut scx = SharedContext {
|
||||||
dst: dst,
|
|
||||||
src_root: src_root,
|
src_root: src_root,
|
||||||
passes: passes,
|
passes: passes,
|
||||||
current: Vec::new(),
|
include_sources: true,
|
||||||
root_path: String::new(),
|
local_sources: HashMap::new(),
|
||||||
|
issue_tracker_base_url: None,
|
||||||
layout: layout::Layout {
|
layout: layout::Layout {
|
||||||
logo: "".to_string(),
|
logo: "".to_string(),
|
||||||
favicon: "".to_string(),
|
favicon: "".to_string(),
|
||||||
|
@ -425,14 +429,8 @@ pub fn run(mut krate: clean::Crate,
|
||||||
krate: krate.name.clone(),
|
krate: krate.name.clone(),
|
||||||
playground_url: "".to_string(),
|
playground_url: "".to_string(),
|
||||||
},
|
},
|
||||||
include_sources: true,
|
|
||||||
local_sources: HashMap::new(),
|
|
||||||
render_redirect_pages: false,
|
|
||||||
issue_tracker_base_url: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try_err!(mkdir(&cx.dst), &cx.dst);
|
|
||||||
|
|
||||||
// Crawl the crate attributes looking for attributes which control how we're
|
// Crawl the crate attributes looking for attributes which control how we're
|
||||||
// going to emit HTML
|
// going to emit HTML
|
||||||
if let Some(attrs) = krate.module.as_ref().map(|m| m.attrs.list("doc")) {
|
if let Some(attrs) = krate.module.as_ref().map(|m| m.attrs.list("doc")) {
|
||||||
|
@ -440,15 +438,15 @@ pub fn run(mut krate: clean::Crate,
|
||||||
match *attr {
|
match *attr {
|
||||||
clean::NameValue(ref x, ref s)
|
clean::NameValue(ref x, ref s)
|
||||||
if "html_favicon_url" == *x => {
|
if "html_favicon_url" == *x => {
|
||||||
cx.layout.favicon = s.to_string();
|
scx.layout.favicon = s.to_string();
|
||||||
}
|
}
|
||||||
clean::NameValue(ref x, ref s)
|
clean::NameValue(ref x, ref s)
|
||||||
if "html_logo_url" == *x => {
|
if "html_logo_url" == *x => {
|
||||||
cx.layout.logo = s.to_string();
|
scx.layout.logo = s.to_string();
|
||||||
}
|
}
|
||||||
clean::NameValue(ref x, ref s)
|
clean::NameValue(ref x, ref s)
|
||||||
if "html_playground_url" == *x => {
|
if "html_playground_url" == *x => {
|
||||||
cx.layout.playground_url = s.to_string();
|
scx.layout.playground_url = s.to_string();
|
||||||
markdown::PLAYGROUND_KRATE.with(|slot| {
|
markdown::PLAYGROUND_KRATE.with(|slot| {
|
||||||
if slot.borrow().is_none() {
|
if slot.borrow().is_none() {
|
||||||
let name = krate.name.clone();
|
let name = krate.name.clone();
|
||||||
|
@ -458,16 +456,25 @@ pub fn run(mut krate: clean::Crate,
|
||||||
}
|
}
|
||||||
clean::NameValue(ref x, ref s)
|
clean::NameValue(ref x, ref s)
|
||||||
if "issue_tracker_base_url" == *x => {
|
if "issue_tracker_base_url" == *x => {
|
||||||
cx.issue_tracker_base_url = Some(s.to_string());
|
scx.issue_tracker_base_url = Some(s.to_string());
|
||||||
}
|
}
|
||||||
clean::Word(ref x)
|
clean::Word(ref x)
|
||||||
if "html_no_source" == *x => {
|
if "html_no_source" == *x => {
|
||||||
cx.include_sources = false;
|
scx.include_sources = false;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try_err!(mkdir(&dst), &dst);
|
||||||
|
krate = render_sources(&dst, &mut scx, krate)?;
|
||||||
|
let cx = Context {
|
||||||
|
current: Vec::new(),
|
||||||
|
root_path: String::new(),
|
||||||
|
dst: dst,
|
||||||
|
render_redirect_pages: false,
|
||||||
|
shared: Arc::new(scx),
|
||||||
|
};
|
||||||
|
|
||||||
// Crawl the crate to build various caches used for the output
|
// Crawl the crate to build various caches used for the output
|
||||||
let analysis = ::ANALYSISKEY.with(|a| a.clone());
|
let analysis = ::ANALYSISKEY.with(|a| a.clone());
|
||||||
|
@ -538,7 +545,6 @@ pub fn run(mut krate: clean::Crate,
|
||||||
CURRENT_LOCATION_KEY.with(|s| s.borrow_mut().clear());
|
CURRENT_LOCATION_KEY.with(|s| s.borrow_mut().clear());
|
||||||
|
|
||||||
write_shared(&cx, &krate, &*cache, index)?;
|
write_shared(&cx, &krate, &*cache, index)?;
|
||||||
let krate = render_sources(&mut cx, krate)?;
|
|
||||||
|
|
||||||
// And finally render the whole crate's documentation
|
// And finally render the whole crate's documentation
|
||||||
cx.krate(krate)
|
cx.krate(krate)
|
||||||
|
@ -760,16 +766,16 @@ fn write_shared(cx: &Context,
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_sources(cx: &mut Context,
|
fn render_sources(dst: &Path, scx: &mut SharedContext,
|
||||||
krate: clean::Crate) -> Result<clean::Crate, Error> {
|
krate: clean::Crate) -> Result<clean::Crate, Error> {
|
||||||
info!("emitting source files");
|
info!("emitting source files");
|
||||||
let dst = cx.dst.join("src");
|
let dst = dst.join("src");
|
||||||
try_err!(mkdir(&dst), &dst);
|
try_err!(mkdir(&dst), &dst);
|
||||||
let dst = dst.join(&krate.name);
|
let dst = dst.join(&krate.name);
|
||||||
try_err!(mkdir(&dst), &dst);
|
try_err!(mkdir(&dst), &dst);
|
||||||
let mut folder = SourceCollector {
|
let mut folder = SourceCollector {
|
||||||
dst: dst,
|
dst: dst,
|
||||||
cx: cx,
|
scx: scx,
|
||||||
};
|
};
|
||||||
Ok(folder.fold_crate(krate))
|
Ok(folder.fold_crate(krate))
|
||||||
}
|
}
|
||||||
|
@ -847,7 +853,7 @@ impl<'a> DocFolder for SourceCollector<'a> {
|
||||||
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
|
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
|
||||||
// If we're including source files, and we haven't seen this file yet,
|
// If we're including source files, and we haven't seen this file yet,
|
||||||
// then we need to render it out to the filesystem
|
// then we need to render it out to the filesystem
|
||||||
if self.cx.include_sources
|
if self.scx.include_sources
|
||||||
// skip all invalid spans
|
// skip all invalid spans
|
||||||
&& item.source.filename != ""
|
&& item.source.filename != ""
|
||||||
// macros from other libraries get special filenames which we can
|
// macros from other libraries get special filenames which we can
|
||||||
|
@ -860,7 +866,7 @@ impl<'a> DocFolder for SourceCollector<'a> {
|
||||||
// something like that), so just don't include sources for the
|
// something like that), so just don't include sources for the
|
||||||
// entire crate. The other option is maintaining this mapping on a
|
// entire crate. The other option is maintaining this mapping on a
|
||||||
// per-file basis, but that's probably not worth it...
|
// per-file basis, but that's probably not worth it...
|
||||||
self.cx
|
self.scx
|
||||||
.include_sources = match self.emit_source(&item.source.filename) {
|
.include_sources = match self.emit_source(&item.source.filename) {
|
||||||
Ok(()) => true,
|
Ok(()) => true,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -880,7 +886,7 @@ impl<'a> SourceCollector<'a> {
|
||||||
/// Renders the given filename into its corresponding HTML source file.
|
/// Renders the given filename into its corresponding HTML source file.
|
||||||
fn emit_source(&mut self, filename: &str) -> io::Result<()> {
|
fn emit_source(&mut self, filename: &str) -> io::Result<()> {
|
||||||
let p = PathBuf::from(filename);
|
let p = PathBuf::from(filename);
|
||||||
if self.cx.local_sources.contains_key(&p) {
|
if self.scx.local_sources.contains_key(&p) {
|
||||||
// We've already emitted this source
|
// We've already emitted this source
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -901,7 +907,7 @@ impl<'a> SourceCollector<'a> {
|
||||||
let mut cur = self.dst.clone();
|
let mut cur = self.dst.clone();
|
||||||
let mut root_path = String::from("../../");
|
let mut root_path = String::from("../../");
|
||||||
let mut href = String::new();
|
let mut href = String::new();
|
||||||
clean_srcpath(&self.cx.src_root, &p, false, |component| {
|
clean_srcpath(&self.scx.src_root, &p, false, |component| {
|
||||||
cur.push(component);
|
cur.push(component);
|
||||||
mkdir(&cur).unwrap();
|
mkdir(&cur).unwrap();
|
||||||
root_path.push_str("../");
|
root_path.push_str("../");
|
||||||
|
@ -925,10 +931,10 @@ impl<'a> SourceCollector<'a> {
|
||||||
description: &desc,
|
description: &desc,
|
||||||
keywords: BASIC_KEYWORDS,
|
keywords: BASIC_KEYWORDS,
|
||||||
};
|
};
|
||||||
layout::render(&mut w, &self.cx.layout,
|
layout::render(&mut w, &self.scx.layout,
|
||||||
&page, &(""), &Source(contents))?;
|
&page, &(""), &Source(contents))?;
|
||||||
w.flush()?;
|
w.flush()?;
|
||||||
self.cx.local_sources.insert(p, href);
|
self.scx.local_sources.insert(p, href);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1265,10 +1271,10 @@ impl Context {
|
||||||
let tyname = shortty(it).to_static_str();
|
let tyname = shortty(it).to_static_str();
|
||||||
let desc = if it.is_crate() {
|
let desc = if it.is_crate() {
|
||||||
format!("API documentation for the Rust `{}` crate.",
|
format!("API documentation for the Rust `{}` crate.",
|
||||||
cx.layout.krate)
|
cx.shared.layout.krate)
|
||||||
} else {
|
} else {
|
||||||
format!("API documentation for the Rust `{}` {} in crate `{}`.",
|
format!("API documentation for the Rust `{}` {} in crate `{}`.",
|
||||||
it.name.as_ref().unwrap(), tyname, cx.layout.krate)
|
it.name.as_ref().unwrap(), tyname, cx.shared.layout.krate)
|
||||||
};
|
};
|
||||||
let keywords = make_item_keywords(it);
|
let keywords = make_item_keywords(it);
|
||||||
let page = layout::Page {
|
let page = layout::Page {
|
||||||
|
@ -1286,7 +1292,7 @@ impl Context {
|
||||||
// write syscall all the time.
|
// write syscall all the time.
|
||||||
let mut writer = BufWriter::new(w);
|
let mut writer = BufWriter::new(w);
|
||||||
if !cx.render_redirect_pages {
|
if !cx.render_redirect_pages {
|
||||||
layout::render(&mut writer, &cx.layout, &page,
|
layout::render(&mut writer, &cx.shared.layout, &page,
|
||||||
&Sidebar{ cx: cx, item: it },
|
&Sidebar{ cx: cx, item: it },
|
||||||
&Item{ cx: cx, item: it })?;
|
&Item{ cx: cx, item: it })?;
|
||||||
|
|
||||||
|
@ -1434,10 +1440,11 @@ impl<'a> Item<'a> {
|
||||||
// know the span, so we plow forward and generate a proper url. The url
|
// know the span, so we plow forward and generate a proper url. The url
|
||||||
// has anchors for the line numbers that we're linking to.
|
// has anchors for the line numbers that we're linking to.
|
||||||
} else if self.item.def_id.is_local() {
|
} else if self.item.def_id.is_local() {
|
||||||
self.cx.local_sources.get(&PathBuf::from(&self.item.source.filename)).map(|path| {
|
let path = PathBuf::from(&self.item.source.filename);
|
||||||
|
self.cx.shared.local_sources.get(&path).map(|path| {
|
||||||
format!("{root}src/{krate}/{path}#{href}",
|
format!("{root}src/{krate}/{path}#{href}",
|
||||||
root = self.cx.root_path,
|
root = self.cx.root_path,
|
||||||
krate = self.cx.layout.krate,
|
krate = self.cx.shared.layout.krate,
|
||||||
path = path,
|
path = path,
|
||||||
href = href)
|
href = href)
|
||||||
})
|
})
|
||||||
|
@ -1520,7 +1527,7 @@ impl<'a> fmt::Display for Item<'a> {
|
||||||
// [src] link in the downstream documentation will actually come back to
|
// [src] link in the downstream documentation will actually come back to
|
||||||
// this page, and this link will be auto-clicked. The `id` attribute is
|
// this page, and this link will be auto-clicked. The `id` attribute is
|
||||||
// used to find the link to auto-click.
|
// used to find the link to auto-click.
|
||||||
if self.cx.include_sources && !is_primitive {
|
if self.cx.shared.include_sources && !is_primitive {
|
||||||
if let Some(l) = self.href() {
|
if let Some(l) = self.href() {
|
||||||
write!(fmt, "<a id='src-{}' class='srclink' \
|
write!(fmt, "<a id='src-{}' class='srclink' \
|
||||||
href='{}' title='{}'>[src]</a>",
|
href='{}' title='{}'>[src]</a>",
|
||||||
|
@ -1752,7 +1759,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Optio
|
||||||
format!("Deprecated{}{}", since, Markdown(&reason))
|
format!("Deprecated{}{}", since, Markdown(&reason))
|
||||||
} else if stab.level == stability::Unstable {
|
} else if stab.level == stability::Unstable {
|
||||||
let unstable_extra = if show_reason {
|
let unstable_extra = if show_reason {
|
||||||
match (!stab.feature.is_empty(), &cx.issue_tracker_base_url, stab.issue) {
|
match (!stab.feature.is_empty(), &cx.shared.issue_tracker_base_url, stab.issue) {
|
||||||
(true, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
|
(true, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
|
||||||
format!(" (<code>{}</code> <a href=\"{}{}\">#{}</a>)",
|
format!(" (<code>{}</code> <a href=\"{}{}\">#{}</a>)",
|
||||||
Escape(&stab.feature), tracker_url, issue_no, issue_no),
|
Escape(&stab.feature), tracker_url, issue_no, issue_no),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue