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!
This commit is contained in:
commit
4e0b936900
@ -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 arc;
|
||||
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 @@ pub mod fmt;
|
||||
// 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::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,62 @@ 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 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 @@ 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 +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 @@ impl Clean<TyParamBound> for ast::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 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
|
||||
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 @@ impl Clean<TyParamBound> for ty::TraitRef {
|
||||
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 @@ impl Clean<Option<Lifetime>> for ty::Region {
|
||||
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 @@ 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)),
|
||||
@ -1040,22 +1232,13 @@ impl Clean<Type> for ty::t {
|
||||
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 @@ 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 +356,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 +406,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) => {
|
||||
@ -394,22 +424,16 @@ impl fmt::Show for clean::Type {
|
||||
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{ -> {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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,3 +130,17 @@ r##"<!DOCTYPE html>
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ use html::markdown;
|
||||
pub struct Context {
|
||||
/// Current hierarchy of components leading down to what's currently being
|
||||
/// rendered
|
||||
pub current: Vec<String> ,
|
||||
pub current: Vec<String>,
|
||||
/// String representation of how to get back to the root path of the 'doc/'
|
||||
/// folder in terms of a relative URL.
|
||||
pub root_path: String,
|
||||
@ -90,6 +90,10 @@ pub struct Context {
|
||||
/// the source files are present in the html rendering, then this will be
|
||||
/// `true`.
|
||||
pub include_sources: bool,
|
||||
/// A flag, which when turned off, will render pages which redirect to the
|
||||
/// real location of an item. This is used to allow external links to
|
||||
/// publicly reused items to redirect to the right location.
|
||||
pub render_redirect_pages: bool,
|
||||
}
|
||||
|
||||
/// Indicates where an external crate can be found.
|
||||
@ -102,13 +106,11 @@ pub enum ExternalLocation {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Different ways an implementor of a trait can be rendered.
|
||||
pub enum Implementor {
|
||||
/// Paths are displayed specially by omitting the `impl XX for` cruft
|
||||
PathType(clean::Type),
|
||||
/// This is the generic representation of a trait implementor, used for
|
||||
/// primitive types and otherwise non-path types.
|
||||
OtherType(clean::Generics, /* trait */ clean::Type, /* for */ clean::Type),
|
||||
/// Metadata about an implementor of a trait.
|
||||
pub struct Implementor {
|
||||
generics: clean::Generics,
|
||||
trait_: clean::Type,
|
||||
for_: clean::Type,
|
||||
}
|
||||
|
||||
/// This cache is used to store information about the `clean::Crate` being
|
||||
@ -159,6 +161,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>,
|
||||
|
||||
@ -226,9 +231,12 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
|
||||
krate: krate.name.clone(),
|
||||
},
|
||||
include_sources: true,
|
||||
render_redirect_pages: false,
|
||||
};
|
||||
try!(mkdir(&cx.dst));
|
||||
|
||||
// Crawl the crate attributes looking for attributes which control how we're
|
||||
// going to emit HTML
|
||||
match krate.module.as_ref().map(|m| m.doc_list().unwrap_or(&[])) {
|
||||
Some(attrs) => {
|
||||
for attr in attrs.iter() {
|
||||
@ -281,6 +289,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,19 +306,58 @@ 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
|
||||
// for future parallelization opportunities
|
||||
let cache = Arc::new(cache);
|
||||
cache_key.replace(Some(cache.clone()));
|
||||
current_location_key.replace(Some(Vec::new()));
|
||||
|
||||
try!(write_shared(&cx, &krate, &*cache, index));
|
||||
let krate = try!(render_sources(&mut cx, krate));
|
||||
|
||||
// And finally render the whole crate's documentation
|
||||
cx.krate(krate)
|
||||
}
|
||||
|
||||
fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::IoResult<String> {
|
||||
// Build the search index from the collected metadata
|
||||
let mut nodeid_to_pathid = HashMap::new();
|
||||
let mut pathid_to_nodeid = Vec::new();
|
||||
{
|
||||
let Cache { search_index: ref mut index,
|
||||
orphan_methods: ref meths, paths: ref mut paths, ..} = cache;
|
||||
let Cache { ref mut search_index,
|
||||
ref orphan_methods,
|
||||
ref mut paths, .. } = *cache;
|
||||
|
||||
// Attach all orphan methods to the type's definition if the type
|
||||
// has since been learned.
|
||||
for &(pid, ref item) in meths.iter() {
|
||||
for &(pid, ref item) in orphan_methods.iter() {
|
||||
let did = ast_util::local_def(pid);
|
||||
match paths.find(&did) {
|
||||
Some(&(ref fqp, _)) => {
|
||||
index.push(IndexItem {
|
||||
search_index.push(IndexItem {
|
||||
ty: shortty(item),
|
||||
name: item.name.clone().unwrap(),
|
||||
path: fqp.slice_to(fqp.len() - 1).connect("::")
|
||||
@ -324,7 +372,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
|
||||
|
||||
// Reduce `NodeId` in paths into smaller sequential numbers,
|
||||
// and prune the paths that do not appear in the index.
|
||||
for item in index.iter() {
|
||||
for item in search_index.iter() {
|
||||
match item.parent {
|
||||
Some(nodeid) => {
|
||||
if !nodeid_to_pathid.contains_key(&nodeid) {
|
||||
@ -339,189 +387,181 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
|
||||
assert_eq!(nodeid_to_pathid.len(), pathid_to_nodeid.len());
|
||||
}
|
||||
|
||||
// Publish the search index
|
||||
let index = {
|
||||
let mut w = MemWriter::new();
|
||||
try!(write!(&mut w, r#"searchIndex['{}'] = \{"items":["#, krate.name));
|
||||
// Collect the index into a string
|
||||
let mut w = MemWriter::new();
|
||||
try!(write!(&mut w, r#"searchIndex['{}'] = \{"items":["#, krate.name));
|
||||
|
||||
let mut lastpath = "".to_string();
|
||||
for (i, item) in cache.search_index.iter().enumerate() {
|
||||
// Omit the path if it is same to that of the prior item.
|
||||
let path;
|
||||
if lastpath.as_slice() == item.path.as_slice() {
|
||||
path = "";
|
||||
} else {
|
||||
lastpath = item.path.to_string();
|
||||
path = item.path.as_slice();
|
||||
};
|
||||
let mut lastpath = "".to_string();
|
||||
for (i, item) in cache.search_index.iter().enumerate() {
|
||||
// Omit the path if it is same to that of the prior item.
|
||||
let path;
|
||||
if lastpath.as_slice() == item.path.as_slice() {
|
||||
path = "";
|
||||
} else {
|
||||
lastpath = item.path.to_string();
|
||||
path = item.path.as_slice();
|
||||
};
|
||||
|
||||
if i > 0 {
|
||||
try!(write!(&mut w, ","));
|
||||
}
|
||||
try!(write!(&mut w, r#"[{:u},"{}","{}",{}"#,
|
||||
item.ty, item.name, path,
|
||||
item.desc.to_json().to_str()));
|
||||
match item.parent {
|
||||
Some(nodeid) => {
|
||||
let pathid = *nodeid_to_pathid.find(&nodeid).unwrap();
|
||||
try!(write!(&mut w, ",{}", pathid));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
try!(write!(&mut w, "]"));
|
||||
if i > 0 {
|
||||
try!(write!(&mut w, ","));
|
||||
}
|
||||
|
||||
try!(write!(&mut w, r#"],"paths":["#));
|
||||
|
||||
for (i, &did) in pathid_to_nodeid.iter().enumerate() {
|
||||
let &(ref fqp, short) = cache.paths.find(&did).unwrap();
|
||||
if i > 0 {
|
||||
try!(write!(&mut w, ","));
|
||||
try!(write!(&mut w, r#"[{:u},"{}","{}",{}"#,
|
||||
item.ty, item.name, path,
|
||||
item.desc.to_json().to_str()));
|
||||
match item.parent {
|
||||
Some(nodeid) => {
|
||||
let pathid = *nodeid_to_pathid.find(&nodeid).unwrap();
|
||||
try!(write!(&mut w, ",{}", pathid));
|
||||
}
|
||||
try!(write!(&mut w, r#"[{:u},"{}"]"#,
|
||||
short, *fqp.last().unwrap()));
|
||||
None => {}
|
||||
}
|
||||
try!(write!(&mut w, "]"));
|
||||
}
|
||||
|
||||
try!(write!(&mut w, r"]\};"));
|
||||
try!(write!(&mut w, r#"],"paths":["#));
|
||||
|
||||
str::from_utf8(w.unwrap().as_slice()).unwrap().to_string()
|
||||
};
|
||||
for (i, &did) in pathid_to_nodeid.iter().enumerate() {
|
||||
let &(ref fqp, short) = cache.paths.find(&did).unwrap();
|
||||
if i > 0 {
|
||||
try!(write!(&mut w, ","));
|
||||
}
|
||||
try!(write!(&mut w, r#"[{:u},"{}"]"#,
|
||||
short, *fqp.last().unwrap()));
|
||||
}
|
||||
|
||||
try!(write!(&mut w, r"]\};"));
|
||||
|
||||
Ok(str::from_utf8(w.unwrap().as_slice()).unwrap().to_string())
|
||||
}
|
||||
|
||||
fn write_shared(cx: &Context,
|
||||
krate: &clean::Crate,
|
||||
cache: &Cache,
|
||||
search_index: String) -> io::IoResult<()> {
|
||||
// Write out the shared files. Note that these are shared among all rustdoc
|
||||
// docs placed in the output directory, so this needs to be a synchronized
|
||||
// operation with respect to all other rustdocs running around.
|
||||
{
|
||||
try!(mkdir(&cx.dst));
|
||||
let _lock = ::flock::Lock::new(&cx.dst.join(".lock"));
|
||||
try!(mkdir(&cx.dst));
|
||||
let _lock = ::flock::Lock::new(&cx.dst.join(".lock"));
|
||||
|
||||
// Add all the static files. These may already exist, but we just
|
||||
// overwrite them anyway to make sure that they're fresh and up-to-date.
|
||||
try!(write(cx.dst.join("jquery.js"),
|
||||
include_bin!("static/jquery-2.1.0.min.js")));
|
||||
try!(write(cx.dst.join("main.js"), include_bin!("static/main.js")));
|
||||
try!(write(cx.dst.join("main.css"), include_bin!("static/main.css")));
|
||||
try!(write(cx.dst.join("normalize.css"),
|
||||
include_bin!("static/normalize.css")));
|
||||
try!(write(cx.dst.join("FiraSans-Regular.woff"),
|
||||
include_bin!("static/FiraSans-Regular.woff")));
|
||||
try!(write(cx.dst.join("FiraSans-Medium.woff"),
|
||||
include_bin!("static/FiraSans-Medium.woff")));
|
||||
try!(write(cx.dst.join("Heuristica-Regular.woff"),
|
||||
include_bin!("static/Heuristica-Regular.woff")));
|
||||
try!(write(cx.dst.join("Heuristica-Italic.woff"),
|
||||
include_bin!("static/Heuristica-Italic.woff")));
|
||||
try!(write(cx.dst.join("Heuristica-Bold.woff"),
|
||||
include_bin!("static/Heuristica-Bold.woff")));
|
||||
// Add all the static files. These may already exist, but we just
|
||||
// overwrite them anyway to make sure that they're fresh and up-to-date.
|
||||
try!(write(cx.dst.join("jquery.js"),
|
||||
include_bin!("static/jquery-2.1.0.min.js")));
|
||||
try!(write(cx.dst.join("main.js"), include_bin!("static/main.js")));
|
||||
try!(write(cx.dst.join("main.css"), include_bin!("static/main.css")));
|
||||
try!(write(cx.dst.join("normalize.css"),
|
||||
include_bin!("static/normalize.css")));
|
||||
try!(write(cx.dst.join("FiraSans-Regular.woff"),
|
||||
include_bin!("static/FiraSans-Regular.woff")));
|
||||
try!(write(cx.dst.join("FiraSans-Medium.woff"),
|
||||
include_bin!("static/FiraSans-Medium.woff")));
|
||||
try!(write(cx.dst.join("Heuristica-Regular.woff"),
|
||||
include_bin!("static/Heuristica-Regular.woff")));
|
||||
try!(write(cx.dst.join("Heuristica-Italic.woff"),
|
||||
include_bin!("static/Heuristica-Italic.woff")));
|
||||
try!(write(cx.dst.join("Heuristica-Bold.woff"),
|
||||
include_bin!("static/Heuristica-Bold.woff")));
|
||||
|
||||
fn collect(path: &Path, krate: &str,
|
||||
key: &str) -> io::IoResult<Vec<String>> {
|
||||
let mut ret = Vec::new();
|
||||
if path.exists() {
|
||||
for line in BufferedReader::new(File::open(path)).lines() {
|
||||
let line = try!(line);
|
||||
if !line.as_slice().starts_with(key) {
|
||||
continue
|
||||
}
|
||||
if line.as_slice().starts_with(
|
||||
format!("{}['{}']", key, krate).as_slice()) {
|
||||
continue
|
||||
}
|
||||
ret.push(line.to_string());
|
||||
fn collect(path: &Path, krate: &str,
|
||||
key: &str) -> io::IoResult<Vec<String>> {
|
||||
let mut ret = Vec::new();
|
||||
if path.exists() {
|
||||
for line in BufferedReader::new(File::open(path)).lines() {
|
||||
let line = try!(line);
|
||||
if !line.as_slice().starts_with(key) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return Ok(ret);
|
||||
}
|
||||
|
||||
// Update the search index
|
||||
let dst = cx.dst.join("search-index.js");
|
||||
let all_indexes = try!(collect(&dst, krate.name.as_slice(),
|
||||
"searchIndex"));
|
||||
let mut w = try!(File::create(&dst));
|
||||
try!(writeln!(&mut w, r"var searchIndex = \{\};"));
|
||||
try!(writeln!(&mut w, "{}", index));
|
||||
for index in all_indexes.iter() {
|
||||
try!(writeln!(&mut w, "{}", *index));
|
||||
}
|
||||
try!(writeln!(&mut w, "initSearch(searchIndex);"));
|
||||
|
||||
// Update the list of all implementors for traits
|
||||
let dst = cx.dst.join("implementors");
|
||||
try!(mkdir(&dst));
|
||||
for (&did, imps) in cache.implementors.iter() {
|
||||
if ast_util::is_local(did) { continue }
|
||||
let &(ref remote_path, remote_item_type) = cache.paths.get(&did);
|
||||
|
||||
let mut mydst = dst.clone();
|
||||
for part in remote_path.slice_to(remote_path.len() - 1).iter() {
|
||||
mydst.push(part.as_slice());
|
||||
try!(mkdir(&mydst));
|
||||
}
|
||||
mydst.push(format!("{}.{}.js",
|
||||
remote_item_type.to_static_str(),
|
||||
*remote_path.get(remote_path.len() - 1)));
|
||||
let all_implementors = try!(collect(&mydst, krate.name.as_slice(),
|
||||
"implementors"));
|
||||
|
||||
try!(mkdir(&mydst.dir_path()));
|
||||
let mut f = BufferedWriter::new(try!(File::create(&mydst)));
|
||||
try!(writeln!(&mut f, r"(function() \{var implementors = \{\};"));
|
||||
|
||||
for implementor in all_implementors.iter() {
|
||||
try!(writeln!(&mut f, "{}", *implementor));
|
||||
}
|
||||
|
||||
try!(write!(&mut f, r"implementors['{}'] = \{", krate.name));
|
||||
for imp in imps.iter() {
|
||||
let &(ref path, item_type) = match *imp {
|
||||
PathType(clean::ResolvedPath { did, .. }) => {
|
||||
cache.paths.get(&did)
|
||||
}
|
||||
PathType(..) | OtherType(..) => continue,
|
||||
};
|
||||
try!(write!(&mut f, r#"{}:"#, *path.get(path.len() - 1)));
|
||||
try!(write!(&mut f, r#""{}"#,
|
||||
path.slice_to(path.len() - 1).connect("/")));
|
||||
try!(write!(&mut f, r#"/{}.{}.html","#,
|
||||
item_type.to_static_str(),
|
||||
*path.get(path.len() - 1)));
|
||||
}
|
||||
try!(writeln!(&mut f, r"\};"));
|
||||
try!(writeln!(&mut f, "{}", r"
|
||||
if (window.register_implementors) {
|
||||
window.register_implementors(implementors);
|
||||
} else {
|
||||
window.pending_implementors = implementors;
|
||||
if line.as_slice().starts_with(
|
||||
format!("{}['{}']", key, krate).as_slice()) {
|
||||
continue
|
||||
}
|
||||
"));
|
||||
try!(writeln!(&mut f, r"\})()"));
|
||||
ret.push(line.to_string());
|
||||
}
|
||||
}
|
||||
return Ok(ret);
|
||||
}
|
||||
|
||||
// Render all source files (this may turn into a giant no-op)
|
||||
{
|
||||
info!("emitting source files");
|
||||
let dst = cx.dst.join("src");
|
||||
try!(mkdir(&dst));
|
||||
let dst = dst.join(krate.name.as_slice());
|
||||
try!(mkdir(&dst));
|
||||
let mut folder = SourceCollector {
|
||||
dst: dst,
|
||||
seen: HashSet::new(),
|
||||
cx: &mut cx,
|
||||
// Update the search index
|
||||
let dst = cx.dst.join("search-index.js");
|
||||
let all_indexes = try!(collect(&dst, krate.name.as_slice(),
|
||||
"searchIndex"));
|
||||
let mut w = try!(File::create(&dst));
|
||||
try!(writeln!(&mut w, r"var searchIndex = \{\};"));
|
||||
try!(writeln!(&mut w, "{}", search_index));
|
||||
for index in all_indexes.iter() {
|
||||
try!(writeln!(&mut w, "{}", *index));
|
||||
}
|
||||
try!(writeln!(&mut w, "initSearch(searchIndex);"));
|
||||
|
||||
// Update the list of all implementors for traits
|
||||
let dst = cx.dst.join("implementors");
|
||||
try!(mkdir(&dst));
|
||||
for (&did, imps) in cache.implementors.iter() {
|
||||
// Private modules can leak through to this phase of rustdoc, which
|
||||
// could contain implementations for otherwise private types. In some
|
||||
// rare cases we could find an implementation for an item which wasn't
|
||||
// indexed, so we just skip this step in that case.
|
||||
//
|
||||
// FIXME: this is a vague explanation for why this can't be a `get`, in
|
||||
// theory it should be...
|
||||
let &(ref remote_path, remote_item_type) = match cache.paths.find(&did) {
|
||||
Some(p) => p,
|
||||
None => continue,
|
||||
};
|
||||
// skip all invalid spans
|
||||
folder.seen.insert("".to_string());
|
||||
krate = folder.fold_crate(krate);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
let mut mydst = dst.clone();
|
||||
for part in remote_path.slice_to(remote_path.len() - 1).iter() {
|
||||
mydst.push(part.as_slice());
|
||||
try!(mkdir(&mydst));
|
||||
}
|
||||
mydst.push(format!("{}.{}.js",
|
||||
remote_item_type.to_static_str(),
|
||||
*remote_path.get(remote_path.len() - 1)));
|
||||
let all_implementors = try!(collect(&mydst, krate.name.as_slice(),
|
||||
"implementors"));
|
||||
|
||||
// And finally render the whole crate's documentation
|
||||
cx.krate(krate, cache)
|
||||
try!(mkdir(&mydst.dir_path()));
|
||||
let mut f = BufferedWriter::new(try!(File::create(&mydst)));
|
||||
try!(writeln!(&mut f, r"(function() \{var implementors = \{\};"));
|
||||
|
||||
for implementor in all_implementors.iter() {
|
||||
try!(write!(&mut f, "{}", *implementor));
|
||||
}
|
||||
|
||||
try!(write!(&mut f, r"implementors['{}'] = [", krate.name));
|
||||
for imp in imps.iter() {
|
||||
try!(write!(&mut f, r#""impl{} {} for {}","#,
|
||||
imp.generics, imp.trait_, imp.for_));
|
||||
}
|
||||
try!(writeln!(&mut f, r"];"));
|
||||
try!(writeln!(&mut f, "{}", r"
|
||||
if (window.register_implementors) {
|
||||
window.register_implementors(implementors);
|
||||
} else {
|
||||
window.pending_implementors = implementors;
|
||||
}
|
||||
"));
|
||||
try!(writeln!(&mut f, r"\})()"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_sources(cx: &mut Context,
|
||||
krate: clean::Crate) -> io::IoResult<clean::Crate> {
|
||||
info!("emitting source files");
|
||||
let dst = cx.dst.join("src");
|
||||
try!(mkdir(&dst));
|
||||
let dst = dst.join(krate.name.as_slice());
|
||||
try!(mkdir(&dst));
|
||||
let mut folder = SourceCollector {
|
||||
dst: dst,
|
||||
seen: HashSet::new(),
|
||||
cx: cx,
|
||||
};
|
||||
// skip all invalid spans
|
||||
folder.seen.insert("".to_string());
|
||||
Ok(folder.fold_crate(krate))
|
||||
}
|
||||
|
||||
/// Writes the entire contents of a string to a destination, not attempting to
|
||||
@ -718,16 +758,11 @@ impl DocFolder for Cache {
|
||||
let v = self.implementors.find_or_insert_with(did, |_| {
|
||||
Vec::new()
|
||||
});
|
||||
match i.for_ {
|
||||
clean::ResolvedPath{..} => {
|
||||
v.unshift(PathType(i.for_.clone()));
|
||||
}
|
||||
_ => {
|
||||
v.push(OtherType(i.generics.clone(),
|
||||
i.trait_.get_ref().clone(),
|
||||
i.for_.clone()));
|
||||
}
|
||||
}
|
||||
v.push(Implementor {
|
||||
generics: i.generics.clone(),
|
||||
trait_: i.trait_.get_ref().clone(),
|
||||
for_: i.for_.clone(),
|
||||
});
|
||||
}
|
||||
Some(..) | None => {}
|
||||
}
|
||||
@ -803,7 +838,7 @@ impl DocFolder for Cache {
|
||||
clean::StructItem(..) | clean::EnumItem(..) |
|
||||
clean::TypedefItem(..) | clean::TraitItem(..) |
|
||||
clean::FunctionItem(..) | clean::ModuleItem(..) |
|
||||
clean::ForeignFunctionItem(..) => {
|
||||
clean::ForeignFunctionItem(..) if !self.privmod => {
|
||||
// Reexported items mean that the same id can show up twice
|
||||
// in the rustdoc ast that we're looking at. We know,
|
||||
// however, that a reexported item doesn't show up in the
|
||||
@ -820,7 +855,7 @@ impl DocFolder for Cache {
|
||||
}
|
||||
// link variants to their parent enum because pages aren't emitted
|
||||
// for each variant
|
||||
clean::VariantItem(..) => {
|
||||
clean::VariantItem(..) if !self.privmod => {
|
||||
let mut stack = self.stack.clone();
|
||||
stack.pop();
|
||||
self.paths.insert(item.def_id, (stack, item_type::Enum));
|
||||
@ -852,41 +887,66 @@ 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
|
||||
}
|
||||
// Private modules may survive the strip-private pass if
|
||||
// they contain impls for public types, but those will get
|
||||
// stripped here
|
||||
clean::Item { inner: clean::ModuleItem(ref m),
|
||||
visibility, .. }
|
||||
if (m.items.len() == 0 &&
|
||||
item.doc_value().is_none()) ||
|
||||
visibility != Some(ast::Public) => None,
|
||||
|
||||
i => Some(i),
|
||||
}
|
||||
@ -941,16 +1001,13 @@ impl Context {
|
||||
///
|
||||
/// This currently isn't parallelized, but it'd be pretty easy to add
|
||||
/// parallelization to this function.
|
||||
fn krate(self, mut krate: clean::Crate, cache: Cache) -> io::IoResult<()> {
|
||||
fn krate(self, mut krate: clean::Crate) -> io::IoResult<()> {
|
||||
let mut item = match krate.module.take() {
|
||||
Some(i) => i,
|
||||
None => return Ok(())
|
||||
};
|
||||
item.name = Some(krate.name);
|
||||
|
||||
// using a rwarc makes this parallelizable in the future
|
||||
cache_key.replace(Some(Arc::new(cache)));
|
||||
|
||||
let mut work = vec!((self, item));
|
||||
loop {
|
||||
match work.pop() {
|
||||
@ -970,7 +1027,7 @@ impl Context {
|
||||
/// The rendering driver uses this closure to queue up more work.
|
||||
fn item(&mut self, item: clean::Item,
|
||||
f: |&mut Context, clean::Item|) -> io::IoResult<()> {
|
||||
fn render(w: io::File, cx: &mut Context, it: &clean::Item,
|
||||
fn render(w: io::File, cx: &Context, it: &clean::Item,
|
||||
pushname: bool) -> io::IoResult<()> {
|
||||
info!("Rendering an item to {}", w.path().display());
|
||||
// A little unfortunate that this is done like this, but it sure
|
||||
@ -997,9 +1054,24 @@ impl Context {
|
||||
// of the pain by using a buffered writer instead of invoking the
|
||||
// write sycall all the time.
|
||||
let mut writer = BufferedWriter::new(w);
|
||||
try!(layout::render(&mut writer as &mut Writer, &cx.layout, &page,
|
||||
&Sidebar{ cx: cx, item: it },
|
||||
&Item{ cx: cx, item: it }));
|
||||
if !cx.render_redirect_pages {
|
||||
try!(layout::render(&mut writer, &cx.layout, &page,
|
||||
&Sidebar{ cx: cx, item: it },
|
||||
&Item{ cx: cx, item: it }));
|
||||
} else {
|
||||
let mut url = "../".repeat(cx.current.len());
|
||||
match cache_key.get().unwrap().paths.find(&it.def_id) {
|
||||
Some(&(ref names, _)) => {
|
||||
for name in names.slice_to(names.len() - 1).iter() {
|
||||
url.push_str(name.as_slice());
|
||||
url.push_str("/");
|
||||
}
|
||||
url.push_str(item_path(it).as_slice());
|
||||
try!(layout::redirect(&mut writer, url.as_slice()));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
writer.flush()
|
||||
}
|
||||
|
||||
@ -1007,6 +1079,17 @@ impl Context {
|
||||
// modules are special because they add a namespace. We also need to
|
||||
// recurse into the items of the module as well.
|
||||
clean::ModuleItem(..) => {
|
||||
// Private modules may survive the strip-private pass if they
|
||||
// contain impls for public types. These modules can also
|
||||
// contain items such as publicly reexported structures.
|
||||
//
|
||||
// External crates will provide links to these structures, so
|
||||
// these modules are recursed into, but not rendered normally (a
|
||||
// flag on the context).
|
||||
if !self.render_redirect_pages {
|
||||
self.render_redirect_pages = ignore_private_module(&item);
|
||||
}
|
||||
|
||||
let name = item.name.get_ref().to_string();
|
||||
let mut item = Some(item);
|
||||
self.recurse(name, |this| {
|
||||
@ -1120,17 +1203,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()));
|
||||
@ -1155,7 +1242,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,
|
||||
@ -1179,6 +1266,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(())
|
||||
}
|
||||
}
|
||||
@ -1234,8 +1322,9 @@ fn document(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
|
||||
fn item_module(w: &mut fmt::Formatter, cx: &Context,
|
||||
item: &clean::Item, items: &[clean::Item]) -> fmt::Result {
|
||||
try!(document(w, item));
|
||||
debug!("{:?}", items);
|
||||
let mut indices = Vec::from_fn(items.len(), |i| i);
|
||||
let mut indices = range(0, items.len()).filter(|i| {
|
||||
!ignore_private_module(&items[*i])
|
||||
}).collect::<Vec<uint>>();
|
||||
|
||||
fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: uint, idx2: uint) -> Ordering {
|
||||
if shortty(i1) == shortty(i2) {
|
||||
@ -1251,6 +1340,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,
|
||||
@ -1275,7 +1366,6 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
|
||||
}
|
||||
}
|
||||
|
||||
debug!("{:?}", indices);
|
||||
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
|
||||
|
||||
debug!("{:?}", indices);
|
||||
@ -1306,6 +1396,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'>\
|
||||
@ -1322,8 +1413,13 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
|
||||
if s.len() == 0 { return Ok(()); }
|
||||
try!(write!(f, "<code> = </code>"));
|
||||
if s.contains("\n") {
|
||||
write!(f, "<a href='{}'>[definition]</a>",
|
||||
item.href())
|
||||
match item.href() {
|
||||
Some(url) => {
|
||||
write!(f, "<a href='{}'>[definition]</a>",
|
||||
url)
|
||||
}
|
||||
None => Ok(()),
|
||||
}
|
||||
} else {
|
||||
write!(f, "<code>{}</code>", s.as_slice())
|
||||
}
|
||||
@ -1473,34 +1569,33 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
try!(write!(w, "</div>"));
|
||||
}
|
||||
|
||||
match cache_key.get().unwrap().implementors.find(&it.def_id) {
|
||||
let cache = cache_key.get().unwrap();
|
||||
try!(write!(w, "
|
||||
<h2 id='implementors'>Implementors</h2>
|
||||
<ul class='item-list' id='implementors-list'>
|
||||
"));
|
||||
match cache.implementors.find(&it.def_id) {
|
||||
Some(implementors) => {
|
||||
try!(write!(w, "
|
||||
<h2 id='implementors'>Implementors</h2>
|
||||
<ul class='item-list' id='implementors-list'>
|
||||
"));
|
||||
for i in implementors.iter() {
|
||||
match *i {
|
||||
PathType(ref ty) => {
|
||||
try!(write!(w, "<li><code>{}</code></li>", *ty));
|
||||
}
|
||||
OtherType(ref generics, ref trait_, ref for_) => {
|
||||
try!(write!(w, "<li><code>impl{} {} for {}</code></li>",
|
||||
*generics, *trait_, *for_));
|
||||
}
|
||||
}
|
||||
try!(writeln!(w, "<li><code>impl{} {} for {}</code></li>",
|
||||
i.generics, i.trait_, i.for_));
|
||||
}
|
||||
try!(write!(w, "</ul>"));
|
||||
try!(write!(w, r#"<script type="text/javascript" async
|
||||
src="{}/implementors/{}/{}.{}.js"></script>"#,
|
||||
cx.current.iter().map(|_| "..")
|
||||
.collect::<Vec<&str>>().connect("/"),
|
||||
cx.current.connect("/"),
|
||||
shortty(it).to_static_str(),
|
||||
*it.name.get_ref()));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
try!(write!(w, "</ul>"));
|
||||
try!(write!(w, r#"<script type="text/javascript" async
|
||||
src="{root_path}/implementors/{path}/{ty}.{name}.js">
|
||||
</script>"#,
|
||||
root_path = Vec::from_elem(cx.current.len(), "..").connect("/"),
|
||||
path = if ast_util::is_local(it.def_id) {
|
||||
cx.current.connect("/")
|
||||
} else {
|
||||
let path = cache.external_paths.get(&it.def_id);
|
||||
path.slice_to(path.len() - 1).connect("/")
|
||||
},
|
||||
ty = shortty(it).to_static_str(),
|
||||
name = *it.name.get_ref()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1879,8 +1974,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{}
|
||||
@ -1911,6 +2009,8 @@ impl<'a> fmt::Show for Sidebar<'a> {
|
||||
fn build_sidebar(m: &clean::Module) -> HashMap<String, Vec<String>> {
|
||||
let mut map = HashMap::new();
|
||||
for item in m.items.iter() {
|
||||
if ignore_private_module(item) { continue }
|
||||
|
||||
let short = shortty(item).to_static_str();
|
||||
let myname = match item.name {
|
||||
None => continue,
|
||||
@ -1951,3 +2051,20 @@ 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)
|
||||
}
|
||||
|
||||
fn ignore_private_module(it: &clean::Item) -> bool {
|
||||
match it.inner {
|
||||
clean::ModuleItem(ref m) => {
|
||||
(m.items.len() == 0 && it.doc_value().is_none()) ||
|
||||
it.visibility != Some(ast::Public)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ 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 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 @@ 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 {
|
||||
|
@ -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 @@ 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;
|
||||
|
@ -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)> )]),
|
||||
|
Loading…
Reference in New Issue
Block a user