auto merge of #13006 : alexcrichton/rust/rollup, r=alexcrichton
Closes #13008 (Made the `clone_from` implementation for `~T` reuse the `T` itself if possible) Closes #13003 (Make method Vec::remove() public) Closes #13002 (disallow duplicate methods in trait impls) Closes #13000 (rustc: test: don't silently ignore bad benches) Closes #12999 (rustc: buffer the output writer for -Z ast-json[-noexpand].) Closes #12993 (syntax: Don't parameterize the the pretty printer) Closes #12990 (`char` reference: s/character/Unicode scalar value/) Closes #12987 (Move syntax-extension-hexfloat.rs) Closes #12983 (Fix linkage1 test which fails due to --as-needed) Closes #12978 (rustc: remove linker_private/linker_private_weak) Closes #12976 (libsyntax: librustdoc: ignore utf-8 BOM in .rs files) Closes #12973 (closes #12967 fix [en|de]coding of HashMap<K,V> where K is a numeric type) Closes #12972 (Add impl IntoStr for ::std::vec_ng::Vec<Ascii>) Closes #12968 (deny missing docs getopts) Closes #12965 (Documentation and formatting changes for option.rs.) Closes #12962 (Relax the memory ordering on the implementation of UnsafeArc) Closes #12958 (Typo fixes.) Closes #12950 (Docsprint: Document ops module, primarily Deref.) Closes #12946 (rustdoc: Implement cross-crate searching)
This commit is contained in:
commit
87e72c3812
@ -3136,8 +3136,12 @@ machine.
|
||||
|
||||
The types `char` and `str` hold textual data.
|
||||
|
||||
A value of type `char` is a Unicode character,
|
||||
represented as a 32-bit unsigned word holding a UCS-4 codepoint.
|
||||
A value of type `char` is a [Unicode scalar value](
|
||||
http://www.unicode.org/glossary/#unicode_scalar_value)
|
||||
(ie. a code point that is not a surrogate),
|
||||
represented as a 32-bit unsigned word in the 0x0000 to 0xD7FF
|
||||
or 0xE000 to 0x10FFFF range.
|
||||
A `[char]` vector is effectively an UCS-4 / UTF-32 string.
|
||||
|
||||
A value of type `str` is a Unicode string,
|
||||
represented as a vector of 8-bit unsigned bytes holding a sequence of UTF-8 codepoints.
|
||||
|
@ -43,7 +43,7 @@ pub fn recalibrate() {
|
||||
Doc comments are markdown, and are currently parsed with the
|
||||
[sundown][sundown] library. rustdoc does not yet do any fanciness such as
|
||||
referencing other items inline, like javadoc's `@see`. One exception to this
|
||||
is that the first paragrah will be used as the "summary" of an item in the
|
||||
is that the first paragraph will be used as the "summary" of an item in the
|
||||
generated documentation:
|
||||
|
||||
~~~
|
||||
@ -79,11 +79,11 @@ rustdoc can also generate JSON, for consumption by other tools, with
|
||||
|
||||
# Using the Documentation
|
||||
|
||||
The web pages generated by rustdoc present the same logical heirarchy that one
|
||||
The web pages generated by rustdoc present the same logical hierarchy that one
|
||||
writes a library with. Every kind of item (function, struct, etc) has its own
|
||||
color, and one can always click on a colored type to jump to its
|
||||
documentation. There is a search bar at the top, which is powered by some
|
||||
javascript and a statically-generated search index. No special web server is
|
||||
JavaScript and a statically-generated search index. No special web server is
|
||||
required for the search.
|
||||
|
||||
[sundown]: https://github.com/vmg/sundown/
|
||||
@ -108,7 +108,7 @@ code, the `ignore` string can be added to the three-backtick form of markdown
|
||||
code block.
|
||||
|
||||
/**
|
||||
# nested codefences confuse sundown => indentation + comment to
|
||||
# nested code fences confuse sundown => indentation + comment to
|
||||
# avoid failing tests
|
||||
```
|
||||
// This is a testable code block
|
||||
@ -126,7 +126,7 @@ You can specify that the test's execution should fail with the `should_fail`
|
||||
directive.
|
||||
|
||||
/**
|
||||
# nested codefences confuse sundown => indentation + comment to
|
||||
# nested code fences confuse sundown => indentation + comment to
|
||||
# avoid failing tests
|
||||
```should_fail
|
||||
// This code block is expected to generate a failure when run
|
||||
@ -138,7 +138,7 @@ You can specify that the code block should be compiled but not run with the
|
||||
`no_run` directive.
|
||||
|
||||
/**
|
||||
# nested codefences confuse sundown => indentation + comment to
|
||||
# nested code fences confuse sundown => indentation + comment to
|
||||
# avoid failing tests
|
||||
```no_run
|
||||
// This code will be compiled but not executed
|
||||
@ -153,7 +153,7 @@ testing the code block (NB. the space after the `#` is required, so
|
||||
that one can still write things like `#[deriving(Eq)]`).
|
||||
|
||||
/**
|
||||
# nested codefences confuse sundown => indentation + comment to
|
||||
# nested code fences confuse sundown => indentation + comment to
|
||||
# avoid failing tests
|
||||
```rust
|
||||
# /!\ The three following lines are comments, which are usually stripped off by
|
||||
@ -162,7 +162,7 @@ that one can still write things like `#[deriving(Eq)]`).
|
||||
# these first five lines but a non breakable one.
|
||||
#
|
||||
# // showing 'fib' in this documentation would just be tedious and detracts from
|
||||
# // what's actualy being documented.
|
||||
# // what's actually being documented.
|
||||
# fn fib(n: int) { n + 2 }
|
||||
|
||||
do spawn { fib(200); }
|
||||
@ -190,7 +190,7 @@ $ rustdoc --test lib.rs --test-args '--help'
|
||||
~~~
|
||||
|
||||
When testing a library, code examples will often show how functions are used,
|
||||
and this code often requires `use`-ing paths from the crate. To accomodate this,
|
||||
and this code often requires `use`-ing paths from the crate. To accommodate this,
|
||||
rustdoc will implicitly add `extern crate <crate>;` where `<crate>` is the name of
|
||||
the crate being tested to the top of each code example. This means that rustdoc
|
||||
must be able to find a compiled version of the library crate being tested. Extra
|
||||
|
@ -83,7 +83,7 @@
|
||||
#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://static.rust-lang.org/doc/master")];
|
||||
#[allow(missing_doc)];
|
||||
#[deny(missing_doc)];
|
||||
#[allow(deprecated_owned_vector)];
|
||||
|
||||
#[feature(globs, phase)];
|
||||
|
@ -186,7 +186,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
|
||||
});
|
||||
|
||||
if sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0 {
|
||||
let mut stdout = io::stdout();
|
||||
let mut stdout = io::BufferedWriter::new(io::stdout());
|
||||
let mut json = json::PrettyEncoder::new(&mut stdout);
|
||||
krate.encode(&mut json);
|
||||
}
|
||||
@ -261,7 +261,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||
front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate));
|
||||
|
||||
if sess.opts.debugging_opts & session::AST_JSON != 0 {
|
||||
let mut stdout = io::stdout();
|
||||
let mut stdout = io::BufferedWriter::new(io::stdout());
|
||||
let mut json = json::PrettyEncoder::new(&mut stdout);
|
||||
krate.encode(&mut json);
|
||||
}
|
||||
@ -596,7 +596,7 @@ struct IdentifiedAnnotation;
|
||||
|
||||
impl pprust::PpAnn for IdentifiedAnnotation {
|
||||
fn pre(&self,
|
||||
s: &mut pprust::State<IdentifiedAnnotation>,
|
||||
s: &mut pprust::State,
|
||||
node: pprust::AnnNode) -> io::IoResult<()> {
|
||||
match node {
|
||||
pprust::NodeExpr(_) => s.popen(),
|
||||
@ -604,7 +604,7 @@ impl pprust::PpAnn for IdentifiedAnnotation {
|
||||
}
|
||||
}
|
||||
fn post(&self,
|
||||
s: &mut pprust::State<IdentifiedAnnotation>,
|
||||
s: &mut pprust::State,
|
||||
node: pprust::AnnNode) -> io::IoResult<()> {
|
||||
match node {
|
||||
pprust::NodeItem(item) => {
|
||||
@ -634,7 +634,7 @@ struct TypedAnnotation {
|
||||
|
||||
impl pprust::PpAnn for TypedAnnotation {
|
||||
fn pre(&self,
|
||||
s: &mut pprust::State<TypedAnnotation>,
|
||||
s: &mut pprust::State,
|
||||
node: pprust::AnnNode) -> io::IoResult<()> {
|
||||
match node {
|
||||
pprust::NodeExpr(_) => s.popen(),
|
||||
@ -642,7 +642,7 @@ impl pprust::PpAnn for TypedAnnotation {
|
||||
}
|
||||
}
|
||||
fn post(&self,
|
||||
s: &mut pprust::State<TypedAnnotation>,
|
||||
s: &mut pprust::State,
|
||||
node: pprust::AnnNode) -> io::IoResult<()> {
|
||||
let tcx = &self.analysis.ty_cx;
|
||||
match node {
|
||||
|
@ -95,10 +95,9 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
|
||||
debug!("current path: {}",
|
||||
ast_util::path_name_i(self.cx.path.get().as_slice()));
|
||||
|
||||
if is_test_fn(&self.cx, i) || is_bench_fn(i) {
|
||||
if is_test_fn(&self.cx, i) || is_bench_fn(&self.cx, i) {
|
||||
match i.node {
|
||||
ast::ItemFn(_, purity, _, _, _)
|
||||
if purity == ast::UnsafeFn => {
|
||||
ast::ItemFn(_, ast::UnsafeFn, _, _, _) => {
|
||||
let sess = self.cx.sess;
|
||||
sess.span_fatal(i.span,
|
||||
"unsafe functions cannot be used for \
|
||||
@ -109,7 +108,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
|
||||
let test = Test {
|
||||
span: i.span,
|
||||
path: self.cx.path.get(),
|
||||
bench: is_bench_fn(i),
|
||||
bench: is_bench_fn(&self.cx, i),
|
||||
ignore: is_ignored(&self.cx, i),
|
||||
should_fail: should_fail(i)
|
||||
};
|
||||
@ -233,7 +232,7 @@ fn is_test_fn(cx: &TestCtxt, i: @ast::Item) -> bool {
|
||||
return has_test_attr && has_test_signature(i);
|
||||
}
|
||||
|
||||
fn is_bench_fn(i: @ast::Item) -> bool {
|
||||
fn is_bench_fn(cx: &TestCtxt, i: @ast::Item) -> bool {
|
||||
let has_bench_attr = attr::contains_name(i.attrs.as_slice(), "bench");
|
||||
|
||||
fn has_test_signature(i: @ast::Item) -> bool {
|
||||
@ -254,6 +253,12 @@ fn is_bench_fn(i: @ast::Item) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
if has_bench_attr && !has_test_signature(i) {
|
||||
let sess = cx.sess;
|
||||
sess.span_err(i.span, "functions used as benches must have signature \
|
||||
`fn(&mut BenchHarness) -> ()`");
|
||||
}
|
||||
|
||||
return has_bench_attr && has_test_signature(i);
|
||||
}
|
||||
|
||||
|
@ -43,24 +43,22 @@ pub enum Visibility {
|
||||
ProtectedVisibility = 2,
|
||||
}
|
||||
|
||||
// This enum omits the obsolete (and no-op) linkage types DLLImportLinkage,
|
||||
// DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage.
|
||||
// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
|
||||
// they've been removed in upstream LLVM commit r203866.
|
||||
pub enum Linkage {
|
||||
ExternalLinkage = 0,
|
||||
AvailableExternallyLinkage = 1,
|
||||
LinkOnceAnyLinkage = 2,
|
||||
LinkOnceODRLinkage = 3,
|
||||
LinkOnceODRAutoHideLinkage = 4,
|
||||
WeakAnyLinkage = 5,
|
||||
WeakODRLinkage = 6,
|
||||
AppendingLinkage = 7,
|
||||
InternalLinkage = 8,
|
||||
PrivateLinkage = 9,
|
||||
DLLImportLinkage = 10,
|
||||
DLLExportLinkage = 11,
|
||||
ExternalWeakLinkage = 12,
|
||||
GhostLinkage = 13,
|
||||
CommonLinkage = 14,
|
||||
LinkerPrivateLinkage = 15,
|
||||
LinkerPrivateWeakLinkage = 16,
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
|
@ -85,7 +85,7 @@ struct LoopScope<'a> {
|
||||
|
||||
impl<'a, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, O> {
|
||||
fn pre(&self,
|
||||
ps: &mut pprust::State<DataFlowContext<'a, O>>,
|
||||
ps: &mut pprust::State,
|
||||
node: pprust::AnnNode) -> io::IoResult<()> {
|
||||
let id = match node {
|
||||
pprust::NodeExpr(expr) => expr.id,
|
||||
|
@ -121,8 +121,6 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
|
||||
"extern_weak" => Some(lib::llvm::ExternalWeakLinkage),
|
||||
"external" => Some(lib::llvm::ExternalLinkage),
|
||||
"internal" => Some(lib::llvm::InternalLinkage),
|
||||
"linker_private" => Some(lib::llvm::LinkerPrivateLinkage),
|
||||
"linker_private_weak" => Some(lib::llvm::LinkerPrivateWeakLinkage),
|
||||
"linkonce" => Some(lib::llvm::LinkOnceAnyLinkage),
|
||||
"linkonce_odr" => Some(lib::llvm::LinkOnceODRLinkage),
|
||||
"private" => Some(lib::llvm::PrivateLinkage),
|
||||
|
@ -48,6 +48,8 @@ use util::ppaux::Repr;
|
||||
use std::rc::Rc;
|
||||
use std::vec_ng::Vec;
|
||||
use std::vec_ng;
|
||||
use collections::HashSet;
|
||||
|
||||
use syntax::abi::AbiSet;
|
||||
use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
|
||||
use syntax::ast;
|
||||
@ -478,7 +480,12 @@ fn convert_methods(ccx: &CrateCtxt,
|
||||
rcvr_visibility: ast::Visibility)
|
||||
{
|
||||
let tcx = ccx.tcx;
|
||||
let mut seen_methods = HashSet::new();
|
||||
for m in ms.iter() {
|
||||
if !seen_methods.insert(m.ident.repr(ccx.tcx)) {
|
||||
tcx.sess.span_err(m.span, "duplicate method in trait impl");
|
||||
}
|
||||
|
||||
let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
|
||||
let m_ty_generics = ty_generics_for_fn_or_method(ccx, &m.generics,
|
||||
num_rcvr_ty_params);
|
||||
|
191
src/librustdoc/flock.rs
Normal file
191
src/librustdoc/flock.rs
Normal file
@ -0,0 +1,191 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Simple file-locking apis for each OS.
|
||||
//!
|
||||
//! This is not meant to be in the standard library, it does nothing with
|
||||
//! green/native threading. This is just a bare-bones enough solution for
|
||||
//! librustdoc, it is not production quality at all.
|
||||
|
||||
#[allow(non_camel_case_types)];
|
||||
|
||||
pub use self::imp::Lock;
|
||||
|
||||
#[cfg(unix)]
|
||||
mod imp {
|
||||
use std::libc;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
mod os {
|
||||
use std::libc;
|
||||
|
||||
pub struct flock {
|
||||
l_type: libc::c_short,
|
||||
l_whence: libc::c_short,
|
||||
l_start: libc::off_t,
|
||||
l_len: libc::off_t,
|
||||
l_pid: libc::pid_t,
|
||||
|
||||
// not actually here, but brings in line with freebsd
|
||||
l_sysid: libc::c_int,
|
||||
}
|
||||
|
||||
pub static F_WRLCK: libc::c_short = 1;
|
||||
pub static F_UNLCK: libc::c_short = 2;
|
||||
pub static F_SETLK: libc::c_int = 6;
|
||||
pub static F_SETLKW: libc::c_int = 7;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
mod os {
|
||||
use std::libc;
|
||||
|
||||
pub struct flock {
|
||||
l_start: libc::off_t,
|
||||
l_len: libc::off_t,
|
||||
l_pid: libc::pid_t,
|
||||
l_type: libc::c_short,
|
||||
l_whence: libc::c_short,
|
||||
l_sysid: libc::c_int,
|
||||
}
|
||||
|
||||
pub static F_UNLCK: libc::c_short = 2;
|
||||
pub static F_WRLCK: libc::c_short = 3;
|
||||
pub static F_SETLK: libc::c_int = 12;
|
||||
pub static F_SETLKW: libc::c_int = 13;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
mod os {
|
||||
use std::libc;
|
||||
|
||||
pub struct flock {
|
||||
l_start: libc::off_t,
|
||||
l_len: libc::off_t,
|
||||
l_pid: libc::pid_t,
|
||||
l_type: libc::c_short,
|
||||
l_whence: libc::c_short,
|
||||
|
||||
// not actually here, but brings in line with freebsd
|
||||
l_sysid: libc::c_int,
|
||||
}
|
||||
|
||||
pub static F_UNLCK: libc::c_short = 2;
|
||||
pub static F_WRLCK: libc::c_short = 3;
|
||||
pub static F_SETLK: libc::c_int = 8;
|
||||
pub static F_SETLKW: libc::c_int = 9;
|
||||
}
|
||||
|
||||
pub struct Lock {
|
||||
priv fd: libc::c_int,
|
||||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path) -> Lock {
|
||||
let fd = p.with_c_str(|s| unsafe {
|
||||
libc::open(s, libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU)
|
||||
});
|
||||
assert!(fd > 0);
|
||||
let flock = os::flock {
|
||||
l_start: 0,
|
||||
l_len: 0,
|
||||
l_pid: 0,
|
||||
l_whence: libc::SEEK_SET as libc::c_short,
|
||||
l_type: os::F_WRLCK,
|
||||
l_sysid: 0,
|
||||
};
|
||||
let ret = unsafe {
|
||||
libc::fcntl(fd, os::F_SETLKW, &flock as *os::flock)
|
||||
};
|
||||
if ret == -1 {
|
||||
unsafe { libc::close(fd); }
|
||||
fail!("could not lock `{}`", p.display())
|
||||
}
|
||||
Lock { fd: fd }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Lock {
|
||||
fn drop(&mut self) {
|
||||
let flock = os::flock {
|
||||
l_start: 0,
|
||||
l_len: 0,
|
||||
l_pid: 0,
|
||||
l_whence: libc::SEEK_SET as libc::c_short,
|
||||
l_type: os::F_UNLCK,
|
||||
l_sysid: 0,
|
||||
};
|
||||
unsafe {
|
||||
libc::fcntl(self.fd, os::F_SETLK, &flock as *os::flock);
|
||||
libc::close(self.fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
mod imp {
|
||||
use std::libc;
|
||||
use std::mem;
|
||||
use std::os::win32::as_utf16_p;
|
||||
use std::ptr;
|
||||
|
||||
static LOCKFILE_EXCLUSIVE_LOCK: libc::DWORD = 0x00000002;
|
||||
|
||||
extern "system" {
|
||||
fn LockFileEx(hFile: libc::HANDLE,
|
||||
dwFlags: libc::DWORD,
|
||||
dwReserved: libc::DWORD,
|
||||
nNumberOfBytesToLockLow: libc::DWORD,
|
||||
nNumberOfBytesToLockHigh: libc::DWORD,
|
||||
lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL;
|
||||
fn UnlockFileEx(hFile: libc::HANDLE,
|
||||
dwReserved: libc::DWORD,
|
||||
nNumberOfBytesToLockLow: libc::DWORD,
|
||||
nNumberOfBytesToLockHigh: libc::DWORD,
|
||||
lpOverlapped: libc::LPOVERLAPPED) -> libc::BOOL;
|
||||
}
|
||||
|
||||
pub struct Lock {
|
||||
priv handle: libc::HANDLE,
|
||||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path) -> Lock {
|
||||
let handle = as_utf16_p(p.as_str().unwrap(), |p| unsafe {
|
||||
libc::CreateFileW(p, libc::GENERIC_READ, 0, ptr::mut_null(),
|
||||
libc::CREATE_ALWAYS,
|
||||
libc::FILE_ATTRIBUTE_NORMAL,
|
||||
ptr::mut_null())
|
||||
});
|
||||
assert!(handle as uint != libc::INVALID_HANDLE_VALUE as uint);
|
||||
let mut overlapped: libc::OVERLAPPED = unsafe { mem::init() };
|
||||
let ret = unsafe {
|
||||
LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0,
|
||||
&mut overlapped)
|
||||
};
|
||||
if ret == 0 {
|
||||
unsafe { libc::CloseHandle(handle); }
|
||||
fail!("could not lock `{}`", p.display())
|
||||
}
|
||||
Lock { handle: handle }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Lock {
|
||||
fn drop(&mut self) {
|
||||
let mut overlapped: libc::OVERLAPPED = unsafe { mem::init() };
|
||||
unsafe {
|
||||
UnlockFileEx(self.handle, 0, 100, 0, &mut overlapped);
|
||||
libc::CloseHandle(self.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ pub fn render<T: fmt::Show, S: fmt::Show>(
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Oswald:700|Inconsolata:400,700'
|
||||
rel='stylesheet' type='text/css'>
|
||||
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}{krate}/main.css\">
|
||||
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}main.css\">
|
||||
|
||||
{favicon, select, none{} other{<link rel=\"shortcut icon\" href=\"#\" />}}
|
||||
</head>
|
||||
@ -74,13 +74,6 @@ pub fn render<T: fmt::Show, S: fmt::Show>(
|
||||
|
||||
<section class=\"footer\"></section>
|
||||
|
||||
<script>
|
||||
var rootPath = \"{root_path}\";
|
||||
</script>
|
||||
<script src=\"{root_path}{krate}/jquery.js\"></script>
|
||||
<script src=\"{root_path}{krate}/search-index.js\"></script>
|
||||
<script src=\"{root_path}{krate}/main.js\"></script>
|
||||
|
||||
<div id=\"help\" class=\"hidden\">
|
||||
<div class=\"shortcuts\">
|
||||
<h1>Keyboard shortcuts</h1>
|
||||
@ -111,6 +104,14 @@ pub fn render<T: fmt::Show, S: fmt::Show>(
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var rootPath = \"{root_path}\";
|
||||
var currentCrate = \"{krate}\";
|
||||
</script>
|
||||
<script src=\"{root_path}jquery.js\"></script>
|
||||
<script src=\"{root_path}main.js\"></script>
|
||||
<script async src=\"{root_path}search-index.js\"></script>
|
||||
</body>
|
||||
</html>
|
||||
",
|
||||
|
@ -36,7 +36,7 @@
|
||||
use std::fmt;
|
||||
use std::local_data;
|
||||
use std::io;
|
||||
use std::io::{fs, File, BufferedWriter};
|
||||
use std::io::{fs, File, BufferedWriter, MemWriter, BufferedReader};
|
||||
use std::str;
|
||||
use std::vec;
|
||||
use std::vec_ng::Vec;
|
||||
@ -283,48 +283,75 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
|
||||
};
|
||||
}
|
||||
|
||||
// Add all the static files
|
||||
let mut dst = cx.dst.join(krate.name.as_slice());
|
||||
try!(mkdir(&dst));
|
||||
try!(write(dst.join("jquery.js"),
|
||||
include_str!("static/jquery-2.1.0.min.js")));
|
||||
try!(write(dst.join("main.js"), include_str!("static/main.js")));
|
||||
try!(write(dst.join("main.css"), include_str!("static/main.css")));
|
||||
try!(write(dst.join("normalize.css"),
|
||||
include_str!("static/normalize.css")));
|
||||
|
||||
// Publish the search index
|
||||
{
|
||||
dst.push("search-index.js");
|
||||
let mut w = BufferedWriter::new(File::create(&dst).unwrap());
|
||||
let w = &mut w as &mut Writer;
|
||||
try!(write!(w, "var searchIndex = ["));
|
||||
let index = {
|
||||
let mut w = MemWriter::new();
|
||||
try!(write!(&mut w, "searchIndex['{}'] = [", krate.name));
|
||||
for (i, item) in cache.search_index.iter().enumerate() {
|
||||
if i > 0 {
|
||||
try!(write!(w, ","));
|
||||
try!(write!(&mut w, ","));
|
||||
}
|
||||
try!(write!(w, "\\{ty:\"{}\",name:\"{}\",path:\"{}\",desc:{}",
|
||||
item.ty, item.name, item.path,
|
||||
item.desc.to_json().to_str()));
|
||||
try!(write!(&mut w, "\\{ty:\"{}\",name:\"{}\",path:\"{}\",desc:{}",
|
||||
item.ty, item.name, item.path,
|
||||
item.desc.to_json().to_str()));
|
||||
match item.parent {
|
||||
Some(id) => {
|
||||
try!(write!(w, ",parent:'{}'", id));
|
||||
try!(write!(&mut w, ",parent:'{}'", id));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
try!(write!(w, "\\}"));
|
||||
try!(write!(&mut w, "\\}"));
|
||||
}
|
||||
try!(write!(w, "];"));
|
||||
try!(write!(w, "var allPaths = \\{"));
|
||||
try!(write!(&mut w, "];"));
|
||||
try!(write!(&mut w, "allPaths['{}'] = \\{", krate.name));
|
||||
for (i, (&id, &(ref fqp, short))) in cache.paths.iter().enumerate() {
|
||||
if i > 0 {
|
||||
try!(write!(w, ","));
|
||||
try!(write!(&mut w, ","));
|
||||
}
|
||||
try!(write!(w, "'{}':\\{type:'{}',name:'{}'\\}",
|
||||
id, short, *fqp.last().unwrap()));
|
||||
try!(write!(&mut w, "'{}':\\{type:'{}',name:'{}'\\}",
|
||||
id, short, *fqp.last().unwrap()));
|
||||
}
|
||||
try!(write!(w, "\\};"));
|
||||
try!(w.flush());
|
||||
try!(write!(&mut w, "\\};"));
|
||||
|
||||
str::from_utf8_owned(w.unwrap()).unwrap()
|
||||
};
|
||||
|
||||
// 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"));
|
||||
|
||||
// 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_str!("static/jquery-2.1.0.min.js")));
|
||||
try!(write(cx.dst.join("main.js"), include_str!("static/main.js")));
|
||||
try!(write(cx.dst.join("main.css"), include_str!("static/main.css")));
|
||||
try!(write(cx.dst.join("normalize.css"),
|
||||
include_str!("static/normalize.css")));
|
||||
|
||||
// Update the search index
|
||||
let dst = cx.dst.join("search-index.js");
|
||||
let mut all_indexes = Vec::new();
|
||||
all_indexes.push(index);
|
||||
if dst.exists() {
|
||||
for line in BufferedReader::new(File::open(&dst)).lines() {
|
||||
let line = try!(line);
|
||||
if !line.starts_with("searchIndex") { continue }
|
||||
if line.starts_with(format!("searchIndex['{}']", krate.name)) {
|
||||
continue
|
||||
}
|
||||
all_indexes.push(line);
|
||||
}
|
||||
}
|
||||
let mut w = try!(File::create(&dst));
|
||||
try!(writeln!(&mut w, r"var searchIndex = \{\}; var allPaths = \{\};"));
|
||||
for index in all_indexes.iter() {
|
||||
try!(writeln!(&mut w, "{}", *index));
|
||||
}
|
||||
try!(writeln!(&mut w, "initSearch(searchIndex);"));
|
||||
}
|
||||
|
||||
// Render all source files (this may turn into a giant no-op)
|
||||
@ -463,6 +490,13 @@ impl<'a> SourceCollector<'a> {
|
||||
};
|
||||
let contents = str::from_utf8_owned(contents).unwrap();
|
||||
|
||||
// Remove the utf-8 BOM if any
|
||||
let contents = if contents.starts_with("\ufeff") {
|
||||
contents.as_slice().slice_from(3)
|
||||
} else {
|
||||
contents.as_slice()
|
||||
};
|
||||
|
||||
// Create the intermediate directories
|
||||
let mut cur = self.dst.clone();
|
||||
let mut root_path = ~"../../";
|
||||
@ -482,7 +516,7 @@ impl<'a> SourceCollector<'a> {
|
||||
root_path: root_path,
|
||||
};
|
||||
try!(layout::render(&mut w as &mut Writer, &self.cx.layout,
|
||||
&page, &(""), &Source(contents.as_slice())));
|
||||
&page, &(""), &Source(contents)));
|
||||
try!(w.flush());
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
/*jslint browser: true, es5: true */
|
||||
/*globals $: true, searchIndex: true, rootPath: true, allPaths: true */
|
||||
/*globals $: true, rootPath: true, allPaths: true */
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
@ -23,7 +23,8 @@
|
||||
map(function(s) {
|
||||
var pair = s.split("=");
|
||||
params[decodeURIComponent(pair[0])] =
|
||||
typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
|
||||
typeof pair[1] === "undefined" ?
|
||||
null : decodeURIComponent(pair[1]);
|
||||
});
|
||||
return params;
|
||||
}
|
||||
@ -111,8 +112,9 @@
|
||||
document.location.href = url;
|
||||
});
|
||||
|
||||
function initSearch(searchIndex) {
|
||||
var currentResults, index, params = getQueryStringParams();
|
||||
function initSearch(rawSearchIndex) {
|
||||
var currentResults, index, searchIndex;
|
||||
var params = getQueryStringParams();
|
||||
|
||||
// Populate search bar with query string search term when provided,
|
||||
// but only if the input bar is empty. This avoid the obnoxious issue
|
||||
@ -126,7 +128,8 @@
|
||||
* Executes the query and builds an index of results
|
||||
* @param {[Object]} query [The user query]
|
||||
* @param {[type]} max [The maximum results returned]
|
||||
* @param {[type]} searchWords [The list of search words to query against]
|
||||
* @param {[type]} searchWords [The list of search words to query
|
||||
* against]
|
||||
* @return {[type]} [A search index of results]
|
||||
*/
|
||||
function execQuery(query, max, searchWords) {
|
||||
@ -148,7 +151,9 @@
|
||||
|
||||
// quoted values mean literal search
|
||||
bb = searchWords.length;
|
||||
if ((val.charAt(0) === "\"" || val.charAt(0) === "'") && val.charAt(val.length - 1) === val.charAt(0)) {
|
||||
if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
|
||||
val.charAt(val.length - 1) === val.charAt(0))
|
||||
{
|
||||
val = val.substr(1, val.length - 2);
|
||||
for (aa = 0; aa < bb; aa += 1) {
|
||||
if (searchWords[aa] === val) {
|
||||
@ -166,7 +171,10 @@
|
||||
val = val.replace(/\_/g, "");
|
||||
for (var i = 0; i < split.length; i++) {
|
||||
for (aa = 0; aa < bb; aa += 1) {
|
||||
if (searchWords[aa].indexOf(split[i]) > -1 || searchWords[aa].indexOf(val) > -1 || searchWords[aa].replace(/_/g, "").indexOf(val) > -1) {
|
||||
if (searchWords[aa].indexOf(split[i]) > -1 ||
|
||||
searchWords[aa].indexOf(val) > -1 ||
|
||||
searchWords[aa].replace(/_/g, "").indexOf(val) > -1)
|
||||
{
|
||||
// filter type: ... queries
|
||||
if (!typeFilter || typeFilter === searchIndex[aa].ty) {
|
||||
results.push([aa, searchWords[aa].replace(/_/g, "").indexOf(val)]);
|
||||
@ -185,6 +193,7 @@
|
||||
results[aa].push(searchIndex[results[aa][0]].path);
|
||||
results[aa].push(searchIndex[results[aa][0]].name);
|
||||
results[aa].push(searchIndex[results[aa][0]].parent);
|
||||
results[aa].push(searchIndex[results[aa][0]].crate);
|
||||
}
|
||||
// if there are no results then return to default and fail
|
||||
if (results.length === 0) {
|
||||
@ -193,7 +202,8 @@
|
||||
|
||||
// sort by exact match
|
||||
results.sort(function search_complete_sort0(aaa, bbb) {
|
||||
if (searchWords[aaa[0]] === valLower && searchWords[bbb[0]] !== valLower) {
|
||||
if (searchWords[aaa[0]] === valLower &&
|
||||
searchWords[bbb[0]] !== valLower) {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
@ -207,7 +217,8 @@
|
||||
// second sorting attempt
|
||||
// sort by item name
|
||||
results.sort(function search_complete_sort1(aaa, bbb) {
|
||||
if (searchWords[aaa[0]].length === searchWords[bbb[0]].length && searchWords[aaa[0]] > searchWords[bbb[0]]) {
|
||||
if (searchWords[aaa[0]].length === searchWords[bbb[0]].length &&
|
||||
searchWords[aaa[0]] > searchWords[bbb[0]]) {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
@ -223,21 +234,26 @@
|
||||
// fourth sorting attempt
|
||||
// sort by type
|
||||
results.sort(function search_complete_sort3(aaa, bbb) {
|
||||
if (searchWords[aaa[0]] === searchWords[bbb[0]] && aaa[2] > bbb[2]) {
|
||||
if (searchWords[aaa[0]] === searchWords[bbb[0]] &&
|
||||
aaa[2] > bbb[2]) {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
// fifth sorting attempt
|
||||
// sort by path
|
||||
results.sort(function search_complete_sort4(aaa, bbb) {
|
||||
if (searchWords[aaa[0]] === searchWords[bbb[0]] && aaa[2] === bbb[2] && aaa[3] > bbb[3]) {
|
||||
if (searchWords[aaa[0]] === searchWords[bbb[0]] &&
|
||||
aaa[2] === bbb[2] && aaa[3] > bbb[3]) {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
// sixth sorting attempt
|
||||
// remove duplicates, according to the data provided
|
||||
for (aa = results.length - 1; aa > 0; aa -= 1) {
|
||||
if (searchWords[results[aa][0]] === searchWords[results[aa - 1][0]] && results[aa][2] === results[aa - 1][2] && results[aa][3] === results[aa - 1][3]) {
|
||||
if (searchWords[results[aa][0]] === searchWords[results[aa - 1][0]] &&
|
||||
results[aa][2] === results[aa - 1][2] &&
|
||||
results[aa][3] === results[aa - 1][3])
|
||||
{
|
||||
results[aa][0] = -1;
|
||||
}
|
||||
}
|
||||
@ -245,7 +261,7 @@
|
||||
var result = results[i],
|
||||
name = result[4].toLowerCase(),
|
||||
path = result[3].toLowerCase(),
|
||||
parent = allPaths[result[5]];
|
||||
parent = allPaths[result[6]][result[5]];
|
||||
|
||||
var valid = validateResult(name, path, split, parent);
|
||||
if (!valid) {
|
||||
@ -256,11 +272,14 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate performs the following boolean logic. For example: "File::open" will give
|
||||
* IF A PARENT EXISTS => ("file" && "open") exists in (name || path || parent)
|
||||
* OR => ("file" && "open") exists in (name || path )
|
||||
* Validate performs the following boolean logic. For example:
|
||||
* "File::open" will give IF A PARENT EXISTS => ("file" && "open")
|
||||
* exists in (name || path || parent) OR => ("file" && "open") exists in
|
||||
* (name || path )
|
||||
*
|
||||
* This could be written functionally, but I wanted to minimise
|
||||
* functions on stack.
|
||||
*
|
||||
* This could be written functionally, but I wanted to minimise functions on stack.
|
||||
* @param {[string]} name [The name of the result]
|
||||
* @param {[string]} path [The path of the result]
|
||||
* @param {[string]} keys [The keys to be used (["file", "open"])]
|
||||
@ -273,8 +292,13 @@
|
||||
//if there is a parent, then validate against parent
|
||||
if (parent !== undefined) {
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
// if previous keys are valid and current key is in the path, name or parent
|
||||
if ((validate) && (name.toLowerCase().indexOf(keys[i]) > -1 || path.toLowerCase().indexOf(keys[i]) > -1 || parent.name.toLowerCase().indexOf(keys[i]) > -1)) {
|
||||
// if previous keys are valid and current key is in the
|
||||
// path, name or parent
|
||||
if ((validate) &&
|
||||
(name.toLowerCase().indexOf(keys[i]) > -1 ||
|
||||
path.toLowerCase().indexOf(keys[i]) > -1 ||
|
||||
parent.name.toLowerCase().indexOf(keys[i]) > -1))
|
||||
{
|
||||
validate = true;
|
||||
} else {
|
||||
validate = false;
|
||||
@ -282,8 +306,12 @@
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
// if previous keys are valid and current key is in the path, name
|
||||
if ((validate) && (name.toLowerCase().indexOf(keys[i]) > -1 || path.toLowerCase().indexOf(keys[i]) > -1)) {
|
||||
// if previous keys are valid and current key is in the
|
||||
// path, name
|
||||
if ((validate) &&
|
||||
(name.toLowerCase().indexOf(keys[i]) > -1 ||
|
||||
path.toLowerCase().indexOf(keys[i]) > -1))
|
||||
{
|
||||
validate = true;
|
||||
} else {
|
||||
validate = false;
|
||||
@ -298,7 +326,10 @@
|
||||
|
||||
matches = query.match(/^(fn|mod|str(uct)?|enum|trait|t(ype)?d(ef)?)\s*:\s*/i);
|
||||
if (matches) {
|
||||
type = matches[1].replace(/^td$/, 'typedef').replace(/^str$/, 'struct').replace(/^tdef$/, 'typedef').replace(/^typed$/, 'typedef');
|
||||
type = matches[1].replace(/^td$/, 'typedef')
|
||||
.replace(/^str$/, 'struct')
|
||||
.replace(/^tdef$/, 'typedef')
|
||||
.replace(/^typed$/, 'typedef');
|
||||
query = query.substring(matches[0].length);
|
||||
}
|
||||
|
||||
@ -314,7 +345,6 @@
|
||||
|
||||
$results.on('click', function() {
|
||||
var dst = $(this).find('a')[0];
|
||||
console.log(window.location.pathname, dst.pathname);
|
||||
if (window.location.pathname == dst.pathname) {
|
||||
$('#search').addClass('hidden');
|
||||
$('#main').removeClass('hidden');
|
||||
@ -362,7 +392,8 @@
|
||||
var output, shown, query = getQuery();
|
||||
|
||||
currentResults = query.id;
|
||||
output = '<h1>Results for ' + query.query + (query.type ? ' (type: ' + query.type + ')' : '') + '</h1>';
|
||||
output = '<h1>Results for ' + query.query +
|
||||
(query.type ? ' (type: ' + query.type + ')' : '') + '</h1>';
|
||||
output += '<table class="search-results">';
|
||||
|
||||
if (results.length > 0) {
|
||||
@ -394,7 +425,7 @@
|
||||
'/index.html" class="' + type +
|
||||
'">' + name + '</a>';
|
||||
} else if (item.parent !== undefined) {
|
||||
var myparent = allPaths[item.parent];
|
||||
var myparent = allPaths[item.crate][item.parent];
|
||||
var anchor = '#' + type + '.' + name;
|
||||
output += item.path + '::' + myparent.name +
|
||||
'::<a href="' + rootPath +
|
||||
@ -449,13 +480,15 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Because searching is incremental by character, only the most recent search query
|
||||
// is added to the browser history.
|
||||
// Because searching is incremental by character, only the most
|
||||
// recent search query is added to the browser history.
|
||||
if (browserSupportsHistoryApi()) {
|
||||
if (!history.state && !params.search) {
|
||||
history.pushState(query, "", "?search=" + encodeURIComponent(query.query));
|
||||
history.pushState(query, "", "?search=" +
|
||||
encodeURIComponent(query.query));
|
||||
} else {
|
||||
history.replaceState(query, "", "?search=" + encodeURIComponent(query.query));
|
||||
history.replaceState(query, "", "?search=" +
|
||||
encodeURIComponent(query.query));
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,91 +505,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add sorting capability through this function?
|
||||
//
|
||||
// // the handler for the table heading filtering
|
||||
// filterdraw = function search_complete_filterdraw(node) {
|
||||
// var name = "",
|
||||
// arrow = "",
|
||||
// op = 0,
|
||||
// tbody = node.parentNode.parentNode.nextSibling,
|
||||
// anchora = {},
|
||||
// tra = {},
|
||||
// tha = {},
|
||||
// td1a = {},
|
||||
// td2a = {},
|
||||
// td3a = {},
|
||||
// aaa = 0,
|
||||
// bbb = 0;
|
||||
//
|
||||
// // the 4 following conditions set the rules for each
|
||||
// // table heading
|
||||
// if (node === ths[0]) {
|
||||
// op = 0;
|
||||
// name = "name";
|
||||
// ths[1].innerHTML = ths[1].innerHTML.split(" ")[0];
|
||||
// ths[2].innerHTML = ths[2].innerHTML.split(" ")[0];
|
||||
// ths[3].innerHTML = ths[3].innerHTML.split(" ")[0];
|
||||
// }
|
||||
// if (node === ths[1]) {
|
||||
// op = 1;
|
||||
// name = "type";
|
||||
// ths[0].innerHTML = ths[0].innerHTML.split(" ")[0];
|
||||
// ths[2].innerHTML = ths[2].innerHTML.split(" ")[0];
|
||||
// ths[3].innerHTML = ths[3].innerHTML.split(" ")[0];
|
||||
// }
|
||||
// if (node === ths[2]) {
|
||||
// op = 2;
|
||||
// name = "path";
|
||||
// ths[0].innerHTML = ths[0].innerHTML.split(" ")[0];
|
||||
// ths[1].innerHTML = ths[1].innerHTML.split(" ")[0];
|
||||
// ths[3].innerHTML = ths[3].innerHTML.split(" ")[0];
|
||||
// }
|
||||
// if (node === ths[3]) {
|
||||
// op = 3;
|
||||
// name = "description";
|
||||
// ths[0].innerHTML = ths[0].innerHTML.split(" ")[0];
|
||||
// ths[1].innerHTML = ths[1].innerHTML.split(" ")[0];
|
||||
// ths[2].innerHTML = ths[2].innerHTML.split(" ")[0];
|
||||
// }
|
||||
//
|
||||
// // ascending or descending search
|
||||
// arrow = node.innerHTML.split(" ")[1];
|
||||
// if (arrow === undefined || arrow === "\u25b2") {
|
||||
// arrow = "\u25bc";
|
||||
// } else {
|
||||
// arrow = "\u25b2";
|
||||
// }
|
||||
//
|
||||
// // filter the data
|
||||
// filterdata.sort(function search_complete_filterDraw_sort(xx, yy) {
|
||||
// if ((arrow === "\u25b2" && xx[op].toLowerCase() < yy[op].toLowerCase()) || (arrow === "\u25bc" && xx[op].toLowerCase() > yy[op].toLowerCase())) {
|
||||
// return 1;
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
|
||||
showResults(results);
|
||||
}
|
||||
|
||||
function buildIndex(searchIndex) {
|
||||
var len = searchIndex.length,
|
||||
i = 0,
|
||||
searchWords = [];
|
||||
function buildIndex(rawSearchIndex) {
|
||||
searchIndex = [];
|
||||
var searchWords = [];
|
||||
for (var crate in rawSearchIndex) {
|
||||
if (!rawSearchIndex.hasOwnProperty(crate)) { continue }
|
||||
var len = rawSearchIndex[crate].length;
|
||||
var i = 0;
|
||||
|
||||
// before any analysis is performed lets gather the search terms to
|
||||
// search against apart from the rest of the data. This is a quick
|
||||
// operation that is cached for the life of the page state so that
|
||||
// all other search operations have access to this cached data for
|
||||
// faster analysis operations
|
||||
for (i = 0; i < len; i += 1) {
|
||||
if (typeof searchIndex[i].name === "string") {
|
||||
searchWords.push(searchIndex[i].name.toLowerCase());
|
||||
} else {
|
||||
searchWords.push("");
|
||||
// before any analysis is performed lets gather the search terms to
|
||||
// search against apart from the rest of the data. This is a quick
|
||||
// operation that is cached for the life of the page state so that
|
||||
// all other search operations have access to this cached data for
|
||||
// faster analysis operations
|
||||
for (i = 0; i < len; i += 1) {
|
||||
rawSearchIndex[crate][i].crate = crate;
|
||||
searchIndex.push(rawSearchIndex[crate][i]);
|
||||
if (typeof rawSearchIndex[crate][i].name === "string") {
|
||||
var word = rawSearchIndex[crate][i].name.toLowerCase();
|
||||
searchWords.push(word);
|
||||
} else {
|
||||
searchWords.push("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return searchWords;
|
||||
}
|
||||
|
||||
@ -567,17 +542,21 @@
|
||||
clearTimeout(keyUpTimeout);
|
||||
keyUpTimeout = setTimeout(search, 100);
|
||||
});
|
||||
// Push and pop states are used to add search results to the browser history.
|
||||
|
||||
// Push and pop states are used to add search results to the browser
|
||||
// history.
|
||||
if (browserSupportsHistoryApi()) {
|
||||
$(window).on('popstate', function(e) {
|
||||
var params = getQueryStringParams();
|
||||
// When browsing back from search results the main page visibility must be reset.
|
||||
// When browsing back from search results the main page
|
||||
// visibility must be reset.
|
||||
if (!params.search) {
|
||||
$('#main.content').removeClass('hidden');
|
||||
$('#search.content').addClass('hidden');
|
||||
}
|
||||
// When browsing forward to search results the previous search will be repeated,
|
||||
// so the currentResults are cleared to ensure the search is successful.
|
||||
// When browsing forward to search results the previous
|
||||
// search will be repeated, so the currentResults are
|
||||
// cleared to ensure the search is successful.
|
||||
currentResults = null;
|
||||
// Synchronize search bar with query string state and
|
||||
// perform the search, but don't empty the bar if there's
|
||||
@ -585,19 +564,46 @@
|
||||
if (params.search !== undefined) {
|
||||
$('.search-input').val(params.search);
|
||||
}
|
||||
// Some browsers fire 'onpopstate' for every page load (Chrome), while others fire the
|
||||
// event only when actually popping a state (Firefox), which is why search() is called
|
||||
// both here and at the end of the startSearch() function.
|
||||
// Some browsers fire 'onpopstate' for every page load
|
||||
// (Chrome), while others fire the event only when actually
|
||||
// popping a state (Firefox), which is why search() is
|
||||
// called both here and at the end of the startSearch()
|
||||
// function.
|
||||
search();
|
||||
});
|
||||
}
|
||||
search();
|
||||
}
|
||||
|
||||
index = buildIndex(searchIndex);
|
||||
index = buildIndex(rawSearchIndex);
|
||||
startSearch();
|
||||
|
||||
// Draw a convenient sidebar of known crates if we have a listing
|
||||
if (rootPath == '../') {
|
||||
console.log('here');
|
||||
var sidebar = $('.sidebar');
|
||||
var div = $('<div>').attr('class', 'block crate');
|
||||
div.append($('<h2>').text('Crates'));
|
||||
|
||||
var crates = [];
|
||||
for (var crate in rawSearchIndex) {
|
||||
if (!rawSearchIndex.hasOwnProperty(crate)) { continue }
|
||||
crates.push(crate);
|
||||
}
|
||||
crates.sort();
|
||||
for (var i = 0; i < crates.length; i++) {
|
||||
var klass = 'crate';
|
||||
if (crates[i] == window.currentCrate) {
|
||||
klass += ' current';
|
||||
}
|
||||
div.append($('<a>', {'href': '../' + crates[i] + '/index.html',
|
||||
'class': klass}).text(crates[i]));
|
||||
div.append($('<br>'));
|
||||
}
|
||||
sidebar.append(div);
|
||||
}
|
||||
}
|
||||
|
||||
initSearch(searchIndex);
|
||||
|
||||
window.initSearch = initSearch;
|
||||
}());
|
||||
|
||||
|
@ -52,6 +52,7 @@ pub mod passes;
|
||||
pub mod plugins;
|
||||
pub mod visit_ast;
|
||||
pub mod test;
|
||||
mod flock;
|
||||
|
||||
pub static SCHEMA_VERSION: &'static str = "0.8.1";
|
||||
|
||||
|
@ -464,8 +464,20 @@ impl<'a> ::Encoder for Encoder<'a> {
|
||||
}
|
||||
|
||||
fn emit_map_elt_key(&mut self, idx: uint, f: |&mut Encoder<'a>|) {
|
||||
use std::str::from_utf8;
|
||||
if idx != 0 { try!(write!(self.wr, ",")) }
|
||||
f(self)
|
||||
// ref #12967, make sure to wrap a key in double quotes,
|
||||
// in the event that its of a type that omits them (eg numbers)
|
||||
let mut buf = MemWriter::new();
|
||||
let mut check_encoder = Encoder::new(&mut buf);
|
||||
f(&mut check_encoder);
|
||||
let buf = buf.unwrap();
|
||||
let out = from_utf8(buf).unwrap();
|
||||
let needs_wrapping = out.char_at(0) != '"' &&
|
||||
out.char_at_reverse(out.len()) != '"';
|
||||
if needs_wrapping { try!(write!(self.wr, "\"")); }
|
||||
f(self);
|
||||
if needs_wrapping { try!(write!(self.wr, "\"")); }
|
||||
}
|
||||
|
||||
fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) {
|
||||
@ -659,13 +671,25 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
|
||||
}
|
||||
|
||||
fn emit_map_elt_key(&mut self, idx: uint, f: |&mut PrettyEncoder<'a>|) {
|
||||
use std::str::from_utf8;
|
||||
if idx == 0 {
|
||||
try!(write!(self.wr, "\n"));
|
||||
} else {
|
||||
try!(write!(self.wr, ",\n"));
|
||||
}
|
||||
try!(write!(self.wr, "{}", spaces(self.indent)));
|
||||
// ref #12967, make sure to wrap a key in double quotes,
|
||||
// in the event that its of a type that omits them (eg numbers)
|
||||
let mut buf = MemWriter::new();
|
||||
let mut check_encoder = PrettyEncoder::new(&mut buf);
|
||||
f(&mut check_encoder);
|
||||
let buf = buf.unwrap();
|
||||
let out = from_utf8(buf).unwrap();
|
||||
let needs_wrapping = out.char_at(0) != '"' &&
|
||||
out.char_at_reverse(out.len()) != '"';
|
||||
if needs_wrapping { try!(write!(self.wr, "\"")); }
|
||||
f(self);
|
||||
if needs_wrapping { try!(write!(self.wr, "\"")); }
|
||||
}
|
||||
|
||||
fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut PrettyEncoder<'a>|) {
|
||||
@ -1306,13 +1330,19 @@ impl ::Decoder for Decoder {
|
||||
}
|
||||
|
||||
fn read_f64(&mut self) -> f64 {
|
||||
use std::from_str::FromStr;
|
||||
debug!("read_f64");
|
||||
match self.stack.pop().unwrap() {
|
||||
Number(f) => f,
|
||||
String(s) => {
|
||||
// re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
|
||||
// is going to have a string here, as per JSON spec..
|
||||
FromStr::from_str(s).unwrap()
|
||||
},
|
||||
value => self.expected("number", &value)
|
||||
}
|
||||
}
|
||||
fn read_f32(&mut self) -> f32 { self.read_f64() as f32 }
|
||||
|
||||
fn read_f32(&mut self) -> f32 { self.read_f64() as f32 }
|
||||
|
||||
fn read_char(&mut self) -> char {
|
||||
@ -2519,4 +2549,57 @@ mod tests {
|
||||
let expected_null = ();
|
||||
assert!(json_null.is_some() && json_null.unwrap() == expected_null);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode_hashmap_with_numeric_key() {
|
||||
use std::str::from_utf8;
|
||||
use std::io::Writer;
|
||||
use std::io::MemWriter;
|
||||
use collections::HashMap;
|
||||
let mut hm: HashMap<uint, bool> = HashMap::new();
|
||||
hm.insert(1, true);
|
||||
let mut mem_buf = MemWriter::new();
|
||||
{
|
||||
let mut encoder = Encoder::new(&mut mem_buf as &mut io::Writer);
|
||||
hm.encode(&mut encoder)
|
||||
}
|
||||
let bytes = mem_buf.unwrap();
|
||||
let json_str = from_utf8(bytes).unwrap();
|
||||
match from_str(json_str) {
|
||||
Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
|
||||
_ => {} // it parsed and we are good to go
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_prettyencode_hashmap_with_numeric_key() {
|
||||
use std::str::from_utf8;
|
||||
use std::io::Writer;
|
||||
use std::io::MemWriter;
|
||||
use collections::HashMap;
|
||||
let mut hm: HashMap<uint, bool> = HashMap::new();
|
||||
hm.insert(1, true);
|
||||
let mut mem_buf = MemWriter::new();
|
||||
{
|
||||
let mut encoder = PrettyEncoder::new(&mut mem_buf as &mut io::Writer);
|
||||
hm.encode(&mut encoder)
|
||||
}
|
||||
let bytes = mem_buf.unwrap();
|
||||
let json_str = from_utf8(bytes).unwrap();
|
||||
match from_str(json_str) {
|
||||
Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
|
||||
_ => {} // it parsed and we are good to go
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() {
|
||||
use collections::HashMap;
|
||||
use Decodable;
|
||||
let json_str = "{\"1\":true}";
|
||||
let json_obj = match from_str(json_str) {
|
||||
Err(_) => fail!("Unable to parse json_str: {:?}", json_str),
|
||||
Ok(o) => o
|
||||
};
|
||||
let mut decoder = Decoder::new(json_obj);
|
||||
let hm: HashMap<uint, bool> = Decodable::decode(&mut decoder);
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use cast;
|
||||
use fmt;
|
||||
use iter::Iterator;
|
||||
use vec::{ImmutableVector, MutableVector, Vector};
|
||||
use vec_ng::Vec;
|
||||
use option::{Option, Some, None};
|
||||
|
||||
/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
|
||||
@ -305,6 +306,14 @@ impl IntoStr for ~[Ascii] {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoStr for Vec<Ascii> {
|
||||
#[inline]
|
||||
fn into_str(self) -> ~str {
|
||||
let v: ~[Ascii] = self.move_iter().collect();
|
||||
unsafe { cast::transmute(v) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to convert to an owned byte array by consuming self
|
||||
pub trait IntoBytes {
|
||||
/// Converts to an owned byte array by consuming self
|
||||
@ -473,6 +482,7 @@ mod tests {
|
||||
use super::*;
|
||||
use str::from_char;
|
||||
use char::from_u32;
|
||||
use vec_ng::Vec;
|
||||
|
||||
macro_rules! v2ascii (
|
||||
( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
|
||||
@ -480,6 +490,10 @@ mod tests {
|
||||
(~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]);
|
||||
)
|
||||
|
||||
macro_rules! vec2ascii (
|
||||
($($e:expr),*) => (Vec::from_slice([$(Ascii{chr:$e}),*]));
|
||||
)
|
||||
|
||||
#[test]
|
||||
fn test_ascii() {
|
||||
assert_eq!(65u8.to_ascii().to_byte(), 65u8);
|
||||
@ -535,6 +549,17 @@ mod tests {
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ascii_vec_ng() {
|
||||
assert_eq!(Vec::from_slice("abCDef&?#".to_ascii().to_lower()).into_str(), ~"abcdef&?#");
|
||||
assert_eq!(Vec::from_slice("abCDef&?#".to_ascii().to_upper()).into_str(), ~"ABCDEF&?#");
|
||||
|
||||
assert_eq!(Vec::from_slice("".to_ascii().to_lower()).into_str(), ~"");
|
||||
assert_eq!(Vec::from_slice("YMCA".to_ascii().to_lower()).into_str(), ~"ymca");
|
||||
assert_eq!(Vec::from_slice("abcDEFxyz:.;".to_ascii().to_upper()).into_str(),
|
||||
~"ABCDEFXYZ:.;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_owned_ascii_vec() {
|
||||
assert_eq!((~"( ;").into_ascii(), v2ascii!(~[40, 32, 59]));
|
||||
@ -550,6 +575,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_ascii_into_str() {
|
||||
assert_eq!(v2ascii!(~[40, 32, 59]).into_str(), ~"( ;");
|
||||
assert_eq!(vec2ascii!(40, 32, 59).into_str(), ~"( ;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -45,8 +45,9 @@ impl<T: Clone> Clone for ~T {
|
||||
fn clone(&self) -> ~T { ~(**self).clone() }
|
||||
|
||||
/// Perform copy-assignment from `source` by reusing the existing allocation.
|
||||
#[inline]
|
||||
fn clone_from(&mut self, source: &~T) {
|
||||
**self = (**source).clone()
|
||||
(**self).clone_from(&(**source));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3643,7 +3643,7 @@ pub mod funcs {
|
||||
pub fn open(path: *c_char, oflag: c_int, mode: c_int)
|
||||
-> c_int;
|
||||
pub fn creat(path: *c_char, mode: mode_t) -> c_int;
|
||||
pub fn fcntl(fd: c_int, cmd: c_int) -> c_int;
|
||||
pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// So we don't have to document the actual methods on the traits.
|
||||
#[allow(missing_doc)];
|
||||
|
||||
/*!
|
||||
*
|
||||
* Traits representing built-in operators, useful for overloading
|
||||
@ -83,6 +80,7 @@
|
||||
*/
|
||||
#[lang="drop"]
|
||||
pub trait Drop {
|
||||
/// The `drop` method, called when the value goes out of scope.
|
||||
fn drop(&mut self);
|
||||
}
|
||||
|
||||
@ -112,6 +110,7 @@ pub trait Drop {
|
||||
*/
|
||||
#[lang="add"]
|
||||
pub trait Add<RHS,Result> {
|
||||
/// The method for the `+` operator
|
||||
fn add(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -141,6 +140,7 @@ pub trait Add<RHS,Result> {
|
||||
*/
|
||||
#[lang="sub"]
|
||||
pub trait Sub<RHS,Result> {
|
||||
/// The method for the `-` operator
|
||||
fn sub(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -170,6 +170,7 @@ pub trait Sub<RHS,Result> {
|
||||
*/
|
||||
#[lang="mul"]
|
||||
pub trait Mul<RHS,Result> {
|
||||
/// The method for the `*` operator
|
||||
fn mul(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -199,6 +200,7 @@ pub trait Mul<RHS,Result> {
|
||||
*/
|
||||
#[lang="div"]
|
||||
pub trait Div<RHS,Result> {
|
||||
/// The method for the `/` operator
|
||||
fn div(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -228,6 +230,7 @@ pub trait Div<RHS,Result> {
|
||||
*/
|
||||
#[lang="rem"]
|
||||
pub trait Rem<RHS,Result> {
|
||||
/// The method for the `%` operator
|
||||
fn rem(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -257,6 +260,7 @@ pub trait Rem<RHS,Result> {
|
||||
*/
|
||||
#[lang="neg"]
|
||||
pub trait Neg<Result> {
|
||||
/// The method for the unary `-` operator
|
||||
fn neg(&self) -> Result;
|
||||
}
|
||||
|
||||
@ -286,6 +290,7 @@ pub trait Neg<Result> {
|
||||
*/
|
||||
#[lang="not"]
|
||||
pub trait Not<Result> {
|
||||
/// The method for the unary `!` operator
|
||||
fn not(&self) -> Result;
|
||||
}
|
||||
|
||||
@ -315,6 +320,7 @@ pub trait Not<Result> {
|
||||
*/
|
||||
#[lang="bitand"]
|
||||
pub trait BitAnd<RHS,Result> {
|
||||
/// The method for the `&` operator
|
||||
fn bitand(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -344,6 +350,7 @@ pub trait BitAnd<RHS,Result> {
|
||||
*/
|
||||
#[lang="bitor"]
|
||||
pub trait BitOr<RHS,Result> {
|
||||
/// The method for the `|` operator
|
||||
fn bitor(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -373,6 +380,7 @@ pub trait BitOr<RHS,Result> {
|
||||
*/
|
||||
#[lang="bitxor"]
|
||||
pub trait BitXor<RHS,Result> {
|
||||
/// The method for the `^` operator
|
||||
fn bitxor(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -402,6 +410,7 @@ pub trait BitXor<RHS,Result> {
|
||||
*/
|
||||
#[lang="shl"]
|
||||
pub trait Shl<RHS,Result> {
|
||||
/// The method for the `<<` operator
|
||||
fn shl(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -431,6 +440,7 @@ pub trait Shl<RHS,Result> {
|
||||
*/
|
||||
#[lang="shr"]
|
||||
pub trait Shr<RHS,Result> {
|
||||
/// The method for the `>>` operator
|
||||
fn shr(&self, rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
@ -461,28 +471,96 @@ pub trait Shr<RHS,Result> {
|
||||
*/
|
||||
#[lang="index"]
|
||||
pub trait Index<Index,Result> {
|
||||
/// The method for the indexing (`Foo[Bar]`) operation
|
||||
fn index(&self, index: &Index) -> Result;
|
||||
}
|
||||
|
||||
/// Dummy dox
|
||||
#[cfg(stage0)]
|
||||
pub trait Deref<Result> {
|
||||
/// dummy dox
|
||||
fn deref<'a>(&'a self) -> &'a Result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The `Deref` trait is used to specify the functionality of dereferencing
|
||||
* operations like `*v`.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* A struct with a single field which is accessible via dereferencing the
|
||||
* struct.
|
||||
*
|
||||
* ```
|
||||
* struct DerefExample<T> {
|
||||
* value: T
|
||||
* }
|
||||
*
|
||||
* impl<T> Deref<T> for DerefExample<T> {
|
||||
* fn deref<'a>(&'a self) -> &'a T {
|
||||
* &self.value
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* fn main() {
|
||||
* let x = DerefExample { value: 'a' };
|
||||
* assert_eq!('a', *x);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
#[cfg(not(stage0))]
|
||||
#[lang="deref"]
|
||||
pub trait Deref<Result> {
|
||||
/// The method called to dereference a value
|
||||
fn deref<'a>(&'a self) -> &'a Result;
|
||||
}
|
||||
|
||||
/// dummy dox
|
||||
#[cfg(stage0)]
|
||||
pub trait DerefMut<Result>: Deref<Result> {
|
||||
/// dummy dox
|
||||
fn deref_mut<'a>(&'a mut self) -> &'a mut Result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The `DerefMut` trait is used to specify the functionality of dereferencing
|
||||
* mutably like `*v = 1;`
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* A struct with a single field which is modifiable via dereferencing the
|
||||
* struct.
|
||||
*
|
||||
* ```
|
||||
* struct DerefMutExample<T> {
|
||||
* value: T
|
||||
* }
|
||||
*
|
||||
* impl<T> Deref<T> for DerefMutExample<T> {
|
||||
* fn deref<'a>(&'a self) -> &'a T {
|
||||
* &self.value
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* impl<T> DerefMut<T> for DerefMutExample<T> {
|
||||
* fn deref_mut<'a>(&'a mut self) -> &'a mut T {
|
||||
* &mut self.value
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* fn main() {
|
||||
* let mut x = DerefMutExample { value: 'a' };
|
||||
* *x = 'b';
|
||||
* assert_eq!('b', *x);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
#[cfg(not(stage0))]
|
||||
#[lang="deref_mut"]
|
||||
pub trait DerefMut<Result>: Deref<Result> {
|
||||
/// The method called to mutably dereference a value
|
||||
fn deref_mut<'a>(&'a mut self) -> &'a mut Result;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ impl<T> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contained value or a default
|
||||
/// Returns the contained value or a default.
|
||||
#[inline]
|
||||
pub fn unwrap_or(self, def: T) -> T {
|
||||
match self {
|
||||
@ -158,7 +158,7 @@ impl<T> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contained value or computes it from a closure
|
||||
/// Returns the contained value or computes it from a closure.
|
||||
#[inline]
|
||||
pub fn unwrap_or_else(self, f: || -> T) -> T {
|
||||
match self {
|
||||
@ -183,7 +183,7 @@ impl<T> Option<T> {
|
||||
match self { None => def, Some(t) => f(t) }
|
||||
}
|
||||
|
||||
/// Apply a function to the contained value or do nothing.
|
||||
/// Applies a function to the contained value or does nothing.
|
||||
/// Returns true if the contained value was mutated.
|
||||
pub fn mutate(&mut self, f: |T| -> T) -> bool {
|
||||
if self.is_some() {
|
||||
@ -192,7 +192,7 @@ impl<T> Option<T> {
|
||||
} else { false }
|
||||
}
|
||||
|
||||
/// Apply a function to the contained value or set it to a default.
|
||||
/// Applies a function to the contained value or sets it to a default.
|
||||
/// Returns true if the contained value was mutated, or false if set to the default.
|
||||
pub fn mutate_or_set(&mut self, def: T, f: |T| -> T) -> bool {
|
||||
if self.is_some() {
|
||||
@ -208,19 +208,19 @@ impl<T> Option<T> {
|
||||
// Iterator constructors
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Return an iterator over the possibly contained value
|
||||
/// Returns an iterator over the possibly contained value.
|
||||
#[inline]
|
||||
pub fn iter<'r>(&'r self) -> Item<&'r T> {
|
||||
Item{opt: self.as_ref()}
|
||||
}
|
||||
|
||||
/// Return a mutable iterator over the possibly contained value
|
||||
/// Returns a mutable iterator over the possibly contained value.
|
||||
#[inline]
|
||||
pub fn mut_iter<'r>(&'r mut self) -> Item<&'r mut T> {
|
||||
Item{opt: self.as_mut()}
|
||||
}
|
||||
|
||||
/// Return a consuming iterator over the possibly contained value
|
||||
/// Returns a consuming iterator over the possibly contained value.
|
||||
#[inline]
|
||||
pub fn move_iter(self) -> Item<T> {
|
||||
Item{opt: self}
|
||||
@ -264,7 +264,7 @@ impl<T> Option<T> {
|
||||
pub fn or_else(self, f: || -> Option<T>) -> Option<T> {
|
||||
match self {
|
||||
Some(_) => self,
|
||||
None => f(),
|
||||
None => f()
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,7 +272,7 @@ impl<T> Option<T> {
|
||||
// Misc
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Take the value out of the option, leaving a `None` in its place.
|
||||
/// Takes the value out of the option, leaving a `None` in its place.
|
||||
#[inline]
|
||||
pub fn take(&mut self) -> Option<T> {
|
||||
mem::replace(self, None)
|
||||
@ -282,7 +282,7 @@ impl<T> Option<T> {
|
||||
#[inline(always)]
|
||||
pub fn filtered(self, f: |t: &T| -> bool) -> Option<T> {
|
||||
match self {
|
||||
Some(x) => if f(&x) {Some(x)} else {None},
|
||||
Some(x) => if f(&x) { Some(x) } else { None },
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
@ -2664,9 +2664,6 @@ impl<'a> StrSlice<'a> for &'a str {
|
||||
return multibyte_char_range_at(*self, i);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn char_at(&self, i: uint) -> char { self.char_range_at(i).ch }
|
||||
|
||||
#[inline]
|
||||
fn char_range_at_reverse(&self, start: uint) -> CharRange {
|
||||
let mut prev = start;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -26,7 +26,7 @@ use clone::Clone;
|
||||
use kinds::Send;
|
||||
use ops::Drop;
|
||||
use ptr::RawPtr;
|
||||
use sync::atomics::{AtomicUint, SeqCst, Relaxed, Acquire};
|
||||
use sync::atomics::{fence, AtomicUint, Relaxed, Acquire, Release};
|
||||
use vec;
|
||||
|
||||
/// An atomically reference counted pointer.
|
||||
@ -109,8 +109,16 @@ impl<T: Send> UnsafeArc<T> {
|
||||
impl<T: Send> Clone for UnsafeArc<T> {
|
||||
fn clone(&self) -> UnsafeArc<T> {
|
||||
unsafe {
|
||||
// This barrier might be unnecessary, but I'm not sure...
|
||||
let old_count = (*self.data).count.fetch_add(1, Acquire);
|
||||
// Using a relaxed ordering is alright here, as knowledge of the original reference
|
||||
// prevents other threads from erroneously deleting the object.
|
||||
//
|
||||
// As explained in the [Boost documentation][1],
|
||||
// Increasing the reference counter can always be done with memory_order_relaxed: New
|
||||
// references to an object can only be formed from an existing reference, and passing
|
||||
// an existing reference from one thread to another must already provide any required
|
||||
// synchronization.
|
||||
// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
|
||||
let old_count = (*self.data).count.fetch_add(1, Relaxed);
|
||||
// FIXME(#12049): this needs some sort of debug assertion
|
||||
if cfg!(test) { assert!(old_count >= 1); }
|
||||
return UnsafeArc { data: self.data };
|
||||
@ -127,12 +135,26 @@ impl<T> Drop for UnsafeArc<T>{
|
||||
if self.data.is_null() {
|
||||
return
|
||||
}
|
||||
// Must be acquire+release, not just release, to make sure this
|
||||
// doesn't get reordered to after the unwrapper pointer load.
|
||||
let old_count = (*self.data).count.fetch_sub(1, SeqCst);
|
||||
// Because `fetch_sub` is already atomic, we do not need to synchronize with other
|
||||
// threads unless we are going to delete the object.
|
||||
let old_count = (*self.data).count.fetch_sub(1, Release);
|
||||
// FIXME(#12049): this needs some sort of debug assertion
|
||||
if cfg!(test) { assert!(old_count >= 1); }
|
||||
if old_count == 1 {
|
||||
// This fence is needed to prevent reordering of use of the data and deletion of
|
||||
// the data. Because it is marked `Release`, the decreasing of the reference count
|
||||
// sychronizes with this `Acquire` fence. This means that use of the data happens
|
||||
// before decreasing the refernce count, which happens before this fence, which
|
||||
// happens before the deletion of the data.
|
||||
//
|
||||
// As explained in the [Boost documentation][1],
|
||||
// It is important to enforce any possible access to the object in one thread
|
||||
// (through an existing reference) to *happen before* deleting the object in a
|
||||
// different thread. This is achieved by a "release" operation after dropping a
|
||||
// reference (any access to the object through this reference must obviously
|
||||
// happened before), and an "acquire" operation before deleting the object.
|
||||
// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
|
||||
fence(Acquire);
|
||||
let _: ~ArcData<T> = cast::transmute(self.data);
|
||||
}
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ impl<T> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn remove(&mut self, index: uint) -> Option<T> {
|
||||
pub fn remove(&mut self, index: uint) -> Option<T> {
|
||||
let len = self.len();
|
||||
if index < len {
|
||||
unsafe { // infallible
|
||||
|
@ -271,13 +271,22 @@ impl CodeMap {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_filemap(&self, filename: FileName, mut src: ~str) -> Rc<FileMap> {
|
||||
pub fn new_filemap(&self, filename: FileName, src: ~str) -> Rc<FileMap> {
|
||||
let mut files = self.files.borrow_mut();
|
||||
let start_pos = match files.get().last() {
|
||||
None => 0,
|
||||
Some(last) => last.deref().start_pos.to_uint() + last.deref().src.len(),
|
||||
};
|
||||
|
||||
// Remove utf-8 BOM if any.
|
||||
// FIXME #12884: no efficient/safe way to remove from the start of a string
|
||||
// and reuse the allocation.
|
||||
let mut src = if src.starts_with("\ufeff") {
|
||||
src.as_slice().slice_from(3).into_owned()
|
||||
} else {
|
||||
src
|
||||
};
|
||||
|
||||
// Append '\n' in case it's not already there.
|
||||
// This is a workaround to prevent CodeMap.lookup_filemap_idx from accidentally
|
||||
// overflowing into the next filemap in case the last byte of span is also the last
|
||||
|
@ -880,8 +880,8 @@ mod test {
|
||||
use super::*;
|
||||
|
||||
// this version doesn't care about getting comments or docstrings in.
|
||||
fn fake_print_crate<A: pprust::PpAnn>(s: &mut pprust::State<A>,
|
||||
krate: &ast::Crate) -> io::IoResult<()> {
|
||||
fn fake_print_crate(s: &mut pprust::State,
|
||||
krate: &ast::Crate) -> io::IoResult<()> {
|
||||
s.print_mod(&krate.module, krate.attrs.as_slice())
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,8 @@ pub enum AnnNode<'a> {
|
||||
}
|
||||
|
||||
pub trait PpAnn {
|
||||
fn pre(&self, _state: &mut State<Self>, _node: AnnNode) -> IoResult<()> { Ok(()) }
|
||||
fn post(&self, _state: &mut State<Self>, _node: AnnNode) -> IoResult<()> { Ok(()) }
|
||||
fn pre(&self, _state: &mut State, _node: AnnNode) -> IoResult<()> { Ok(()) }
|
||||
fn post(&self, _state: &mut State, _node: AnnNode) -> IoResult<()> { Ok(()) }
|
||||
}
|
||||
|
||||
pub struct NoAnn;
|
||||
@ -56,7 +56,7 @@ pub struct CurrentCommentAndLiteral {
|
||||
cur_lit: uint,
|
||||
}
|
||||
|
||||
pub struct State<'a, A> {
|
||||
pub struct State<'a> {
|
||||
s: pp::Printer,
|
||||
cm: Option<&'a CodeMap>,
|
||||
intr: @token::IdentInterner,
|
||||
@ -64,15 +64,16 @@ pub struct State<'a, A> {
|
||||
literals: Option<Vec<comments::Literal> >,
|
||||
cur_cmnt_and_lit: CurrentCommentAndLiteral,
|
||||
boxes: RefCell<Vec<pp::Breaks> >,
|
||||
ann: &'a A
|
||||
ann: &'a PpAnn
|
||||
}
|
||||
|
||||
pub fn rust_printer(writer: ~io::Writer) -> State<'static, NoAnn> {
|
||||
pub fn rust_printer(writer: ~io::Writer) -> State<'static> {
|
||||
static NO_ANN: NoAnn = NoAnn;
|
||||
rust_printer_annotated(writer, &NO_ANN)
|
||||
}
|
||||
|
||||
pub fn rust_printer_annotated<'a, A: PpAnn>(writer: ~io::Writer, ann: &'a A) -> State<'a, A> {
|
||||
pub fn rust_printer_annotated<'a>(writer: ~io::Writer,
|
||||
ann: &'a PpAnn) -> State<'a> {
|
||||
State {
|
||||
s: pp::mk_printer(writer, default_columns),
|
||||
cm: None,
|
||||
@ -95,14 +96,14 @@ pub static default_columns: uint = 78u;
|
||||
// Requires you to pass an input filename and reader so that
|
||||
// it can scan the input text for comments and literals to
|
||||
// copy forward.
|
||||
pub fn print_crate<'a, A: PpAnn>(cm: &'a CodeMap,
|
||||
span_diagnostic: &diagnostic::SpanHandler,
|
||||
krate: &ast::Crate,
|
||||
filename: ~str,
|
||||
input: &mut io::Reader,
|
||||
out: ~io::Writer,
|
||||
ann: &'a A,
|
||||
is_expanded: bool) -> IoResult<()> {
|
||||
pub fn print_crate<'a>(cm: &'a CodeMap,
|
||||
span_diagnostic: &diagnostic::SpanHandler,
|
||||
krate: &ast::Crate,
|
||||
filename: ~str,
|
||||
input: &mut io::Reader,
|
||||
out: ~io::Writer,
|
||||
ann: &'a PpAnn,
|
||||
is_expanded: bool) -> IoResult<()> {
|
||||
let (cmnts, lits) = comments::gather_comments_and_literals(
|
||||
span_diagnostic,
|
||||
filename,
|
||||
@ -133,7 +134,7 @@ pub fn print_crate<'a, A: PpAnn>(cm: &'a CodeMap,
|
||||
eof(&mut s.s)
|
||||
}
|
||||
|
||||
pub fn to_str(f: |&mut State<NoAnn>| -> IoResult<()>) -> ~str {
|
||||
pub fn to_str(f: |&mut State| -> IoResult<()>) -> ~str {
|
||||
let mut s = rust_printer(~MemWriter::new());
|
||||
f(&mut s).unwrap();
|
||||
eof(&mut s.s).unwrap();
|
||||
@ -237,7 +238,7 @@ pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> ~str {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: PpAnn> State<'a, A> {
|
||||
impl<'a> State<'a> {
|
||||
pub fn ibox(&mut self, u: uint) -> IoResult<()> {
|
||||
self.boxes.borrow_mut().get().push(pp::Inconsistent);
|
||||
pp::ibox(&mut self.s, u)
|
||||
@ -365,7 +366,7 @@ impl<'a, A: PpAnn> State<'a, A> {
|
||||
}
|
||||
|
||||
pub fn commasep<T>(&mut self, b: Breaks, elts: &[T],
|
||||
op: |&mut State<A>, &T| -> IoResult<()>)
|
||||
op: |&mut State, &T| -> IoResult<()>)
|
||||
-> IoResult<()> {
|
||||
try!(self.rbox(0u, b));
|
||||
let mut first = true;
|
||||
@ -381,7 +382,7 @@ impl<'a, A: PpAnn> State<'a, A> {
|
||||
&mut self,
|
||||
b: Breaks,
|
||||
elts: &[T],
|
||||
op: |&mut State<A>, &T| -> IoResult<()>,
|
||||
op: |&mut State, &T| -> IoResult<()>,
|
||||
get_span: |&T| -> codemap::Span) -> IoResult<()> {
|
||||
try!(self.rbox(0u, b));
|
||||
let len = elts.len();
|
||||
|
@ -10,3 +10,5 @@
|
||||
|
||||
#[no_mangle]
|
||||
pub static foo: int = 3;
|
||||
|
||||
pub fn bar() {}
|
||||
|
19
src/test/compile-fail/issue-12997-1.rs
Normal file
19
src/test/compile-fail/issue-12997-1.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: --test
|
||||
|
||||
//! Test that makes sure wrongly-typed bench functions aren't ignored
|
||||
|
||||
#[bench]
|
||||
fn foo() { } //~ ERROR functions used as benches
|
||||
|
||||
#[bench]
|
||||
fn bar(x: int, y: int) { } //~ ERROR functions used as benches
|
17
src/test/compile-fail/issue-12997-2.rs
Normal file
17
src/test/compile-fail/issue-12997-2.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: --test
|
||||
|
||||
//! Test that makes sure wrongly-typed bench functions are rejected
|
||||
|
||||
// error-pattern:expected &-ptr but found int
|
||||
#[bench]
|
||||
fn bar(x: int) { }
|
26
src/test/compile-fail/issue-8153.rs
Normal file
26
src/test/compile-fail/issue-8153.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that duplicate methods in impls are not allowed
|
||||
|
||||
struct Foo;
|
||||
|
||||
trait Bar {
|
||||
fn bar(&self) -> int;
|
||||
}
|
||||
|
||||
impl Bar for Foo {
|
||||
fn bar(&self) -> int {1}
|
||||
fn bar(&self) -> int {2} //~ ERROR duplicate method
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}", Foo.bar());
|
||||
}
|
@ -26,6 +26,13 @@ extern {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// It appears that the --as-needed flag to linkers will not pull in a dynamic
|
||||
// library unless it satisfies a non weak undefined symbol. The 'other' crate
|
||||
// is compiled as a dynamic library where it would only be used for a
|
||||
// weak-symbol as part of an executable, so the dynamic library woudl be
|
||||
// discarded. By adding and calling `other::bar`, we get around this problem.
|
||||
other::bar();
|
||||
|
||||
assert!(!foo.is_null());
|
||||
assert_eq!(unsafe { *foo }, 3);
|
||||
assert!(something_that_should_never_exist.is_null());
|
||||
|
13
src/test/run-pass/utf8-bom.rs
Normal file
13
src/test/run-pass/utf8-bom.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// This file has utf-8 BOM, it should be compiled normally without error.
|
||||
|
||||
pub fn main() {}
|
Loading…
x
Reference in New Issue
Block a user