diff options
| author | Pietro Albini <pietro@pietroalbini.org> | 2018-09-22 09:56:30 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-09-22 09:56:30 +0200 |
| commit | 23636e3f99ea8dba2d5e91637d818ebfbe6c1b96 (patch) | |
| tree | d25f86f367b740a63971e965a2e819106aba593a /src | |
| parent | e59df621a85e40a1c99d134f3f0d1a7d17db4ff5 (diff) | |
| parent | 06b197582e1974e925925d28196b1ed867208ebf (diff) | |
| download | rust-23636e3f99ea8dba2d5e91637d818ebfbe6c1b96.tar.gz rust-23636e3f99ea8dba2d5e91637d818ebfbe6c1b96.zip | |
Rollup merge of #54350 - Munksgaard:support-edition-in-doc-test, r=steveklabnik
Support specifying edition in doc test Fixes #52623 r? @QuietMisdreavus
Diffstat (limited to 'src')
| -rw-r--r-- | src/doc/rustdoc/src/documentation-tests.md | 16 | ||||
| -rw-r--r-- | src/doc/unstable-book/src/language-features/try-blocks.md | 4 | ||||
| -rw-r--r-- | src/librustdoc/html/markdown.rs | 107 | ||||
| -rw-r--r-- | src/librustdoc/test.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax_pos/edition.rs | 2 | ||||
| -rw-r--r-- | src/test/rustdoc/edition-doctest.rs | 54 |
6 files changed, 149 insertions, 36 deletions
diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index e4af122d0cb..dd8dcb7ff9b 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -323,6 +323,22 @@ compiles, then the test will fail. However please note that code failing with the current Rust release may work in a future release, as new features are added. +```text +/// Only runs on the 2018 edition. +/// +/// ```edition2018 +/// let result: Result<i32, ParseIntError> = try { +/// "1".parse::<i32>()? +/// + "2".parse::<i32>()? +/// + "3".parse::<i32>()? +/// }; +/// ``` +``` + +`edition2018` tells `rustdoc` that the code sample should be compiled the 2018 +edition of Rust. Similarly, you can specify `edition2015` to compile the code +with the 2015 edition. + ## Syntax reference The *exact* syntax for code blocks, including the edge cases, can be found diff --git a/src/doc/unstable-book/src/language-features/try-blocks.md b/src/doc/unstable-book/src/language-features/try-blocks.md index 866b37a39a7..e342c260a73 100644 --- a/src/doc/unstable-book/src/language-features/try-blocks.md +++ b/src/doc/unstable-book/src/language-features/try-blocks.md @@ -9,9 +9,7 @@ The tracking issue for this feature is: [#31436] The `try_blocks` feature adds support for `try` blocks. A `try` block creates a new scope one can use the `?` operator in. -```rust,ignore -// This code needs the 2018 edition - +```rust,edition2018 #![feature(try_blocks)] use std::num::ParseIntError; diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 18ad862c11b..d14275aeb6b 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -37,6 +37,7 @@ use std::fmt::{self, Write}; use std::borrow::Cow; use std::ops::Range; use std::str; +use syntax::edition::Edition; use html::toc::TocBuilder; use html::highlight; @@ -170,6 +171,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> { let event = self.inner.next(); let compile_fail; let ignore; + let edition; if let Some(Event::Start(Tag::CodeBlock(lang))) = event { let parse_result = LangString::parse(&lang, self.check_error_codes); if !parse_result.rust { @@ -177,6 +179,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> { } compile_fail = parse_result.compile_fail; ignore = parse_result.ignore; + edition = parse_result.edition; } else { return event; } @@ -212,6 +215,17 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> { } else { "" }; + + let edition_string = if let Some(e @ Edition::Edition2018) = edition { + format!("&edition={}{}", e, + if channel == "&version=nightly" { "" } + else { "&version=nightly" }) + } else if let Some(e) = edition { + format!("&edition={}", e) + } else { + "".to_owned() + }; + // These characters don't need to be escaped in a URI. // FIXME: use a library function for percent encoding. fn dont_escape(c: u8) -> bool { @@ -231,26 +245,44 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> { } } Some(format!( - r#"<a class="test-arrow" target="_blank" href="{}?code={}{}">Run</a>"#, - url, test_escaped, channel + r#"<a class="test-arrow" target="_blank" href="{}?code={}{}{}">Run</a>"#, + url, test_escaped, channel, edition_string )) }); + let tooltip = if ignore { - Some(("This example is not tested", "ignore")) + Some(("This example is not tested".to_owned(), "ignore")) } else if compile_fail { - Some(("This example deliberately fails to compile", "compile_fail")) + Some(("This example deliberately fails to compile".to_owned(), "compile_fail")) + } else if let Some(e) = edition { + Some((format!("This code runs with edition {}", e), "edition")) } else { None }; - s.push_str(&highlight::render_with_highlighting( - &text, - Some(&format!("rust-example-rendered{}", - if ignore { " ignore" } - else if compile_fail { " compile_fail" } - else { "" })), - playground_button.as_ref().map(String::as_str), - tooltip)); - Some(Event::Html(s.into())) + + if let Some((s1, s2)) = tooltip { + s.push_str(&highlight::render_with_highlighting( + &text, + Some(&format!("rust-example-rendered{}", + if ignore { " ignore" } + else if compile_fail { " compile_fail" } + else if edition.is_some() { " edition " } + else { "" })), + playground_button.as_ref().map(String::as_str), + Some((s1.as_str(), s2)))); + Some(Event::Html(s.into())) + } else { + s.push_str(&highlight::render_with_highlighting( + &text, + Some(&format!("rust-example-rendered{}", + if ignore { " ignore" } + else if compile_fail { " compile_fail" } + else if edition.is_some() { " edition " } + else { "" })), + playground_button.as_ref().map(String::as_str), + None)); + Some(Event::Html(s.into())) + } }) } } @@ -577,6 +609,7 @@ pub struct LangString { pub compile_fail: bool, pub error_codes: Vec<String>, pub allow_fail: bool, + pub edition: Option<Edition> } impl LangString { @@ -591,6 +624,7 @@ impl LangString { compile_fail: false, error_codes: Vec::new(), allow_fail: false, + edition: None, } } @@ -625,6 +659,11 @@ impl LangString { seen_rust_tags = !seen_other_tags || seen_rust_tags; data.no_run = true; } + x if allow_error_code_check && x.starts_with("edition") => { + // allow_error_code_check is true if we're on nightly, which + // is needed for edition support + data.edition = x[7..].parse::<Edition>().ok(); + } x if allow_error_code_check && x.starts_with("E") && x.len() == 5 => { if x[1..].parse::<u32>().is_ok() { data.error_codes.push(x.to_owned()); @@ -925,12 +964,14 @@ mod tests { use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap}; use super::plain_summary_line; use std::cell::RefCell; + use syntax::edition::Edition; #[test] fn test_lang_string_parse() { fn t(s: &str, should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool, - compile_fail: bool, allow_fail: bool, error_codes: Vec<String>) { + compile_fail: bool, allow_fail: bool, error_codes: Vec<String>, + edition: Option<Edition>) { assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString { should_panic, no_run, @@ -941,6 +982,7 @@ mod tests { error_codes, original: s.to_owned(), allow_fail, + edition, }) } @@ -948,23 +990,26 @@ mod tests { Vec::new() } - // marker | should_panic| no_run| ignore| rust | test_harness| compile_fail - // | allow_fail | error_codes - t("", false, false, false, true, false, false, false, v()); - t("rust", false, false, false, true, false, false, false, v()); - t("sh", false, false, false, false, false, false, false, v()); - t("ignore", false, false, true, true, false, false, false, v()); - t("should_panic", true, false, false, true, false, false, false, v()); - t("no_run", false, true, false, true, false, false, false, v()); - t("test_harness", false, false, false, true, true, false, false, v()); - t("compile_fail", false, true, false, true, false, true, false, v()); - t("allow_fail", false, false, false, true, false, false, true, v()); - t("{.no_run .example}", false, true, false, true, false, false, false, v()); - t("{.sh .should_panic}", true, false, false, false, false, false, false, v()); - t("{.example .rust}", false, false, false, true, false, false, false, v()); - t("{.test_harness .rust}", false, false, false, true, true, false, false, v()); - t("text, no_run", false, true, false, false, false, false, false, v()); - t("text,no_run", false, true, false, false, false, false, false, v()); + // ignore-tidy-linelength + // marker | should_panic | no_run | ignore | rust | test_harness + // | compile_fail | allow_fail | error_codes | edition + t("", false, false, false, true, false, false, false, v(), None); + t("rust", false, false, false, true, false, false, false, v(), None); + t("sh", false, false, false, false, false, false, false, v(), None); + t("ignore", false, false, true, true, false, false, false, v(), None); + t("should_panic", true, false, false, true, false, false, false, v(), None); + t("no_run", false, true, false, true, false, false, false, v(), None); + t("test_harness", false, false, false, true, true, false, false, v(), None); + t("compile_fail", false, true, false, true, false, true, false, v(), None); + t("allow_fail", false, false, false, true, false, false, true, v(), None); + t("{.no_run .example}", false, true, false, true, false, false, false, v(), None); + t("{.sh .should_panic}", true, false, false, false, false, false, false, v(), None); + t("{.example .rust}", false, false, false, true, false, false, false, v(), None); + t("{.test_harness .rust}", false, false, false, true, true, false, false, v(), None); + t("text, no_run", false, true, false, false, false, false, false, v(), None); + t("text,no_run", false, true, false, false, false, false, false, v(), None); + t("edition2015", false, false, false, true, false, false, false, v(), Some(Edition::Edition2015)); + t("edition2018", false, false, false, true, false, false, false, v(), Some(Edition::Edition2018)); } #[test] diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 8a9ca924ee1..dbebc3ab393 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -545,7 +545,7 @@ impl Collector { let opts = self.opts.clone(); let maybe_sysroot = self.maybe_sysroot.clone(); let linker = self.linker.clone(); - let edition = self.edition; + let edition = config.edition.unwrap_or(self.edition); debug!("Creating test {}: {}", name, test); self.tests.push(testing::TestDescAndFn { desc: testing::TestDesc { diff --git a/src/libsyntax_pos/edition.rs b/src/libsyntax_pos/edition.rs index 7709db72a02..5819cd7f480 100644 --- a/src/libsyntax_pos/edition.rs +++ b/src/libsyntax_pos/edition.rs @@ -12,7 +12,7 @@ use std::fmt; use std::str::FromStr; /// The edition of the compiler (RFC 2052) -#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)] #[non_exhaustive] pub enum Edition { // editions must be kept in order, oldest to newest diff --git a/src/test/rustdoc/edition-doctest.rs b/src/test/rustdoc/edition-doctest.rs new file mode 100644 index 00000000000..322d461f854 --- /dev/null +++ b/src/test/rustdoc/edition-doctest.rs @@ -0,0 +1,54 @@ +// Copyright 2018 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 + +/// ```rust,edition2018 +/// #![feature(try_blocks)] +/// +/// use std::num::ParseIntError; +/// +/// let result: Result<i32, ParseIntError> = try { +/// "1".parse::<i32>()? +/// + "2".parse::<i32>()? +/// + "3".parse::<i32>()? +/// }; +/// assert_eq!(result, Ok(6)); +/// +/// let result: Result<i32, ParseIntError> = try { +/// "1".parse::<i32>()? +/// + "foo".parse::<i32>()? +/// + "3".parse::<i32>()? +/// }; +/// assert!(result.is_err()); +/// ``` + + +/// ```rust,edition2015,compile_fail,E0574 +/// #![feature(try_blocks)] +/// +/// use std::num::ParseIntError; +/// +/// let result: Result<i32, ParseIntError> = try { +/// "1".parse::<i32>()? +/// + "2".parse::<i32>()? +/// + "3".parse::<i32>()? +/// }; +/// assert_eq!(result, Ok(6)); +/// +/// let result: Result<i32, ParseIntError> = try { +/// "1".parse::<i32>()? +/// + "foo".parse::<i32>()? +/// + "3".parse::<i32>()? +/// }; +/// assert!(result.is_err()); +/// ``` + +pub fn foo() {} |
