Skip to content

Commit 95eb8a6

Browse files
committed
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>`.
1 parent 0ef85c1 commit 95eb8a6

File tree

1 file changed

+47
-40
lines changed

1 file changed

+47
-40
lines changed

src/librustdoc/html/render.rs

+47-40
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,20 @@ pub struct Context {
9191
/// String representation of how to get back to the root path of the 'doc/'
9292
/// folder in terms of a relative URL.
9393
pub root_path: String,
94-
/// The path to the crate root source minus the file name.
95-
/// Used for simplifying paths to the highlighted source code files.
96-
pub src_root: PathBuf,
9794
/// The current destination folder of where HTML artifacts should be placed.
9895
/// This changes as the context descends into the module hierarchy.
9996
pub dst: PathBuf,
97+
/// A flag, which when `true`, will render pages which redirect to the
98+
/// real location of an item. This is used to allow external links to
99+
/// publicly reused items to redirect to the right location.
100+
pub render_redirect_pages: bool,
101+
pub shared: Arc<SharedContext>,
102+
}
103+
104+
pub struct SharedContext {
105+
/// The path to the crate root source minus the file name.
106+
/// Used for simplifying paths to the highlighted source code files.
107+
pub src_root: PathBuf,
100108
/// This describes the layout of each page, and is not modified after
101109
/// creation of the context (contains info like the favicon and added html).
102110
pub layout: layout::Layout,
@@ -106,10 +114,6 @@ pub struct Context {
106114
pub include_sources: bool,
107115
/// The local file sources we've emitted and their respective url-paths.
108116
pub local_sources: HashMap<PathBuf, String>,
109-
/// A flag, which when turned off, will render pages which redirect to the
110-
/// real location of an item. This is used to allow external links to
111-
/// publicly reused items to redirect to the right location.
112-
pub render_redirect_pages: bool,
113117
/// All the passes that were run on this crate.
114118
pub passes: HashSet<String>,
115119
/// The base-URL of the issue tracker for when an item has been tagged with
@@ -259,7 +263,7 @@ pub struct Cache {
259263

260264
/// Helper struct to render all source code to HTML pages
261265
struct SourceCollector<'a> {
262-
cx: &'a mut Context,
266+
scx: &'a mut SharedContext,
263267

264268
/// Root destination to place all HTML output into
265269
dst: PathBuf,
@@ -412,43 +416,37 @@ pub fn run(mut krate: clean::Crate,
412416
Some(p) => p.to_path_buf(),
413417
None => PathBuf::new(),
414418
};
415-
let mut cx = Context {
416-
dst: dst,
419+
let mut scx = SharedContext {
417420
src_root: src_root,
418421
passes: passes,
419-
current: Vec::new(),
420-
root_path: String::new(),
422+
include_sources: true,
423+
local_sources: HashMap::new(),
424+
issue_tracker_base_url: None,
421425
layout: layout::Layout {
422426
logo: "".to_string(),
423427
favicon: "".to_string(),
424428
external_html: external_html.clone(),
425429
krate: krate.name.clone(),
426430
playground_url: "".to_string(),
427431
},
428-
include_sources: true,
429-
local_sources: HashMap::new(),
430-
render_redirect_pages: false,
431-
issue_tracker_base_url: None,
432432
};
433433

434-
try_err!(mkdir(&cx.dst), &cx.dst);
435-
436434
// Crawl the crate attributes looking for attributes which control how we're
437435
// going to emit HTML
438436
if let Some(attrs) = krate.module.as_ref().map(|m| m.attrs.list("doc")) {
439437
for attr in attrs {
440438
match *attr {
441439
clean::NameValue(ref x, ref s)
442440
if "html_favicon_url" == *x => {
443-
cx.layout.favicon = s.to_string();
441+
scx.layout.favicon = s.to_string();
444442
}
445443
clean::NameValue(ref x, ref s)
446444
if "html_logo_url" == *x => {
447-
cx.layout.logo = s.to_string();
445+
scx.layout.logo = s.to_string();
448446
}
449447
clean::NameValue(ref x, ref s)
450448
if "html_playground_url" == *x => {
451-
cx.layout.playground_url = s.to_string();
449+
scx.layout.playground_url = s.to_string();
452450
markdown::PLAYGROUND_KRATE.with(|slot| {
453451
if slot.borrow().is_none() {
454452
let name = krate.name.clone();
@@ -458,16 +456,25 @@ pub fn run(mut krate: clean::Crate,
458456
}
459457
clean::NameValue(ref x, ref s)
460458
if "issue_tracker_base_url" == *x => {
461-
cx.issue_tracker_base_url = Some(s.to_string());
459+
scx.issue_tracker_base_url = Some(s.to_string());
462460
}
463461
clean::Word(ref x)
464462
if "html_no_source" == *x => {
465-
cx.include_sources = false;
463+
scx.include_sources = false;
466464
}
467465
_ => {}
468466
}
469467
}
470468
}
469+
try_err!(mkdir(&dst), &dst);
470+
krate = render_sources(&dst, &mut scx, krate)?;
471+
let cx = Context {
472+
current: Vec::new(),
473+
root_path: String::new(),
474+
dst: dst,
475+
render_redirect_pages: false,
476+
shared: Arc::new(scx),
477+
};
471478

472479
// Crawl the crate to build various caches used for the output
473480
let analysis = ::ANALYSISKEY.with(|a| a.clone());
@@ -538,7 +545,6 @@ pub fn run(mut krate: clean::Crate,
538545
CURRENT_LOCATION_KEY.with(|s| s.borrow_mut().clear());
539546

540547
write_shared(&cx, &krate, &*cache, index)?;
541-
let krate = render_sources(&mut cx, krate)?;
542548

543549
// And finally render the whole crate's documentation
544550
cx.krate(krate)
@@ -760,16 +766,16 @@ fn write_shared(cx: &Context,
760766
Ok(())
761767
}
762768

763-
fn render_sources(cx: &mut Context,
769+
fn render_sources(dst: &Path, scx: &mut SharedContext,
764770
krate: clean::Crate) -> Result<clean::Crate, Error> {
765771
info!("emitting source files");
766-
let dst = cx.dst.join("src");
772+
let dst = dst.join("src");
767773
try_err!(mkdir(&dst), &dst);
768774
let dst = dst.join(&krate.name);
769775
try_err!(mkdir(&dst), &dst);
770776
let mut folder = SourceCollector {
771777
dst: dst,
772-
cx: cx,
778+
scx: scx,
773779
};
774780
Ok(folder.fold_crate(krate))
775781
}
@@ -847,7 +853,7 @@ impl<'a> DocFolder for SourceCollector<'a> {
847853
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
848854
// If we're including source files, and we haven't seen this file yet,
849855
// then we need to render it out to the filesystem
850-
if self.cx.include_sources
856+
if self.scx.include_sources
851857
// skip all invalid spans
852858
&& item.source.filename != ""
853859
// macros from other libraries get special filenames which we can
@@ -860,7 +866,7 @@ impl<'a> DocFolder for SourceCollector<'a> {
860866
// something like that), so just don't include sources for the
861867
// entire crate. The other option is maintaining this mapping on a
862868
// per-file basis, but that's probably not worth it...
863-
self.cx
869+
self.scx
864870
.include_sources = match self.emit_source(&item.source.filename) {
865871
Ok(()) => true,
866872
Err(e) => {
@@ -880,7 +886,7 @@ impl<'a> SourceCollector<'a> {
880886
/// Renders the given filename into its corresponding HTML source file.
881887
fn emit_source(&mut self, filename: &str) -> io::Result<()> {
882888
let p = PathBuf::from(filename);
883-
if self.cx.local_sources.contains_key(&p) {
889+
if self.scx.local_sources.contains_key(&p) {
884890
// We've already emitted this source
885891
return Ok(());
886892
}
@@ -901,7 +907,7 @@ impl<'a> SourceCollector<'a> {
901907
let mut cur = self.dst.clone();
902908
let mut root_path = String::from("../../");
903909
let mut href = String::new();
904-
clean_srcpath(&self.cx.src_root, &p, false, |component| {
910+
clean_srcpath(&self.scx.src_root, &p, false, |component| {
905911
cur.push(component);
906912
mkdir(&cur).unwrap();
907913
root_path.push_str("../");
@@ -925,10 +931,10 @@ impl<'a> SourceCollector<'a> {
925931
description: &desc,
926932
keywords: BASIC_KEYWORDS,
927933
};
928-
layout::render(&mut w, &self.cx.layout,
934+
layout::render(&mut w, &self.scx.layout,
929935
&page, &(""), &Source(contents))?;
930936
w.flush()?;
931-
self.cx.local_sources.insert(p, href);
937+
self.scx.local_sources.insert(p, href);
932938
Ok(())
933939
}
934940
}
@@ -1265,10 +1271,10 @@ impl Context {
12651271
let tyname = shortty(it).to_static_str();
12661272
let desc = if it.is_crate() {
12671273
format!("API documentation for the Rust `{}` crate.",
1268-
cx.layout.krate)
1274+
cx.shared.layout.krate)
12691275
} else {
12701276
format!("API documentation for the Rust `{}` {} in crate `{}`.",
1271-
it.name.as_ref().unwrap(), tyname, cx.layout.krate)
1277+
it.name.as_ref().unwrap(), tyname, cx.shared.layout.krate)
12721278
};
12731279
let keywords = make_item_keywords(it);
12741280
let page = layout::Page {
@@ -1286,7 +1292,7 @@ impl Context {
12861292
// write syscall all the time.
12871293
let mut writer = BufWriter::new(w);
12881294
if !cx.render_redirect_pages {
1289-
layout::render(&mut writer, &cx.layout, &page,
1295+
layout::render(&mut writer, &cx.shared.layout, &page,
12901296
&Sidebar{ cx: cx, item: it },
12911297
&Item{ cx: cx, item: it })?;
12921298

@@ -1434,10 +1440,11 @@ impl<'a> Item<'a> {
14341440
// know the span, so we plow forward and generate a proper url. The url
14351441
// has anchors for the line numbers that we're linking to.
14361442
} else if self.item.def_id.is_local() {
1437-
self.cx.local_sources.get(&PathBuf::from(&self.item.source.filename)).map(|path| {
1443+
let path = PathBuf::from(&self.item.source.filename);
1444+
self.cx.shared.local_sources.get(&path).map(|path| {
14381445
format!("{root}src/{krate}/{path}#{href}",
14391446
root = self.cx.root_path,
1440-
krate = self.cx.layout.krate,
1447+
krate = self.cx.shared.layout.krate,
14411448
path = path,
14421449
href = href)
14431450
})
@@ -1520,7 +1527,7 @@ impl<'a> fmt::Display for Item<'a> {
15201527
// [src] link in the downstream documentation will actually come back to
15211528
// this page, and this link will be auto-clicked. The `id` attribute is
15221529
// used to find the link to auto-click.
1523-
if self.cx.include_sources && !is_primitive {
1530+
if self.cx.shared.include_sources && !is_primitive {
15241531
if let Some(l) = self.href() {
15251532
write!(fmt, "<a id='src-{}' class='srclink' \
15261533
href='{}' title='{}'>[src]</a>",
@@ -1752,7 +1759,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Optio
17521759
format!("Deprecated{}{}", since, Markdown(&reason))
17531760
} else if stab.level == stability::Unstable {
17541761
let unstable_extra = if show_reason {
1755-
match (!stab.feature.is_empty(), &cx.issue_tracker_base_url, stab.issue) {
1762+
match (!stab.feature.is_empty(), &cx.shared.issue_tracker_base_url, stab.issue) {
17561763
(true, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
17571764
format!(" (<code>{}</code> <a href=\"{}{}\">#{}</a>)",
17581765
Escape(&stab.feature), tracker_url, issue_no, issue_no),

0 commit comments

Comments
 (0)