diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-07-02 11:08:21 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-07-02 11:08:21 -0700 |
| commit | ff1dd44b40a7243f43a8d32ba8bd6026197c320b (patch) | |
| tree | 4460cbf0a917a289d1d3744d9645c5ab131ea9df /src/librustdoc | |
| parent | aa1163b92de7717eb7c5eba002b4012e0574a7fe (diff) | |
| parent | ca2778ede7c21efc3cf2e4e1152875ec09360770 (diff) | |
| download | rust-ff1dd44b40a7243f43a8d32ba8bd6026197c320b.tar.gz rust-ff1dd44b40a7243f43a8d32ba8bd6026197c320b.zip | |
Merge remote-tracking branch 'origin/master' into 0.11.0-release
Conflicts: src/libstd/lib.rs
Diffstat (limited to 'src/librustdoc')
| -rw-r--r-- | src/librustdoc/clean/inline.rs | 3 | ||||
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 152 | ||||
| -rw-r--r-- | src/librustdoc/core.rs | 15 | ||||
| -rw-r--r-- | src/librustdoc/doctree.rs | 12 | ||||
| -rw-r--r-- | src/librustdoc/externalfiles.rs | 70 | ||||
| -rw-r--r-- | src/librustdoc/flock.rs | 7 | ||||
| -rw-r--r-- | src/librustdoc/fold.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/html/format.rs | 37 | ||||
| -rw-r--r-- | src/librustdoc/html/layout.rs | 11 | ||||
| -rw-r--r-- | src/librustdoc/html/markdown.rs | 44 | ||||
| -rw-r--r-- | src/librustdoc/html/render.rs | 131 | ||||
| -rw-r--r-- | src/librustdoc/html/static/main.css | 28 | ||||
| -rw-r--r-- | src/librustdoc/lib.rs | 54 | ||||
| -rw-r--r-- | src/librustdoc/markdown.rs | 59 | ||||
| -rw-r--r-- | src/librustdoc/plugins.rs | 2 | ||||
| -rw-r--r-- | src/librustdoc/test.rs | 9 | ||||
| -rw-r--r-- | src/librustdoc/visit_ast.rs | 21 |
17 files changed, 414 insertions, 245 deletions
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d243c61ddaf..2d498e7f302 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -18,6 +18,7 @@ use rustc::metadata::csearch; use rustc::metadata::decoder; use rustc::middle::def; use rustc::middle::ty; +use rustc::middle::stability; use core; use doctree; @@ -102,6 +103,7 @@ fn try_inline_def(cx: &core::DocContext, attrs: load_attrs(tcx, did), inner: inner, visibility: Some(ast::Public), + stability: stability::lookup(tcx, did).clean(), def_id: did, }); Some(ret) @@ -317,6 +319,7 @@ fn build_impl(cx: &core::DocContext, name: None, attrs: attrs, visibility: Some(ast::Inherited), + stability: stability::lookup(tcx, did).clean(), def_id: did, }) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d7bbb439dbb..87151708812 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -29,6 +29,7 @@ use rustc::middle::def; use rustc::middle::subst; use rustc::middle::subst::VecPerParamSpace; use rustc::middle::ty; +use rustc::middle::stability; use std::rc::Rc; use std::u32; @@ -44,6 +45,17 @@ pub static SCHEMA_VERSION: &'static str = "0.8.3"; mod inline; +// load the current DocContext from TLD +fn get_cx() -> Gc<core::DocContext> { + *super::ctxtkey.get().unwrap() +} + +// extract the stability index for a node from TLD, if possible +fn get_stability(def_id: ast::DefId) -> Option<Stability> { + get_cx().tcx_opt().and_then(|tcx| stability::lookup(tcx, def_id)) + .map(|stab| stab.clean()) +} + pub trait Clean<T> { fn clean(&self) -> T; } @@ -97,7 +109,7 @@ pub struct Crate { impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> { fn clean(&self) -> Crate { - let cx = super::ctxtkey.get().unwrap(); + let cx = get_cx(); let mut externs = Vec::new(); cx.sess().cstore.iter_crate_data(|n, meta| { @@ -158,6 +170,7 @@ impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> { name: Some(prim.to_url_str().to_string()), attrs: Vec::new(), visibility: None, + stability: None, def_id: ast_util::local_def(prim.to_node_id()), inner: PrimitiveItem(prim), }; @@ -193,25 +206,18 @@ pub struct ExternalCrate { impl Clean<ExternalCrate> for cstore::crate_metadata { fn clean(&self) -> ExternalCrate { let mut primitives = Vec::new(); - let cx = super::ctxtkey.get().unwrap(); - match cx.maybe_typed { - core::Typed(ref tcx) => { - csearch::each_top_level_item_of_crate(&tcx.sess.cstore, - self.cnum, - |def, _, _| { - let did = match def { - decoder::DlDef(def::DefMod(did)) => did, - _ => return - }; - let attrs = inline::load_attrs(tcx, did); - match Primitive::find(attrs.as_slice()) { - Some(prim) => primitives.push(prim), - None => {} - } - }); - } - core::NotTyped(..) => {} - } + get_cx().tcx_opt().map(|tcx| { + csearch::each_top_level_item_of_crate(&tcx.sess.cstore, + self.cnum, + |def, _, _| { + let did = match def { + decoder::DlDef(def::DefMod(did)) => did, + _ => return + }; + let attrs = inline::load_attrs(tcx, did); + Primitive::find(attrs.as_slice()).map(|prim| primitives.push(prim)); + }) + }); ExternalCrate { name: self.name.to_string(), attrs: decoder::get_crate_attributes(self.data()).clean(), @@ -233,6 +239,7 @@ pub struct Item { pub inner: ItemEnum, pub visibility: Option<Visibility>, pub def_id: ast::DefId, + pub stability: Option<Stability>, } impl Item { @@ -380,6 +387,7 @@ impl Clean<Item> for doctree::Module { attrs: self.attrs.clean(), source: where.clean(), visibility: self.vis.clean(), + stability: self.stab.clean(), def_id: ast_util::local_def(self.id), inner: ModuleItem(Module { is_crate: self.is_crate, @@ -465,9 +473,8 @@ impl Clean<TyParam> for ast::TyParam { impl Clean<TyParam> for ty::TypeParameterDef { fn clean(&self) -> TyParam { - let cx = super::ctxtkey.get().unwrap(); - cx.external_typarams.borrow_mut().get_mut_ref().insert(self.def_id, - self.ident.clean()); + get_cx().external_typarams.borrow_mut().get_mut_ref() + .insert(self.def_id, self.ident.clean()); TyParam { name: self.ident.clean(), did: self.def_id, @@ -515,7 +522,7 @@ fn external_path(name: &str, substs: &subst::Substs) -> Path { impl Clean<TyParamBound> for ty::BuiltinBound { fn clean(&self) -> TyParamBound { - let cx = super::ctxtkey.get().unwrap(); + let cx = get_cx(); let tcx = match cx.maybe_typed { core::Typed(ref tcx) => tcx, core::NotTyped(_) => return RegionBound, @@ -550,7 +557,7 @@ impl Clean<TyParamBound> for ty::BuiltinBound { impl Clean<TyParamBound> for ty::TraitRef { fn clean(&self) -> TyParamBound { - let cx = super::ctxtkey.get().unwrap(); + let cx = get_cx(); let tcx = match cx.maybe_typed { core::Typed(ref tcx) => tcx, core::NotTyped(_) => return RegionBound, @@ -709,8 +716,9 @@ impl Clean<Item> for ast::Method { name: Some(self.ident.clean()), attrs: self.attrs.clean().move_iter().collect(), source: self.span.clean(), - def_id: ast_util::local_def(self.id.clone()), + def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: get_stability(ast_util::local_def(self.id)), inner: MethodItem(Method { generics: self.generics.clean(), self_: self.explicit_self.node.clean(), @@ -749,6 +757,7 @@ impl Clean<Item> for ast::TypeMethod { source: self.span.clean(), def_id: ast_util::local_def(self.id), visibility: None, + stability: get_stability(ast_util::local_def(self.id)), inner: TyMethodItem(TyMethod { fn_style: self.fn_style.clone(), decl: decl, @@ -792,6 +801,7 @@ impl Clean<Item> for doctree::Function { attrs: self.attrs.clean(), source: self.where.clean(), visibility: self.vis.clean(), + stability: self.stab.clean(), def_id: ast_util::local_def(self.id), inner: FunctionItem(Function { decl: self.decl.clean(), @@ -854,14 +864,10 @@ impl Clean<FnDecl> for ast::FnDecl { impl<'a> Clean<FnDecl> for (ast::DefId, &'a ty::FnSig) { fn clean(&self) -> FnDecl { - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tcx) => tcx, - core::NotTyped(_) => unreachable!(), - }; + let cx = get_cx(); let (did, sig) = *self; let mut names = if did.node != 0 { - csearch::get_method_arg_names(&tcx.sess.cstore, did).move_iter() + csearch::get_method_arg_names(&cx.tcx().sess.cstore, did).move_iter() } else { Vec::new().move_iter() }.peekable(); @@ -932,6 +938,7 @@ impl Clean<Item> for doctree::Trait { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: TraitItem(Trait { methods: self.methods.clean(), generics: self.generics.clean(), @@ -985,11 +992,7 @@ impl Clean<TraitMethod> for ast::TraitMethod { impl Clean<Item> for ty::Method { fn clean(&self) -> Item { - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tcx) => tcx, - core::NotTyped(_) => unreachable!(), - }; + let cx = get_cx(); let (self_, sig) = match self.explicit_self { ast::SelfStatic => (ast::SelfStatic.clean(), self.fty.sig.clone()), s => { @@ -1015,8 +1018,9 @@ impl Clean<Item> for ty::Method { Item { name: Some(self.ident.clean()), visibility: Some(ast::Inherited), + stability: get_stability(self.def_id), def_id: self.def_id, - attrs: inline::load_attrs(tcx, self.def_id), + attrs: inline::load_attrs(cx.tcx(), self.def_id), source: Span::empty(), inner: TyMethodItem(TyMethod { fn_style: self.fty.fn_style, @@ -1261,12 +1265,7 @@ impl Clean<Type> for ty::t { ty::ty_struct(did, ref substs) | ty::ty_enum(did, ref substs) | ty::ty_trait(box ty::TyTrait { def_id: did, ref substs, .. }) => { - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tycx) => tycx, - core::NotTyped(_) => unreachable!(), - }; - let fqn = csearch::get_item_path(tcx, did); + let fqn = csearch::get_item_path(get_cx().tcx(), did); let fqn: Vec<String> = fqn.move_iter().map(|i| { i.to_str() }).collect(); @@ -1277,8 +1276,8 @@ impl Clean<Type> for ty::t { }; let path = external_path(fqn.last().unwrap().to_str().as_slice(), substs); - cx.external_paths.borrow_mut().get_mut_ref().insert(did, - (fqn, kind)); + get_cx().external_paths.borrow_mut().get_mut_ref() + .insert(did, (fqn, kind)); ResolvedPath { path: path, typarams: None, @@ -1318,6 +1317,7 @@ impl Clean<Item> for ast::StructField { attrs: self.node.attrs.clean().move_iter().collect(), source: self.span.clean(), visibility: Some(vis), + stability: get_stability(ast_util::local_def(self.node.id)), def_id: ast_util::local_def(self.node.id), inner: StructFieldItem(TypedStructField(self.node.ty.clean())), } @@ -1332,17 +1332,14 @@ impl Clean<Item> for ty::field_ty { } else { Some(self.name) }; - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tycx) => tycx, - core::NotTyped(_) => unreachable!(), - }; - let ty = ty::lookup_item_type(tcx, self.id); + let cx = get_cx(); + let ty = ty::lookup_item_type(cx.tcx(), self.id); Item { name: name.clean(), - attrs: inline::load_attrs(tcx, self.id), + attrs: inline::load_attrs(cx.tcx(), self.id), source: Span::empty(), visibility: Some(self.vis), + stability: get_stability(self.id), def_id: self.id, inner: StructFieldItem(TypedStructField(ty.ty.clean())), } @@ -1373,6 +1370,7 @@ impl Clean<Item> for doctree::Struct { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: StructItem(Struct { struct_type: self.struct_type, generics: self.generics.clean(), @@ -1418,6 +1416,7 @@ impl Clean<Item> for doctree::Enum { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: EnumItem(Enum { variants: self.variants.clean(), generics: self.generics.clean(), @@ -1439,6 +1438,7 @@ impl Clean<Item> for doctree::Variant { attrs: self.attrs.clean(), source: self.where.clean(), visibility: self.vis.clean(), + stability: self.stab.clean(), def_id: ast_util::local_def(self.id), inner: VariantItem(Variant { kind: self.kind.clean(), @@ -1450,11 +1450,7 @@ impl Clean<Item> for doctree::Variant { impl Clean<Item> for ty::VariantInfo { fn clean(&self) -> Item { // use syntax::parse::token::special_idents::unnamed_field; - let cx = super::ctxtkey.get().unwrap(); - let tcx = match cx.maybe_typed { - core::Typed(ref tycx) => tycx, - core::NotTyped(_) => fail!("tcx not present"), - }; + let cx = get_cx(); let kind = match self.arg_names.as_ref().map(|s| s.as_slice()) { None | Some([]) if self.args.len() == 0 => CLikeVariant, None | Some([]) => { @@ -1470,6 +1466,7 @@ impl Clean<Item> for ty::VariantInfo { name: Some(name.clean()), attrs: Vec::new(), visibility: Some(ast::Public), + stability: get_stability(self.id), // FIXME: this is not accurate, we need an id for // the specific field but we're using the id // for the whole variant. Nothing currently @@ -1485,11 +1482,12 @@ impl Clean<Item> for ty::VariantInfo { }; Item { name: Some(self.name.clean()), - attrs: inline::load_attrs(tcx, self.id), + attrs: inline::load_attrs(cx.tcx(), self.id), source: Span::empty(), visibility: Some(ast::Public), def_id: self.id, inner: VariantItem(Variant { kind: kind }), + stability: None, } } } @@ -1626,6 +1624,7 @@ impl Clean<Item> for doctree::Typedef { source: self.where.clean(), def_id: ast_util::local_def(self.id.clone()), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: TypedefItem(Typedef { type_: self.ty.clean(), generics: self.gen.clean(), @@ -1675,6 +1674,7 @@ impl Clean<Item> for doctree::Static { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: StaticItem(Static { type_: self.type_.clean(), mutability: self.mutability.clean(), @@ -1720,6 +1720,7 @@ impl Clean<Item> for doctree::Impl { source: self.where.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: self.stab.clean(), inner: ImplItem(Impl { generics: self.generics.clean(), trait_: self.trait_.clean(), @@ -1754,6 +1755,7 @@ impl Clean<Vec<Item>> for ast::ViewItem { source: self.span.clean(), def_id: ast_util::local_def(0), visibility: self.vis.clean(), + stability: None, inner: ViewItemItem(ViewItem { inner: node.clean() }), } }; @@ -1895,6 +1897,7 @@ impl Clean<Item> for ast::ForeignItem { source: self.span.clean(), def_id: ast_util::local_def(self.id), visibility: self.vis.clean(), + stability: None, inner: inner, } } @@ -1977,7 +1980,7 @@ fn name_from_pat(p: &ast::Pat) -> String { /// Given a Type, resolve it using the def_map fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>, id: ast::NodeId) -> Type { - let cx = super::ctxtkey.get().unwrap(); + let cx = get_cx(); let tycx = match cx.maybe_typed { core::Typed(ref tycx) => tycx, // If we're extracting tests, this return value doesn't matter. @@ -2012,7 +2015,7 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>, def::DefTyParamBinder(i) => return TyParamBinder(i), _ => {} }; - let did = register_def(&**cx, def); + let did = register_def(&*cx, def); ResolvedPath { path: path, typarams: tpbs, did: did } } @@ -2051,13 +2054,9 @@ fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource { } fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> { - let cx = super::ctxtkey.get().unwrap(); - match cx.maybe_typed { - core::Typed(ref tcx) => { - tcx.def_map.borrow().find(&id).map(|&def| register_def(&**cx, def)) - } - core::NotTyped(_) => None - } + get_cx().tcx_opt().and_then(|tcx| { + tcx.def_map.borrow().find(&id).map(|&def| register_def(&*get_cx(), def)) + }) } #[deriving(Clone, Encodable, Decodable)] @@ -2072,6 +2071,7 @@ impl Clean<Item> for doctree::Macro { attrs: self.attrs.clean(), source: self.where.clean(), visibility: ast::Public.clean(), + stability: self.stab.clean(), def_id: ast_util::local_def(self.id), inner: MacroItem(Macro { source: self.where.to_src(), @@ -2079,3 +2079,19 @@ impl Clean<Item> for doctree::Macro { } } } + +#[deriving(Clone, Encodable, Decodable)] +pub struct Stability { + pub level: attr::StabilityLevel, + pub text: String +} + +impl Clean<Stability> for attr::Stability { + fn clean(&self) -> Stability { + Stability { + level: self.level, + text: self.text.as_ref().map_or("".to_string(), + |interned| interned.get().to_string()), + } + } +} diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index ba0161da7e6..245b2d162a7 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -10,7 +10,7 @@ use rustc; use rustc::{driver, middle}; -use rustc::middle::privacy; +use rustc::middle::{privacy, ty}; use rustc::lint; use syntax::ast; @@ -26,6 +26,7 @@ use visit_ast::RustdocVisitor; use clean; use clean::Clean; +/// Are we generating documentation (`Typed`) or tests (`NotTyped`)? pub enum MaybeTyped { Typed(middle::ty::ctxt), NotTyped(driver::session::Session) @@ -52,6 +53,18 @@ impl DocContext { NotTyped(ref sess) => sess } } + + pub fn tcx_opt<'a>(&'a self) -> Option<&'a ty::ctxt> { + match self.maybe_typed { + Typed(ref tcx) => Some(tcx), + NotTyped(_) => None + } + } + + pub fn tcx<'a>(&'a self) -> &'a ty::ctxt { + let tcx_opt = self.tcx_opt(); + tcx_opt.expect("tcx not present") + } } pub struct CrateAnalysis { diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index b8a2a6195b7..313f1c81c79 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -14,6 +14,7 @@ use syntax; use syntax::codemap::Span; use syntax::ast; +use syntax::attr; use syntax::ast::{Ident, NodeId}; use std::gc::Gc; @@ -32,6 +33,7 @@ pub struct Module { pub statics: Vec<Static>, pub traits: Vec<Trait>, pub vis: ast::Visibility, + pub stab: Option<attr::Stability>, pub impls: Vec<Impl>, pub foreigns: Vec<ast::ForeignMod>, pub view_items: Vec<ast::ViewItem>, @@ -45,6 +47,7 @@ impl Module { name : name, id: 0, vis: ast::Inherited, + stab: None, where_outer: syntax::codemap::DUMMY_SP, where_inner: syntax::codemap::DUMMY_SP, attrs : Vec::new(), @@ -83,6 +86,7 @@ pub enum TypeBound { pub struct Struct { pub vis: ast::Visibility, + pub stab: Option<attr::Stability>, pub id: NodeId, pub struct_type: StructType, pub name: Ident, @@ -94,6 +98,7 @@ pub struct Struct { pub struct Enum { pub vis: ast::Visibility, + pub stab: Option<attr::Stability>, pub variants: Vec<Variant>, pub generics: ast::Generics, pub attrs: Vec<ast::Attribute>, @@ -108,6 +113,7 @@ pub struct Variant { pub kind: ast::VariantKind, pub id: ast::NodeId, pub vis: ast::Visibility, + pub stab: Option<attr::Stability>, pub where: Span, } @@ -117,6 +123,7 @@ pub struct Function { pub id: NodeId, pub name: Ident, pub vis: ast::Visibility, + pub stab: Option<attr::Stability>, pub fn_style: ast::FnStyle, pub where: Span, pub generics: ast::Generics, @@ -130,6 +137,7 @@ pub struct Typedef { pub attrs: Vec<ast::Attribute>, pub where: Span, pub vis: ast::Visibility, + pub stab: Option<attr::Stability>, } pub struct Static { @@ -139,6 +147,7 @@ pub struct Static { pub name: Ident, pub attrs: Vec<ast::Attribute>, pub vis: ast::Visibility, + pub stab: Option<attr::Stability>, pub id: ast::NodeId, pub where: Span, } @@ -152,6 +161,7 @@ pub struct Trait { pub id: ast::NodeId, pub where: Span, pub vis: ast::Visibility, + pub stab: Option<attr::Stability>, } pub struct Impl { @@ -162,6 +172,7 @@ pub struct Impl { pub attrs: Vec<ast::Attribute>, pub where: Span, pub vis: ast::Visibility, + pub stab: Option<attr::Stability>, pub id: ast::NodeId, } @@ -170,6 +181,7 @@ pub struct Macro { pub id: ast::NodeId, pub attrs: Vec<ast::Attribute>, pub where: Span, + pub stab: Option<attr::Stability>, } pub fn struct_type_from_def(sd: &ast::StructDef) -> StructType { diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs new file mode 100644 index 00000000000..0931f132c02 --- /dev/null +++ b/src/librustdoc/externalfiles.rs @@ -0,0 +1,70 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::{io, str}; + +#[deriving(Clone)] +pub struct ExternalHtml{ + pub in_header: String, + pub before_content: String, + pub after_content: String +} + +impl ExternalHtml { + pub fn load(in_header: &[String], before_content: &[String], after_content: &[String]) + -> Option<ExternalHtml> { + match (load_external_files(in_header), + load_external_files(before_content), + load_external_files(after_content)) { + (Some(ih), Some(bc), Some(ac)) => Some(ExternalHtml { + in_header: ih, + before_content: bc, + after_content: ac + }), + _ => None + } + } +} + +pub fn load_string(input: &Path) -> io::IoResult<Option<String>> { + let mut f = try!(io::File::open(input)); + let d = try!(f.read_to_end()); + Ok(str::from_utf8(d.as_slice()).map(|s| s.to_string())) +} + +macro_rules! load_or_return { + ($input: expr, $cant_read: expr, $not_utf8: expr) => { + { + let input = Path::new($input); + match ::externalfiles::load_string(&input) { + Err(e) => { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: {}", input.display(), e); + return $cant_read; + } + Ok(None) => { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: not UTF-8", input.display()); + return $not_utf8; + } + Ok(Some(s)) => s + } + } + } +} + +pub fn load_external_files(names: &[String]) -> Option<String> { + let mut out = String::new(); + for name in names.iter() { + out.push_str(load_or_return!(name.as_slice(), None, None).as_slice()); + out.push_char('\n'); + } + Some(out) +} diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index 800e7f065f1..f07c0163676 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -104,7 +104,7 @@ mod imp { l_sysid: 0, }; let ret = unsafe { - libc::fcntl(fd, os::F_SETLKW, &flock as *os::flock) + libc::fcntl(fd, os::F_SETLKW, &flock as *const os::flock) }; if ret == -1 { unsafe { libc::close(fd); } @@ -125,7 +125,7 @@ mod imp { l_sysid: 0, }; unsafe { - libc::fcntl(self.fd, os::F_SETLK, &flock as *os::flock); + libc::fcntl(self.fd, os::F_SETLK, &flock as *const os::flock); libc::close(self.fd); } } @@ -162,7 +162,8 @@ mod imp { impl Lock { pub fn new(p: &Path) -> Lock { - let p_16 = p.as_str().unwrap().to_utf16().append_one(0); + let p_16: Vec<u16> = p.as_str().unwrap().utf16_units().collect(); + let p_16 = p_16.append_one(0); let handle = unsafe { libc::CreateFileW(p_16.as_ptr(), libc::FILE_GENERIC_READ | diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 77b12aec97b..60853f450ab 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -19,7 +19,7 @@ pub trait DocFolder { /// don't override! fn fold_item_recur(&mut self, item: Item) -> Option<Item> { - let Item { attrs, name, source, visibility, def_id, inner } = item; + let Item { attrs, name, source, visibility, def_id, inner, stability } = item; let inner = inner; let inner = match inner { StructItem(mut i) => { @@ -83,7 +83,7 @@ pub trait DocFolder { }; Some(Item { attrs: attrs, name: name, source: source, inner: inner, - visibility: visibility, def_id: def_id }) + visibility: visibility, stability: stability, def_id: def_id }) } fn fold_mod(&mut self, m: Module) -> Module { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 1173f6eb5b8..9677b9004cd 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -37,6 +37,10 @@ pub struct FnStyleSpace(pub ast::FnStyle); pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl); /// Similar to VisSpace, but used for mutability pub struct MutableSpace(pub clean::Mutability); +/// Wrapper struct for properly emitting the stability level. +pub struct Stability<'a>(pub &'a Option<clean::Stability>); +/// Wrapper struct for emitting the stability level concisely. +pub struct ConciseStability<'a>(pub &'a Option<clean::Stability>); impl VisSpace { pub fn get(&self) -> Option<ast::Visibility> { @@ -185,7 +189,7 @@ fn path(w: &mut fmt::Formatter, path: &clean::Path, print_all: bool, let mut generics = String::new(); let last = path.segments.last().unwrap(); if last.lifetimes.len() > 0 || last.types.len() > 0 { - let mut counter = 0; + let mut counter = 0u; generics.push_str("<"); for lifetime in last.lifetimes.iter() { if counter > 0 { generics.push_str(", "); } @@ -596,3 +600,34 @@ impl fmt::Show for MutableSpace { } } } + +impl<'a> fmt::Show for Stability<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let Stability(stab) = *self; + match *stab { + Some(ref stability) => { + write!(f, "<a class='stability {lvl}' title='{reason}'>{lvl}</a>", + lvl = stability.level.to_str(), + reason = stability.text) + } + None => Ok(()) + } + } +} + +impl<'a> fmt::Show for ConciseStability<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let ConciseStability(stab) = *self; + match *stab { + Some(ref stability) => { + write!(f, "<a class='stability {lvl}' title='{lvl}{colon}{reason}'></a>", + lvl = stability.level.to_str(), + colon = if stability.text.len() > 0 { ": " } else { "" }, + reason = stability.text) + } + None => { + write!(f, "<a class='stability Unmarked' title='No stability level'></a>") + } + } + } +} diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 61a2d3c5d9c..aa298d07780 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -11,10 +11,13 @@ use std::fmt; use std::io; +use externalfiles::ExternalHtml; + #[deriving(Clone)] pub struct Layout { pub logo: String, pub favicon: String, + pub external_html: ExternalHtml, pub krate: String, pub playground_url: String, } @@ -44,6 +47,7 @@ r##"<!DOCTYPE html> <link rel="stylesheet" type="text/css" href="{root_path}main.css"> {favicon} + {in_header} </head> <body> <!--[if lte IE 8]> @@ -53,6 +57,8 @@ r##"<!DOCTYPE html> </div> <![endif]--> + {before_content} + <section class="sidebar"> {logo} {sidebar} @@ -105,6 +111,8 @@ r##"<!DOCTYPE html> </div> </div> + {after_content} + <script> window.rootPath = "{root_path}"; window.currentCrate = "{krate}"; @@ -133,6 +141,9 @@ r##"<!DOCTYPE html> } else { format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon) }, + in_header = layout.external_html.in_header, + before_content = layout.external_html.before_content, + after_content = layout.external_html.after_content, sidebar = *sidebar, krate = layout.krate, play_url = layout.playground_url, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index cfd004c0c83..de4bbeb6e30 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -66,13 +66,13 @@ type hoedown_document = libc::c_void; // this is opaque to us struct hoedown_renderer { opaque: *mut hoedown_html_renderer_state, - blockcode: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer, - *hoedown_buffer, *mut libc::c_void)>, - blockquote: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer, + blockcode: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, + *const hoedown_buffer, *mut libc::c_void)>, + blockquote: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, *mut libc::c_void)>, - blockhtml: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer, + blockhtml: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, *mut libc::c_void)>, - header: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer, + header: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, libc::c_int, *mut libc::c_void)>, other: [libc::size_t, ..28], } @@ -81,7 +81,8 @@ struct hoedown_html_renderer_state { opaque: *mut libc::c_void, toc_data: html_toc_data, flags: libc::c_uint, - link_attributes: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer, + link_attributes: Option<extern "C" fn(*mut hoedown_buffer, + *const hoedown_buffer, *mut libc::c_void)>, } @@ -93,13 +94,13 @@ struct html_toc_data { } struct MyOpaque { - dfltblk: extern "C" fn(*mut hoedown_buffer, *hoedown_buffer, - *hoedown_buffer, *mut libc::c_void), + dfltblk: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, + *const hoedown_buffer, *mut libc::c_void), toc_builder: Option<TocBuilder>, } struct hoedown_buffer { - data: *u8, + data: *const u8, size: libc::size_t, asize: libc::size_t, unit: libc::size_t, @@ -118,12 +119,12 @@ extern { max_nesting: libc::size_t) -> *mut hoedown_document; fn hoedown_document_render(doc: *mut hoedown_document, ob: *mut hoedown_buffer, - document: *u8, + document: *const u8, doc_size: libc::size_t); fn hoedown_document_free(md: *mut hoedown_document); fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer; - fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *libc::c_char); + fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char); fn hoedown_buffer_free(b: *mut hoedown_buffer); } @@ -147,13 +148,13 @@ local_data_key!(test_idx: Cell<uint>) local_data_key!(pub playground_krate: Option<String>) pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { - extern fn block(ob: *mut hoedown_buffer, text: *hoedown_buffer, - lang: *hoedown_buffer, opaque: *mut libc::c_void) { + extern fn block(ob: *mut hoedown_buffer, text: *const hoedown_buffer, + lang: *const hoedown_buffer, opaque: *mut libc::c_void) { unsafe { if text.is_null() { return } let opaque = opaque as *mut hoedown_html_renderer_state; - let my_opaque: &MyOpaque = &*((*opaque).opaque as *MyOpaque); + let my_opaque: &MyOpaque = &*((*opaque).opaque as *const MyOpaque); slice::raw::buf_as_slice((*text).data, (*text).size as uint, |text| { let origtext = str::from_utf8(text).unwrap(); debug!("docblock: ==============\n{}\n=======", text); @@ -205,15 +206,13 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { s.push_str(highlight::highlight(text.as_slice(), None, id) .as_slice()); let output = s.to_c_str(); - output.with_ref(|r| { - hoedown_buffer_puts(ob, r) - }) + hoedown_buffer_puts(ob, output.as_ptr()); } }) } } - extern fn header(ob: *mut hoedown_buffer, text: *hoedown_buffer, + extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer, level: libc::c_int, opaque: *mut libc::c_void) { // hoedown does this, we may as well too "\n".with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) }); @@ -304,8 +303,10 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { } pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { - extern fn block(_ob: *mut hoedown_buffer, text: *hoedown_buffer, - lang: *hoedown_buffer, opaque: *mut libc::c_void) { + extern fn block(_ob: *mut hoedown_buffer, + text: *const hoedown_buffer, + lang: *const hoedown_buffer, + opaque: *mut libc::c_void) { unsafe { if text.is_null() { return } let block_info = if lang.is_null() { @@ -333,7 +334,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { } } - extern fn header(_ob: *mut hoedown_buffer, text: *hoedown_buffer, + extern fn header(_ob: *mut hoedown_buffer, + text: *const hoedown_buffer, level: libc::c_int, opaque: *mut libc::c_void) { unsafe { let opaque = opaque as *mut hoedown_html_renderer_state; diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index aacb13156b7..917eab4eeb9 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -41,17 +41,18 @@ use std::str; use std::string::String; use std::sync::Arc; +use externalfiles::ExternalHtml; + use serialize::json::ToJson; use syntax::ast; use syntax::ast_util; -use syntax::attr; -use syntax::parse::token::InternedString; use rustc::util::nodemap::NodeSet; use clean; use doctree; use fold::DocFolder; -use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace}; +use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability}; +use html::format::{ConciseStability}; use html::highlight; use html::item_type::{ItemType, shortty}; use html::item_type; @@ -78,7 +79,7 @@ pub struct Context { /// This changes as the context descends into the module hierarchy. pub dst: Path, /// This describes the layout of each page, and is not modified after - /// creation of the context (contains info like the favicon) + /// creation of the context (contains info like the favicon and added html). pub layout: layout::Layout, /// This map is a list of what should be displayed on the sidebar of the /// current page. The key is the section header (traits, modules, @@ -112,6 +113,15 @@ pub struct Implementor { generics: clean::Generics, trait_: clean::Type, for_: clean::Type, + stability: Option<clean::Stability>, +} + +/// Metadata about implementations for a type. +#[deriving(Clone)] +pub struct Impl { + impl_: clean::Impl, + dox: Option<String>, + stability: Option<clean::Stability>, } /// This cache is used to store information about the `clean::Crate` being @@ -135,7 +145,7 @@ pub struct Cache { /// /// The values of the map are a list of implementations and documentation /// found on that implementation. - pub impls: HashMap<ast::DefId, Vec<(clean::Impl, Option<String>)>>, + pub impls: HashMap<ast::DefId, Vec<Impl>>, /// Maintains a mapping of local crate node ids to the fully qualified name /// and "short type description" of that node. This is used when generating @@ -220,7 +230,7 @@ local_data_key!(pub cache_key: Arc<Cache>) local_data_key!(pub current_location_key: Vec<String> ) /// Generates the documentation for `crate` into the directory `dst` -pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { +pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) -> io::IoResult<()> { let mut cx = Context { dst: dst, current: Vec::new(), @@ -229,12 +239,14 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { layout: layout::Layout { logo: "".to_string(), favicon: "".to_string(), + external_html: external_html.clone(), krate: krate.name.clone(), playground_url: "".to_string(), }, include_sources: true, render_redirect_pages: false, }; + try!(mkdir(&cx.dst)); // Crawl the crate attributes looking for attributes which control how we're @@ -546,7 +558,8 @@ fn write_shared(cx: &Context, // going on). If they're in different crates then the crate defining // the trait will be interested in our implementation. if imp.def_id.krate == did.krate { continue } - try!(write!(&mut f, r#""impl{} {} for {}","#, + try!(write!(&mut f, r#""{}impl{} {} for {}","#, + ConciseStability(&imp.stability), imp.generics, imp.trait_, imp.for_)); } try!(writeln!(&mut f, r"];")); @@ -778,6 +791,7 @@ impl DocFolder for Cache { generics: i.generics.clone(), trait_: i.trait_.get_ref().clone(), for_: i.for_.clone(), + stability: item.stability.clone(), }); } Some(..) | None => {} @@ -963,7 +977,11 @@ impl DocFolder for Cache { let v = self.impls.find_or_insert_with(did, |_| { Vec::new() }); - v.push((i, dox)); + v.push(Impl { + impl_: i, + dox: dox, + stability: item.stability.clone(), + }); } None => {} } @@ -1244,19 +1262,8 @@ impl<'a> fmt::Show for Item<'a> { try!(write!(fmt, "<a class='{}' href=''>{}</a>", shortty(self.item), self.item.name.get_ref().as_slice())); - // Write stability attributes - match attr::find_stability_generic(self.item.attrs.iter()) { - Some((ref stability, _)) => { - try!(write!(fmt, - "<a class='stability {lvl}' title='{reason}'>{lvl}</a>", - lvl = stability.level.to_str(), - reason = match stability.text { - Some(ref s) => (*s).clone(), - None => InternedString::new(""), - })); - } - None => {} - } + // Write stability level + try!(write!(fmt, "{}", Stability(&self.item.stability))); // Write `src` tag // @@ -1450,10 +1457,11 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, try!(write!(w, " <tr> - <td><code>{}static {}{}: {}</code>{}</td> + <td>{}<code>{}static {}{}: {}</code>{}</td> <td class='docblock'>{} </td> </tr> ", + ConciseStability(&myitem.stability), VisSpace(myitem.visibility), MutableSpace(s.mutability), *myitem.name.get_ref(), @@ -1488,7 +1496,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, if myitem.name.is_none() { continue } try!(write!(w, " <tr> - <td><a class='{class}' href='{href}' + <td>{stab}<a class='{class}' href='{href}' title='{title}'>{}</a></td> <td class='docblock short'>{}</td> </tr> @@ -1497,7 +1505,8 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, Markdown(shorter(myitem.doc_value())), class = shortty(myitem), href = item_path(myitem), - title = full_path(cx, myitem))); + title = full_path(cx, myitem), + stab = ConciseStability(&myitem.stability))); } } } @@ -1561,9 +1570,10 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, try!(document(w, it)); fn meth(w: &mut fmt::Formatter, m: &clean::TraitMethod) -> fmt::Result { - try!(write!(w, "<h3 id='{}.{}' class='method'><code>", - shortty(m.item()), - *m.item().name.get_ref())); + try!(write!(w, "<h3 id='{}.{}' class='method'>{}<code>", + shortty(m.item()), + *m.item().name.get_ref(), + ConciseStability(&m.item().stability))); try!(render_method(w, m.item())); try!(write!(w, "</code></h3>")); try!(document(w, m.item())); @@ -1600,7 +1610,8 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, match cache.implementors.find(&it.def_id) { Some(implementors) => { for i in implementors.iter() { - try!(writeln!(w, "<li><code>impl{} {} for {}</code></li>", + try!(writeln!(w, "<li>{}<code>impl{} {} for {}</code></li>", + ConciseStability(&i.stability), i.generics, i.trait_, i.for_)); } } @@ -1673,7 +1684,8 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item, try!(write!(w, "<h2 class='fields'>Fields</h2>\n<table>")); for field in fields { try!(write!(w, "<tr><td id='structfield.{name}'>\ - <code>{name}</code></td><td>", + {stab}<code>{name}</code></td><td>", + stab = ConciseStability(&field.stability), name = field.name.get_ref().as_slice())); try!(document(w, field)); try!(write!(w, "</td></tr>")); @@ -1739,7 +1751,8 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item, if e.variants.len() > 0 { try!(write!(w, "<h2 class='variants'>Variants</h2>\n<table>")); for variant in e.variants.iter() { - try!(write!(w, "<tr><td id='variant.{name}'><code>{name}</code></td><td>", + try!(write!(w, "<tr><td id='variant.{name}'>{stab}<code>{name}</code></td><td>", + stab = ConciseStability(&variant.stability), name = variant.name.get_ref().as_slice())); try!(document(w, variant)); match variant.inner { @@ -1849,39 +1862,25 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item, fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result { match cache_key.get().unwrap().impls.find(&it.def_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<String>)>>(); - let mut traits = v.iter().filter(|p| { - p.ref0().trait_.is_some() - }); - let traits = traits.collect::<Vec<&(clean::Impl, Option<String>)>>(); - + let (non_trait, traits) = v.partitioned(|i| i.impl_.trait_.is_none()); 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)); + for i in non_trait.iter() { + try!(render_impl(w, i)); } } 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; - } + let (derived, manual) = traits.partition(|i| i.impl_.derived); + for i in manual.iter() { + try!(render_impl(w, i)); } - if any_derived { + if derived.len() > 0 { 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)); - } + for i in derived.iter() { + try!(render_impl(w, i)); } } } @@ -1891,15 +1890,16 @@ fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result { Ok(()) } -fn render_impl(w: &mut fmt::Formatter, i: &clean::Impl, - dox: &Option<String>) -> fmt::Result { - try!(write!(w, "<h3 class='impl'><code>impl{} ", i.generics)); - match i.trait_ { +fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result { + try!(write!(w, "<h3 class='impl'>{}<code>impl{} ", + ConciseStability(&i.stability), + i.impl_.generics)); + match i.impl_.trait_ { Some(ref ty) => try!(write!(w, "{} for ", *ty)), None => {} } - try!(write!(w, "{}</code></h3>", i.for_)); - match *dox { + try!(write!(w, "{}</code></h3>", i.impl_.for_)); + match i.dox { Some(ref dox) => { try!(write!(w, "<div class='docblock'>{}</div>", Markdown(dox.as_slice()))); @@ -1909,8 +1909,9 @@ fn render_impl(w: &mut fmt::Formatter, i: &clean::Impl, fn docmeth(w: &mut fmt::Formatter, item: &clean::Item, dox: bool) -> fmt::Result { - try!(write!(w, "<h4 id='method.{}' class='method'><code>", - *item.name.get_ref())); + try!(write!(w, "<h4 id='method.{}' class='method'>{}<code>", + *item.name.get_ref(), + ConciseStability(&item.stability))); try!(render_method(w, item)); try!(write!(w, "</code></h4>\n")); match item.doc_value() { @@ -1922,8 +1923,8 @@ fn render_impl(w: &mut fmt::Formatter, i: &clean::Impl, } } - try!(write!(w, "<div class='methods'>")); - for meth in i.methods.iter() { + try!(write!(w, "<div class='impl-methods'>")); + for meth in i.impl_.methods.iter() { try!(docmeth(w, meth, true)); } @@ -1944,11 +1945,11 @@ fn render_impl(w: &mut fmt::Formatter, i: &clean::Impl, // If we've implemented a trait, then also emit documentation for all // default methods which weren't overridden in the implementation block. - match i.trait_ { + match i.impl_.trait_ { Some(clean::ResolvedPath { did, .. }) => { try!({ match cache_key.get().unwrap().traits.find(&did) { - Some(t) => try!(render_default_methods(w, t, i)), + Some(t) => try!(render_default_methods(w, t, &i.impl_)), None => {} } Ok(()) diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index a88992f6c4c..97048229ac4 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -258,8 +258,9 @@ nav.sub { .content .multi-column li { width: 100%; display: inline-block; } .content .method { font-size: 1em; } -.content .methods { margin-left: 20px; } -.content .methods .docblock { margin-left: 20px; } +.content .methods .docblock { margin-left: 40px; } + +.content .impl-methods .docblock { margin-left: 40px; } nav { border-bottom: 1px solid #e0e0e0; @@ -372,20 +373,29 @@ p a:hover { text-decoration: underline; } } .stability { - border-left: 6px solid #000; + border-left: 6px solid; + padding: 3px 6px; border-radius: 3px; - font-weight: 400; - padding: 4px 10px; +} + +h1 .stability { text-transform: lowercase; + font-weight: 400; margin-left: 14px; + padding: 4px 10px; +} + +.impl-methods .stability { + margin-right: 20px; } -.stability.Deprecated { border-color: #D60027; color: #880017; } -.stability.Experimental { border-color: #EC5315; color: #a53c0e; } -.stability.Unstable { border-color: #FFD700; color: #b39800; } -.stability.Stable { border-color: #AEC516; color: #7c8b10; } +.stability.Deprecated { border-color: #A071A8; color: #82478C; } +.stability.Experimental { border-color: #D46D6A; color: #AA3C39; } +.stability.Unstable { border-color: #D4B16A; color: #AA8439; } +.stability.Stable { border-color: #54A759; color: #2D8632; } .stability.Frozen { border-color: #009431; color: #007726; } .stability.Locked { border-color: #0084B6; color: #00668c; } +.stability.Unmarked { border-color: #FFFFFF; } :target { background: #FDFFD3; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e11e6b41cb1..d878313ee28 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -32,6 +32,7 @@ use std::io::{File, MemWriter}; use std::str; use std::gc::Gc; use serialize::{json, Decodable, Encodable}; +use externalfiles::ExternalHtml; // reexported from `clean` so it can be easily updated with the mod itself pub use clean::SCHEMA_VERSION; @@ -39,6 +40,8 @@ pub use clean::SCHEMA_VERSION; pub mod clean; pub mod core; pub mod doctree; +#[macro_escape] +pub mod externalfiles; pub mod fold; pub mod html { pub mod highlight; @@ -113,16 +116,17 @@ pub fn opts() -> Vec<getopts::OptGroup> { "ARGS"), optmulti("", "markdown-css", "CSS files to include via <link> in a rendered Markdown file", "FILES"), - optmulti("", "markdown-in-header", - "files to include inline in the <head> section of a rendered Markdown file", + optmulti("", "html-in-header", + "files to include inline in the <head> section of a rendered Markdown file \ + or generated documentation", "FILES"), - optmulti("", "markdown-before-content", + optmulti("", "html-before-content", "files to include inline between <body> and the content of a rendered \ - Markdown file", + Markdown file or generated documentation", "FILES"), - optmulti("", "markdown-after-content", + optmulti("", "html-after-content", "files to include inline between the content and </body> of a rendered \ - Markdown file", + Markdown file or generated documentation", "FILES"), optopt("", "markdown-playground-url", "URL to send code snippets to", "URL") @@ -179,6 +183,14 @@ pub fn main_args(args: &[String]) -> int { let output = matches.opt_str("o").map(|s| Path::new(s)); let cfgs = matches.opt_strs("cfg"); + let external_html = match ExternalHtml::load( + matches.opt_strs("html-in-header").as_slice(), + matches.opt_strs("html-before-content").as_slice(), + matches.opt_strs("html-after-content").as_slice()) { + Some(eh) => eh, + None => return 3 + }; + match (should_test, markdown_input) { (true, true) => { return markdown::test(input, libs, test_args) @@ -187,7 +199,7 @@ pub fn main_args(args: &[String]) -> int { return test::run(input, cfgs, libs, test_args) } (false, true) => return markdown::render(input, output.unwrap_or(Path::new("doc")), - &matches), + &matches, &external_html), (false, false) => {} } @@ -215,7 +227,7 @@ pub fn main_args(args: &[String]) -> int { let started = time::precise_time_ns(); match matches.opt_str("w").as_ref().map(|s| s.as_slice()) { Some("html") | None => { - match html::render::run(krate, output.unwrap_or(Path::new("doc"))) { + match html::render::run(krate, &external_html, output.unwrap_or(Path::new("doc"))) { Ok(()) => {} Err(e) => fail!("failed to generate documentation: {}", e), } @@ -396,18 +408,17 @@ fn json_output(krate: clean::Crate, res: Vec<plugins::PluginJson> , // "crate": { parsed crate ... }, // "plugins": { output of plugins ... } // } - let mut json = box std::collections::TreeMap::new(); - json.insert("schema".to_string(), - json::String(SCHEMA_VERSION.to_string())); - let plugins_json = box res.move_iter() - .filter_map(|opt| { - match opt { - None => None, - Some((string, json)) => { - Some((string.to_string(), json)) - } + let mut json = std::collections::TreeMap::new(); + json.insert("schema".to_string(), json::String(SCHEMA_VERSION.to_string())); + let plugins_json = res.move_iter() + .filter_map(|opt| { + match opt { + None => None, + Some((string, json)) => { + Some((string.to_string(), json)) } - }).collect(); + } + }).collect(); // FIXME #8335: yuck, Rust -> str -> JSON round trip! No way to .encode // straight to the Rust JSON representation. @@ -417,7 +428,7 @@ fn json_output(krate: clean::Crate, res: Vec<plugins::PluginJson> , let mut encoder = json::Encoder::new(&mut w as &mut io::Writer); krate.encode(&mut encoder).unwrap(); } - str::from_utf8(w.unwrap().as_slice()).unwrap().to_string() + str::from_utf8_owned(w.unwrap()).unwrap() }; let crate_json = match json::from_str(crate_json_str.as_slice()) { Ok(j) => j, @@ -428,6 +439,5 @@ fn json_output(krate: clean::Crate, res: Vec<plugins::PluginJson> , json.insert("plugins".to_string(), json::Object(plugins_json)); let mut file = try!(File::create(&dst)); - try!(json::Object(json).to_writer(&mut file)); - Ok(()) + json::Object(json).to_writer(&mut file) } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 76366240f1a..da271be4768 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -9,43 +9,19 @@ // except according to those terms. use std::collections::HashSet; -use std::{str, io}; +use std::io; use std::string::String; use getopts; use testing; +use externalfiles::ExternalHtml; + use html::escape::Escape; use html::markdown; use html::markdown::{MarkdownWithToc, find_testable_code, reset_headers}; use test::Collector; -fn load_string(input: &Path) -> io::IoResult<Option<String>> { - let mut f = try!(io::File::open(input)); - let d = try!(f.read_to_end()); - Ok(str::from_utf8(d.as_slice()).map(|s| s.to_string())) -} -macro_rules! load_or_return { - ($input: expr, $cant_read: expr, $not_utf8: expr) => { - { - let input = Path::new($input); - match load_string(&input) { - Err(e) => { - let _ = writeln!(&mut io::stderr(), - "error reading `{}`: {}", input.display(), e); - return $cant_read; - } - Ok(None) => { - let _ = writeln!(&mut io::stderr(), - "error reading `{}`: not UTF-8", input.display()); - return $not_utf8; - } - Ok(Some(s)) => s - } - } - } -} - /// Separate any lines at the start of the file that begin with `%`. fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { let mut metadata = Vec::new(); @@ -62,18 +38,10 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { (metadata, "") } -fn load_external_files(names: &[String]) -> Option<String> { - let mut out = String::new(); - for name in names.iter() { - out.push_str(load_or_return!(name.as_slice(), None, None).as_slice()); - out.push_char('\n'); - } - Some(out) -} - /// Render `input` (e.g. "foo.md") into an HTML file in `output` /// (e.g. output = "bar" => "bar/foo.html"). -pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int { +pub fn render(input: &str, mut output: Path, matches: &getopts::Matches, + external_html: &ExternalHtml) -> int { let input_p = Path::new(input); output.push(input_p.filestem().unwrap()); output.set_extension("html"); @@ -91,17 +59,6 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int } let playground = playground.unwrap_or("".to_string()); - let (in_header, before_content, after_content) = - match (load_external_files(matches.opt_strs("markdown-in-header") - .as_slice()), - load_external_files(matches.opt_strs("markdown-before-content") - .as_slice()), - load_external_files(matches.opt_strs("markdown-after-content") - .as_slice())) { - (Some(a), Some(b), Some(c)) => (a,b,c), - _ => return 3 - }; - let mut out = match io::File::create(&output) { Err(e) => { let _ = writeln!(&mut io::stderr(), @@ -153,10 +110,10 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int </html>"#, title = Escape(title), css = css, - in_header = in_header, - before_content = before_content, + in_header = external_html.in_header, + before_content = external_html.before_content, text = MarkdownWithToc(text), - after_content = after_content, + after_content = external_html.after_content, playground = playground, ); diff --git a/src/librustdoc/plugins.rs b/src/librustdoc/plugins.rs index e5bced8038b..9ac36665563 100644 --- a/src/librustdoc/plugins.rs +++ b/src/librustdoc/plugins.rs @@ -48,7 +48,7 @@ impl PluginManager { let lib = lib_result.unwrap(); unsafe { let plugin = lib.symbol("rustdoc_plugin_entrypoint").unwrap(); - self.callbacks.push(mem::transmute::<*u8,PluginCallback>(plugin)); + self.callbacks.push(mem::transmute::<*mut u8,PluginCallback>(plugin)); } self.dylibs.push(lib); } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index e7fc3cedf5e..7e7f10f7178 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -140,7 +140,14 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool, let old = io::stdio::set_stderr(box w1); spawn(proc() { let mut p = io::ChanReader::new(rx); - let mut err = old.unwrap_or(box io::stderr() as Box<Writer + Send>); + let mut err = match old { + Some(old) => { + // Chop off the `Send` bound. + let old: Box<Writer> = old; + old + } + None => box io::stderr() as Box<Writer>, + }; io::util::copy(&mut p, &mut err).unwrap(); }); let emitter = diagnostic::EmitterWriter::new(box w2); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 00fe0134f00..b7ef0956a7c 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -15,9 +15,12 @@ use syntax::abi; use syntax::ast; use syntax::ast_util; use syntax::ast_map; +use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::codemap::Span; +use rustc::middle::stability; + use std::gc::{Gc, GC}; use core; @@ -41,6 +44,14 @@ impl<'a> RustdocVisitor<'a> { } } + fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> { + let tcx = match self.cx.maybe_typed { + core::Typed(ref tcx) => tcx, + core::NotTyped(_) => return None + }; + stability::lookup(tcx, ast_util::local_def(id)) + } + pub fn visit(&mut self, krate: &ast::Crate) { self.attrs = krate.attrs.iter().map(|x| (*x).clone()).collect(); @@ -65,6 +76,7 @@ impl<'a> RustdocVisitor<'a> { struct_type: struct_type, name: item.ident, vis: item.vis, + stab: self.stability(item.id), attrs: item.attrs.iter().map(|x| *x).collect(), generics: generics.clone(), fields: sd.fields.iter().map(|x| (*x).clone()).collect(), @@ -81,6 +93,7 @@ impl<'a> RustdocVisitor<'a> { name: x.node.name, attrs: x.node.attrs.iter().map(|x| *x).collect(), vis: x.node.vis, + stab: self.stability(x.node.id), id: x.node.id, kind: x.node.kind.clone(), where: x.span, @@ -90,6 +103,7 @@ impl<'a> RustdocVisitor<'a> { name: it.ident, variants: vars, vis: it.vis, + stab: self.stability(it.id), generics: params.clone(), attrs: it.attrs.iter().map(|x| *x).collect(), id: it.id, @@ -104,6 +118,7 @@ impl<'a> RustdocVisitor<'a> { Function { id: item.id, vis: item.vis, + stab: self.stability(item.id), attrs: item.attrs.iter().map(|x| *x).collect(), decl: fd.clone(), name: item.ident, @@ -125,6 +140,7 @@ impl<'a> RustdocVisitor<'a> { om.where_inner = m.inner; om.attrs = attrs; om.vis = vis; + om.stab = self.stability(id); om.id = id; for i in m.items.iter() { self.visit_item(&**i, &mut om); @@ -258,6 +274,7 @@ impl<'a> RustdocVisitor<'a> { attrs: item.attrs.iter().map(|x| *x).collect(), where: item.span, vis: item.vis, + stab: self.stability(item.id), }; om.typedefs.push(t); }, @@ -271,6 +288,7 @@ impl<'a> RustdocVisitor<'a> { attrs: item.attrs.iter().map(|x| *x).collect(), where: item.span, vis: item.vis, + stab: self.stability(item.id), }; om.statics.push(s); }, @@ -284,6 +302,7 @@ impl<'a> RustdocVisitor<'a> { attrs: item.attrs.iter().map(|x| *x).collect(), where: item.span, vis: item.vis, + stab: self.stability(item.id), }; om.traits.push(t); }, @@ -297,6 +316,7 @@ impl<'a> RustdocVisitor<'a> { id: item.id, where: item.span, vis: item.vis, + stab: self.stability(item.id), }; om.impls.push(i); }, @@ -309,6 +329,7 @@ impl<'a> RustdocVisitor<'a> { attrs: item.attrs.iter().map(|x| *x).collect(), name: item.ident, where: item.span, + stab: self.stability(item.id), }) } } |
