diff --git a/src/config/mod.rs b/src/config/mod.rs index 7538b26522d..c6555a2849f 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -27,6 +27,7 @@ pub(crate) mod file_lines; #[allow(unreachable_pub)] pub(crate) mod lists; pub(crate) mod macro_names; +pub(crate) mod style_edition; // This macro defines configuration options used in rustfmt. Each option // is defined as follows: diff --git a/src/config/options.rs b/src/config/options.rs index e37f4027e4a..0c8c604f089 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -468,3 +468,27 @@ pub enum MatchArmLeadingPipe { /// Preserve any existing leading pipes Preserve, } + +/// Defines the default values for each config according to [the style guide]. +/// rustfmt output may differ between style editions. +/// +/// [the style guide]: https://doc.rust-lang.org/nightly/style-guide/ +#[config_type] +pub enum StyleEdition { + #[value = "2015"] + #[doc_hint = "2015"] + /// [Edition 2015]() + Edition2015, + #[value = "2018"] + #[doc_hint = "2018"] + /// [Edition 2018]() + Edition2018, + #[value = "2021"] + #[doc_hint = "2021"] + /// [Edition 2021]() + Edition2021, + #[value = "2024"] + #[doc_hint = "2024"] + /// [Edition 2024](). + Edition2024, +} diff --git a/src/config/style_edition.rs b/src/config/style_edition.rs new file mode 100644 index 00000000000..4dd5f0164fa --- /dev/null +++ b/src/config/style_edition.rs @@ -0,0 +1,69 @@ +use crate::config::StyleEdition; + +/// Defines the default value for the given style edition +pub(crate) trait StyleEditionDefault { + type ConfigType; + fn style_edition_default(style_edition: StyleEdition) -> Self::ConfigType; +} + +/// macro to help implement `StyleEditionDefault` for config options +#[macro_export] +macro_rules! style_edition_default { + ($ty:ident, $config_ty:ty, _ => $default:expr) => { + impl $crate::config::style_edition::StyleEditionDefault for $ty { + type ConfigType = $config_ty; + + fn style_edition_default(_: $crate::config::StyleEdition) -> Self::ConfigType { + $default + } + } + }; + ($ty:ident, $config_ty:ty, Edition2024 => $default_2024:expr, _ => $default_2015:expr) => { + impl $crate::config::style_edition::StyleEditionDefault for $ty { + type ConfigType = $config_ty; + + fn style_edition_default( + style_edition: $crate::config::StyleEdition, + ) -> Self::ConfigType { + match style_edition { + $crate::config::StyleEdition::Edition2015 + | $crate::config::StyleEdition::Edition2018 + | $crate::config::StyleEdition::Edition2021 => $default_2015, + $crate::config::StyleEdition::Edition2024 => $default_2024, + } + } + } + }; +} + +#[cfg(test)] +mod test { + use super::*; + use crate::config::StyleEdition; + + #[test] + fn test_impl_default_style_edition_struct_for_all_editions() { + struct Unit; + style_edition_default!(Unit, usize, _ => 100); + + // regardless of the style edition used the value will always return 100 + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2015), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2018), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2021), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2024), 100); + } + + #[test] + fn test_impl_default_style_edition_for_old_and_new_editions() { + struct Unit; + style_edition_default!(Unit, usize, Edition2024 => 50, _ => 100); + + // style edition 2015-2021 are all the same + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2015), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2018), 100); + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2021), 100); + + // style edition 2024 + assert_eq!(Unit::style_edition_default(StyleEdition::Edition2024), 50); + } +}