diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-05-28 19:53:37 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-05-31 21:59:50 -0700 |
| commit | c2e3aa37daedf698072b4aadbc420f24505b2b2d (patch) | |
| tree | 2821fa90613a5e130e2074de7be74740ed541bb1 | |
| parent | ba9be0a72bd4aabb67e9b72edd261b2fe449dc86 (diff) | |
| download | rust-c2e3aa37daedf698072b4aadbc420f24505b2b2d.tar.gz rust-c2e3aa37daedf698072b4aadbc420f24505b2b2d.zip | |
rustdoc: Create anchor pages for primitive types
This commit adds support in rustdoc to recognize the `#[doc(primitive = "foo")]` attribute. This attribute indicates that the current module is the "owner" of the primitive type `foo`. For rustdoc, this means that the doc-comment for the module is the doc-comment for the primitive type, plus a signal to all downstream crates that hyperlinks for primitive types will be directed at the crate containing the `#[doc]` directive. Additionally, rustdoc will favor crates closest to the one being documented which "implements the primitive type". For example, documentation of libcore links to libcore for primitive types, but documentation for libstd and beyond all links to libstd for primitive types. This change involves no compiler modifications, it is purely a rustdoc change. The landing pages for the primitive types primarily serve to show a list of implemented traits for the primitive type itself. The primitive types documented includes both strings and slices in a semi-ad-hoc way, but in a way that should provide at least somewhat meaningful documentation. Closes #14474
37 files changed, 443 insertions, 87 deletions
diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs index 51ba01a68aa..146f29dd9f1 100644 --- a/src/libcore/bool.rs +++ b/src/libcore/bool.rs @@ -12,6 +12,8 @@ //! //! A `to_bit` conversion function. +#![doc(primitive = "bool")] + use num::{Int, one, zero}; ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 6b0f0b70561..76ff56a77a4 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -24,6 +24,7 @@ //! and, as such, should be performed via the `from_u32` function.. #![allow(non_snake_case_functions)] +#![doc(primitive = "char")] use mem::transmute; use option::{None, Option, Some}; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 75d3db596ba..cadc874891d 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -10,6 +10,8 @@ //! Operations and constants for 32-bits floats (`f32` type) +#![doc(primitive = "f32")] + use intrinsics; use mem; use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index d59aad077cc..5e19015dd02 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -10,6 +10,8 @@ //! Operations and constants for 64-bits floats (`f64` type) +#![doc(primitive = "f64")] + use intrinsics; use mem; use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; diff --git a/src/libcore/num/i16.rs b/src/libcore/num/i16.rs index 957e585e71c..b821ff60a73 100644 --- a/src/libcore/num/i16.rs +++ b/src/libcore/num/i16.rs @@ -10,5 +10,7 @@ //! Operations and constants for signed 16-bits integers (`i16` type) +#![doc(primitive = "i16")] + int_module!(i16, 16) diff --git a/src/libcore/num/i32.rs b/src/libcore/num/i32.rs index cfeb1020f44..a8cab1f95b0 100644 --- a/src/libcore/num/i32.rs +++ b/src/libcore/num/i32.rs @@ -10,5 +10,7 @@ //! Operations and constants for signed 32-bits integers (`i32` type) +#![doc(primitive = "i32")] + int_module!(i32, 32) diff --git a/src/libcore/num/i64.rs b/src/libcore/num/i64.rs index 21ae162d4aa..6009b953bb4 100644 --- a/src/libcore/num/i64.rs +++ b/src/libcore/num/i64.rs @@ -10,5 +10,7 @@ //! Operations and constants for signed 64-bits integers (`i64` type) +#![doc(primitive = "i64")] + int_module!(i64, 64) diff --git a/src/libcore/num/i8.rs b/src/libcore/num/i8.rs index b9ae13da075..b3a5557b20c 100644 --- a/src/libcore/num/i8.rs +++ b/src/libcore/num/i8.rs @@ -10,5 +10,7 @@ //! Operations and constants for signed 8-bits integers (`i8` type) +#![doc(primitive = "i8")] + int_module!(i8, 8) diff --git a/src/libcore/num/int.rs b/src/libcore/num/int.rs index 4979e9e01d3..06d64e73abd 100644 --- a/src/libcore/num/int.rs +++ b/src/libcore/num/int.rs @@ -10,6 +10,8 @@ //! Operations and constants for architecture-sized signed integers (`int` type) +#![doc(primitive = "int")] + #[cfg(target_word_size = "32")] int_module!(int, 32) #[cfg(target_word_size = "64")] int_module!(int, 64) diff --git a/src/libcore/num/u16.rs b/src/libcore/num/u16.rs index b3c701115c5..eb4bd427d51 100644 --- a/src/libcore/num/u16.rs +++ b/src/libcore/num/u16.rs @@ -10,4 +10,6 @@ //! Operations and constants for unsigned 16-bits integers (`u16` type) +#![doc(primitive = "u16")] + uint_module!(u16, i16, 16) diff --git a/src/libcore/num/u32.rs b/src/libcore/num/u32.rs index 46f90dca833..9522b2e86ac 100644 --- a/src/libcore/num/u32.rs +++ b/src/libcore/num/u32.rs @@ -10,5 +10,7 @@ //! Operations and constants for unsigned 32-bits integers (`u32` type) +#![doc(primitive = "u32")] + uint_module!(u32, i32, 32) diff --git a/src/libcore/num/u64.rs b/src/libcore/num/u64.rs index bd4333ab589..7a654f4bffa 100644 --- a/src/libcore/num/u64.rs +++ b/src/libcore/num/u64.rs @@ -10,5 +10,7 @@ //! Operations and constants for unsigned 64-bits integer (`u64` type) +#![doc(primitive = "u64")] + uint_module!(u64, i64, 64) diff --git a/src/libcore/num/u8.rs b/src/libcore/num/u8.rs index 00871a1c8fa..6a42ce07e5d 100644 --- a/src/libcore/num/u8.rs +++ b/src/libcore/num/u8.rs @@ -10,5 +10,7 @@ //! Operations and constants for unsigned 8-bits integers (`u8` type) +#![doc(primitive = "u8")] + uint_module!(u8, i8, 8) diff --git a/src/libcore/num/uint.rs b/src/libcore/num/uint.rs index 99ed7e10bf9..2f539fff61a 100644 --- a/src/libcore/num/uint.rs +++ b/src/libcore/num/uint.rs @@ -10,5 +10,7 @@ //! Operations and constants for architecture-sized unsigned integers (`uint` type) +#![doc(primitive = "uint")] + uint_module!(uint, int, ::int::BITS) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 9771d766e65..8f885dafffa 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -12,6 +12,8 @@ //! //! For more details `std::slice`. +#![doc(primitive = "slice")] + use mem::transmute; use clone::Clone; use container::Container; diff --git a/src/libcore/str.rs b/src/libcore/str.rs index a19e720446b..21dbaf70597 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -12,6 +12,8 @@ //! //! For more details, see std::str +#![doc(primitive = "str")] + use mem; use char; use clone::Clone; diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 7639700eac9..f9a14b1de50 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -59,6 +59,8 @@ //! assert_eq!(d, (0u32, 0.0f32)); //! ``` +#![doc(primitive = "tuple")] + use clone::Clone; #[cfg(not(test))] use cmp::*; #[cfg(not(test))] use default::Default; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b2ed1036c55..18cf928f04c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -28,6 +28,7 @@ use rustc::metadata::decoder; use rustc::middle::ty; use std::rc::Rc; +use std::u32; use core; use doctree; @@ -81,6 +82,7 @@ pub struct Crate { pub name: String, pub module: Option<Item>, pub externs: Vec<(ast::CrateNum, ExternalCrate)>, + pub primitives: Vec<Primitive>, } impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> { @@ -92,6 +94,7 @@ impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> { externs.push((n, meta.clean())); }); + // Figure out the name of this crate let input = driver::FileInput(cx.src.clone()); let t_outputs = driver::build_output_filenames(&input, &None, @@ -100,10 +103,47 @@ impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> { cx.sess()); let id = link::find_crate_id(self.attrs.as_slice(), t_outputs.out_filestem.as_slice()); + + // Clean the module, translating the entire libsyntax AST to one that is + // understood by rustdoc. + let mut module = self.module.clean(); + + // Collect all inner modules which are tagged as implementations of + // primitives. + let mut primitives = Vec::new(); + { + let m = match module.inner { + ModuleItem(ref mut m) => m, + _ => unreachable!(), + }; + let mut tmp = Vec::new(); + for child in m.items.iter() { + match child.inner { + ModuleItem(..) => {}, + _ => continue, + } + let prim = match Primitive::find(child.attrs.as_slice()) { + Some(prim) => prim, + None => continue, + }; + primitives.push(prim); + tmp.push(Item { + source: Span::empty(), + name: Some(prim.to_url_str().to_string()), + attrs: child.attrs.clone(), + visibility: Some(ast::Public), + def_id: ast_util::local_def(prim.to_node_id()), + inner: PrimitiveItem(prim), + }); + } + m.items.extend(tmp.move_iter()); + } + Crate { name: id.name.to_string(), - module: Some(self.module.clean()), + module: Some(module), externs: externs, + primitives: primitives, } } } @@ -112,15 +152,35 @@ impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> { pub struct ExternalCrate { pub name: String, pub attrs: Vec<Attribute>, + pub primitives: Vec<Primitive>, } 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(ast::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(..) => {} + } ExternalCrate { name: self.name.to_string(), - attrs: decoder::get_crate_attributes(self.data()).clean() - .move_iter() - .collect(), + attrs: decoder::get_crate_attributes(self.data()).clean(), + primitives: primitives, } } } @@ -227,6 +287,7 @@ pub enum ItemEnum { /// `static`s from an extern block ForeignStaticItem(Static), MacroItem(Macro), + PrimitiveItem(Primitive), } #[deriving(Clone, Encodable, Decodable)] @@ -931,7 +992,7 @@ pub enum Type { /// For references to self Self(ast::DefId), /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char. - Primitive(ast::PrimTy), + Primitive(Primitive), Closure(Box<ClosureDecl>, Option<Lifetime>), Proc(Box<ClosureDecl>), /// extern "ABI" fn @@ -939,10 +1000,6 @@ pub enum Type { Tuple(Vec<Type>), Vector(Box<Type>), FixedVector(Box<Type>, String), - String, - Bool, - /// aka TyNil - Unit, /// aka TyBot Bottom, Unique(Box<Type>), @@ -956,6 +1013,19 @@ pub enum Type { // region, raw, other boxes, mutable } +#[deriving(Clone, Encodable, Decodable, Eq, TotalEq, Hash)] +pub enum Primitive { + Int, I8, I16, I32, I64, + Uint, U8, U16, U32, U64, + F32, F64, F128, + Char, + Bool, + Nil, + Str, + Slice, + PrimitiveTuple, +} + #[deriving(Clone, Encodable, Decodable)] pub enum TypeKind { TypeEnum, @@ -967,11 +1037,97 @@ pub enum TypeKind { TypeVariant, } +impl Primitive { + fn from_str(s: &str) -> Option<Primitive> { + match s.as_slice() { + "int" => Some(Int), + "i8" => Some(I8), + "i16" => Some(I16), + "i32" => Some(I32), + "i64" => Some(I64), + "uint" => Some(Uint), + "u8" => Some(U8), + "u16" => Some(U16), + "u32" => Some(U32), + "u64" => Some(U64), + "bool" => Some(Bool), + "nil" => Some(Nil), + "char" => Some(Char), + "str" => Some(Str), + "f32" => Some(F32), + "f64" => Some(F64), + "f128" => Some(F128), + "slice" => Some(Slice), + "tuple" => Some(PrimitiveTuple), + _ => None, + } + } + + fn find(attrs: &[Attribute]) -> Option<Primitive> { + for attr in attrs.iter() { + let list = match *attr { + List(ref k, ref l) if k.as_slice() == "doc" => l, + _ => continue, + }; + for sub_attr in list.iter() { + let value = match *sub_attr { + NameValue(ref k, ref v) + if k.as_slice() == "primitive" => v.as_slice(), + _ => continue, + }; + match Primitive::from_str(value) { + Some(p) => return Some(p), + None => {} + } + } + } + return None + } + + pub fn to_str(&self) -> &'static str { + match *self { + Int => "int", + I8 => "i8", + I16 => "i16", + I32 => "i32", + I64 => "i64", + Uint => "uint", + U8 => "u8", + U16 => "u16", + U32 => "u32", + U64 => "u64", + F32 => "f32", + F64 => "f64", + F128 => "f128", + Str => "str", + Bool => "bool", + Char => "char", + Nil => "()", + Slice => "slice", + PrimitiveTuple => "tuple", + } + } + + pub fn to_url_str(&self) -> &'static str { + match *self { + Nil => "nil", + other => other.to_str(), + } + } + + /// Creates a rustdoc-specific node id for primitive types. + /// + /// These node ids are generally never used by the AST itself. + pub fn to_node_id(&self) -> ast::NodeId { + u32::MAX - 1 - (*self as u32) + } +} + impl Clean<Type> for ast::Ty { fn clean(&self) -> Type { use syntax::ast::*; match self.node { - TyNil => Unit, + TyNil => Primitive(Nil), TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()), TyRptr(ref l, ref m) => BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(), @@ -999,16 +1155,26 @@ impl Clean<Type> for ast::Ty { impl Clean<Type> for ty::t { fn clean(&self) -> Type { match ty::get(*self).sty { - ty::ty_nil => Unit, ty::ty_bot => Bottom, - ty::ty_bool => Bool, - ty::ty_char => Primitive(ast::TyChar), - ty::ty_int(t) => Primitive(ast::TyInt(t)), - ty::ty_uint(u) => Primitive(ast::TyUint(u)), - ty::ty_float(f) => Primitive(ast::TyFloat(f)), + ty::ty_nil => Primitive(Nil), + ty::ty_bool => Primitive(Bool), + ty::ty_char => Primitive(Char), + ty::ty_int(ast::TyI) => Primitive(Int), + ty::ty_int(ast::TyI8) => Primitive(I8), + ty::ty_int(ast::TyI16) => Primitive(I16), + ty::ty_int(ast::TyI32) => Primitive(I32), + ty::ty_int(ast::TyI64) => Primitive(I64), + ty::ty_uint(ast::TyU) => Primitive(Uint), + ty::ty_uint(ast::TyU8) => Primitive(U8), + ty::ty_uint(ast::TyU16) => Primitive(U16), + ty::ty_uint(ast::TyU32) => Primitive(U32), + ty::ty_uint(ast::TyU64) => Primitive(U64), + ty::ty_float(ast::TyF32) => Primitive(F32), + ty::ty_float(ast::TyF64) => Primitive(F64), + ty::ty_float(ast::TyF128) => Primitive(F128), + ty::ty_str => Primitive(Str), ty::ty_box(t) => Managed(box t.clean()), ty::ty_uniq(t) => Unique(box t.clean()), - ty::ty_str => String, ty::ty_vec(mt, None) => Vector(box mt.ty.clean()), ty::ty_vec(mt, Some(i)) => FixedVector(box mt.ty.clean(), format!("{}", i)), @@ -1056,11 +1222,12 @@ impl Clean<Type> for ty::t { ty::ty_trait(..) => TypeTrait, _ => TypeEnum, }; + let path = external_path(fqn.last().unwrap().to_str().as_slice(), + substs); cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind)); ResolvedPath { - path: external_path(fqn.last().unwrap().to_str().as_slice(), - substs), + path: path, typarams: None, did: did, } @@ -1748,7 +1915,7 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>, let tycx = match cx.maybe_typed { core::Typed(ref tycx) => tycx, // If we're extracting tests, this return value doesn't matter. - core::NotTyped(_) => return Bool + core::NotTyped(_) => return Primitive(Bool), }; debug!("searching for {:?} in defmap", id); let def = match tycx.def_map.borrow().find(&id) { @@ -1759,9 +1926,22 @@ fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>, match def { ast::DefSelfTy(i) => return Self(ast_util::local_def(i)), ast::DefPrimTy(p) => match p { - ast::TyStr => return String, - ast::TyBool => return Bool, - _ => return Primitive(p) + ast::TyStr => return Primitive(Str), + ast::TyBool => return Primitive(Bool), + ast::TyChar => return Primitive(Char), + ast::TyInt(ast::TyI) => return Primitive(Int), + ast::TyInt(ast::TyI8) => return Primitive(I8), + ast::TyInt(ast::TyI16) => return Primitive(I16), + ast::TyInt(ast::TyI32) => return Primitive(I32), + ast::TyInt(ast::TyI64) => return Primitive(I64), + ast::TyUint(ast::TyU) => return Primitive(Uint), + ast::TyUint(ast::TyU8) => return Primitive(U8), + ast::TyUint(ast::TyU16) => return Primitive(U16), + ast::TyUint(ast::TyU32) => return Primitive(U32), + ast::TyUint(ast::TyU64) => return Primitive(U64), + ast::TyFloat(ast::TyF32) => return Primitive(F32), + ast::TyFloat(ast::TyF64) => return Primitive(F64), + ast::TyFloat(ast::TyF128) => return Primitive(F128), }, ast::DefTyParam(i, _) => return Generic(i), ast::DefTyParamBinder(i) => return TyParamBinder(i), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 3b3f4378d67..50f25a0f8f1 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -263,6 +263,47 @@ fn path(w: &mut fmt::Formatter, path: &clean::Path, print_all: bool, Ok(()) } +fn primitive_link(f: &mut fmt::Formatter, + prim: clean::Primitive, + name: &str) -> fmt::Result { + let m = cache_key.get().unwrap(); + let mut needs_termination = false; + match m.primitive_locations.find(&prim) { + Some(&ast::LOCAL_CRATE) => { + let loc = current_location_key.get().unwrap(); + let len = if loc.len() == 0 {0} else {loc.len() - 1}; + try!(write!(f, "<a href='{}primitive.{}.html'>", + "../".repeat(len), + prim.to_url_str())); + needs_termination = true; + } + Some(&cnum) => { + let loc = match *m.extern_locations.get(&cnum) { + render::Remote(ref s) => Some(s.to_string()), + render::Local => { + let loc = current_location_key.get().unwrap(); + Some(("../".repeat(loc.len())).to_string()) + } + render::Unknown => None, + }; + match loc { + Some(s) => { + try!(write!(f, "<a href='{}/primitive.{}.html'>", + s, prim.to_url_str())); + needs_termination = true; + } + None => {} + } + } + None => {} + } + try!(write!(f, "{}", name)); + if needs_termination { + try!(write!(f, "</a>")); + } + Ok(()) +} + /// Helper to render type parameters fn tybounds(w: &mut fmt::Formatter, typarams: &Option<Vec<clean::TyParamBound> >) -> fmt::Result { @@ -297,27 +338,7 @@ impl fmt::Show for clean::Type { tybounds(f, typarams) } clean::Self(..) => f.write("Self".as_bytes()), - clean::Primitive(prim) => { - let s = match prim { - ast::TyInt(ast::TyI) => "int", - ast::TyInt(ast::TyI8) => "i8", - ast::TyInt(ast::TyI16) => "i16", - ast::TyInt(ast::TyI32) => "i32", - ast::TyInt(ast::TyI64) => "i64", - ast::TyUint(ast::TyU) => "uint", - ast::TyUint(ast::TyU8) => "u8", - ast::TyUint(ast::TyU16) => "u16", - ast::TyUint(ast::TyU32) => "u32", - ast::TyUint(ast::TyU64) => "u64", - ast::TyFloat(ast::TyF32) => "f32", - ast::TyFloat(ast::TyF64) => "f64", - ast::TyFloat(ast::TyF128) => "f128", - ast::TyStr => "str", - ast::TyBool => "bool", - ast::TyChar => "char", - }; - f.write(s.as_bytes()) - } + clean::Primitive(prim) => primitive_link(f, prim, prim.to_str()), clean::Closure(ref decl, ref region) => { write!(f, "{style}{lifetimes}|{args}|{bounds}\ {arrow, select, yes{ -> {ret}} other{}}", @@ -329,7 +350,7 @@ impl fmt::Show for clean::Type { }, args = decl.decl.inputs, arrow = match decl.decl.output { - clean::Unit => "no", + clean::Primitive(clean::Nil) => "no", _ => "yes", }, ret = decl.decl.output, @@ -379,7 +400,10 @@ impl fmt::Show for clean::Type { ": {}", m.collect::<Vec<String>>().connect(" + ")) }, - arrow = match decl.decl.output { clean::Unit => "no", _ => "yes" }, + arrow = match decl.decl.output { + clean::Primitive(clean::Nil) => "no", + _ => "yes", + }, ret = decl.decl.output) } clean::BareFunction(ref decl) => { @@ -403,13 +427,13 @@ impl fmt::Show for clean::Type { } f.write(")".as_bytes()) } - clean::Vector(ref t) => write!(f, "[{}]", **t), + clean::Vector(ref t) => { + primitive_link(f, clean::Slice, format!("[{}]", **t).as_slice()) + } clean::FixedVector(ref t, ref s) => { - write!(f, "[{}, ..{}]", **t, *s) + primitive_link(f, clean::Slice, + format!("[{}, ..{}]", **t, *s).as_slice()) } - clean::String => f.write("str".as_bytes()), - clean::Bool => f.write("bool".as_bytes()), - clean::Unit => f.write("()".as_bytes()), clean::Bottom => f.write("!".as_bytes()), clean::Unique(ref t) => write!(f, "~{}", **t), clean::Managed(ref t) => write!(f, "@{}", **t), @@ -454,7 +478,10 @@ impl fmt::Show for clean::FnDecl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({args}){arrow, select, yes{ -> {ret}} other{}}", args = self.inputs, - arrow = match self.output { clean::Unit => "no", _ => "yes" }, + arrow = match self.output { + clean::Primitive(clean::Nil) => "no", + _ => "yes" + }, ret = self.output) } } @@ -490,7 +517,10 @@ impl<'a> fmt::Show for Method<'a> { write!(f, "({args}){arrow, select, yes{ -> {ret}} other{}}", args = args, - arrow = match d.output { clean::Unit => "no", _ => "yes" }, + arrow = match d.output { + clean::Primitive(clean::Nil) => "no", + _ => "yes" + }, ret = d.output) } } diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 0f000f4e5ae..f36c81f8f8d 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -37,6 +37,7 @@ pub enum ItemType { ForeignFunction = 13, ForeignStatic = 14, Macro = 15, + Primitive = 16, } impl ItemType { @@ -58,6 +59,7 @@ impl ItemType { ForeignFunction => "ffi", ForeignStatic => "ffs", Macro => "macro", + Primitive => "primitive", } } } @@ -92,6 +94,7 @@ pub fn shortty(item: &clean::Item) -> ItemType { clean::ForeignFunctionItem(..) => ForeignFunction, clean::ForeignStaticItem(..) => ForeignStatic, clean::MacroItem(..) => Macro, + clean::PrimitiveItem(..) => Primitive, } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c5e6c73e38f..d82a83cbd39 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -157,6 +157,9 @@ pub struct Cache { /// Cache of where external crate documentation can be found. pub extern_locations: HashMap<ast::CrateNum, ExternalLocation>, + /// Cache of where documentation for primitives can be found. + pub primitive_locations: HashMap<clean::Primitive, ast::CrateNum>, + /// Set of definitions which have been inlined from external crates. pub inlined: HashSet<ast::DefId>, @@ -281,6 +284,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { parent_stack: Vec::new(), search_index: Vec::new(), extern_locations: HashMap::new(), + primitive_locations: HashMap::new(), privmod: false, public_items: public_items, orphan_methods: Vec::new(), @@ -297,13 +301,27 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { cache.stack.push(krate.name.clone()); krate = cache.fold_crate(krate); - + // Cache where all our extern crates are located for &(n, ref e) in krate.externs.iter() { cache.extern_locations.insert(n, extern_location(e, &cx.dst)); let did = ast::DefId { krate: n, node: ast::CRATE_NODE_ID }; cache.paths.insert(did, (vec![e.name.to_string()], item_type::Module)); } + // Cache where all known primitives have their documentation located. + // + // Favor linking to as local extern as possible, so iterate all crates in + // reverse topological order. + for &(n, ref e) in krate.externs.iter().rev() { + for &prim in e.primitives.iter() { + cache.primitive_locations.insert(prim, n); + } + } + for &prim in krate.primitives.iter() { + cache.primitive_locations.insert(prim, ast::LOCAL_CRATE); + } + + // Build our search index let index = try!(build_index(&krate, &mut cache)); // Freeze the cache now that the index has been built. Put an Arc into TLS @@ -854,30 +872,63 @@ impl DocFolder for Cache { Some(item) => { match item { clean::Item{ attrs, inner: clean::ImplItem(i), .. } => { - match i.for_ { - clean::ResolvedPath { did, .. } => { + use clean::{Primitive, Vector, ResolvedPath, BorrowedRef}; + use clean::{FixedVector, Slice, Tuple, PrimitiveTuple}; + + // extract relevant documentation for this impl + let dox = match attrs.move_iter().find(|a| { + match *a { + clean::NameValue(ref x, _) + if "doc" == x.as_slice() => { + true + } + _ => false + } + }) { + Some(clean::NameValue(_, dox)) => Some(dox), + Some(..) | None => None, + }; + + // Figure out the id of this impl. This may map to a + // primitive rather than always to a struct/enum. + let did = match i.for_ { + ResolvedPath { did, .. } => Some(did), + + // References to primitives are picked up as well to + // recognize implementations for &str, this may not + // be necessary in a DST world. + Primitive(p) | + BorrowedRef { type_: box Primitive(p), ..} => + { + Some(ast_util::local_def(p.to_node_id())) + } + + // In a DST world, we may only need + // Vector/FixedVector, but for now we also pick up + // borrowed references + Vector(..) | FixedVector(..) | + BorrowedRef{ type_: box Vector(..), .. } | + BorrowedRef{ type_: box FixedVector(..), .. } => + { + Some(ast_util::local_def(Slice.to_node_id())) + } + + Tuple(..) => { + let id = PrimitiveTuple.to_node_id(); + Some(ast_util::local_def(id)) + } + + _ => None, + }; + + match did { + Some(did) => { let v = self.impls.find_or_insert_with(did, |_| { Vec::new() }); - // extract relevant documentation for this impl - match attrs.move_iter().find(|a| { - match *a { - clean::NameValue(ref x, _) - if "doc" == x.as_slice() => { - true - } - _ => false - } - }) { - Some(clean::NameValue(_, dox)) => { - v.push((i, Some(dox))); - } - Some(..) | None => { - v.push((i, None)); - } - } + v.push((i, dox)); } - _ => {} + None => {} } None } @@ -1119,17 +1170,21 @@ impl<'a> fmt::Show for Item<'a> { clean::TraitItem(..) => try!(write!(fmt, "Trait ")), clean::StructItem(..) => try!(write!(fmt, "Struct ")), clean::EnumItem(..) => try!(write!(fmt, "Enum ")), + clean::PrimitiveItem(..) => try!(write!(fmt, "Primitive Type ")), _ => {} } - let cur = self.cx.current.as_slice(); - let amt = if self.ismodule() { cur.len() - 1 } else { cur.len() }; - for (i, component) in cur.iter().enumerate().take(amt) { - let mut trail = String::new(); - for _ in range(0, cur.len() - i - 1) { - trail.push_str("../"); + let is_primitive = match self.item.inner { + clean::PrimitiveItem(..) => true, + _ => false, + }; + if !is_primitive { + let cur = self.cx.current.as_slice(); + let amt = if self.ismodule() { cur.len() - 1 } else { cur.len() }; + for (i, component) in cur.iter().enumerate().take(amt) { + try!(write!(fmt, "<a href='{}index.html'>{}</a>::", + "../".repeat(cur.len() - i - 1), + component.as_slice())); } - try!(write!(fmt, "<a href='{}index.html'>{}</a>::", - trail, component.as_slice())); } try!(write!(fmt, "<a class='{}' href=''>{}</a>", shortty(self.item), self.item.name.get_ref().as_slice())); @@ -1154,7 +1209,7 @@ impl<'a> fmt::Show for Item<'a> { // [src] link in the downstream documentation will actually come back to // this page, and this link will be auto-clicked. The `id` attribute is // used to find the link to auto-click. - if self.cx.include_sources { + if self.cx.include_sources && !is_primitive { match self.href() { Some(l) => { try!(write!(fmt, @@ -1178,6 +1233,7 @@ impl<'a> fmt::Show for Item<'a> { clean::EnumItem(ref e) => item_enum(fmt, self.item, e), clean::TypedefItem(ref t) => item_typedef(fmt, self.item, t), clean::MacroItem(ref m) => item_macro(fmt, self.item, m), + clean::PrimitiveItem(ref p) => item_primitive(fmt, self.item, p), _ => Ok(()) } } @@ -1250,6 +1306,8 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, } (&clean::ViewItemItem(..), _) => Less, (_, &clean::ViewItemItem(..)) => Greater, + (&clean::PrimitiveItem(..), _) => Less, + (_, &clean::PrimitiveItem(..)) => Greater, (&clean::ModuleItem(..), _) => Less, (_, &clean::ModuleItem(..)) => Greater, (&clean::MacroItem(..), _) => Less, @@ -1305,6 +1363,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, clean::ForeignFunctionItem(..) => ("ffi-fns", "Foreign Functions"), clean::ForeignStaticItem(..) => ("ffi-statics", "Foreign Statics"), clean::MacroItem(..) => ("macros", "Macros"), + clean::PrimitiveItem(..) => ("primitives", "Primitive Types"), }; try!(write!(w, "<h2 id='{id}' class='section-header'>\ @@ -1877,8 +1936,11 @@ impl<'a> fmt::Show for Sidebar<'a> { try!(write!(w, "<div class='block {}'><h2>{}</h2>", short, longty)); for item in items.iter() { let curty = shortty(cur).to_static_str(); - let class = if cur.name.get_ref() == item && - short == curty { "current" } else { "" }; + let class = if cur.name.get_ref() == item && short == curty { + "current" + } else { + "" + }; try!(write!(w, "<a class='{ty} {class}' href='{curty, select, mod{../} other{} @@ -1949,3 +2011,10 @@ fn item_macro(w: &mut fmt::Formatter, it: &clean::Item, try!(w.write(highlight::highlight(t.source.as_slice(), Some("macro")).as_bytes())); document(w, it) } + +fn item_primitive(w: &mut fmt::Formatter, + it: &clean::Item, + _p: &clean::Primitive) -> fmt::Result { + try!(document(w, it)); + render_methods(w, it) +} diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index d153728ccce..6c9bc793582 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -527,7 +527,8 @@ "variant", "ffi", "ffs", - "macro"]; + "macro", + "primitive"]; function itemTypeFromName(typename) { for (var i = 0; i < itemTypes.length; ++i) { diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index efb0689404a..60b2a82f007 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -67,11 +67,22 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult { fn fold_item(&mut self, i: Item) -> Option<Item> { match i.inner { clean::ImplItem(clean::Impl{ - for_: clean::ResolvedPath{ did, .. }, .. + for_: clean::ResolvedPath{ did, .. }, + ref trait_, .. }) => { + // Impls for stripped don't need to exist if self.stripped.contains(&did.node) { return None; } + // Impls of stripped traits also don't need to exist + match *trait_ { + Some(clean::ResolvedPath { did, .. }) => { + if self.stripped.contains(&did.node) { + return None + } + } + _ => {} + } } _ => {} } @@ -161,6 +172,9 @@ impl<'a> fold::DocFolder for Stripper<'a> { // tymethods/macros have no control over privacy clean::MacroItem(..) | clean::TyMethodItem(..) => {} + + // Primitives are never stripped + clean::PrimitiveItem(..) => {} } let fastreturn = match i.inner { diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index b7bd3705bf2..bbf1458da21 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -12,6 +12,7 @@ #![allow(missing_doc)] #![allow(unsigned_negate)] +#![doc(primitive = "f32")] use prelude::*; diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index e7b29c733ec..cfa8534160b 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -11,6 +11,7 @@ //! Operations and constants for 64-bits floats (`f64` type) #![allow(missing_doc)] +#![doc(primitive = "f64")] use prelude::*; diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index e0c5d93f28a..cfa0662e225 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -10,6 +10,8 @@ //! Operations and constants for signed 16-bits integers (`i16` type) +#![doc(primitive = "i16")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 6938689f47d..3c656b20ee5 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -10,6 +10,8 @@ //! Operations and constants for signed 32-bits integers (`i32` type) +#![doc(primitive = "i32")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index 4be43876105..857f78efc9c 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -10,6 +10,8 @@ //! Operations and constants for signed 64-bits integers (`i64` type) +#![doc(primitive = "i64")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index b0459ca46f1..a939c1d6b76 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -10,6 +10,8 @@ //! Operations and constants for signed 8-bits integers (`i8` type) +#![doc(primitive = "i8")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index 774b0d7d8cf..415d11b3145 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -10,6 +10,8 @@ //! Operations and constants for architecture-sized signed integers (`int` type) +#![doc(primitive = "int")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs index 5200fbd7a3b..3b018414be2 100644 --- a/src/libstd/num/u16.rs +++ b/src/libstd/num/u16.rs @@ -10,6 +10,8 @@ //! Operations and constants for unsigned 16-bits integers (`u16` type) +#![doc(primitive = "u16")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs index 18cdb9e7e87..98012943109 100644 --- a/src/libstd/num/u32.rs +++ b/src/libstd/num/u32.rs @@ -10,6 +10,8 @@ //! Operations and constants for unsigned 32-bits integers (`u32` type) +#![doc(primitive = "u32")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs index 7c17d2cd0bd..b3a8bfc20df 100644 --- a/src/libstd/num/u64.rs +++ b/src/libstd/num/u64.rs @@ -10,6 +10,8 @@ //! Operations and constants for unsigned 64-bits integer (`u64` type) +#![doc(primitive = "u64")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs index 05d86fba40e..d72049d2533 100644 --- a/src/libstd/num/u8.rs +++ b/src/libstd/num/u8.rs @@ -10,6 +10,8 @@ //! Operations and constants for unsigned 8-bits integers (`u8` type) +#![doc(primitive = "u8")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index ac38f740931..1f43ad8af33 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -10,6 +10,8 @@ //! Operations and constants for architecture-sized unsigned integers (`uint` type) +#![doc(primitive = "uint")] + use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; use num::strconv; diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index 1433270346e..430629a1f88 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -97,6 +97,8 @@ There are a number of free functions that create or take vectors, for example: */ +#![doc(primitive = "slice")] + use mem::transmute; use clone::Clone; use cmp::{TotalOrd, Ordering, Less, Greater}; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index a35b4e7a151..11b9d0e85ff 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -65,6 +65,8 @@ is the same as `&[u8]`. */ +#![doc(primitive = "str")] + use char::Char; use char; use clone::Clone; |
