std: Modernize the local_data api
This commit brings the local_data api up to modern rust standards with a few key improvements: * The `pop` and `set` methods have been combined into one method, `replace` * The `get_mut` method has been removed. All interior mutability should be done through `RefCell`. * All functionality is now exposed as a method on the keys themselves. Instead of importing std::local_data, you now use "key.replace()" and "key.get()". * All closures have been removed in favor of RAII functionality. This means that get() and get_mut() no long require closures, but rather return Option<SmartPointer> where the smart pointer takes care of relinquishing the borrow and also implements the necessary Deref traits * The modify() function was removed to cut the local_data interface down to its bare essentials (similarly to how RefCell removed set/get). [breaking-change]
This commit is contained in:
parent
ef6daf9935
commit
ab92ea526d
23 changed files with 444 additions and 661 deletions
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::local_data;
|
||||
use std::strbuf::StrBuf;
|
||||
|
||||
use syntax::ast;
|
||||
|
|
@ -206,78 +205,72 @@ fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
|
|||
generics.push_str(">");
|
||||
}
|
||||
|
||||
// Did someone say rightward-drift?
|
||||
local_data::get(current_location_key, |loc| {
|
||||
let loc = loc.unwrap();
|
||||
let loc = current_location_key.get().unwrap();
|
||||
let cache = cache_key.get().unwrap();
|
||||
let abs_root = root(&**cache, loc.as_slice());
|
||||
let rel_root = match path.segments.get(0).name.as_slice() {
|
||||
"self" => Some("./".to_owned()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
local_data::get(cache_key, |cache| {
|
||||
let cache = cache.unwrap();
|
||||
let abs_root = root(&**cache, loc.as_slice());
|
||||
let rel_root = match path.segments.get(0).name.as_slice() {
|
||||
"self" => Some("./".to_owned()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if print_all {
|
||||
let amt = path.segments.len() - 1;
|
||||
match rel_root {
|
||||
Some(root) => {
|
||||
let mut root = StrBuf::from_str(root);
|
||||
for seg in path.segments.slice_to(amt).iter() {
|
||||
if "super" == seg.name || "self" == seg.name {
|
||||
try!(write!(w, "{}::", seg.name));
|
||||
} else {
|
||||
root.push_str(seg.name);
|
||||
root.push_str("/");
|
||||
try!(write!(w, "<a class='mod'
|
||||
href='{}index.html'>{}</a>::",
|
||||
root.as_slice(),
|
||||
seg.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
for seg in path.segments.slice_to(amt).iter() {
|
||||
try!(write!(w, "{}::", seg.name));
|
||||
}
|
||||
if print_all {
|
||||
let amt = path.segments.len() - 1;
|
||||
match rel_root {
|
||||
Some(root) => {
|
||||
let mut root = StrBuf::from_str(root);
|
||||
for seg in path.segments.slice_to(amt).iter() {
|
||||
if "super" == seg.name || "self" == seg.name {
|
||||
try!(write!(w, "{}::", seg.name));
|
||||
} else {
|
||||
root.push_str(seg.name);
|
||||
root.push_str("/");
|
||||
try!(write!(w, "<a class='mod'
|
||||
href='{}index.html'>{}</a>::",
|
||||
root.as_slice(),
|
||||
seg.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match info(&**cache) {
|
||||
// This is a documented path, link to it!
|
||||
Some((ref fqp, shortty)) if abs_root.is_some() => {
|
||||
let mut url = StrBuf::from_str(abs_root.unwrap());
|
||||
let to_link = fqp.slice_to(fqp.len() - 1);
|
||||
for component in to_link.iter() {
|
||||
url.push_str(*component);
|
||||
url.push_str("/");
|
||||
}
|
||||
match shortty {
|
||||
item_type::Module => {
|
||||
url.push_str(*fqp.last().unwrap());
|
||||
url.push_str("/index.html");
|
||||
}
|
||||
_ => {
|
||||
url.push_str(shortty.to_static_str());
|
||||
url.push_str(".");
|
||||
url.push_str(*fqp.last().unwrap());
|
||||
url.push_str(".html");
|
||||
}
|
||||
}
|
||||
|
||||
try!(write!(w, "<a class='{}' href='{}' title='{}'>{}</a>",
|
||||
shortty, url, fqp.connect("::"), last.name));
|
||||
None => {
|
||||
for seg in path.segments.slice_to(amt).iter() {
|
||||
try!(write!(w, "{}::", seg.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match info(&**cache) {
|
||||
// This is a documented path, link to it!
|
||||
Some((ref fqp, shortty)) if abs_root.is_some() => {
|
||||
let mut url = StrBuf::from_str(abs_root.unwrap());
|
||||
let to_link = fqp.slice_to(fqp.len() - 1);
|
||||
for component in to_link.iter() {
|
||||
url.push_str(*component);
|
||||
url.push_str("/");
|
||||
}
|
||||
match shortty {
|
||||
item_type::Module => {
|
||||
url.push_str(*fqp.last().unwrap());
|
||||
url.push_str("/index.html");
|
||||
}
|
||||
_ => {
|
||||
try!(write!(w, "{}", last.name));
|
||||
url.push_str(shortty.to_static_str());
|
||||
url.push_str(".");
|
||||
url.push_str(*fqp.last().unwrap());
|
||||
url.push_str(".html");
|
||||
}
|
||||
}
|
||||
try!(write!(w, "{}", generics.as_slice()));
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
|
||||
try!(write!(w, "<a class='{}' href='{}' title='{}'>{}</a>",
|
||||
shortty, url, fqp.connect("::"), last.name));
|
||||
}
|
||||
|
||||
_ => {
|
||||
try!(write!(w, "{}", last.name));
|
||||
}
|
||||
}
|
||||
try!(write!(w, "{}", generics.as_slice()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Helper to render type parameters
|
||||
|
|
@ -302,10 +295,8 @@ impl fmt::Show for clean::Type {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
clean::TyParamBinder(id) | clean::Generic(id) => {
|
||||
local_data::get(cache_key, |cache| {
|
||||
let m = cache.unwrap();
|
||||
f.buf.write(m.typarams.get(&id).as_bytes())
|
||||
})
|
||||
let m = cache_key.get().unwrap();
|
||||
f.buf.write(m.typarams.get(&id).as_bytes())
|
||||
}
|
||||
clean::ResolvedPath{id, typarams: ref tp, path: ref path} => {
|
||||
try!(resolved_path(f.buf, id, path, false));
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
|
||||
use libc;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::local_data;
|
||||
use std::str;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
use collections::HashMap;
|
||||
|
||||
use html::toc::TocBuilder;
|
||||
|
|
@ -139,7 +139,7 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> {
|
|||
}
|
||||
}
|
||||
|
||||
local_data_key!(used_header_map: HashMap<~str, uint>)
|
||||
local_data_key!(used_header_map: RefCell<HashMap<~str, uint>>)
|
||||
|
||||
pub fn render(w: &mut io::Writer, s: &str, print_toc: bool) -> fmt::Result {
|
||||
extern fn block(ob: *mut hoedown_buffer, text: *hoedown_buffer,
|
||||
|
|
@ -216,15 +216,12 @@ pub fn render(w: &mut io::Writer, s: &str, print_toc: bool) -> fmt::Result {
|
|||
let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
|
||||
|
||||
// Make sure our hyphenated ID is unique for this page
|
||||
let id = local_data::get_mut(used_header_map, |map| {
|
||||
let map = map.unwrap();
|
||||
match map.find_mut(&id) {
|
||||
None => {}
|
||||
Some(a) => { *a += 1; return format!("{}-{}", id, *a - 1) }
|
||||
}
|
||||
map.insert(id.clone(), 1);
|
||||
id.clone()
|
||||
});
|
||||
let map = used_header_map.get().unwrap();
|
||||
let id = match map.borrow_mut().find_mut(&id) {
|
||||
None => id,
|
||||
Some(a) => { *a += 1; format!("{}-{}", id, *a - 1) }
|
||||
};
|
||||
map.borrow_mut().insert(id.clone(), 1);
|
||||
|
||||
let sec = match opaque.toc_builder {
|
||||
Some(ref mut builder) => {
|
||||
|
|
@ -348,7 +345,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
|
|||
/// used at the beginning of rendering an entire HTML page to reset from the
|
||||
/// previous state (if any).
|
||||
pub fn reset_headers() {
|
||||
local_data::set(used_header_map, HashMap::new())
|
||||
used_header_map.replace(Some(RefCell::new(HashMap::new())));
|
||||
}
|
||||
|
||||
impl<'a> fmt::Show for Markdown<'a> {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ use collections::{HashMap, HashSet};
|
|||
use std::fmt;
|
||||
use std::io::{fs, File, BufferedWriter, MemWriter, BufferedReader};
|
||||
use std::io;
|
||||
use std::local_data;
|
||||
use std::str;
|
||||
use std::strbuf::StrBuf;
|
||||
|
||||
|
|
@ -243,24 +242,22 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
|
|||
}
|
||||
|
||||
// Crawl the crate to build various caches used for the output
|
||||
let mut cache = local_data::get(::analysiskey, |analysis| {
|
||||
let public_items = analysis.map(|a| a.public_items.clone());
|
||||
let public_items = public_items.unwrap_or(NodeSet::new());
|
||||
Cache {
|
||||
impls: HashMap::new(),
|
||||
typarams: HashMap::new(),
|
||||
paths: HashMap::new(),
|
||||
traits: HashMap::new(),
|
||||
implementors: HashMap::new(),
|
||||
stack: Vec::new(),
|
||||
parent_stack: Vec::new(),
|
||||
search_index: Vec::new(),
|
||||
extern_locations: HashMap::new(),
|
||||
privmod: false,
|
||||
public_items: public_items,
|
||||
orphan_methods: Vec::new(),
|
||||
}
|
||||
});
|
||||
let public_items = ::analysiskey.get().map(|a| a.public_items.clone());
|
||||
let public_items = public_items.unwrap_or(NodeSet::new());
|
||||
let mut cache = Cache {
|
||||
impls: HashMap::new(),
|
||||
typarams: HashMap::new(),
|
||||
paths: HashMap::new(),
|
||||
traits: HashMap::new(),
|
||||
implementors: HashMap::new(),
|
||||
stack: Vec::new(),
|
||||
parent_stack: Vec::new(),
|
||||
search_index: Vec::new(),
|
||||
extern_locations: HashMap::new(),
|
||||
privmod: false,
|
||||
public_items: public_items,
|
||||
orphan_methods: Vec::new(),
|
||||
};
|
||||
cache.stack.push(krate.name.clone());
|
||||
krate = cache.fold_crate(krate);
|
||||
|
||||
|
|
@ -833,7 +830,7 @@ impl Context {
|
|||
item.name = Some(krate.name);
|
||||
|
||||
// using a rwarc makes this parallelizable in the future
|
||||
local_data::set(cache_key, Arc::new(cache));
|
||||
cache_key.replace(Some(Arc::new(cache)));
|
||||
|
||||
let mut work = vec!((self, item));
|
||||
loop {
|
||||
|
|
@ -859,7 +856,7 @@ impl Context {
|
|||
info!("Rendering an item to {}", w.path().display());
|
||||
// A little unfortunate that this is done like this, but it sure
|
||||
// does make formatting *a lot* nicer.
|
||||
local_data::set(current_location_key, cx.current.clone());
|
||||
current_location_key.replace(Some(cx.current.clone()));
|
||||
|
||||
let mut title = StrBuf::from_str(cx.current.connect("::"));
|
||||
if pushname {
|
||||
|
|
@ -1299,31 +1296,28 @@ fn item_trait(w: &mut Writer, it: &clean::Item,
|
|||
try!(write!(w, "</div>"));
|
||||
}
|
||||
|
||||
local_data::get(cache_key, |cache| {
|
||||
let cache = cache.unwrap();
|
||||
match cache.implementors.find(&it.id) {
|
||||
Some(implementors) => {
|
||||
try!(write!(w, "
|
||||
<h2 id='implementors'>Implementors</h2>
|
||||
<ul class='item-list'>
|
||||
"));
|
||||
for i in implementors.iter() {
|
||||
match *i {
|
||||
PathType(ref ty) => {
|
||||
try!(write!(w, "<li><code>{}</code></li>", *ty));
|
||||
}
|
||||
OtherType(ref generics, ref trait_, ref for_) => {
|
||||
try!(write!(w, "<li><code>impl{} {} for {}</code></li>",
|
||||
*generics, *trait_, *for_));
|
||||
}
|
||||
match cache_key.get().unwrap().implementors.find(&it.id) {
|
||||
Some(implementors) => {
|
||||
try!(write!(w, "
|
||||
<h2 id='implementors'>Implementors</h2>
|
||||
<ul class='item-list'>
|
||||
"));
|
||||
for i in implementors.iter() {
|
||||
match *i {
|
||||
PathType(ref ty) => {
|
||||
try!(write!(w, "<li><code>{}</code></li>", *ty));
|
||||
}
|
||||
OtherType(ref generics, ref trait_, ref for_) => {
|
||||
try!(write!(w, "<li><code>impl{} {} for {}</code></li>",
|
||||
*generics, *trait_, *for_));
|
||||
}
|
||||
}
|
||||
try!(write!(w, "</ul>"));
|
||||
}
|
||||
None => {}
|
||||
try!(write!(w, "</ul>"));
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
None => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_method(w: &mut Writer, meth: &clean::Item) -> fmt::Result {
|
||||
|
|
@ -1550,51 +1544,48 @@ fn render_struct(w: &mut Writer, it: &clean::Item,
|
|||
}
|
||||
|
||||
fn render_methods(w: &mut Writer, it: &clean::Item) -> fmt::Result {
|
||||
local_data::get(cache_key, |cache| {
|
||||
let c = cache.unwrap();
|
||||
match c.impls.find(&it.id) {
|
||||
Some(v) => {
|
||||
let mut non_trait = v.iter().filter(|p| {
|
||||
p.ref0().trait_.is_none()
|
||||
});
|
||||
let non_trait = non_trait.collect::<Vec<&(clean::Impl, Option<~str>)>>();
|
||||
let mut traits = v.iter().filter(|p| {
|
||||
p.ref0().trait_.is_some()
|
||||
});
|
||||
let traits = traits.collect::<Vec<&(clean::Impl, Option<~str>)>>();
|
||||
match cache_key.get().unwrap().impls.find(&it.id) {
|
||||
Some(v) => {
|
||||
let mut non_trait = v.iter().filter(|p| {
|
||||
p.ref0().trait_.is_none()
|
||||
});
|
||||
let non_trait = non_trait.collect::<Vec<&(clean::Impl, Option<~str>)>>();
|
||||
let mut traits = v.iter().filter(|p| {
|
||||
p.ref0().trait_.is_some()
|
||||
});
|
||||
let traits = traits.collect::<Vec<&(clean::Impl, Option<~str>)>>();
|
||||
|
||||
if non_trait.len() > 0 {
|
||||
try!(write!(w, "<h2 id='methods'>Methods</h2>"));
|
||||
for &(ref i, ref dox) in non_trait.move_iter() {
|
||||
if non_trait.len() > 0 {
|
||||
try!(write!(w, "<h2 id='methods'>Methods</h2>"));
|
||||
for &(ref i, ref dox) in non_trait.move_iter() {
|
||||
try!(render_impl(w, i, dox));
|
||||
}
|
||||
}
|
||||
if traits.len() > 0 {
|
||||
try!(write!(w, "<h2 id='implementations'>Trait \
|
||||
Implementations</h2>"));
|
||||
let mut any_derived = false;
|
||||
for & &(ref i, ref dox) in traits.iter() {
|
||||
if !i.derived {
|
||||
try!(render_impl(w, i, dox));
|
||||
} else {
|
||||
any_derived = true;
|
||||
}
|
||||
}
|
||||
if traits.len() > 0 {
|
||||
try!(write!(w, "<h2 id='implementations'>Trait \
|
||||
Implementations</h2>"));
|
||||
let mut any_derived = false;
|
||||
for & &(ref i, ref dox) in traits.iter() {
|
||||
if !i.derived {
|
||||
if any_derived {
|
||||
try!(write!(w, "<h3 id='derived_implementations'>Derived Implementations \
|
||||
</h3>"));
|
||||
for &(ref i, ref dox) in traits.move_iter() {
|
||||
if i.derived {
|
||||
try!(render_impl(w, i, dox));
|
||||
} else {
|
||||
any_derived = true;
|
||||
}
|
||||
}
|
||||
if any_derived {
|
||||
try!(write!(w, "<h3 id='derived_implementations'>Derived Implementations \
|
||||
</h3>"));
|
||||
for &(ref i, ref dox) in traits.move_iter() {
|
||||
if i.derived {
|
||||
try!(render_impl(w, i, dox));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
None => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_impl(w: &mut Writer, i: &clean::Impl,
|
||||
|
|
@ -1644,9 +1635,8 @@ fn render_impl(w: &mut Writer, i: &clean::Impl,
|
|||
match trait_id {
|
||||
None => {}
|
||||
Some(id) => {
|
||||
try!(local_data::get(cache_key, |cache| {
|
||||
let cache = cache.unwrap();
|
||||
match cache.traits.find(&id) {
|
||||
try!({
|
||||
match cache_key.get().unwrap().traits.find(&id) {
|
||||
Some(t) => {
|
||||
for method in t.methods.iter() {
|
||||
let n = method.item().name.clone();
|
||||
|
|
@ -1661,7 +1651,7 @@ fn render_impl(w: &mut Writer, i: &clean::Impl,
|
|||
None => {}
|
||||
}
|
||||
Ok(())
|
||||
}))
|
||||
})
|
||||
}
|
||||
}
|
||||
try!(write!(w, "</div>"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue