From d39d4517aa1e30bfdfefaf5b07235bd522eab9d1 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Sun, 17 Nov 2019 21:36:10 +0300 Subject: [PATCH 1/4] Add support for Rust edition --- book-example/book.toml | 1 + book-example/src/format/config.md | 5 +- src/book/mod.rs | 22 +++++-- src/config.rs | 105 ++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 7 deletions(-) diff --git a/book-example/book.toml b/book-example/book.toml index 100247fa..0c5ece6b 100644 --- a/book-example/book.toml +++ b/book-example/book.toml @@ -3,6 +3,7 @@ title = "mdBook Documentation" description = "Create book from markdown files. Like Gitbook but implemented in Rust" authors = ["Mathieu David", "Michael-F-Bryan"] language = "en" +edition = "2018" [output.html] mathjax-support = true diff --git a/book-example/src/format/config.md b/book-example/src/format/config.md index e1145aa8..0b671557 100644 --- a/book-example/src/format/config.md +++ b/book-example/src/format/config.md @@ -9,6 +9,7 @@ Here is an example of what a ***book.toml*** file might look like: title = "Example book" author = "John Doe" description = "The example book covers examples." +edition = "2018" [build] build-dir = "my-example-book" @@ -43,6 +44,7 @@ This is general information about your book. `src` directly under the root folder. But this is configurable with the `src` key in the configuration file. - **language:** The main language of the book, which is used as a language attribute `` for example. +- **edition**: Rust edition to use by default for the code snippets. Defaults to `rustdoc` defaults (2015). **book.toml** ```toml @@ -52,6 +54,7 @@ authors = ["John Doe", "Jane Doe"] description = "The example book covers examples." src = "my-src" # the source files will be found in `root/my-src` instead of `root/src` language = "en" +edition = "2018" ``` ### Build options @@ -178,7 +181,7 @@ The following configuration options are available: an icon link will be output in the menu bar of the book. - **git-repository-icon:** The FontAwesome icon class to use for the git repository link. Defaults to `fa-github`. - + Available configuration options for the `[output.html.fold]` table: - **enable:** Enable section-folding. When off, all folds are open. diff --git a/src/book/mod.rs b/src/book/mod.rs index 2015801c..959800ed 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -27,7 +27,7 @@ use crate::preprocess::{ use crate::renderer::{CmdRenderer, HtmlHandlebars, MarkdownRenderer, RenderContext, Renderer}; use crate::utils; -use crate::config::Config; +use crate::config::{Config, RustEdition}; /// The object used to manage and build a book. pub struct MDBook { @@ -262,11 +262,21 @@ impl MDBook { let mut tmpf = utils::fs::create_file(&path)?; tmpf.write_all(ch.content.as_bytes())?; - let output = Command::new("rustdoc") - .arg(&path) - .arg("--test") - .args(&library_args) - .output()?; + let mut cmd = Command::new("rustdoc"); + cmd.arg(&path).arg("--test").args(&library_args); + + if let Some(edition) = self.config.book.edition { + match edition { + RustEdition::E2015 => { + cmd.args(&["--edition", "2015"]); + } + RustEdition::E2018 => { + cmd.args(&["--edition", "2018"]); + } + } + } + + let output = cmd.output()?; if !output.status.success() { bail!(ErrorKind::Subprocess( diff --git a/src/config.rs b/src/config.rs index 18d70ed7..2c4e12d3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -393,6 +393,8 @@ pub struct BookConfig { pub multilingual: bool, /// The main language of the book. pub language: Option, + /// Rust edition to use for the code. + pub edition: Option, } impl Default for BookConfig { @@ -404,10 +406,60 @@ impl Default for BookConfig { src: PathBuf::from("src"), multilingual: false, language: Some(String::from("en")), + edition: None, } } } +#[derive(Debug, Copy, Clone, PartialEq)] +/// Rust edition to use for the code. +pub enum RustEdition { + /// The 2018 edition of Rust + E2018, + /// The 2015 edition of Rust + E2015, +} + +impl Serialize for RustEdition { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: Serializer, + { + match self { + RustEdition::E2015 => serializer.serialize_str("2015"), + RustEdition::E2018 => serializer.serialize_str("2018"), + } + } +} + +impl<'de> Deserialize<'de> for RustEdition { + fn deserialize(de: D) -> std::result::Result + where + D: Deserializer<'de>, + { + use serde::de::Error; + + let raw = Value::deserialize(de)?; + + let edition = match raw { + Value::String(s) => s, + _ => { + return Err(D::Error::custom("Rust edition should be a string")); + } + }; + + let edition = match edition.as_str() { + "2018" => RustEdition::E2018, + "2015" => RustEdition::E2015, + _ => { + return Err(D::Error::custom("Unknown Rust edition")); + } + }; + + Ok(edition) + } +} + /// Configuration for the build procedure. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(default, rename_all = "kebab-case")] @@ -647,6 +699,7 @@ mod tests { multilingual: true, src: PathBuf::from("source"), language: Some(String::from("ja")), + edition: None, }; let build_should_be = BuildConfig { build_dir: PathBuf::from("outputs"), @@ -678,6 +731,58 @@ mod tests { assert_eq!(got.html_config().unwrap(), html_should_be); } + #[test] + fn edition_2015() { + let src = r#" + [book] + title = "mdBook Documentation" + description = "Create book from markdown files. Like Gitbook but implemented in Rust" + authors = ["Mathieu David"] + src = "./source" + edition = "2015" + "#; + + let book_should_be = BookConfig { + title: Some(String::from("mdBook Documentation")), + description: Some(String::from( + "Create book from markdown files. Like Gitbook but implemented in Rust", + )), + authors: vec![String::from("Mathieu David")], + src: PathBuf::from("./source"), + edition: Some(RustEdition::E2015), + ..Default::default() + }; + + let got = Config::from_str(src).unwrap(); + assert_eq!(got.book, book_should_be); + } + + #[test] + fn edition_2018() { + let src = r#" + [book] + title = "mdBook Documentation" + description = "Create book from markdown files. Like Gitbook but implemented in Rust" + authors = ["Mathieu David"] + src = "./source" + edition = "2018" + "#; + + let book_should_be = BookConfig { + title: Some(String::from("mdBook Documentation")), + description: Some(String::from( + "Create book from markdown files. Like Gitbook but implemented in Rust", + )), + authors: vec![String::from("Mathieu David")], + src: PathBuf::from("./source"), + edition: Some(RustEdition::E2018), + ..Default::default() + }; + + let got = Config::from_str(src).unwrap(); + assert_eq!(got.book, book_should_be); + } + #[test] fn load_arbitrary_output_type() { #[derive(Debug, Deserialize, PartialEq)] From 53d821bf6d5aea11c6cb928322c67f936c150591 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Mon, 18 Nov 2019 01:03:14 +0300 Subject: [PATCH 2/4] Add edition to hbs renderer --- src/renderer/html_handlebars/hbs_renderer.rs | 87 ++++++++++++++++++-- 1 file changed, 79 insertions(+), 8 deletions(-) diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index e0d3fd4b..6029f0c9 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -1,5 +1,5 @@ use crate::book::{Book, BookItem}; -use crate::config::{Config, HtmlConfig, Playpen}; +use crate::config::{Config, HtmlConfig, Playpen, RustEdition}; use crate::errors::*; use crate::renderer::html_handlebars::helpers; use crate::renderer::{RenderContext, Renderer}; @@ -85,7 +85,7 @@ impl HtmlHandlebars { debug!("Render template"); let rendered = ctx.handlebars.render("index", &ctx.data)?; - let rendered = self.post_process(rendered, &ctx.html_config.playpen); + let rendered = self.post_process(rendered, &ctx.html_config.playpen, ctx.edition); // Write to file debug!("Creating {}", filepath.display()); @@ -96,7 +96,8 @@ impl HtmlHandlebars { ctx.data.insert("path_to_root".to_owned(), json!("")); ctx.data.insert("is_index".to_owned(), json!("true")); let rendered_index = ctx.handlebars.render("index", &ctx.data)?; - let rendered_index = self.post_process(rendered_index, &ctx.html_config.playpen); + let rendered_index = + self.post_process(rendered_index, &ctx.html_config.playpen, ctx.edition); debug!("Creating index.html from {}", path); utils::fs::write_file(&ctx.destination, "index.html", rendered_index.as_bytes())?; } @@ -106,10 +107,15 @@ impl HtmlHandlebars { } #[cfg_attr(feature = "cargo-clippy", allow(clippy::let_and_return))] - fn post_process(&self, rendered: String, playpen_config: &Playpen) -> String { + fn post_process( + &self, + rendered: String, + playpen_config: &Playpen, + edition: Option, + ) -> String { let rendered = build_header_links(&rendered); let rendered = fix_code_blocks(&rendered); - let rendered = add_playpen_pre(&rendered, playpen_config); + let rendered = add_playpen_pre(&rendered, playpen_config, edition); rendered } @@ -343,6 +349,7 @@ impl Renderer for HtmlHandlebars { data: data.clone(), is_index, html_config: html_config.clone(), + edition: ctx.config.book.edition, }; self.render_item(item, ctx, &mut print_content)?; is_index = false; @@ -358,7 +365,7 @@ impl Renderer for HtmlHandlebars { debug!("Render template"); let rendered = handlebars.render("index", &data)?; - let rendered = self.post_process(rendered, &html_config.playpen); + let rendered = self.post_process(rendered, &html_config.playpen, ctx.config.book.edition); utils::fs::write_file(&destination, "print.html", rendered.as_bytes())?; debug!("Creating print.html ✓"); @@ -605,7 +612,7 @@ fn fix_code_blocks(html: &str) -> String { .into_owned() } -fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String { +fn add_playpen_pre(html: &str, playpen_config: &Playpen, edition: Option) -> String { let regex = Regex::new(r##"((?s)]?class="([^"]+)".*?>(.*?))"##).unwrap(); regex .replace_all(html, |caps: &Captures<'_>| { @@ -617,10 +624,24 @@ fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String { if (!classes.contains("ignore") && !classes.contains("noplaypen")) || classes.contains("mdbook-runnable") { + let contains_e2015 = classes.contains("edition2015"); + let contains_e2018 = classes.contains("edition2018"); + let edition_class = if contains_e2015 || contains_e2018 { + // the user forced edition, we should not overwrite it + "" + } else { + match edition { + Some(RustEdition::E2015) => " edition2015", + Some(RustEdition::E2018) => " edition2018", + None => "", + } + }; + // wrap the contents in an external pre block format!( - "
{}
", + "
{}
", classes, + edition_class, { let content: Cow<'_, str> = if playpen_config.editable && classes.contains("editable") @@ -711,6 +732,7 @@ struct RenderItemContext<'a> { data: serde_json::Map, is_index: bool, html_config: HtmlConfig, + edition: Option, } #[cfg(test)] @@ -777,6 +799,55 @@ mod tests { editable: true, ..Playpen::default() }, + None, + ); + assert_eq!(&*got, *should_be); + } + } + #[test] + fn add_playpen_edition2015() { + let inputs = [ + ("x()", + "
\n#![allow(unused_variables)]\nfn main() {\nx()\n}\n
"), + ("fn main() {}", + "
fn main() {}\n
"), + ("fn main() {}", + "
fn main() {}\n
"), + ("fn main() {}", + "
fn main() {}\n
"), + ]; + for (src, should_be) in &inputs { + let got = add_playpen_pre( + src, + &Playpen { + editable: true, + ..Playpen::default() + }, + Some(RustEdition::E2015), + ); + assert_eq!(&*got, *should_be); + } + } + #[test] + fn add_playpen_edition2018() { + let inputs = [ + ("x()", + "
\n#![allow(unused_variables)]\nfn main() {\nx()\n}\n
"), + ("fn main() {}", + "
fn main() {}\n
"), + ("fn main() {}", + "
fn main() {}\n
"), + ("fn main() {}", + "
fn main() {}\n
"), + ]; + for (src, should_be) in &inputs { + let got = add_playpen_pre( + src, + &Playpen { + editable: true, + ..Playpen::default() + }, + Some(RustEdition::E2018), ); assert_eq!(&*got, *should_be); } From 255756cfee35486670e152ce82487c24da3b2949 Mon Sep 17 00:00:00 2001 From: kngwyu Date: Tue, 10 Mar 2020 00:02:54 +0900 Subject: [PATCH 3/4] Make new [rust] config and move edition config under it --- book-example/src/format/config.md | 10 ++- src/book/mod.rs | 2 +- src/config.rs | 95 +++++++++++--------- src/renderer/html_handlebars/hbs_renderer.rs | 4 +- 4 files changed, 66 insertions(+), 45 deletions(-) diff --git a/book-example/src/format/config.md b/book-example/src/format/config.md index 0b671557..a76c9d08 100644 --- a/book-example/src/format/config.md +++ b/book-example/src/format/config.md @@ -9,6 +9,8 @@ Here is an example of what a ***book.toml*** file might look like: title = "Example book" author = "John Doe" description = "The example book covers examples." + +[rust] edition = "2018" [build] @@ -44,7 +46,6 @@ This is general information about your book. `src` directly under the root folder. But this is configurable with the `src` key in the configuration file. - **language:** The main language of the book, which is used as a language attribute `` for example. -- **edition**: Rust edition to use by default for the code snippets. Defaults to `rustdoc` defaults (2015). **book.toml** ```toml @@ -54,9 +55,14 @@ authors = ["John Doe", "Jane Doe"] description = "The example book covers examples." src = "my-src" # the source files will be found in `root/my-src` instead of `root/src` language = "en" -edition = "2018" ``` +### Rust options + +Options for the Rust compiler used for playpen. + +- **edition**: Rust edition to use by default for the code snippets. Defaults to `rustdoc` defaults (2015). + ### Build options This controls the build process of your book. diff --git a/src/book/mod.rs b/src/book/mod.rs index 959800ed..57ae2e3f 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -265,7 +265,7 @@ impl MDBook { let mut cmd = Command::new("rustdoc"); cmd.arg(&path).arg("--test").args(&library_args); - if let Some(edition) = self.config.book.edition { + if let Some(edition) = self.config.rust.edition { match edition { RustEdition::E2015 => { cmd.args(&["--edition", "2015"]); diff --git a/src/config.rs b/src/config.rs index 2c4e12d3..b0b09f90 100644 --- a/src/config.rs +++ b/src/config.rs @@ -72,6 +72,8 @@ pub struct Config { pub book: BookConfig, /// Information about the build environment. pub build: BuildConfig, + /// Information passed to the Rust playground + pub rust: RustConfig, rest: Value, } @@ -280,6 +282,7 @@ impl Default for Config { Config { book: BookConfig::default(), build: BuildConfig::default(), + rust: RustConfig::default(), rest: Value::Table(Table::default()), } } @@ -320,9 +323,15 @@ impl<'de> Deserialize<'de> for Config { .and_then(|value| value.try_into().ok()) .unwrap_or_default(); + let rust: RustConfig = table + .remove("rust") + .and_then(|value| value.try_into().ok()) + .unwrap_or_default(); + Ok(Config { book, build, + rust, rest: Value::Table(table), }) } @@ -393,8 +402,6 @@ pub struct BookConfig { pub multilingual: bool, /// The main language of the book. pub language: Option, - /// Rust edition to use for the code. - pub edition: Option, } impl Default for BookConfig { @@ -406,11 +413,42 @@ impl Default for BookConfig { src: PathBuf::from("src"), multilingual: false, language: Some(String::from("en")), - edition: None, } } } +/// Configuration for the build procedure. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(default, rename_all = "kebab-case")] +pub struct BuildConfig { + /// Where to put built artefacts relative to the book's root directory. + pub build_dir: PathBuf, + /// Should non-existent markdown files specified in `SUMMARY.md` be created + /// if they don't exist? + pub create_missing: bool, + /// Should the default preprocessors always be used when they are + /// compatible with the renderer? + pub use_default_preprocessors: bool, +} + +impl Default for BuildConfig { + fn default() -> BuildConfig { + BuildConfig { + build_dir: PathBuf::from("book"), + create_missing: true, + use_default_preprocessors: true, + } + } +} + +/// Configuration for the Rust compiler(e.g., for playpen) +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +#[serde(default, rename_all = "kebab-case")] +pub struct RustConfig { + /// Rust edition used in playpen + pub edition: Option, +} + #[derive(Debug, Copy, Clone, PartialEq)] /// Rust edition to use for the code. pub enum RustEdition { @@ -451,8 +489,8 @@ impl<'de> Deserialize<'de> for RustEdition { let edition = match edition.as_str() { "2018" => RustEdition::E2018, "2015" => RustEdition::E2015, - _ => { - return Err(D::Error::custom("Unknown Rust edition")); + e => { + return Err(D::Error::custom(format!("Unknown Rust edition: {}", e))); } }; @@ -460,30 +498,6 @@ impl<'de> Deserialize<'de> for RustEdition { } } -/// Configuration for the build procedure. -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(default, rename_all = "kebab-case")] -pub struct BuildConfig { - /// Where to put built artefacts relative to the book's root directory. - pub build_dir: PathBuf, - /// Should non-existent markdown files specified in `SUMMARY.md` be created - /// if they don't exist? - pub create_missing: bool, - /// Should the default preprocessors always be used when they are - /// compatible with the renderer? - pub use_default_preprocessors: bool, -} - -impl Default for BuildConfig { - fn default() -> BuildConfig { - BuildConfig { - build_dir: PathBuf::from("book"), - create_missing: true, - use_default_preprocessors: true, - } - } -} - /// Configuration for the HTML renderer. #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] #[serde(default, rename_all = "kebab-case")] @@ -699,13 +713,13 @@ mod tests { multilingual: true, src: PathBuf::from("source"), language: Some(String::from("ja")), - edition: None, }; let build_should_be = BuildConfig { build_dir: PathBuf::from("outputs"), create_missing: false, use_default_preprocessors: true, }; + let rust_should_be = RustConfig { edition: None }; let playpen_should_be = Playpen { editable: true, copyable: true, @@ -728,6 +742,7 @@ mod tests { assert_eq!(got.book, book_should_be); assert_eq!(got.build, build_should_be); + assert_eq!(got.rust, rust_should_be); assert_eq!(got.html_config().unwrap(), html_should_be); } @@ -739,6 +754,7 @@ mod tests { description = "Create book from markdown files. Like Gitbook but implemented in Rust" authors = ["Mathieu David"] src = "./source" + [rust] edition = "2015" "#; @@ -749,12 +765,17 @@ mod tests { )), authors: vec![String::from("Mathieu David")], src: PathBuf::from("./source"), - edition: Some(RustEdition::E2015), ..Default::default() }; let got = Config::from_str(src).unwrap(); assert_eq!(got.book, book_should_be); + + let rust_should_be = RustConfig { + edition: Some(RustEdition::E2015), + }; + let got = Config::from_str(src).unwrap(); + assert_eq!(got.rust, rust_should_be); } #[test] @@ -765,22 +786,16 @@ mod tests { description = "Create book from markdown files. Like Gitbook but implemented in Rust" authors = ["Mathieu David"] src = "./source" + [rust] edition = "2018" "#; - let book_should_be = BookConfig { - title: Some(String::from("mdBook Documentation")), - description: Some(String::from( - "Create book from markdown files. Like Gitbook but implemented in Rust", - )), - authors: vec![String::from("Mathieu David")], - src: PathBuf::from("./source"), + let rust_should_be = RustConfig { edition: Some(RustEdition::E2018), - ..Default::default() }; let got = Config::from_str(src).unwrap(); - assert_eq!(got.book, book_should_be); + assert_eq!(got.rust, rust_should_be); } #[test] diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 6029f0c9..302ec419 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -349,7 +349,7 @@ impl Renderer for HtmlHandlebars { data: data.clone(), is_index, html_config: html_config.clone(), - edition: ctx.config.book.edition, + edition: ctx.config.rust.edition, }; self.render_item(item, ctx, &mut print_content)?; is_index = false; @@ -365,7 +365,7 @@ impl Renderer for HtmlHandlebars { debug!("Render template"); let rendered = handlebars.render("index", &data)?; - let rendered = self.post_process(rendered, &html_config.playpen, ctx.config.book.edition); + let rendered = self.post_process(rendered, &html_config.playpen, ctx.config.rust.edition); utils::fs::write_file(&destination, "print.html", rendered.as_bytes())?; debug!("Creating print.html ✓"); From 28ce8f5ac028ce860e5d6d090d0c18d3d1312f82 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 21 Apr 2020 12:21:56 -0700 Subject: [PATCH 4/4] Some edition cleanup and fixes. --- book-example/book.toml | 2 + book-example/src/format/config.md | 14 +++++- src/config.rs | 49 +++----------------- src/renderer/html_handlebars/hbs_renderer.rs | 4 +- 4 files changed, 23 insertions(+), 46 deletions(-) diff --git a/book-example/book.toml b/book-example/book.toml index 0c5ece6b..d21c8487 100644 --- a/book-example/book.toml +++ b/book-example/book.toml @@ -3,6 +3,8 @@ title = "mdBook Documentation" description = "Create book from markdown files. Like Gitbook but implemented in Rust" authors = ["Mathieu David", "Michael-F-Bryan"] language = "en" + +[rust] edition = "2018" [output.html] diff --git a/book-example/src/format/config.md b/book-example/src/format/config.md index a76c9d08..82c896c3 100644 --- a/book-example/src/format/config.md +++ b/book-example/src/format/config.md @@ -59,9 +59,19 @@ language = "en" ### Rust options -Options for the Rust compiler used for playpen. +Options for the Rust language, relevant to running tests and playground +integration. -- **edition**: Rust edition to use by default for the code snippets. Defaults to `rustdoc` defaults (2015). +- **edition**: Rust edition to use by default for the code snippets. Default + is "2015". Individual code blocks can be controlled with the `edition2015` + or `edition2018` annotations, such as: + + ~~~text + ```rust,edition2015 + // This only works in 2015. + let try = true; + ``` + ~~~ ### Build options diff --git a/src/config.rs b/src/config.rs index b0b09f90..36190ebf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -72,7 +72,7 @@ pub struct Config { pub book: BookConfig, /// Information about the build environment. pub build: BuildConfig, - /// Information passed to the Rust playground + /// Information about Rust language support. pub rust: RustConfig, rest: Value, } @@ -340,6 +340,7 @@ impl<'de> Deserialize<'de> for Config { impl Serialize for Config { fn serialize(&self, s: S) -> std::result::Result { use serde::ser::Error; + // TODO: This should probably be removed and use a derive instead. let mut table = self.rest.clone(); @@ -349,8 +350,10 @@ impl Serialize for Config { return Err(S::Error::custom("Unable to serialize the BookConfig")); } }; + let rust_config = Value::try_from(&self.rust).expect("should always be serializable"); table.insert("book", book_config).expect("unreachable"); + table.insert("rust", rust_config).expect("unreachable"); table.serialize(s) } } @@ -449,55 +452,17 @@ pub struct RustConfig { pub edition: Option, } -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] /// Rust edition to use for the code. pub enum RustEdition { /// The 2018 edition of Rust + #[serde(rename = "2018")] E2018, /// The 2015 edition of Rust + #[serde(rename = "2015")] E2015, } -impl Serialize for RustEdition { - fn serialize(&self, serializer: S) -> std::result::Result - where - S: Serializer, - { - match self { - RustEdition::E2015 => serializer.serialize_str("2015"), - RustEdition::E2018 => serializer.serialize_str("2018"), - } - } -} - -impl<'de> Deserialize<'de> for RustEdition { - fn deserialize(de: D) -> std::result::Result - where - D: Deserializer<'de>, - { - use serde::de::Error; - - let raw = Value::deserialize(de)?; - - let edition = match raw { - Value::String(s) => s, - _ => { - return Err(D::Error::custom("Rust edition should be a string")); - } - }; - - let edition = match edition.as_str() { - "2018" => RustEdition::E2018, - "2015" => RustEdition::E2015, - e => { - return Err(D::Error::custom(format!("Unknown Rust edition: {}", e))); - } - }; - - Ok(edition) - } -} - /// Configuration for the HTML renderer. #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] #[serde(default, rename_all = "kebab-case")] diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 302ec419..14012c12 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -808,7 +808,7 @@ mod tests { fn add_playpen_edition2015() { let inputs = [ ("x()", - "
\n#![allow(unused_variables)]\nfn main() {\nx()\n}\n
"), + "
\n#![allow(unused)]\nfn main() {\nx()\n}\n
"), ("fn main() {}", "
fn main() {}\n
"), ("fn main() {}", @@ -832,7 +832,7 @@ mod tests { fn add_playpen_edition2018() { let inputs = [ ("x()", - "
\n#![allow(unused_variables)]\nfn main() {\nx()\n}\n
"), + "
\n#![allow(unused)]\nfn main() {\nx()\n}\n
"), ("fn main() {}", "
fn main() {}\n
"), ("fn main() {}",