Skip to content

Commit 78937b9

Browse files
committed
std: Document builtin syntax extensions
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
1 parent bb31cb8 commit 78937b9

File tree

5 files changed

+277
-12
lines changed

5 files changed

+277
-12
lines changed

mk/docs.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ endif
271271
$(2) += doc/$(1)/index.html
272272
doc/$(1)/index.html: $$(LIB_DOC_DEP_$(1))
273273
@$$(call E, rustdoc $$@)
274-
$$(Q)$$(RUSTDOC) --cfg stage2 $$<
274+
$$(Q)$$(RUSTDOC) --cfg dox --cfg stage2 $$<
275275
endef
276276

277277
$(foreach crate,$(DOC_CRATES),$(eval $(call DEF_LIB_DOC,$(crate),DOC_TARGETS)))

mk/tests.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ endif
694694
ifeq ($(2),$$(CFG_BUILD))
695695
$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)): $$(DOCTESTDEP_$(1)_$(2)_$(3)_$(4))
696696
@$$(call E, run doc-$(4) [$(2)])
697-
$$(Q)$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test $$< --test-args "$$(TESTARGS)" && touch $$@
697+
$$(Q)$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --cfg dox --test $$< --test-args "$$(TESTARGS)" && touch $$@
698698
else
699699
$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)):
700700
touch $$@

src/librustdoc/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,16 @@ pub fn main_args(args: &[~str]) -> int {
168168
let markdown_input = input.ends_with(".md") || input.ends_with(".markdown");
169169

170170
let output = matches.opt_str("o").map(|s| Path::new(s));
171+
let cfgs = matches.opt_strs("cfg");
171172

172173
match (should_test, markdown_input) {
173174
(true, true) => {
174175
return markdown::test(input,
175176
libs,
176177
test_args.move_iter().collect())
177178
}
178-
(true, false) => return test::run(input, libs, test_args),
179+
(true, false) => return test::run(input, cfgs.move_iter().collect(),
180+
libs, test_args),
179181

180182
(false, true) => return markdown::render(input, output.unwrap_or(Path::new("doc")),
181183
&matches),

src/librustdoc/test.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ use rustc::back::link;
2222
use rustc::driver::driver;
2323
use rustc::driver::session;
2424
use rustc::metadata::creader::Loader;
25+
use syntax::ast;
26+
use syntax::codemap::{CodeMap, dummy_spanned};
2527
use syntax::diagnostic;
26-
use syntax::codemap::CodeMap;
28+
use syntax::parse::token;
2729

2830
use core;
2931
use clean;
@@ -33,7 +35,8 @@ use html::markdown;
3335
use passes;
3436
use visit_ast::RustdocVisitor;
3537

36-
pub fn run(input: &str, libs: HashSet<Path>, mut test_args: Vec<~str>) -> int {
38+
pub fn run(input: &str, cfgs: Vec<~str>,
39+
libs: HashSet<Path>, mut test_args: Vec<~str>) -> int {
3740
let input_path = Path::new(input);
3841
let input = driver::FileInput(input_path.clone());
3942

@@ -54,7 +57,11 @@ pub fn run(input: &str, libs: HashSet<Path>, mut test_args: Vec<~str>) -> int {
5457
Some(input_path),
5558
span_diagnostic_handler);
5659

57-
let cfg = driver::build_configuration(&sess);
60+
let mut cfg = driver::build_configuration(&sess);
61+
cfg.extend(cfgs.move_iter().map(|cfg_| {
62+
let cfg_ = token::intern_and_get_ident(cfg_);
63+
@dummy_spanned(ast::MetaWord(cfg_))
64+
}));
5865
let krate = driver::phase_1_parse_input(&sess, cfg, &input);
5966
let (krate, _) = driver::phase_2_configure_and_expand(&sess, &mut Loader::new(&sess), krate,
6067
&from_str("rustdoc-test").unwrap());
@@ -160,17 +167,14 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
160167

161168
fn maketest(s: &str, cratename: &str, loose_feature_gating: bool) -> ~str {
162169
let mut prog = ~r"
163-
#[deny(warnings)];
164-
#[allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)];
165-
166-
// FIXME: remove when ~[] disappears from tests.
167-
#[allow(deprecated_owned_vector)];
170+
#![deny(warnings)]
171+
#![allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)]
168172
";
169173

170174
if loose_feature_gating {
171175
// FIXME #12773: avoid inserting these when the tutorial & manual
172176
// etc. have been updated to not use them so prolifically.
173-
prog.push_str("#[ feature(macro_rules, globs, struct_variant, managed_boxes) ];\n");
177+
prog.push_str("#![feature(macro_rules, globs, struct_variant, managed_boxes) ]\n");
174178
}
175179

176180
if !s.contains("extern crate") {

src/libstd/macros.rs

+259
Original file line numberDiff line numberDiff line change
@@ -332,3 +332,262 @@ macro_rules! log (
332332
if log_enabled!($lvl) { println!($($args)*) }
333333
)
334334
)
335+
336+
/// Built-in macros to the compiler itself.
337+
///
338+
/// These macros do not have any corresponding definition with a `macro_rules!`
339+
/// macro, but are documented here. Their implementations can be found hardcoded
340+
/// into libsyntax itself.
341+
#[cfg(dox)]
342+
pub mod builtin {
343+
/// The core macro for formatted string creation & output.
344+
///
345+
/// This macro takes as its first argument a callable expression which will
346+
/// receive as its first argument a value of type `&fmt::Arguments`. This
347+
/// value can be passed to the functions in `std::fmt` for performing useful
348+
/// functions. All other formatting macros (`format!`, `write!`,
349+
/// `println!`, etc) are proxied through this one.
350+
///
351+
/// For more information, see the documentation in `std::fmt`.
352+
///
353+
/// # Example
354+
///
355+
/// ```rust
356+
/// use std::fmt;
357+
///
358+
/// let s = format_args!(fmt::format, "hello {}", "world");
359+
/// assert_eq!(s, format!("hello {}", "world"));
360+
///
361+
/// format_args!(|args| {
362+
/// // pass `args` to another function, etc.
363+
/// }, "hello {}", "world");
364+
/// ```
365+
#[macro_export]
366+
macro_rules! format_args( ($closure:expr, $fmt:expr $($args:tt)*) => ({
367+
/* compiler built-in */
368+
}) )
369+
370+
/// Inspect an environment variable at compile time.
371+
///
372+
/// This macro will expand to the value of the named environment variable at
373+
/// compile time, yielding an expression of type `&'static str`.
374+
///
375+
/// If the environment variable is not defined, then a compilation error
376+
/// will be emitted. To not emit a compile error, use the `option_env!`
377+
/// macro instead.
378+
///
379+
/// # Example
380+
///
381+
/// ```rust
382+
/// let user: &'static str = env!("USER");
383+
/// println!("the user who compiled this code is: {}", user);
384+
/// ```
385+
#[macro_export]
386+
macro_rules! env( ($name:expr) => ({ /* compiler built-in */ }) )
387+
388+
/// Optionally inspect an environment variable at compile time.
389+
///
390+
/// If the named environment variable is present at compile time, this will
391+
/// expand into an expression of type `Option<&'static str>` whose value is
392+
/// `Some` of the value of the environment variable. If the environment
393+
/// variable is not present, then this will expand to `None`.
394+
///
395+
/// A compile time error is never emitted when using this macro regardless
396+
/// of whether the environment variable is present or not.
397+
///
398+
/// # Example
399+
///
400+
/// ```rust
401+
/// let key: Option<&'static str> = option_env!("SECRET_KEY");
402+
/// println!("the secret key might be: {}", key);
403+
/// ```
404+
#[macro_export]
405+
macro_rules! option_env( ($name:expr) => ({ /* compiler built-in */ }) )
406+
407+
/// Concatenate literals into a static byte slice.
408+
///
409+
/// This macro takes any number of comma-separated literal expressions,
410+
/// yielding an expression of type `&'static [u8]` which is the
411+
/// concatenation (left to right) of all the literals in their byte format.
412+
///
413+
/// This extension currently only supports string literals, character
414+
/// literals, and integers less than 256. The byte slice returned is the
415+
/// utf8-encoding of strings and characters.
416+
///
417+
/// # Example
418+
///
419+
/// ```
420+
/// let rust = bytes!("r", 'u', "st");
421+
/// assert_eq!(rust[1], 'u' as u8);
422+
/// ```
423+
#[macro_export]
424+
macro_rules! bytes( ($($e:expr),*) => ({ /* compiler built-in */ }) )
425+
426+
/// Concatenate identifiers into one identifier.
427+
///
428+
/// This macro takes any number of comma-separated identifiers, and
429+
/// concatenates them all into one, yielding an expression which is a new
430+
/// identifier. Note that hygiene makes it such that this macro cannot
431+
/// capture local variables, and macros are only allowed in item,
432+
/// statement or expression position, meaning this macro may be difficult to
433+
/// use in some situations.
434+
///
435+
/// # Example
436+
///
437+
/// ```
438+
/// fn foobar() -> int { 23 }
439+
///
440+
/// let f = concat_idents!(foo, bar);
441+
/// println!("{}", f());
442+
/// ```
443+
#[macro_export]
444+
macro_rules! concat_idents( ($($e:ident),*) => ({ /* compiler built-in */ }) )
445+
446+
/// Concatenates literals into a static string slice.
447+
///
448+
/// This macro takes any number of comma-separated literals, yielding an
449+
/// expression of type `&'static str` which represents all of the literals
450+
/// concatenated left-to-right.
451+
///
452+
/// Integer and floating point literals are stringified in order to be
453+
/// concatenated.
454+
///
455+
/// # Example
456+
///
457+
/// ```
458+
/// let s = concat!("test", 10, 'b', true);
459+
/// assert_eq!(s, "test10btrue");
460+
/// ```
461+
#[macro_export]
462+
macro_rules! concat( ($($e:expr),*) => ({ /* compiler built-in */ }) )
463+
464+
/// A macro which expands to the line number on which it was invoked.
465+
///
466+
/// The expanded expression has type `uint`, and the returned line is not
467+
/// the invocation of the `line!()` macro itself, but rather the first macro
468+
/// invocation leading up to the invocation of the `line!()` macro.
469+
///
470+
/// # Example
471+
///
472+
/// ```
473+
/// let current_line = line!();
474+
/// println!("defined on line: {}", current_line);
475+
/// ```
476+
#[macro_export]
477+
macro_rules! line( () => ({ /* compiler built-in */ }) )
478+
479+
/// A macro which expands to the column number on which it was invoked.
480+
///
481+
/// The expanded expression has type `uint`, and the returned column is not
482+
/// the invocation of the `col!()` macro itself, but rather the first macro
483+
/// invocation leading up to the invocation of the `col!()` macro.
484+
///
485+
/// # Example
486+
///
487+
/// ```
488+
/// let current_col = col!();
489+
/// println!("defined on column: {}", current_col);
490+
/// ```
491+
#[macro_export]
492+
macro_rules! col( () => ({ /* compiler built-in */ }) )
493+
494+
/// A macro which expands to the file name from which it was invoked.
495+
///
496+
/// The expanded expression has type `&'static str`, and the returned file
497+
/// is not the invocation of the `file!()` macro itself, but rather the
498+
/// first macro invocation leading up to the invocation of the `file!()`
499+
/// macro.
500+
///
501+
/// # Example
502+
///
503+
/// ```
504+
/// let this_file = file!();
505+
/// println!("defined in file: {}", this_file);
506+
/// ```
507+
#[macro_export]
508+
macro_rules! file( () => ({ /* compiler built-in */ }) )
509+
510+
/// A macro which stringifies its argument.
511+
///
512+
/// This macro will yield an expression of type `&'static str` which is the
513+
/// stringification of all the tokens passed to the macro. No restrictions
514+
/// are placed on the syntax of the macro invocation itself.
515+
///
516+
/// # Example
517+
///
518+
/// ```
519+
/// let one_plus_one = stringify!(1 + 1);
520+
/// assert_eq!(one_plus_one, "1 + 1");
521+
/// ```
522+
#[macro_export]
523+
macro_rules! stringify( ($t:tt) => ({ /* compiler built-in */ }) )
524+
525+
/// Includes a utf8-encoded file as a string.
526+
///
527+
/// This macro will yield an expression of type `&'static str` which is the
528+
/// contents of the filename specified. The file is located relative to the
529+
/// current file (similarly to how modules are found),
530+
///
531+
/// # Example
532+
///
533+
/// ```rust,ignore
534+
/// let secret_key = include_str!("secret-key.ascii");
535+
/// ```
536+
#[macro_export]
537+
macro_rules! include_str( ($file:expr) => ({ /* compiler built-in */ }) )
538+
539+
/// Includes a file as a byte slice.
540+
///
541+
/// This macro will yield an expression of type `&'static [u8]` which is
542+
/// the contents of the filename specified. The file is located relative to
543+
/// the current file (similarly to how modules are found),
544+
///
545+
/// # Example
546+
///
547+
/// ```rust,ignore
548+
/// let secret_key = include_bin!("secret-key.bin");
549+
/// ```
550+
#[macro_export]
551+
macro_rules! include_bin( ($file:expr) => ({ /* compiler built-in */ }) )
552+
553+
/// Expands to a string that represents the current module path.
554+
///
555+
/// The current module path can be thought of as the hierarchy of modules
556+
/// leading back up to the crate root. The first component of the path
557+
/// returned is the name of the crate currently being compiled.
558+
///
559+
/// # Example
560+
///
561+
/// ```rust
562+
/// mod test {
563+
/// pub fn foo() {
564+
/// assert!(module_path!().ends_with("test"));
565+
/// }
566+
/// }
567+
///
568+
/// test::foo();
569+
/// ```
570+
#[macro_export]
571+
macro_rules! module_path( () => ({ /* compiler built-in */ }) )
572+
573+
/// Boolean evaluation of configuration flags.
574+
///
575+
/// In addition to the `#[cfg]` attribute, this macro is provided to allow
576+
/// boolean expression evaluation of configuration flags. This frequently
577+
/// leads to less duplicated code.
578+
///
579+
/// The syntax given to this macro is the same syntax as the `cfg`
580+
/// attribute.
581+
///
582+
/// # Example
583+
///
584+
/// ```rust
585+
/// let my_directory = if cfg!(windows) {
586+
/// "windows-specific-directory"
587+
/// } else {
588+
/// "unix-directory"
589+
/// };
590+
/// ```
591+
#[macro_export]
592+
macro_rules! cfg( ($cfg:tt) => ({ /* compiler built-in */ }) )
593+
}

0 commit comments

Comments
 (0)