diff --git a/src/libextra/crypto/digest.rs b/src/libextra/crypto/digest.rs index 85c256c47a380..372e2313de7b2 100644 --- a/src/libextra/crypto/digest.rs +++ b/src/libextra/crypto/digest.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Common functionality related to cryptographic digest functions + use std::vec; use hex::ToHex; diff --git a/src/libextra/crypto/md5.rs b/src/libextra/crypto/md5.rs index 5ef113971abb0..864fc64f82bec 100644 --- a/src/libextra/crypto/md5.rs +++ b/src/libextra/crypto/md5.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + use std::iter::range_step; use cryptoutil::{write_u32_le, read_u32v_le, FixedBuffer, FixedBuffer64, StandardPadding}; diff --git a/src/libextra/crypto/sha2.rs b/src/libextra/crypto/sha2.rs index 4a8b62ffd1141..fb9a6df50e48c 100644 --- a/src/libextra/crypto/sha2.rs +++ b/src/libextra/crypto/sha2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + use std::iter::range_step; use cryptoutil::{write_u64_be, write_u32_be, read_u64v_be, read_u32v_be, add_bytes_to_bits, diff --git a/src/libextra/enum_set.rs b/src/libextra/enum_set.rs index 242faa2b4da20..da9e0a225ba1b 100644 --- a/src/libextra/enum_set.rs +++ b/src/libextra/enum_set.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! A structure for holding a set of enum variants +//! +//! This module defines a container which uses an efficient bit mask +//! representation to hold C-like enum variants. + #[deriving(Clone, Eq, IterBytes, ToStr)] /// A specialized Set implementation to use enum types. pub struct EnumSet { diff --git a/src/libextra/io_util.rs b/src/libextra/io_util.rs index b75295ffd22ea..904ed13eabbcc 100644 --- a/src/libextra/io_util.rs +++ b/src/libextra/io_util.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + use std::io::{Reader, BytesReader}; use std::io; use std::cast; diff --git a/src/libextra/md4.rs b/src/libextra/md4.rs index abce22f98c6bf..96238986bf1c8 100644 --- a/src/libextra/md4.rs +++ b/src/libextra/md4.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; use std::vec; diff --git a/src/libextra/rl.rs b/src/libextra/rl.rs index 7662a159ba49a..c8a17451a7051 100644 --- a/src/libextra/rl.rs +++ b/src/libextra/rl.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Bindings for the ability to read lines of input from the console + use std::c_str::ToCStr; use std::libc::{c_char, c_int}; use std::{local_data, str, rt}; use std::unstable::finally::Finally; -pub mod rustrt { +mod rustrt { use std::libc::{c_char, c_int}; externfn!(fn linenoise(prompt: *c_char) -> *c_char) diff --git a/src/libextra/stats.rs b/src/libextra/stats.rs index 9ac0d73c2ecf5..cc6ce715ad331 100644 --- a/src/libextra/stats.rs +++ b/src/libextra/stats.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + use sort; use std::cmp; use std::hashmap; diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs index 75060166f8c0a..b5b182ea8c580 100644 --- a/src/libextra/sync.rs +++ b/src/libextra/sync.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + /** * The concurrency primitives you know and love. * diff --git a/src/libextra/terminfo/terminfo.rs b/src/libextra/terminfo/terminfo.rs index 0e0231ad3f44a..57e00885b2fb1 100644 --- a/src/libextra/terminfo/terminfo.rs +++ b/src/libextra/terminfo/terminfo.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + use std::hashmap::HashMap; /// A parsed terminfo entry. diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 0c896007fc3ba..ef8b859efd63e 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -199,6 +199,7 @@ pub fn phase_2_configure_and_expand(sess: Session, pub struct CrateAnalysis { exp_map2: middle::resolve::ExportMap2, + exported_items: middle::privacy::ExportedItems, ty_cx: ty::ctxt, maps: astencode::Maps, reachable: @mut HashSet @@ -310,6 +311,7 @@ pub fn phase_3_run_analysis_passes(sess: Session, CrateAnalysis { exp_map2: exp_map2, ty_cx: ty_cx, + exported_items: exported_items, maps: astencode::Maps { root_map: root_map, method_map: method_map, diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 84cffc0e94c7f..8b21ce3202432 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -955,6 +955,11 @@ impl Visitor<()> for MissingDocLintVisitor { ~"missing documentation for a function"); } + ast::item_mod(*) if it.vis == ast::public => { + self.check_attrs(it.attrs, it.id, it.span, + ~"missing documentation for a module"); + } + ast::item_enum(ref edef, _) if it.vis == ast::public => { self.check_attrs(it.attrs, it.id, it.span, ~"missing documentation for an enum"); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 7537366014e05..69d9f8f5946d7 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -10,14 +10,17 @@ use rustc; use rustc::{driver, middle}; +use rustc::middle::privacy; use syntax::ast; +use syntax::ast_util::is_local; use syntax::diagnostic; use syntax::parse; use syntax; use std::os; use std::local_data; +use std::hashmap::HashMap; use visit_ast::RustdocVisitor; use clean; @@ -29,10 +32,19 @@ pub struct DocContext { sess: driver::session::Session } +pub struct CrateAnalysis { + exported_items: privacy::ExportedItems, + reexports: HashMap, +} + /// Parses, resolves, and typechecks the given crate -fn get_ast_and_resolve(cpath: &Path, libs: ~[Path]) -> DocContext { +fn get_ast_and_resolve(cpath: &Path, + libs: ~[Path]) -> (DocContext, CrateAnalysis) { use syntax::codemap::dummy_spanned; - use rustc::driver::driver::*; + use rustc::driver::driver::{file_input, build_configuration, + phase_1_parse_input, + phase_2_configure_and_expand, + phase_3_run_analysis_passes}; let parsesess = parse::new_parse_sess(None); let input = file_input(cpath.clone()); @@ -60,14 +72,26 @@ fn get_ast_and_resolve(cpath: &Path, libs: ~[Path]) -> DocContext { let mut crate = phase_1_parse_input(sess, cfg.clone(), &input); crate = phase_2_configure_and_expand(sess, cfg, crate); - let analysis = phase_3_run_analysis_passes(sess, &crate); + let driver::driver::CrateAnalysis { + exported_items, ty_cx, exp_map2, _ + } = phase_3_run_analysis_passes(sess, &crate); + + let mut reexports = HashMap::new(); + for (&module, nodes) in exp_map2.iter() { + reexports.insert(module, nodes.iter() + .filter(|e| e.reexport && is_local(e.def_id)) + .map(|e| e.def_id.node) + .to_owned_vec()); + } debug2!("crate: {:?}", crate); - DocContext { crate: crate, tycx: analysis.ty_cx, sess: sess } + return (DocContext { crate: crate, tycx: ty_cx, sess: sess }, + CrateAnalysis { reexports: reexports, exported_items: exported_items }); } -pub fn run_core (libs: ~[Path], path: &Path) -> clean::Crate { - let ctxt = @get_ast_and_resolve(path, libs); +pub fn run_core (libs: ~[Path], path: &Path) -> (clean::Crate, CrateAnalysis) { + let (ctxt, analysis) = get_ast_and_resolve(path, libs); + let ctxt = @ctxt; debug2!("defmap:"); for (k, v) in ctxt.tycx.def_map.iter() { debug2!("{:?}: {:?}", k, v); @@ -77,5 +101,5 @@ pub fn run_core (libs: ~[Path], path: &Path) -> clean::Crate { let v = @mut RustdocVisitor::new(); v.visit(&ctxt.crate); - v.clean() + (v.clean(), analysis) } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index bb78b5aabb5f9..3fc7988fd82fa 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -220,7 +220,7 @@ pub fn run(mut crate: clean::Crate, dst: Path) { }; mkdir(&cx.dst); - match crate.module.get_ref().doc_list() { + match crate.module.as_ref().map(|m| m.doc_list().unwrap_or(&[])) { Some(attrs) => { for attr in attrs.iter() { match *attr { @@ -582,7 +582,7 @@ impl DocFolder for Cache { clean::StructItem(*) | clean::EnumItem(*) | clean::TypedefItem(*) | clean::TraitItem(*) | clean::FunctionItem(*) | clean::ModuleItem(*) | - clean::VariantItem(*) => { + clean::ForeignFunctionItem(*) | clean::VariantItem(*) => { self.paths.insert(item.id, (self.stack.clone(), shortty(&item))); } _ => {} diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index 43f2896a0d2b4..aa419a90563b7 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -9,11 +9,14 @@ // except according to those terms. use std::num; +use std::cell::Cell; use std::uint; use std::hashmap::HashSet; +use std::local_data; use syntax::ast; +use core; use clean; use clean::Item; use plugins; @@ -51,110 +54,157 @@ pub fn strip_hidden(crate: clean::Crate) -> plugins::PluginResult { /// Strip private items from the point of view of a crate or externally from a /// crate, specified by the `xcrate` flag. -pub fn strip_private(mut crate: clean::Crate) -> plugins::PluginResult { +pub fn strip_private(crate: clean::Crate) -> plugins::PluginResult { // This stripper collects all *retained* nodes. - struct Stripper<'self>(&'self mut HashSet); - impl<'self> fold::DocFolder for Stripper<'self> { - fn fold_item(&mut self, i: Item) -> Option { - match i.inner { - // These items can all get re-exported - clean::TypedefItem(*) | clean::StaticItem(*) | - clean::StructItem(*) | clean::EnumItem(*) | - clean::TraitItem(*) | clean::FunctionItem(*) | - clean::ViewItemItem(*) | clean::MethodItem(*) | - clean::ForeignFunctionItem(*) | clean::ForeignStaticItem(*) => { - // XXX: re-exported items should get surfaced in the docs as - // well (using the output of resolve analysis) - if i.visibility != Some(ast::public) { - return None; - } - } + let mut retained = HashSet::new(); + let crate = Cell::new(crate); + let exported_items = do local_data::get(super::analysiskey) |analysis| { + let analysis = analysis.unwrap(); + let mut exported_items = analysis.exported_items.clone(); + { + let mut finder = ExportedItemsFinder { + exported_items: &mut exported_items, + analysis: analysis, + }; + let c = finder.fold_crate(crate.take()); + crate.put_back(c); + } + exported_items + }; + let mut crate = crate.take(); - // These are public-by-default (if the enum/struct was public) - clean::VariantItem(*) | clean::StructFieldItem(*) => { - if i.visibility == Some(ast::private) { - return None; + // strip all private items + { + let mut stripper = Stripper { + retained: &mut retained, + exported_items: &exported_items, + }; + crate = stripper.fold_crate(crate); + } + + // strip all private implementations of traits + { + let mut stripper = ImplStripper(&retained); + crate = stripper.fold_crate(crate); + } + (crate, None) +} + +struct ExportedItemsFinder<'self> { + exported_items: &'self mut HashSet, + analysis: &'self core::CrateAnalysis, +} + +impl<'self> fold::DocFolder for ExportedItemsFinder<'self> { + fn fold_item(&mut self, i: Item) -> Option { + match i.inner { + clean::ModuleItem(*) => { + if self.analysis.exported_items.contains(&i.id) { + match self.analysis.reexports.find(&i.id) { + Some(l) => { + for &id in l.iter() { + self.exported_items.insert(id); + } + } + None => {} } } + } + _ => {} + } + return self.fold_item_recur(i); + } +} + +struct Stripper<'self> { + retained: &'self mut HashSet, + exported_items: &'self HashSet, +} - // handled below - clean::ModuleItem(*) => {} +impl<'self> fold::DocFolder for Stripper<'self> { + fn fold_item(&mut self, i: Item) -> Option { + match i.inner { + // These items can all get re-exported + clean::TypedefItem(*) | clean::StaticItem(*) | + clean::StructItem(*) | clean::EnumItem(*) | + clean::TraitItem(*) | clean::FunctionItem(*) | + clean::VariantItem(*) | clean::MethodItem(*) | + clean::ForeignFunctionItem(*) | clean::ForeignStaticItem(*) => { + if !self.exported_items.contains(&i.id) { + return None; + } + } - // impls/tymethods have no control over privacy - clean::ImplItem(*) | clean::TyMethodItem(*) => {} + clean::ViewItemItem(*) | clean::StructFieldItem(*) => { + if i.visibility != Some(ast::public) { + return None; + } } - let fastreturn = match i.inner { - // nothing left to do for traits (don't want to filter their - // methods out, visibility controlled by the trait) - clean::TraitItem(*) => true, + // handled below + clean::ModuleItem(*) => {} - // implementations of traits are always public. - clean::ImplItem(ref imp) if imp.trait_.is_some() => true, + // impls/tymethods have no control over privacy + clean::ImplItem(*) | clean::TyMethodItem(*) => {} + } - _ => false, - }; + let fastreturn = match i.inner { + // nothing left to do for traits (don't want to filter their + // methods out, visibility controlled by the trait) + clean::TraitItem(*) => true, - let i = if fastreturn { - self.insert(i.id); - return Some(i); - } else { - self.fold_item_recur(i) - }; + // implementations of traits are always public. + clean::ImplItem(ref imp) if imp.trait_.is_some() => true, - match i { - Some(i) => { - match i.inner { - // emptied modules/impls have no need to exist - clean::ModuleItem(ref m) if m.items.len() == 0 => None, - clean::ImplItem(ref i) if i.methods.len() == 0 => None, - _ => { - self.insert(i.id); - Some(i) - } + _ => false, + }; + + let i = if fastreturn { + self.retained.insert(i.id); + return Some(i); + } else { + self.fold_item_recur(i) + }; + + match i { + Some(i) => { + match i.inner { + // emptied modules/impls have no need to exist + clean::ModuleItem(ref m) if m.items.len() == 0 => None, + clean::ImplItem(ref i) if i.methods.len() == 0 => None, + _ => { + self.retained.insert(i.id); + Some(i) } } - None => None, } + None => None, } } +} - // This stripper discards all private impls of traits - struct ImplStripper<'self>(&'self HashSet); - impl<'self> fold::DocFolder for ImplStripper<'self> { - fn fold_item(&mut self, i: Item) -> Option { - match i.inner { - clean::ImplItem(ref imp) => { - match imp.trait_ { - Some(clean::ResolvedPath{ id, _ }) => { - if !self.contains(&id) { - return None; - } +// This stripper discards all private impls of traits +struct ImplStripper<'self>(&'self HashSet); +impl<'self> fold::DocFolder for ImplStripper<'self> { + fn fold_item(&mut self, i: Item) -> Option { + match i.inner { + clean::ImplItem(ref imp) => { + match imp.trait_ { + Some(clean::ResolvedPath{ id, _ }) => { + if !self.contains(&id) { + return None; } - Some(*) | None => {} } + Some(*) | None => {} } - _ => {} } - self.fold_item_recur(i) + _ => {} } + self.fold_item_recur(i) } - - let mut retained = HashSet::new(); - // First, strip all private items - { - let mut stripper = Stripper(&mut retained); - crate = stripper.fold_crate(crate); - } - - // Next, strip all private implementations of traits - { - let mut stripper = ImplStripper(&retained); - crate = stripper.fold_crate(crate); - } - (crate, None) } + pub fn unindent_comments(crate: clean::Crate) -> plugins::PluginResult { struct CommentCleaner; impl fold::DocFolder for CommentCleaner { diff --git a/src/librustdoc/rustdoc.rs b/src/librustdoc/rustdoc.rs index a724ff3bf74d8..e989796ae8876 100644 --- a/src/librustdoc/rustdoc.rs +++ b/src/librustdoc/rustdoc.rs @@ -24,6 +24,7 @@ extern mod rustc; extern mod extra; use std::cell::Cell; +use std::local_data; use std::rt::io::Writer; use std::rt::io::file::FileInfo; use std::rt::io; @@ -73,6 +74,7 @@ static DEFAULT_PASSES: &'static [&'static str] = &[ ]; local_data_key!(pub ctxtkey: @core::DocContext) +local_data_key!(pub analysiskey: core::CrateAnalysis) type Output = (clean::Crate, ~[plugins::PluginJson]); @@ -191,11 +193,12 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output { let libs = Cell::new(matches.opt_strs("L").map(|s| Path(*s))); let cr = Cell::new(Path(cratefile)); info2!("starting to run rustc"); - let crate = do std::task::try { + let (crate, analysis) = do std::task::try { let cr = cr.take(); core::run_core(libs.take(), &cr) }.unwrap(); info2!("finished with rustc"); + local_data::set(analysiskey, analysis); // Process all of the crate attributes, extracting plugin metadata along // with the passes which we are supposed to run. diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index 93a66f6d91770..f6669893170ae 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -135,6 +135,7 @@ impl Clone for @[T] { } #[cfg(not(test))] +#[allow(missing_doc)] pub mod traits { use at_vec::append; use clone::Clone; @@ -152,6 +153,7 @@ pub mod traits { #[cfg(test)] pub mod traits {} +#[allow(missing_doc)] pub mod raw { use at_vec::capacity; use cast; diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index a03f21d69c8d5..4032515f985e3 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -647,21 +647,6 @@ impl<'self> Formatter<'self> { // the format! syntax extension. fn run(&mut self, piece: &rt::Piece, cur: Option<&str>) { - let setcount = |slot: &mut Option, cnt: &parse::Count| { - match *cnt { - parse::CountIs(n) => { *slot = Some(n); } - parse::CountImplied => { *slot = None; } - parse::CountIsParam(i) => { - let v = self.args[i].value; - unsafe { *slot = Some(*(v as *util::Void as *uint)); } - } - parse::CountIsNextParam => { - let v = self.curarg.next().unwrap().value; - unsafe { *slot = Some(*(v as *util::Void as *uint)); } - } - } - }; - match *piece { rt::String(s) => { self.buf.write(s.as_bytes()); } rt::CurrentArgument(()) => { self.buf.write(cur.unwrap().as_bytes()); } @@ -670,8 +655,8 @@ impl<'self> Formatter<'self> { self.fill = arg.format.fill; self.align = arg.format.align; self.flags = arg.format.flags; - setcount(&mut self.width, &arg.format.width); - setcount(&mut self.precision, &arg.format.precision); + self.width = self.getcount(&arg.format.width); + self.precision = self.getcount(&arg.format.precision); // Extract the correct argument let value = match arg.position { @@ -688,6 +673,39 @@ impl<'self> Formatter<'self> { } } + #[cfg(stage0)] + fn getcount(&mut self, cnt: &parse::Count) -> Option { + match *cnt { + parse::CountIs(n) => { Some(n) } + parse::CountImplied => { None } + parse::CountIsParam(i) => { + let v = self.args[i].value; + unsafe { Some(*(v as *util::Void as *uint)) } + } + parse::CountIsNextParam => { + let v = self.curarg.next().unwrap().value; + unsafe { Some(*(v as *util::Void as *uint)) } + } + parse::CountIsName(*) => unreachable!() + } + } + + #[cfg(not(stage0))] + fn getcount(&mut self, cnt: &rt::Count) -> Option { + match *cnt { + rt::CountIs(n) => { Some(n) } + rt::CountImplied => { None } + rt::CountIsParam(i) => { + let v = self.args[i].value; + unsafe { Some(*(v as *util::Void as *uint)) } + } + rt::CountIsNextParam => { + let v = self.curarg.next().unwrap().value; + unsafe { Some(*(v as *util::Void as *uint)) } + } + } + } + fn execute(&mut self, method: &rt::Method, arg: Argument) { match *method { // Pluralization is selection upon a numeric value specified as the diff --git a/src/libstd/fmt/parse.rs b/src/libstd/fmt/parse.rs index a95bd563a8123..11b869c930ef4 100644 --- a/src/libstd/fmt/parse.rs +++ b/src/libstd/fmt/parse.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Parsing of format strings +//! +//! These structures are used when parsing format strings for the compiler. +//! Parsing does not currently happen at runtime (structures of std::fmt::rt are +//! generated instead). + use prelude::*; use char; @@ -42,6 +48,7 @@ pub struct Argument<'self> { /// Specification for the formatting of an argument in the format string. #[deriving(Eq)] +#[cfg(stage0)] pub struct FormatSpec<'self> { /// Optionally specified character to fill alignment with fill: Option, @@ -59,6 +66,26 @@ pub struct FormatSpec<'self> { ty: &'self str } +/// Specification for the formatting of an argument in the format string. +#[deriving(Eq)] +#[cfg(not(stage0))] +pub struct FormatSpec<'self> { + /// Optionally specified character to fill alignment with + fill: Option, + /// Optionally specified alignment + align: Alignment, + /// Packed version of various flags provided + flags: uint, + /// The integer precision to use + precision: Count<'self>, + /// The string width requested for the resulting format + width: Count<'self>, + /// The descriptor string representing the name of the format desired for + /// this argument, this can be empty or any number of characters, although + /// it is required to be one word. + ty: &'self str +} + /// Enum describing where an argument for a format can be located. #[deriving(Eq)] #[allow(missing_doc)] @@ -86,9 +113,22 @@ pub enum Flag { /// can reference either an argument or a literal integer. #[deriving(Eq)] #[allow(missing_doc)] +#[cfg(stage0)] pub enum Count { CountIs(uint), CountIsParam(uint), + CountIsName(&'static str), // not actually used, see stage1 + CountIsNextParam, + CountImplied, +} + +#[deriving(Eq)] +#[allow(missing_doc)] +#[cfg(not(stage0))] +pub enum Count<'self> { + CountIs(uint), + CountIsName(&'self str), + CountIsParam(uint), CountIsNextParam, CountImplied, } @@ -338,10 +378,22 @@ impl<'self> Parser<'self> { spec.flags |= 1 << (FlagAlternate as uint); } // Width and precision + let mut havewidth = false; if self.consume('0') { - spec.flags |= 1 << (FlagSignAwareZeroPad as uint); + // small ambiguity with '0$' as a format string. In theory this is a + // '0' flag and then an ill-formatted format string with just a '$' + // and no count, but this is better if we instead interpret this as + // no '0' flag and '0$' as the width instead. + if self.consume('$') { + spec.width = CountIsParam(0); + havewidth = true; + } else { + spec.flags |= 1 << (FlagSignAwareZeroPad as uint); + } + } + if !havewidth { + spec.width = self.count(); } - spec.width = self.count(); if self.consume('.') { if self.consume('*') { spec.precision = CountIsNextParam; @@ -542,6 +594,7 @@ impl<'self> Parser<'self> { /// Parses a Count parameter at the current position. This does not check /// for 'CountIsNextParam' because that is only used in precision, not /// width. + #[cfg(stage0)] fn count(&mut self) -> Count { match self.integer() { Some(i) => { @@ -554,6 +607,30 @@ impl<'self> Parser<'self> { None => { CountImplied } } } + #[cfg(not(stage0))] + fn count(&mut self) -> Count<'self> { + match self.integer() { + Some(i) => { + if self.consume('$') { + CountIsParam(i) + } else { + CountIs(i) + } + } + None => { + let tmp = self.cur.clone(); + match self.word() { + word if word.len() > 0 && self.consume('$') => { + CountIsName(word) + } + _ => { + self.cur = tmp; + CountImplied + } + } + } + } + } /// Parses a word starting at the current position. A word is considered to /// be an alphabetic character followed by any number of alphanumeric @@ -777,6 +854,18 @@ mod tests { }, method: None, })]); + same("{:a$.b$s}", ~[Argument(Argument { + position: ArgumentNext, + format: FormatSpec { + fill: None, + align: AlignUnknown, + flags: 0, + precision: CountIsName("b"), + width: CountIsName("a"), + ty: "s", + }, + method: None, + })]); } #[test] fn format_flags() { diff --git a/src/libstd/fmt/rt.rs b/src/libstd/fmt/rt.rs index 90763836fc6b6..063d712dfa9fe 100644 --- a/src/libstd/fmt/rt.rs +++ b/src/libstd/fmt/rt.rs @@ -34,6 +34,7 @@ pub struct Argument<'self> { method: Option<&'self Method<'self>> } +#[cfg(stage0)] pub struct FormatSpec { fill: char, align: parse::Alignment, @@ -42,6 +43,20 @@ pub struct FormatSpec { width: parse::Count, } +#[cfg(not(stage0))] +pub struct FormatSpec { + fill: char, + align: parse::Alignment, + flags: uint, + precision: Count, + width: Count, +} + +#[cfg(not(stage0))] +pub enum Count { + CountIs(uint), CountIsParam(uint), CountIsNextParam, CountImplied, +} + pub enum Position { ArgumentNext, ArgumentIs(uint) } diff --git a/src/libstd/select.rs b/src/libstd/select.rs index 049b301144bed..8ce23f4b53b27 100644 --- a/src/libstd/select.rs +++ b/src/libstd/select.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + use cell::Cell; use comm; use container::Container; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 88497bdaa8235..decfbb0785c38 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -1253,6 +1253,7 @@ Section: Trait implementations */ #[cfg(not(test))] +#[allow(missing_doc)] pub mod traits { use ops::Add; use cmp::{TotalOrd, Ordering, Less, Equal, Greater, Eq, Ord, Equiv, TotalEq}; diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 77e38b480676b..f31dbfec78a96 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -603,6 +603,7 @@ impl<'self, T> RandomAccessIterator<&'self [T]> for ChunkIter<'self, T> { // Equality #[cfg(not(test))] +#[allow(missing_doc)] pub mod traits { use super::*; diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index c936cb9ab908e..1114e3a9893f5 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -991,6 +991,7 @@ pub fn std_macros() -> @str { pub mod $c { #[allow(unused_imports)]; #[allow(non_uppercase_statics)]; + #[allow(missing_doc)]; use super::*; diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 7518816be1e93..31befed6c0cd4 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -177,6 +177,9 @@ impl Context { parse::CountIsParam(i) => { self.verify_arg_type(Left(i), Unsigned); } + parse::CountIsName(s) => { + self.verify_arg_type(Right(s.to_managed()), Unsigned); + } parse::CountIsNextParam => { if self.check_positional_ok() { self.verify_arg_type(Left(self.next_arg), Unsigned); @@ -361,21 +364,31 @@ impl Context { let trans_count = |c: parse::Count| { match c { parse::CountIs(i) => { - self.ecx.expr_call_global(sp, ctpath("CountIs"), + self.ecx.expr_call_global(sp, rtpath("CountIs"), ~[self.ecx.expr_uint(sp, i)]) } parse::CountIsParam(i) => { - self.ecx.expr_call_global(sp, ctpath("CountIsParam"), + self.ecx.expr_call_global(sp, rtpath("CountIsParam"), ~[self.ecx.expr_uint(sp, i)]) } parse::CountImplied => { - let path = self.ecx.path_global(sp, ctpath("CountImplied")); + let path = self.ecx.path_global(sp, rtpath("CountImplied")); self.ecx.expr_path(path) } parse::CountIsNextParam => { - let path = self.ecx.path_global(sp, ctpath("CountIsNextParam")); + let path = self.ecx.path_global(sp, rtpath("CountIsNextParam")); self.ecx.expr_path(path) } + parse::CountIsName(n) => { + let n = n.to_managed(); + let i = match self.name_positions.find_copy(&n) { + Some(i) => i, + None => 0, // error already emitted elsewhere + }; + let i = i + self.args.len(); + self.ecx.expr_call_global(sp, rtpath("CountIsParam"), + ~[self.ecx.expr_uint(sp, i)]) + } } }; let trans_method = |method: &parse::Method| { diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs index 372bf803ec459..22710ad90e873 100644 --- a/src/test/compile-fail/lint-missing-doc.rs +++ b/src/test/compile-fail/lint-missing-doc.rs @@ -29,6 +29,9 @@ pub struct PubFoo2 { c: int, } +mod module_no_dox {} +pub mod pub_module_no_dox {} //~ ERROR: missing documentation + /// dox pub fn foo() {} pub fn foo2() {} //~ ERROR: missing documentation diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index 7611871b0e760..75d11eddb1bc6 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -119,7 +119,10 @@ pub fn main() { t!(format!("{:0>2s}", "a"), "0a"); t!(format!("{:.*s}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa"); t!(format!("{:.1$s}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa"); + t!(format!("{:.a$s}", "aaaaaaaaaaaaaaaaaa", a=4), "aaaa"); t!(format!("{:1$s}", "a", 4), "a "); + t!(format!("{1:0$s}", 4, "a"), "a "); + t!(format!("{:a$s}", "a", a=4), "a "); t!(format!("{:-#s}", "a"), "a"); t!(format!("{:+#s}", "a"), "a");