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
This commit is contained in:
Alex Crichton 2014-05-28 19:53:37 -07:00
parent ba9be0a72b
commit c2e3aa37da
37 changed files with 444 additions and 88 deletions

View File

@ -12,6 +12,8 @@
//!
//! A `to_bit` conversion function.
#![doc(primitive = "bool")]
use num::{Int, one, zero};
/////////////////////////////////////////////////////////////////////////////

View File

@ -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};

View File

@ -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};

View File

@ -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};

View File

@ -10,5 +10,7 @@
//! Operations and constants for signed 16-bits integers (`i16` type)
#![doc(primitive = "i16")]
int_module!(i16, 16)

View File

@ -10,5 +10,7 @@
//! Operations and constants for signed 32-bits integers (`i32` type)
#![doc(primitive = "i32")]
int_module!(i32, 32)

View File

@ -10,5 +10,7 @@
//! Operations and constants for signed 64-bits integers (`i64` type)
#![doc(primitive = "i64")]
int_module!(i64, 64)

View File

@ -10,5 +10,7 @@
//! Operations and constants for signed 8-bits integers (`i8` type)
#![doc(primitive = "i8")]
int_module!(i8, 8)

View File

@ -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)

View File

@ -10,4 +10,6 @@
//! Operations and constants for unsigned 16-bits integers (`u16` type)
#![doc(primitive = "u16")]
uint_module!(u16, i16, 16)

View File

@ -10,5 +10,7 @@
//! Operations and constants for unsigned 32-bits integers (`u32` type)
#![doc(primitive = "u32")]
uint_module!(u32, i32, 32)

View File

@ -10,5 +10,7 @@
//! Operations and constants for unsigned 64-bits integer (`u64` type)
#![doc(primitive = "u64")]
uint_module!(u64, i64, 64)

View File

@ -10,5 +10,7 @@
//! Operations and constants for unsigned 8-bits integers (`u8` type)
#![doc(primitive = "u8")]
uint_module!(u8, i8, 8)

View File

@ -10,5 +10,7 @@
//! Operations and constants for architecture-sized unsigned integers (`uint` type)
#![doc(primitive = "uint")]
uint_module!(uint, int, ::int::BITS)

View File

@ -12,6 +12,8 @@
//!
//! For more details `std::slice`.
#![doc(primitive = "slice")]
use mem::transmute;
use clone::Clone;
use container::Container;

View File

@ -12,6 +12,8 @@
//!
//! For more details, see std::str
#![doc(primitive = "str")]
use mem;
use char;
use clone::Clone;

View File

@ -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;

View File

@ -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),

View File

@ -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{ -&gt; {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::FixedVector(ref t, ref s) => {
write!(f, "[{}, ..{}]", **t, *s)
clean::Vector(ref t) => {
primitive_link(f, clean::Slice, format!("[{}]", **t).as_slice())
}
clean::FixedVector(ref t, ref 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{ -&gt; {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{ -&gt; {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)
}
}

View File

@ -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,
}
}

View File

@ -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)
}

View File

@ -527,7 +527,8 @@
"variant",
"ffi",
"ffs",
"macro"];
"macro",
"primitive"];
function itemTypeFromName(typename) {
for (var i = 0; i < itemTypes.length; ++i) {

View File

@ -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 {

View File

@ -12,6 +12,7 @@
#![allow(missing_doc)]
#![allow(unsigned_negate)]
#![doc(primitive = "f32")]
use prelude::*;

View File

@ -11,6 +11,7 @@
//! Operations and constants for 64-bits floats (`f64` type)
#![allow(missing_doc)]
#![doc(primitive = "f64")]
use prelude::*;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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};

View File

@ -65,6 +65,8 @@ is the same as `&[u8]`.
*/
#![doc(primitive = "str")]
use char::Char;
use char;
use clone::Clone;