]> git.proxmox.com Git - rustc.git/blobdiff - src/librustdoc/html/format.rs
Imported Upstream version 1.0.0~beta.3
[rustc.git] / src / librustdoc / html / format.rs
index ed37b973f787ec16e4d9f9497f89732351789657..d2dccca362ef81fa80f32024636a48c101846dad 100644 (file)
@@ -18,6 +18,7 @@
 use std::fmt;
 use std::iter::repeat;
 
+use syntax::abi::Abi;
 use syntax::ast;
 use syntax::ast_util;
 
@@ -54,6 +55,7 @@ pub struct WhereClause<'a>(pub &'a clean::Generics);
 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> {
@@ -92,7 +94,7 @@ impl<'a> fmt::Display for TyParamBounds<'a> {
 
 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("&lt;"));
 
         for (i, life) in self.lifetimes.iter().enumerate() {
@@ -102,8 +104,8 @@ impl fmt::Display for clean::Generics {
             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() {
@@ -112,7 +114,7 @@ impl fmt::Display for clean::Generics {
                 }
                 try!(f.write_str(&tp.name));
 
-                if tp.bounds.len() > 0 {
+                if !tp.bounds.is_empty() {
                     try!(write!(f, ": {}", TyParamBounds(&tp.bounds)));
                 }
 
@@ -130,7 +132,7 @@ impl fmt::Display for clean::Generics {
 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 "));
@@ -173,7 +175,7 @@ impl fmt::Display for clean::Lifetime {
 
 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&lt;"));
             for (i, lt) in self.lifetimes.iter().enumerate() {
                 if i > 0 {
@@ -210,7 +212,7 @@ impl fmt::Display for clean::PathParameters {
             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("&lt;"));
                     let mut comma = false;
                     for lifetime in lifetimes {
@@ -281,48 +283,46 @@ impl fmt::Display for clean::Path {
     }
 }
 
+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,
@@ -334,8 +334,7 @@ fn path<F, G>(w: &mut fmt::Formatter,
             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);
@@ -355,37 +354,14 @@ fn path<F, G>(w: &mut fmt::Formatter,
         }
     }
 
-    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(())
 }
 
@@ -491,7 +467,8 @@ impl fmt::Display for clean::Type {
             }
             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 {
@@ -527,6 +504,29 @@ impl fmt::Display for clean::Type {
                 }
                 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, "&lt;{} as {}&gt;::{}", self_type, trait_, name)
             }
@@ -541,7 +541,7 @@ impl fmt::Display for clean::Arguments {
     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_));
@@ -585,8 +585,8 @@ impl<'a> fmt::Display for Method<'a> {
             }
         }
         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_));
@@ -661,17 +661,7 @@ impl fmt::Display for clean::ViewListIdent {
     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),
@@ -703,6 +693,16 @@ impl fmt::Display for RawMutableSpace {
     }
 }
 
+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;
@@ -734,7 +734,7 @@ impl<'a> fmt::Display for ConciseStability<'a> {
                 };
                 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 => {