about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-04-04 01:01:51 -0700
committerbors <bors@rust-lang.org>2014-04-04 01:01:51 -0700
commit540c2a2a27846044b176f3ef82f5add2d703e10c (patch)
tree344d9b60b3abed0a6ae934af86b3dd0cfa5a1a06 /src
parent7056f97093a5b0bee3cacbdee2f9a60cfc1488f0 (diff)
parent78937b9779b1dac99546922740935aa96c87b6be (diff)
downloadrust-540c2a2a27846044b176f3ef82f5add2d703e10c.tar.gz
rust-540c2a2a27846044b176f3ef82f5add2d703e10c.zip
auto merge of #13255 : alexcrichton/rust/issue-5605, r=huonw
These syntax extensions need a place to be documented, and this starts passing a
`--cfg dox` parameter to `rustdoc` when building and testing documentation in
order to document macros so that they have no effect on the compiled crate, but
only documentation.

Closes #5605
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/lib.rs4
-rw-r--r--src/librustdoc/test.rs22
-rw-r--r--src/libstd/macros.rs259
3 files changed, 275 insertions, 10 deletions
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 35c2fd146cd..5e53632dbba 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -168,6 +168,7 @@ pub fn main_args(args: &[~str]) -> int {
     let markdown_input = input.ends_with(".md") || input.ends_with(".markdown");
 
     let output = matches.opt_str("o").map(|s| Path::new(s));
+    let cfgs = matches.opt_strs("cfg");
 
     match (should_test, markdown_input) {
         (true, true) => {
@@ -175,7 +176,8 @@ pub fn main_args(args: &[~str]) -> int {
                                   libs,
                                   test_args.move_iter().collect())
         }
-        (true, false) => return test::run(input, libs, test_args),
+        (true, false) => return test::run(input, cfgs.move_iter().collect(),
+                                          libs, test_args),
 
         (false, true) => return markdown::render(input, output.unwrap_or(Path::new("doc")),
                                                  &matches),
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index afc01d0eb62..2138d210443 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -22,8 +22,10 @@ use rustc::back::link;
 use rustc::driver::driver;
 use rustc::driver::session;
 use rustc::metadata::creader::Loader;
+use syntax::ast;
+use syntax::codemap::{CodeMap, dummy_spanned};
 use syntax::diagnostic;
-use syntax::codemap::CodeMap;
+use syntax::parse::token;
 
 use core;
 use clean;
@@ -33,7 +35,8 @@ use html::markdown;
 use passes;
 use visit_ast::RustdocVisitor;
 
-pub fn run(input: &str, libs: HashSet<Path>, mut test_args: Vec<~str>) -> int {
+pub fn run(input: &str, cfgs: Vec<~str>,
+           libs: HashSet<Path>, mut test_args: Vec<~str>) -> int {
     let input_path = Path::new(input);
     let input = driver::FileInput(input_path.clone());
 
@@ -54,7 +57,11 @@ pub fn run(input: &str, libs: HashSet<Path>, mut test_args: Vec<~str>) -> int {
                                       Some(input_path),
                                       span_diagnostic_handler);
 
-    let cfg = driver::build_configuration(&sess);
+    let mut cfg = driver::build_configuration(&sess);
+    cfg.extend(cfgs.move_iter().map(|cfg_| {
+        let cfg_ = token::intern_and_get_ident(cfg_);
+        @dummy_spanned(ast::MetaWord(cfg_))
+    }));
     let krate = driver::phase_1_parse_input(&sess, cfg, &input);
     let (krate, _) = driver::phase_2_configure_and_expand(&sess, &mut Loader::new(&sess), krate,
                                                           &from_str("rustdoc-test").unwrap());
@@ -160,17 +167,14 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
 
 fn maketest(s: &str, cratename: &str, loose_feature_gating: bool) -> ~str {
     let mut prog = ~r"
-#[deny(warnings)];
-#[allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)];
-
-// FIXME: remove when ~[] disappears from tests.
-#[allow(deprecated_owned_vector)];
+#![deny(warnings)]
+#![allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)]
 ";
 
     if loose_feature_gating {
         // FIXME #12773: avoid inserting these when the tutorial & manual
         // etc. have been updated to not use them so prolifically.
-        prog.push_str("#[ feature(macro_rules, globs, struct_variant, managed_boxes) ];\n");
+        prog.push_str("#![feature(macro_rules, globs, struct_variant, managed_boxes) ]\n");
     }
 
     if !s.contains("extern crate") {
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 9b1c5a406cf..1a35252f8ca 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -332,3 +332,262 @@ macro_rules! log (
         if log_enabled!($lvl) { println!($($args)*) }
     )
 )
+
+/// Built-in macros to the compiler itself.
+///
+/// These macros do not have any corresponding definition with a `macro_rules!`
+/// macro, but are documented here. Their implementations can be found hardcoded
+/// into libsyntax itself.
+#[cfg(dox)]
+pub mod builtin {
+    /// The core macro for formatted string creation & output.
+    ///
+    /// This macro takes as its first argument a callable expression which will
+    /// receive as its first argument a value of type `&fmt::Arguments`. This
+    /// value can be passed to the functions in `std::fmt` for performing useful
+    /// functions. All other formatting macros (`format!`, `write!`,
+    /// `println!`, etc) are proxied through this one.
+    ///
+    /// For more information, see the documentation in `std::fmt`.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::fmt;
+    ///
+    /// let s = format_args!(fmt::format, "hello {}", "world");
+    /// assert_eq!(s, format!("hello {}", "world"));
+    ///
+    /// format_args!(|args| {
+    ///     // pass `args` to another function, etc.
+    /// }, "hello {}", "world");
+    /// ```
+    #[macro_export]
+    macro_rules! format_args( ($closure:expr, $fmt:expr $($args:tt)*) => ({
+        /* compiler built-in */
+    }) )
+
+    /// Inspect an environment variable at compile time.
+    ///
+    /// This macro will expand to the value of the named environment variable at
+    /// compile time, yielding an expression of type `&'static str`.
+    ///
+    /// If the environment variable is not defined, then a compilation error
+    /// will be emitted.  To not emit a compile error, use the `option_env!`
+    /// macro instead.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let user: &'static str = env!("USER");
+    /// println!("the user who compiled this code is: {}", user);
+    /// ```
+    #[macro_export]
+    macro_rules! env( ($name:expr) => ({ /* compiler built-in */ }) )
+
+    /// Optionally inspect an environment variable at compile time.
+    ///
+    /// If the named environment variable is present at compile time, this will
+    /// expand into an expression of type `Option<&'static str>` whose value is
+    /// `Some` of the value of the environment variable. If the environment
+    /// variable is not present, then this will expand to `None`.
+    ///
+    /// A compile time error is never emitted when using this macro regardless
+    /// of whether the environment variable is present or not.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let key: Option<&'static str> = option_env!("SECRET_KEY");
+    /// println!("the secret key might be: {}", key);
+    /// ```
+    #[macro_export]
+    macro_rules! option_env( ($name:expr) => ({ /* compiler built-in */ }) )
+
+    /// Concatenate literals into a static byte slice.
+    ///
+    /// This macro takes any number of comma-separated literal expressions,
+    /// yielding an expression of type `&'static [u8]` which is the
+    /// concatenation (left to right) of all the literals in their byte format.
+    ///
+    /// This extension currently only supports string literals, character
+    /// literals, and integers less than 256. The byte slice returned is the
+    /// utf8-encoding of strings and characters.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// let rust = bytes!("r", 'u', "st");
+    /// assert_eq!(rust[1], 'u' as u8);
+    /// ```
+    #[macro_export]
+    macro_rules! bytes( ($($e:expr),*) => ({ /* compiler built-in */ }) )
+
+    /// Concatenate identifiers into one identifier.
+    ///
+    /// This macro takes any number of comma-separated identifiers, and
+    /// concatenates them all into one, yielding an expression which is a new
+    /// identifier. Note that hygiene makes it such that this macro cannot
+    /// capture local variables, and macros are only allowed in item,
+    /// statement or expression position, meaning this macro may be difficult to
+    /// use in some situations.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// fn foobar() -> int { 23 }
+    ///
+    /// let f = concat_idents!(foo, bar);
+    /// println!("{}", f());
+    /// ```
+    #[macro_export]
+    macro_rules! concat_idents( ($($e:ident),*) => ({ /* compiler built-in */ }) )
+
+    /// Concatenates literals into a static string slice.
+    ///
+    /// This macro takes any number of comma-separated literals, yielding an
+    /// expression of type `&'static str` which represents all of the literals
+    /// concatenated left-to-right.
+    ///
+    /// Integer and floating point literals are stringified in order to be
+    /// concatenated.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// let s = concat!("test", 10, 'b', true);
+    /// assert_eq!(s, "test10btrue");
+    /// ```
+    #[macro_export]
+    macro_rules! concat( ($($e:expr),*) => ({ /* compiler built-in */ }) )
+
+    /// A macro which expands to the line number on which it was invoked.
+    ///
+    /// The expanded expression has type `uint`, and the returned line is not
+    /// the invocation of the `line!()` macro itself, but rather the first macro
+    /// invocation leading up to the invocation of the `line!()` macro.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// let current_line = line!();
+    /// println!("defined on line: {}", current_line);
+    /// ```
+    #[macro_export]
+    macro_rules! line( () => ({ /* compiler built-in */ }) )
+
+    /// A macro which expands to the column number on which it was invoked.
+    ///
+    /// The expanded expression has type `uint`, and the returned column is not
+    /// the invocation of the `col!()` macro itself, but rather the first macro
+    /// invocation leading up to the invocation of the `col!()` macro.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// let current_col = col!();
+    /// println!("defined on column: {}", current_col);
+    /// ```
+    #[macro_export]
+    macro_rules! col( () => ({ /* compiler built-in */ }) )
+
+    /// A macro which expands to the file name from which it was invoked.
+    ///
+    /// The expanded expression has type `&'static str`, and the returned file
+    /// is not the invocation of the `file!()` macro itself, but rather the
+    /// first macro invocation leading up to the invocation of the `file!()`
+    /// macro.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// let this_file = file!();
+    /// println!("defined in file: {}", this_file);
+    /// ```
+    #[macro_export]
+    macro_rules! file( () => ({ /* compiler built-in */ }) )
+
+    /// A macro which stringifies its argument.
+    ///
+    /// This macro will yield an expression of type `&'static str` which is the
+    /// stringification of all the tokens passed to the macro. No restrictions
+    /// are placed on the syntax of the macro invocation itself.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// let one_plus_one = stringify!(1 + 1);
+    /// assert_eq!(one_plus_one, "1 + 1");
+    /// ```
+    #[macro_export]
+    macro_rules! stringify( ($t:tt) => ({ /* compiler built-in */ }) )
+
+    /// Includes a utf8-encoded file as a string.
+    ///
+    /// This macro will yield an expression of type `&'static str` which is the
+    /// contents of the filename specified. The file is located relative to the
+    /// current file (similarly to how modules are found),
+    ///
+    /// # Example
+    ///
+    /// ```rust,ignore
+    /// let secret_key = include_str!("secret-key.ascii");
+    /// ```
+    #[macro_export]
+    macro_rules! include_str( ($file:expr) => ({ /* compiler built-in */ }) )
+
+    /// Includes a file as a byte slice.
+    ///
+    /// This macro will yield an expression of type `&'static [u8]` which is
+    /// the contents of the filename specified. The file is located relative to
+    /// the current file (similarly to how modules are found),
+    ///
+    /// # Example
+    ///
+    /// ```rust,ignore
+    /// let secret_key = include_bin!("secret-key.bin");
+    /// ```
+    #[macro_export]
+    macro_rules! include_bin( ($file:expr) => ({ /* compiler built-in */ }) )
+
+    /// Expands to a string that represents the current module path.
+    ///
+    /// The current module path can be thought of as the hierarchy of modules
+    /// leading back up to the crate root. The first component of the path
+    /// returned is the name of the crate currently being compiled.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// mod test {
+    ///     pub fn foo() {
+    ///         assert!(module_path!().ends_with("test"));
+    ///     }
+    /// }
+    ///
+    /// test::foo();
+    /// ```
+    #[macro_export]
+    macro_rules! module_path( () => ({ /* compiler built-in */ }) )
+
+    /// Boolean evaluation of configuration flags.
+    ///
+    /// In addition to the `#[cfg]` attribute, this macro is provided to allow
+    /// boolean expression evaluation of configuration flags. This frequently
+    /// leads to less duplicated code.
+    ///
+    /// The syntax given to this macro is the same syntax as the `cfg`
+    /// attribute.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let my_directory = if cfg!(windows) {
+    ///     "windows-specific-directory"
+    /// } else {
+    ///     "unix-directory"
+    /// };
+    /// ```
+    #[macro_export]
+    macro_rules! cfg( ($cfg:tt) => ({ /* compiler built-in */ }) )
+}