From a23d3ccb840621183f395906cdbe468d643a381f Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 26 Jul 2024 17:43:50 -0500 Subject: [PATCH] refactor: track configs set from cli flags --- src/bin/main.rs | 57 ++++++++++++++++++++++++------------ src/config/config_type.rs | 61 +++++++++++++++++++++++++++++++++++++-- src/config/file_lines.rs | 2 +- src/config/mod.rs | 14 +++++++++ 4 files changed, 113 insertions(+), 21 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 88281d296be..4c9798f6c72 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -263,24 +263,35 @@ fn format_string(input: String, options: GetOptsOptions) -> Result { let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; if options.check { - config.set().emit_mode(EmitMode::Diff); + config.set_cli().emit_mode(EmitMode::Diff); } else { match options.emit_mode { // Emit modes which work with standard input // None means default, which is Stdout. - None | Some(EmitMode::Stdout) | Some(EmitMode::Checkstyle) | Some(EmitMode::Json) => {} + None => { + config + .set() + .emit_mode(options.emit_mode.unwrap_or(EmitMode::Stdout)); + } + Some(EmitMode::Stdout) | Some(EmitMode::Checkstyle) | Some(EmitMode::Json) => { + config + .set_cli() + .emit_mode(options.emit_mode.unwrap_or(EmitMode::Stdout)); + } Some(emit_mode) => { return Err(OperationError::StdinBadEmit(emit_mode).into()); } } - config - .set() - .emit_mode(options.emit_mode.unwrap_or(EmitMode::Stdout)); } config.set().verbose(Verbosity::Quiet); // parse file_lines - config.set().file_lines(options.file_lines); + if options.file_lines.is_all() { + config.set().file_lines(options.file_lines); + } else { + config.set_cli().file_lines(options.file_lines); + } + for f in config.file_lines().files() { match *f { FileName::Stdin => {} @@ -650,36 +661,46 @@ impl GetOptsOptions { impl CliOptions for GetOptsOptions { fn apply_to(self, config: &mut Config) { if self.verbose { - config.set().verbose(Verbosity::Verbose); + config.set_cli().verbose(Verbosity::Verbose); } else if self.quiet { - config.set().verbose(Verbosity::Quiet); + config.set_cli().verbose(Verbosity::Quiet); } else { config.set().verbose(Verbosity::Normal); } - config.set().file_lines(self.file_lines); - config.set().unstable_features(self.unstable_features); + + if self.file_lines.is_all() { + config.set().file_lines(self.file_lines); + } else { + config.set_cli().file_lines(self.file_lines); + } + + if self.unstable_features { + config.set_cli().unstable_features(self.unstable_features); + } else { + config.set().unstable_features(self.unstable_features); + } if let Some(skip_children) = self.skip_children { - config.set().skip_children(skip_children); + config.set_cli().skip_children(skip_children); } if let Some(error_on_unformatted) = self.error_on_unformatted { - config.set().error_on_unformatted(error_on_unformatted); + config.set_cli().error_on_unformatted(error_on_unformatted); } if let Some(edition) = self.edition { - config.set().edition(edition); + config.set_cli().edition(edition); } if self.check { - config.set().emit_mode(EmitMode::Diff); + config.set_cli().emit_mode(EmitMode::Diff); } else if let Some(emit_mode) = self.emit_mode { - config.set().emit_mode(emit_mode); + config.set_cli().emit_mode(emit_mode); } if self.backup { - config.set().make_backup(true); + config.set_cli().make_backup(true); } if let Some(color) = self.color { - config.set().color(color); + config.set_cli().color(color); } if self.print_misformatted_file_names { - config.set().print_misformatted_file_names(true); + config.set_cli().print_misformatted_file_names(true); } for (key, val) in self.inline_config { diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 41d6cdab104..c3d5b7a43cf 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -89,7 +89,10 @@ macro_rules! create_config { // - 1: true if the option was manually initialized // - 2: the option value // - 3: true if the option is unstable - $($i: (Cell, bool, <$ty as StyleEditionDefault>::ConfigType, bool)),+ + // - 4: true if the option was set manually from a CLI flag + // FIXME: 4 is probably unnecessary and duplicative + // https://github.com/rust-lang/rustfmt/issues/6252 + $($i: (Cell, bool, <$ty as StyleEditionDefault>::ConfigType, bool, bool)),+ } // Just like the Config struct but with each property wrapped @@ -136,6 +139,35 @@ macro_rules! create_config { )+ } + #[allow(unreachable_pub)] + pub struct CliConfigSetter<'a>(&'a mut Config); + + impl<'a> CliConfigSetter<'a> { + $( + #[allow(unreachable_pub)] + pub fn $i(&mut self, value: <$ty as StyleEditionDefault>::ConfigType) { + (self.0).$i.2 = value; + (self.0).$i.4 = true; + match stringify!($i) { + "max_width" + | "use_small_heuristics" + | "fn_call_width" + | "single_line_if_else_max_width" + | "single_line_let_else_max_width" + | "attr_fn_like_width" + | "struct_lit_width" + | "struct_variant_width" + | "array_width" + | "chain_width" => self.0.set_heuristics(), + "merge_imports" => self.0.set_merge_imports(), + "fn_args_layout" => self.0.set_fn_args_layout(), + "hide_parse_errors" => self.0.set_hide_parse_errors(), + &_ => (), + } + } + )+ + } + // Query each option, returns true if the user set the option, false if // a default was used. #[allow(unreachable_pub)] @@ -150,6 +182,20 @@ macro_rules! create_config { )+ } + // Query each option, returns true if the user set the option via a CLI flag, + // false if a default was used. + #[allow(unreachable_pub)] + pub struct CliConfigWasSet<'a>(&'a Config); + + impl<'a> CliConfigWasSet<'a> { + $( + #[allow(unreachable_pub)] + pub fn $i(&self) -> bool { + (self.0).$i.4 + } + )+ + } + impl Config { $( #[allow(unreachable_pub)] @@ -169,7 +215,8 @@ macro_rules! create_config { <$ty as StyleEditionDefault>::style_edition_default( style_edition ), - $stb + $stb, + false, ), )+ } @@ -180,11 +227,21 @@ macro_rules! create_config { ConfigSetter(self) } + #[allow(unreachable_pub)] + pub fn set_cli(&mut self) -> CliConfigSetter<'_> { + CliConfigSetter(self) + } + #[allow(unreachable_pub)] pub fn was_set(&self) -> ConfigWasSet<'_> { ConfigWasSet(self) } + #[allow(unreachable_pub)] + pub fn was_set_cli(&self) -> CliConfigWasSet<'_> { + CliConfigWasSet(self) + } + fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config { $( if let Some(option_value) = parsed.$i { diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 224864393d3..bc5a28b7423 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -201,7 +201,7 @@ impl FileLines { } /// Returns `true` if this `FileLines` contains all lines in all files. - pub(crate) fn is_all(&self) -> bool { + pub fn is_all(&self) -> bool { self.0.is_none() } diff --git a/src/config/mod.rs b/src/config/mod.rs index b38ca2b8dec..ac8f7c5d7a4 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -741,6 +741,20 @@ make_backup = false assert_eq!(config.unstable_features(), true); } + #[test] + fn test_set_cli() { + let mut config = Config::default(); + assert_eq!(config.was_set().edition(), false); + assert_eq!(config.was_set_cli().edition(), false); + config.set().edition(Edition::Edition2021); + assert_eq!(config.was_set().edition(), false); + assert_eq!(config.was_set_cli().edition(), false); + config.set_cli().edition(Edition::Edition2021); + assert_eq!(config.was_set().edition(), false); + assert_eq!(config.was_set_cli().edition(), true); + assert_eq!(config.was_set_cli().emit_mode(), false); + } + #[cfg(test)] mod deprecated_option_merge_imports { use super::*;