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:
parent
ba9be0a72b
commit
c2e3aa37da
|
@ -12,6 +12,8 @@
|
|||
//!
|
||||
//! A `to_bit` conversion function.
|
||||
|
||||
#![doc(primitive = "bool")]
|
||||
|
||||
use num::{Int, one, zero};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
|
||||
//! Operations and constants for signed 16-bits integers (`i16` type)
|
||||
|
||||
#![doc(primitive = "i16")]
|
||||
|
||||
int_module!(i16, 16)
|
||||
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
|
||||
//! Operations and constants for signed 32-bits integers (`i32` type)
|
||||
|
||||
#![doc(primitive = "i32")]
|
||||
|
||||
int_module!(i32, 32)
|
||||
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
|
||||
//! Operations and constants for signed 64-bits integers (`i64` type)
|
||||
|
||||
#![doc(primitive = "i64")]
|
||||
|
||||
int_module!(i64, 64)
|
||||
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
|
||||
//! Operations and constants for signed 8-bits integers (`i8` type)
|
||||
|
||||
#![doc(primitive = "i8")]
|
||||
|
||||
int_module!(i8, 8)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -10,4 +10,6 @@
|
|||
|
||||
//! Operations and constants for unsigned 16-bits integers (`u16` type)
|
||||
|
||||
#![doc(primitive = "u16")]
|
||||
|
||||
uint_module!(u16, i16, 16)
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
|
||||
//! Operations and constants for unsigned 32-bits integers (`u32` type)
|
||||
|
||||
#![doc(primitive = "u32")]
|
||||
|
||||
uint_module!(u32, i32, 32)
|
||||
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
|
||||
//! Operations and constants for unsigned 64-bits integer (`u64` type)
|
||||
|
||||
#![doc(primitive = "u64")]
|
||||
|
||||
uint_module!(u64, i64, 64)
|
||||
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
|
||||
//! Operations and constants for unsigned 8-bits integers (`u8` type)
|
||||
|
||||
#![doc(primitive = "u8")]
|
||||
|
||||
uint_module!(u8, i8, 8)
|
||||
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
|
||||
//! Operations and constants for architecture-sized unsigned integers (`uint` type)
|
||||
|
||||
#![doc(primitive = "uint")]
|
||||
|
||||
uint_module!(uint, int, ::int::BITS)
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
//!
|
||||
//! For more details `std::slice`.
|
||||
|
||||
#![doc(primitive = "slice")]
|
||||
|
||||
use mem::transmute;
|
||||
use clone::Clone;
|
||||
use container::Container;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
//!
|
||||
//! For more details, see std::str
|
||||
|
||||
#![doc(primitive = "str")]
|
||||
|
||||
use mem;
|
||||
use char;
|
||||
use clone::Clone;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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::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{ -> {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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -527,7 +527,8 @@
|
|||
"variant",
|
||||
"ffi",
|
||||
"ffs",
|
||||
"macro"];
|
||||
"macro",
|
||||
"primitive"];
|
||||
|
||||
function itemTypeFromName(typename) {
|
||||
for (var i = 0; i < itemTypes.length; ++i) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#![allow(missing_doc)]
|
||||
#![allow(unsigned_negate)]
|
||||
#![doc(primitive = "f32")]
|
||||
|
||||
use prelude::*;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
//! Operations and constants for 64-bits floats (`f64` type)
|
||||
|
||||
#![allow(missing_doc)]
|
||||
#![doc(primitive = "f64")]
|
||||
|
||||
use prelude::*;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -65,6 +65,8 @@ is the same as `&[u8]`.
|
|||
|
||||
*/
|
||||
|
||||
#![doc(primitive = "str")]
|
||||
|
||||
use char::Char;
|
||||
use char;
|
||||
use clone::Clone;
|
||||
|
|
Loading…
Reference in New Issue