提交 4e0b9369 编写于 作者: B bors

auto merge of #14513 : alexcrichton/rust/rustdoc-primitives, r=huonw

This is currently rebased on top of #14478, but that's just to preemptively avoid rebase conflicts and to provide a better preview. This can land independently of that PR.

This change crates a dedicated page in rustdoc for primitive types to outline everything you can do with them (at least in a basic way).

* Preview - http://people.mozilla.org/~acrichton/doc/
* Exhibit A - http://people.mozilla.org/~acrichton/doc/std/#primitives
* Exhibit B - http://people.mozilla.org/~acrichton/doc/std/primitive.str.html
* Exhibit C - http://people.mozilla.org/~acrichton/doc/std/primitive.slice.html

Please don't hesitate to be nitpickity, it's easy to overlook a thing here or there!
......@@ -4,7 +4,7 @@
**Int to string**
Use [`ToStr`](../std/to_str/trait.ToStr.html).
Use [`ToStr`](std/to_str/trait.ToStr.html).
~~~
let x: int = 42;
......@@ -13,8 +13,8 @@ let y: String = x.to_str().to_string();
**String to int**
Use [`FromStr`](../std/from_str/trait.FromStr.html), and its helper function,
[`from_str`](../std/from_str/fn.from_str.html).
Use [`FromStr`](std/from_str/trait.FromStr.html), and its helper function,
[`from_str`](std/from_str/fn.from_str.html).
~~~
let x: Option<int> = from_str("42");
......@@ -35,8 +35,8 @@ let y: String = format!("{:X}", x); // uppercase hexadecimal
**String to int, in non-base-10**
Use [`FromStrRadix`](../std/num/trait.FromStrRadix.html), and its helper
function, [`from_str_radix`](../std/num/fn.from_str_radix.html).
Use [`FromStrRadix`](std/num/trait.FromStrRadix.html), and its helper
function, [`from_str_radix`](std/num/fn.from_str_radix.html).
~~~
use std::num;
......@@ -48,7 +48,7 @@ let y: i64 = x.unwrap();
**Vector of Bytes to String**
To return a Borrowed String Slice (&str) use the str helper function
[`from_utf8`](../std/str/fn.from_utf8.html).
[`from_utf8`](std/str/fn.from_utf8.html).
~~~
use std::str;
......@@ -58,7 +58,7 @@ let x: &str = str::from_utf8(bytes).unwrap();
~~~
To return an Owned String use the str helper function
[`from_utf8_owned`](../std/str/fn.from_utf8_owned.html).
[`from_utf8_owned`](std/str/fn.from_utf8_owned.html).
~~~
use std::str;
......@@ -68,8 +68,8 @@ let x: Option<String> =
let y: String = x.unwrap();
~~~
To return a [`MaybeOwned`](../std/str/enum.MaybeOwned.html) use the str helper
function [`from_utf8_lossy`](../std/str/fn.from_utf8_owned.html).
To return a [`MaybeOwned`](std/str/type.MaybeOwned.html) use the str helper
function [`from_utf8_lossy`](std/str/fn.from_utf8_owned.html).
This function also replaces non-valid utf-8 sequences with U+FFFD replacement
character.
......@@ -85,11 +85,11 @@ let y = str::from_utf8_lossy(x);
## How do I read from a file?
Use
[`File::open`](../std/io/fs/struct.File.html#method.open)
[`File::open`](std/io/fs/struct.File.html#method.open)
to create a
[`File`](../std/io/fs/struct.File.html)
[`File`](std/io/fs/struct.File.html)
struct, which implements the
[`Reader`](../std/io/trait.Reader.html)
[`Reader`](std/io/trait.Reader.html)
trait.
~~~ {.ignore}
......@@ -103,7 +103,8 @@ let reader : File = File::open(&path).unwrap_or_else(on_error);
## How do I iterate over the lines in a file?
Use the [`lines`](../std/io/trait.Buffer.html#method.lines) method on a [`BufferedReader`](../std/io/buffered/struct.BufferedReader.html).
Use the [`lines`](std/io/trait.Buffer.html#method.lines) method on a
[`BufferedReader`](std/io/struct.BufferedReader.html).
~~~
use std::io::BufferedReader;
......@@ -121,7 +122,7 @@ for line in reader.lines() {
## How do I search for a substring?
Use the [`find_str`](../std/str/trait.StrSlice.html#tymethod.find_str) method.
Use the [`find_str`](std/str/trait.StrSlice.html#tymethod.find_str) method.
~~~
let str = "Hello, this is some random string";
......@@ -132,7 +133,7 @@ let index: Option<uint> = str.find_str("rand");
## How do I get the length of a vector?
The [`Container`](../std/container/trait.Container.html) trait provides the `len` method.
The [`Container`](std/container/trait.Container.html) trait provides the `len` method.
~~~
let u: Vec<u32> = vec![0, 1, 2];
......@@ -144,7 +145,7 @@ println!("u: {}, v: {}, w: {}", u.len(), v.len(), w.len()); // 3, 4, 5
## How do I iterate over a vector?
Use the [`iter`](../std/vec/trait.ImmutableVector.html#tymethod.iter) method.
Use the [`iter`](std/slice/trait.ImmutableVector.html#tymethod.iter) method.
~~~
let values: Vec<int> = vec![1, 2, 3, 4, 5];
......@@ -153,9 +154,9 @@ for value in values.iter() { // value: &int
}
~~~
(See also [`mut_iter`](../std/vec/trait.MutableVector.html#tymethod.mut_iter)
(See also [`mut_iter`](std/slice/trait.MutableVector.html#tymethod.mut_iter)
which yields `&mut int` and
[`move_iter`](../std/vec/trait.OwnedVector.html#tymethod.move_iter) which yields
[`move_iter`](std/slice/trait.OwnedVector.html#tymethod.move_iter) which yields
`int` while consuming the `values` vector.)
# Type system
......
......@@ -21,7 +21,7 @@ Some examples that demonstrate different aspects of the language:
* The extra library's [json] module. Enums and pattern matching
[sprocketnes]: https://github.com/pcwalton/sprocketnes
[hash]: https://github.com/mozilla/rust/blob/master/src/libstd/hash.rs
[hash]: https://github.com/mozilla/rust/blob/master/src/libstd/hash/mod.rs
[HashMap]: https://github.com/mozilla/rust/blob/master/src/libcollections/hashmap.rs
[json]: https://github.com/mozilla/rust/blob/master/src/libserialize/json.rs
......@@ -149,6 +149,6 @@ example we were setting RUST_LOG to the name of the hello crate. Multiple paths
can be combined to control the exact logging you want to see. For example, when
debugging linking in the compiler you might set
`RUST_LOG=rustc::metadata::creader,rustc::util::filesearch,rustc::back::rpath`
For a full description see [the language reference][1].
For a full description see [the logging crate][1].
[1]:http://doc.rust-lang.org/doc/master/rust.html#logging-system
[1]:log/index.html
......@@ -499,9 +499,9 @@ shouldn't get triggered.
The second of these two functions, `eh_personality`, is used by the failure
mechanisms of the compiler. This is often mapped to GCC's personality function
(see the [libstd implementation](../std/rt/unwind/) for more information), but
crates which do not trigger failure can be assured that this function is never
called.
(see the [libstd implementation](std/rt/unwind/index.html) for more
information), but crates which do not trigger failure can be assured that this
function is never called.
## Using libcore
......@@ -511,7 +511,8 @@ called.
With the above techniques, we've got a bare-metal executable running some Rust
code. There is a good deal of functionality provided by the standard library,
however, that is necessary to be productive in Rust. If the standard library is
not sufficient, then [libcore](../core/) is designed to be used instead.
not sufficient, then [libcore](core/index.html) is designed to be used
instead.
The core library has very few dependencies and is much more portable than the
standard library itself. Additionally, the core library has most of the
......
......@@ -97,6 +97,7 @@
pub mod rc;
#[cfg(not(test))]
#[doc(hidden)]
mod std {
pub use core::fmt;
pub use core::option;
......
......@@ -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};
......
......@@ -134,10 +134,12 @@
// crate.
mod should_not_exist;
#[doc(hidden)]
mod core {
pub use failure;
}
#[doc(hidden)]
mod std {
pub use clone;
pub use cmp;
......
......@@ -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)
......@@ -234,8 +234,8 @@
//! similar and complementary: they are often employed to indicate a
//! lack of a return value; and they are trivially converted between
//! each other, so `Result`s are often handled by first converting to
//! `Option` with the [`ok`](enum.Result.html#method.ok) and
//! [`err`](enum.Result.html#method.ok) methods.
//! `Option` with the [`ok`](type.Result.html#method.ok) and
//! [`err`](type.Result.html#method.ok) methods.
//!
//! Whereas `Option` only indicates the lack of a value, `Result` is
//! specifically for error reporting, and carries with it an error
......
......@@ -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;
......
......@@ -62,17 +62,22 @@ fn try_inline_def(cx: &core::DocContext,
clean::TraitItem(build_external_trait(tcx, did))
}
ast::DefFn(did, style) => {
// If this function is a tuple struct constructor, we just skip it
if csearch::get_tuple_struct_definition_if_ctor(&tcx.sess.cstore,
did).is_some() {
return None
}
record_extern_fqn(cx, did, clean::TypeFunction);
clean::FunctionItem(build_external_function(tcx, did, style))
}
ast::DefStruct(did) => {
record_extern_fqn(cx, did, clean::TypeStruct);
ret.extend(build_impls(tcx, did).move_iter());
ret.extend(build_impls(cx, tcx, did).move_iter());
clean::StructItem(build_struct(tcx, did))
}
ast::DefTy(did) => {
record_extern_fqn(cx, did, clean::TypeEnum);
ret.extend(build_impls(tcx, did).move_iter());
ret.extend(build_impls(cx, tcx, did).move_iter());
build_type(tcx, did)
}
// Assume that the enum type is reexported next to the variant, and
......@@ -193,7 +198,8 @@ fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
})
}
fn build_impls(tcx: &ty::ctxt,
fn build_impls(cx: &core::DocContext,
tcx: &ty::ctxt,
did: ast::DefId) -> Vec<clean::Item> {
ty::populate_implementations_for_type_if_necessary(tcx, did);
let mut impls = Vec::new();
......@@ -205,6 +211,38 @@ fn build_impls(tcx: &ty::ctxt,
}
}
// If this is the first time we've inlined something from this crate, then
// we inline *all* impls from the crate into this crate. Note that there's
// currently no way for us to filter this based on type, and we likely need
// many impls for a variety of reasons.
//
// Primarily, the impls will be used to populate the documentation for this
// type being inlined, but impls can also be used when generating
// documentation for primitives (no way to find those specifically).
if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
csearch::each_top_level_item_of_crate(&tcx.sess.cstore,
did.krate,
|def, _, _| {
populate_impls(tcx, def, &mut impls)
});
fn populate_impls(tcx: &ty::ctxt,
def: decoder::DefLike,
impls: &mut Vec<clean::Item>) {
match def {
decoder::DlImpl(did) => impls.push(build_impl(tcx, did)),
decoder::DlDef(ast::DefMod(did)) => {
csearch::each_child_of_item(&tcx.sess.cstore,
did,
|def, _, _| {
populate_impls(tcx, def, impls)
})
}
_ => {}
}
}
}
impls
}
......@@ -259,7 +297,8 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
// FIXME: this doesn't handle reexports inside the module itself.
// Should they be handled?
csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, _| {
csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, vis| {
if vis != ast::Public { return }
match def {
decoder::DlDef(def) => {
match try_inline_def(cx, tcx, def) {
......@@ -267,7 +306,8 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt,
None => {}
}
}
decoder::DlImpl(did) => items.push(build_impl(tcx, did)),
// All impls were inlined above
decoder::DlImpl(..) => {}
decoder::DlField => fail!("unimplemented field"),
}
});
......
......@@ -28,6 +28,7 @@
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 @@ fn clean(&self) -> Crate {
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,62 @@ fn clean(&self) -> Crate {
cx.sess());
let id = link::find_crate_id(self.attrs.as_slice(),
t_outputs.out_filestem.as_slice());
// Clean the crate, 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.
//
// Note that this loop only searches the top-level items of the crate,
// and this is intentional. If we were to search the entire crate for an
// item tagged with `#[doc(primitive)]` then we we would also have to
// search the entirety of external modules for items tagged
// `#[doc(primitive)]`, which is a pretty inefficient process (decoding
// all that metadata unconditionally).
//
// In order to keep the metadata load under control, the
// `#[doc(primitive)]` feature is explicitly designed to only allow the
// primitive tags to show up as the top level items in a crate.
//
// Also note that this does not attempt to deal with modules tagged
// duplicately for the same primitive. This is handled later on when
// rendering by delegating everything to a hash map.
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 +167,35 @@ fn clean(&self) -> Crate {
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 +302,7 @@ pub enum ItemEnum {
/// `static`s from an extern block
ForeignStaticItem(Static),
MacroItem(Macro),
PrimitiveItem(Primitive),
}
#[deriving(Clone, Encodable, Decodable)]
......@@ -400,14 +476,19 @@ fn clean(&self) -> TyParamBound {
}
}
fn external_path(name: &str) -> Path {
fn external_path(name: &str, substs: &ty::substs) -> Path {
Path {
global: false,
segments: vec![PathSegment {
name: name.to_string(),
lifetimes: Vec::new(),
types: Vec::new(),
}]
lifetimes: match substs.regions {
ty::ErasedRegions => Vec::new(),
ty::NonerasedRegions(ref v) => {
v.iter().filter_map(|v| v.clean()).collect()
}
},
types: substs.tps.clean(),
}],
}
}
......@@ -418,16 +499,21 @@ fn clean(&self) -> TyParamBound {
core::Typed(ref tcx) => tcx,
core::NotTyped(_) => return RegionBound,
};
let empty = ty::substs::empty();
let (did, path) = match *self {
ty::BoundStatic => return RegionBound,
ty::BoundSend =>
(tcx.lang_items.send_trait().unwrap(), external_path("Send")),
(tcx.lang_items.send_trait().unwrap(),
external_path("Send", &empty)),
ty::BoundSized =>
(tcx.lang_items.sized_trait().unwrap(), external_path("Sized")),
(tcx.lang_items.sized_trait().unwrap(),
external_path("Sized", &empty)),
ty::BoundCopy =>
(tcx.lang_items.copy_trait().unwrap(), external_path("Copy")),
(tcx.lang_items.copy_trait().unwrap(),
external_path("Copy", &empty)),
ty::BoundShare =>
(tcx.lang_items.share_trait().unwrap(), external_path("Share")),
(tcx.lang_items.share_trait().unwrap(),
external_path("Share", &empty)),
};
let fqn = csearch::get_item_path(tcx, did);
let fqn = fqn.move_iter().map(|i| i.to_str().to_string()).collect();
......@@ -451,7 +537,8 @@ fn clean(&self) -> TyParamBound {
let fqn = csearch::get_item_path(tcx, self.def_id);
let fqn = fqn.move_iter().map(|i| i.to_str().to_string())
.collect::<Vec<String>>();
let path = external_path(fqn.last().unwrap().as_slice());
let path = external_path(fqn.last().unwrap().as_slice(),
&self.substs);
cx.external_paths.borrow_mut().get_mut_ref().insert(self.def_id,
(fqn, TypeTrait));
TraitBound(ResolvedPath {
......@@ -519,9 +606,9 @@ fn clean(&self) -> Option<Lifetime> {
ty::ReStatic => Some(Lifetime("static".to_string())),
ty::ReLateBound(_, ty::BrNamed(_, name)) =>
Some(Lifetime(token::get_name(name).get().to_string())),
ty::ReEarlyBound(_, _, name) => Some(Lifetime(name.clean())),
ty::ReLateBound(..) |
ty::ReEarlyBound(..) |
ty::ReFree(..) |
ty::ReScope(..) |
ty::ReInfer(..) |
......@@ -920,7 +1007,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
......@@ -928,10 +1015,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>),
......@@ -945,6 +1028,19 @@ pub enum Type {
// region, raw, other boxes, mutable
}
#[deriving(Clone, Encodable, Decodable, PartialEq, 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,
......@@ -956,11 +1052,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(),
......@@ -988,16 +1170,26 @@ fn clean(&self) -> Type {
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)),
......@@ -1040,22 +1232,13 @@ fn clean(&self) -> Type {
let fqn: Vec<String> = fqn.move_iter().map(|i| {
i.to_str().to_string()
}).collect();
let mut path = external_path(fqn.last()
.unwrap()
.to_str()
.as_slice());
let kind = match ty::get(*self).sty {
ty::ty_struct(..) => TypeStruct,
ty::ty_trait(..) => TypeTrait,
_ => TypeEnum,
};
path.segments.get_mut(0).lifetimes = match substs.regions {
ty::ErasedRegions => Vec::new(),
ty::NonerasedRegions(ref v) => {
v.iter().filter_map(|v| v.clean()).collect()
}
};
path.segments.get_mut(0).types = substs.tps.clean();
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 {
......@@ -1747,7 +1930,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) {
......@@ -1758,9 +1941,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),
......
......@@ -42,6 +42,7 @@ pub struct DocContext {
pub external_traits: RefCell<Option<HashMap<ast::DefId, clean::Trait>>>,
pub external_typarams: RefCell<Option<HashMap<ast::DefId, String>>>,
pub inlined: RefCell<Option<HashSet<ast::DefId>>>,
pub populated_crate_impls: RefCell<HashSet<ast::CrateNum>>,
}
impl DocContext {
......@@ -114,6 +115,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>)
external_typarams: RefCell::new(Some(HashMap::new())),
external_paths: RefCell::new(Some(HashMap::new())),
inlined: RefCell::new(Some(HashSet::new())),
populated_crate_impls: RefCell::new(HashSet::new()),
}, CrateAnalysis {
exported_items: exported_items,
public_items: public_items,
......
......@@ -263,6 +263,53 @@ 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 path = m.paths.get(&ast::DefId {
krate: cnum,
node: ast::CRATE_NODE_ID,
});
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()))
}
render::Unknown => None,
};
match loc {
Some(root) => {
try!(write!(f, "<a href='{}{}/primitive.{}.html'>",
root,
path.ref0().as_slice().head().unwrap(),
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 +344,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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 +356,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
},
args = decl.decl.inputs,
arrow = match decl.decl.output {
clean::Unit => "no",
clean::Primitive(clean::Nil) => "no",
_ => "yes",
},
ret = decl.decl.output,
......@@ -379,7 +406,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
": {}",
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) => {
......@@ -394,22 +424,16 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
decl.decl)
}
clean::Tuple(ref typs) => {
try!(f.write("(".as_bytes()));
for (i, typ) in typs.iter().enumerate() {
if i > 0 {
try!(f.write(", ".as_bytes()))
}
try!(write!(f, "{}", *typ));
}
f.write(")".as_bytes())
primitive_link(f, clean::PrimitiveTuple,
format!("({:#})", typs).as_slice())
}
clean::Vector(ref t) => {
primitive_link(f, clean::Slice, format!("[{}]", **t).as_slice())
}
clean::Vector(ref t) => write!(f, "[{}]", **t),
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{ -&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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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)
}
}
......
......@@ -37,6 +37,7 @@ pub enum ItemType {
ForeignFunction = 13,
ForeignStatic = 14,
Macro = 15,
Primitive = 16,
}
impl ItemType {
......@@ -58,6 +59,7 @@ pub fn to_static_str(&self) -> &'static str {
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,
}
}
......@@ -130,3 +130,17 @@ pub fn render<T: fmt::Show, S: fmt::Show>(
fn nonestr<'a>(s: &'a str) -> &'a str {
if s == "" { "none" } else { s }
}
pub fn redirect(dst: &mut io::Writer, url: &str) -> io::IoResult<()> {
write!(dst,
r##"<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="refresh" content="0;URL={url}">
</head>
<body>
</body>
</html>"##,
url = url,
)
}
此差异已折叠。
......@@ -527,7 +527,8 @@
"variant",
"ffi",
"ffs",
"macro"];
"macro",
"primitive"];
function itemTypeFromName(typename) {
for (var i = 0; i < itemTypes.length; ++i) {
......@@ -658,15 +659,13 @@
var list = $('#implementors-list');
var libs = Object.getOwnPropertyNames(imp);
for (var i = 0; i < libs.length; i++) {
var structs = Object.getOwnPropertyNames(imp[libs[i]]);
if (libs[i] == currentCrate) continue;
var structs = imp[libs[i]];
for (var j = 0; j < structs.length; j++) {
console.log(i, structs[j]);
var path = rootPath + imp[libs[i]][structs[j]];
var klass = path.contains("type.") ? "type" : "struct";
var link = $('<a>').text(structs[j])
.attr('href', path)
.attr('class', klass);
var code = $('<code>').append(link);
var code = $('<code>').append(structs[j]);
$.each(code.find('a'), function(idx, a) {
$(a).attr('href', rootPath + $(a).attr('href'));
});
var li = $('<li>').append(code);
list.append(li);
}
......
......@@ -67,11 +67,22 @@ impl<'a> fold::DocFolder for ImplStripper<'a> {
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 types 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 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
// tymethods/macros have no control over privacy
clean::MacroItem(..) | clean::TyMethodItem(..) => {}
// Primitives are never stripped
clean::PrimitiveItem(..) => {}
}
let fastreturn = match i.inner {
......
......@@ -79,6 +79,7 @@ pub fn run(input: &str,
external_traits: RefCell::new(None),
external_typarams: RefCell::new(None),
inlined: RefCell::new(None),
populated_crate_impls: RefCell::new(HashSet::new()),
};
super::ctxtkey.replace(Some(ctx));
......
......@@ -82,6 +82,7 @@ pub fn local_id() -> uint {
}
}
#[doc(hidden)]
pub trait HomingIO {
fn home<'r>(&'r mut self) -> &'r mut HomeHandle;
......
......@@ -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 @@
*/
#![doc(primitive = "slice")]
use mem::transmute;
use clone::Clone;
use cmp::{TotalOrd, Ordering, Less, Greater};
......
......@@ -65,6 +65,8 @@ fn main() {
*/
#![doc(primitive = "str")]
use char::Char;
use char;
use clone::Clone;
......
......@@ -288,7 +288,7 @@ pub enum SubstructureFields<'a> {
/**
non-matching variants of the enum, [(variant index, ast::Variant,
[field span, field ident, fields])] (i.e. all fields for self are in the
[field span, field ident, fields])] \(i.e. all fields for self are in the
first tuple, for other1 are in the second tuple, etc.)
*/
EnumNonMatching(&'a [(uint, P<ast::Variant>, Vec<(Span, Option<Ident>, @Expr)> )]),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册