From c639cf6ee9ae78d01ca0a34c1a9c05d6c0406fa7 Mon Sep 17 00:00:00 2001 From: Tom Jakubowski Date: Tue, 16 Dec 2014 12:40:43 -0800 Subject: [PATCH] rustdoc: Use unboxed closure sugar This unfortunately leaves sugaring Fn/FnMut/FnOnce on cross-crate re-exports for future work. cc #19909 --- src/librustdoc/clean/mod.rs | 63 +++++++++++++++-------- src/librustdoc/html/format.rs | 97 +++++++++++++++++++++-------------- 2 files changed, 100 insertions(+), 60 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 749686fa283..8dae353c64f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -526,8 +526,10 @@ fn external_path(cx: &DocContext, name: &str, substs: &subst::Substs) -> Path { global: false, segments: vec![PathSegment { name: name.to_string(), - lifetimes: lifetimes, - types: types, + params: PathParameters::AngleBracketed { + lifetimes: lifetimes, + types: types, + } }], } } @@ -1743,32 +1745,49 @@ impl Clean for ast::Path { } } +#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq)] +pub enum PathParameters { + AngleBracketed { + lifetimes: Vec, + types: Vec, + }, + Parenthesized { + inputs: Vec, + output: Option + } +} + +impl Clean for ast::PathParameters { + fn clean(&self, cx: &DocContext) -> PathParameters { + match *self { + ast::AngleBracketedParameters(ref data) => { + PathParameters::AngleBracketed { + lifetimes: data.lifetimes.clean(cx), + types: data.types.clean(cx) + } + } + + ast::ParenthesizedParameters(ref data) => { + PathParameters::Parenthesized { + inputs: data.inputs.clean(cx), + output: data.output.clean(cx) + } + } + } + } +} + #[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq)] pub struct PathSegment { pub name: String, - pub lifetimes: Vec, - pub types: Vec, + pub params: PathParameters } impl Clean for ast::PathSegment { fn clean(&self, cx: &DocContext) -> PathSegment { - let (lifetimes, types) = match self.parameters { - ast::AngleBracketedParameters(ref data) => { - (data.lifetimes.clean(cx), data.types.clean(cx)) - } - - ast::ParenthesizedParameters(ref data) => { - // FIXME -- rustdoc should be taught about Foo() notation - let inputs = Tuple(data.inputs.clean(cx)); - let output = data.output.as_ref().map(|t| t.clean(cx)).unwrap_or(Tuple(Vec::new())); - (Vec::new(), vec![inputs, output]) - } - }; - PathSegment { name: self.identifier.clean(cx), - lifetimes: lifetimes, - types: types, + params: self.parameters.clean(cx) } } } @@ -2399,8 +2418,10 @@ fn lang_struct(cx: &DocContext, did: Option, global: false, segments: vec![PathSegment { name: name.to_string(), - lifetimes: vec![], - types: vec![t.clean(cx)], + params: PathParameters::AngleBracketed { + lifetimes: vec![], + types: vec![t.clean(cx)], + } }], }, } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 83f760f15f6..841588e4012 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -171,6 +171,58 @@ impl fmt::Show for clean::TyParamBound { } } +impl fmt::Show for clean::PathParameters { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + clean::PathParameters::AngleBracketed { ref lifetimes, ref types } => { + if lifetimes.len() > 0 || types.len() > 0 { + try!(f.write("<".as_bytes())); + let mut comma = false; + for lifetime in lifetimes.iter() { + if comma { + try!(f.write(", ".as_bytes())); + } + comma = true; + try!(write!(f, "{}", *lifetime)); + } + for ty in types.iter() { + if comma { + try!(f.write(", ".as_bytes())); + } + comma = true; + try!(write!(f, "{}", *ty)); + } + try!(f.write(">".as_bytes())); + } + } + clean::PathParameters::Parenthesized { ref inputs, ref output } => { + try!(f.write("(".as_bytes())); + let mut comma = false; + for ty in inputs.iter() { + if comma { + try!(f.write(", ".as_bytes())); + } + comma = true; + try!(write!(f, "{}", *ty)); + } + try!(f.write(")".as_bytes())); + if let Some(ref ty) = *output { + try!(f.write(" -> ".as_bytes())); + try!(write!(f, "{}", ty)); + } + } + } + Ok(()) + } +} + +impl fmt::Show for clean::PathSegment { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(f.write(self.name.as_bytes())); + write!(f, "{}", self.params) + } +} + impl fmt::Show for clean::Path { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.global { @@ -181,27 +233,7 @@ impl fmt::Show for clean::Path { if i > 0 { try!(f.write("::".as_bytes())) } - try!(f.write(seg.name.as_bytes())); - - if seg.lifetimes.len() > 0 || seg.types.len() > 0 { - try!(f.write("<".as_bytes())); - let mut comma = false; - for lifetime in seg.lifetimes.iter() { - if comma { - try!(f.write(", ".as_bytes())); - } - comma = true; - try!(write!(f, "{}", *lifetime)); - } - for ty in seg.types.iter() { - if comma { - try!(f.write(", ".as_bytes())); - } - comma = true; - try!(write!(f, "{}", *ty)); - } - try!(f.write(">".as_bytes())); - } + try!(write!(f, "{}", seg)); } Ok(()) } @@ -243,23 +275,8 @@ fn path(w: &mut fmt::Formatter, G: FnOnce(&render::Cache) -> Option<(Vec, ItemType)>, { // The generics will get written to both the title and link - let mut generics = String::new(); let last = path.segments.last().unwrap(); - if last.lifetimes.len() > 0 || last.types.len() > 0 { - let mut counter = 0u; - generics.push_str("<"); - for lifetime in last.lifetimes.iter() { - if counter > 0 { generics.push_str(", "); } - counter += 1; - generics.push_str(format!("{}", *lifetime).as_slice()); - } - for ty in last.types.iter() { - if counter > 0 { generics.push_str(", "); } - counter += 1; - generics.push_str(format!("{}", *ty).as_slice()); - } - generics.push_str(">"); - } + let generics = format!("{}", last.params); let loc = CURRENT_LOCATION_KEY.with(|l| l.borrow().clone()); let cache = cache(); @@ -660,8 +677,10 @@ impl fmt::Show for clean::ViewListIdent { global: false, segments: vec!(clean::PathSegment { name: self.name.clone(), - lifetimes: Vec::new(), - types: Vec::new(), + params: clean::PathParameters::AngleBracketed { + lifetimes: Vec::new(), + types: Vec::new(), + } }) }; resolved_path(f, did, &path, false)