use std::fmt;
use std::iter::repeat;
+use syntax::abi::Abi;
use syntax::ast;
use syntax::ast_util;
pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
/// Wrapper struct for emitting a comma-separated list of items
pub struct CommaSep<'a, T: 'a>(pub &'a [T]);
+pub struct AbiSpace(pub Abi);
impl VisSpace {
pub fn get(&self) -> Option<ast::Visibility> {
impl fmt::Display for clean::Generics {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- if self.lifetimes.len() == 0 && self.type_params.len() == 0 { return Ok(()) }
+ if self.lifetimes.is_empty() && self.type_params.is_empty() { return Ok(()) }
try!(f.write_str("<"));
for (i, life) in self.lifetimes.iter().enumerate() {
try!(write!(f, "{}", *life));
}
- if self.type_params.len() > 0 {
- if self.lifetimes.len() > 0 {
+ if !self.type_params.is_empty() {
+ if !self.lifetimes.is_empty() {
try!(f.write_str(", "));
}
for (i, tp) in self.type_params.iter().enumerate() {
}
try!(f.write_str(&tp.name));
- if tp.bounds.len() > 0 {
+ if !tp.bounds.is_empty() {
try!(write!(f, ": {}", TyParamBounds(&tp.bounds)));
}
impl<'a> fmt::Display for WhereClause<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let &WhereClause(gens) = self;
- if gens.where_predicates.len() == 0 {
+ if gens.where_predicates.is_empty() {
return Ok(());
}
try!(f.write_str(" <span class='where'>where "));
impl fmt::Display for clean::PolyTrait {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- if self.lifetimes.len() > 0 {
+ if !self.lifetimes.is_empty() {
try!(f.write_str("for<"));
for (i, lt) in self.lifetimes.iter().enumerate() {
if i > 0 {
clean::PathParameters::AngleBracketed {
ref lifetimes, ref types, ref bindings
} => {
- if lifetimes.len() > 0 || types.len() > 0 || bindings.len() > 0 {
+ if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
try!(f.write_str("<"));
let mut comma = false;
for lifetime in lifetimes {
}
}
+pub fn href(did: ast::DefId) -> Option<(String, ItemType, Vec<String>)> {
+ let cache = cache();
+ let loc = CURRENT_LOCATION_KEY.with(|l| l.borrow().clone());
+ let &(ref fqp, shortty) = match cache.paths.get(&did) {
+ Some(p) => p,
+ None => return None,
+ };
+ let mut url = if ast_util::is_local(did) || cache.inlined.contains(&did) {
+ repeat("../").take(loc.len()).collect::<String>()
+ } else {
+ match cache.extern_locations[&did.krate] {
+ render::Remote(ref s) => s.to_string(),
+ render::Local => repeat("../").take(loc.len()).collect::<String>(),
+ render::Unknown => return None,
+ }
+ };
+ for component in &fqp[..fqp.len() - 1] {
+ url.push_str(component);
+ url.push_str("/");
+ }
+ match shortty {
+ ItemType::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");
+ }
+ }
+ Some((url, shortty, fqp.to_vec()))
+}
+
/// Used when rendering a `ResolvedPath` structure. This invokes the `path`
/// rendering function with the necessary arguments for linking to a local path.
-fn resolved_path(w: &mut fmt::Formatter, did: ast::DefId, p: &clean::Path,
+fn resolved_path(w: &mut fmt::Formatter, did: ast::DefId, path: &clean::Path,
print_all: bool) -> fmt::Result {
- path(w, p, print_all,
- |cache, loc| {
- if ast_util::is_local(did) || cache.inlined.contains(&did) {
- Some(repeat("../").take(loc.len()).collect::<String>())
- } else {
- match cache.extern_locations[&did.krate] {
- render::Remote(ref s) => Some(s.to_string()),
- render::Local => {
- Some(repeat("../").take(loc.len()).collect::<String>())
- }
- render::Unknown => None,
- }
- }
- },
- |cache| {
- match cache.paths.get(&did) {
- None => None,
- Some(&(ref fqp, shortty)) => Some((fqp.clone(), shortty))
- }
- })
-}
-
-fn path<F, G>(w: &mut fmt::Formatter,
- path: &clean::Path,
- print_all: bool,
- root: F,
- info: G)
- -> fmt::Result where
- F: FnOnce(&render::Cache, &[String]) -> Option<String>,
- G: FnOnce(&render::Cache) -> Option<(Vec<String>, ItemType)>,
-{
- // The generics will get written to both the title and link
let last = path.segments.last().unwrap();
- let generics = format!("{}", last.params);
-
- let loc = CURRENT_LOCATION_KEY.with(|l| l.borrow().clone());
- let cache = cache();
- let abs_root = root(&*cache, &loc);
let rel_root = match &*path.segments[0].name {
"self" => Some("./".to_string()),
_ => None,
Some(root) => {
let mut root = String::from_str(&root);
for seg in &path.segments[..amt] {
- if "super" == seg.name ||
- "self" == seg.name {
+ if "super" == seg.name || "self" == seg.name {
try!(write!(w, "{}::", seg.name));
} else {
root.push_str(&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 = String::from_str(&abs_root.unwrap());
- let to_link = &fqp[..fqp.len() - 1];
- for component in to_link {
- url.push_str(component);
- url.push_str("/");
- }
- match shortty {
- ItemType::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");
- }
- }
-
+ match href(did) {
+ Some((url, shortty, fqp)) => {
try!(write!(w, "<a class='{}' href='{}' title='{}'>{}</a>",
shortty, url, fqp.connect("::"), last.name));
}
-
- _ => {
- try!(write!(w, "{}", last.name));
- }
+ _ => try!(write!(w, "{}", last.name)),
}
- try!(write!(w, "{}", generics));
+ try!(write!(w, "{}", last.params));
Ok(())
}
}
clean::Bottom => f.write_str("!"),
clean::RawPointer(m, ref t) => {
- write!(f, "*{}{}", RawMutableSpace(m), **t)
+ primitive_link(f, clean::PrimitiveType::PrimitiveRawPointer,
+ &format!("*{}{}", RawMutableSpace(m), **t))
}
clean::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty} => {
let lt = match *l {
}
Ok(())
}
+ // It's pretty unsightly to look at `<A as B>::C` in output, and
+ // we've got hyperlinking on our side, so try to avoid longer
+ // notation as much as possible by making `C` a hyperlink to trait
+ // `B` to disambiguate.
+ //
+ // FIXME: this is still a lossy conversion and there should probably
+ // be a better way of representing this in general? Most of
+ // the ugliness comes from inlining across crates where
+ // everything comes in as a fully resolved QPath (hard to
+ // look at).
+ clean::QPath {
+ ref name,
+ ref self_type,
+ trait_: box clean::ResolvedPath { did, ref typarams, .. },
+ } => {
+ try!(write!(f, "{}::", self_type));
+ let path = clean::Path::singleton(name.clone());
+ try!(resolved_path(f, did, &path, false));
+
+ // FIXME: `typarams` are not rendered, and this seems bad?
+ drop(typarams);
+ Ok(())
+ }
clean::QPath { ref name, ref self_type, ref trait_ } => {
write!(f, "<{} as {}>::{}", self_type, trait_, name)
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, input) in self.values.iter().enumerate() {
if i > 0 { try!(write!(f, ", ")); }
- if input.name.len() > 0 {
+ if !input.name.is_empty() {
try!(write!(f, "{}: ", input.name));
}
try!(write!(f, "{}", input.type_));
}
}
for (i, input) in d.inputs.values.iter().enumerate() {
- if i > 0 || args.len() > 0 { args.push_str(", "); }
- if input.name.len() > 0 {
+ if i > 0 || !args.is_empty() { args.push_str(", "); }
+ if !input.name.is_empty() {
args.push_str(&format!("{}: ", input.name));
}
args.push_str(&format!("{}", input.type_));
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.source {
Some(did) => {
- let path = clean::Path {
- global: false,
- segments: vec!(clean::PathSegment {
- name: self.name.clone(),
- params: clean::PathParameters::AngleBracketed {
- lifetimes: Vec::new(),
- types: Vec::new(),
- bindings: Vec::new()
- }
- })
- };
+ let path = clean::Path::singleton(self.name.clone());
resolved_path(f, did, &path, false)
}
_ => write!(f, "{}", self.name),
}
}
+impl fmt::Display for AbiSpace {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {
+ Abi::Rust => Ok(()),
+ Abi::C => write!(f, "extern "),
+ abi => write!(f, "extern {} ", abi),
+ }
+ }
+}
+
impl<'a> fmt::Display for Stability<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Stability(stab) = *self;
};
write!(f, "<a class='stability {lvl}' title='{lvl}{colon}{reason}'></a>",
lvl = Escape(&*lvl),
- colon = if stability.reason.len() > 0 { ": " } else { "" },
+ colon = if !stability.reason.is_empty() { ": " } else { "" },
reason = Escape(&*stability.reason))
}
None => {