diff --git a/crates/ruff_cli/src/commands/show_settings.rs b/crates/ruff_cli/src/commands/show_settings.rs index baeed55a08f36..28f52c01be395 100644 --- a/crates/ruff_cli/src/commands/show_settings.rs +++ b/crates/ruff_cli/src/commands/show_settings.rs @@ -35,7 +35,7 @@ pub(crate) fn show_settings( if let Some(settings_path) = pyproject_config.path.as_ref() { writeln!(writer, "Settings path: {settings_path:?}")?; } - writeln!(writer, "{settings:#?}")?; + writeln!(writer, "{settings}")?; Ok(()) } diff --git a/crates/ruff_formatter/src/lib.rs b/crates/ruff_formatter/src/lib.rs index dfac3df3fc345..5300f169152c2 100644 --- a/crates/ruff_formatter/src/lib.rs +++ b/crates/ruff_formatter/src/lib.rs @@ -35,6 +35,7 @@ mod source_code; use crate::formatter::Formatter; use crate::group_id::UniqueGroupIdBuilder; use crate::prelude::TagKind; +use std::fmt; use std::fmt::{Debug, Display}; use std::marker::PhantomData; use std::num::{NonZeroU16, NonZeroU8, TryFromIntError}; @@ -113,6 +114,12 @@ impl Default for IndentWidth { } } +impl fmt::Display for IndentWidth { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + std::write!(f, "{}", self.0) + } +} + impl TryFrom for IndentWidth { type Error = TryFromIntError; @@ -146,6 +153,12 @@ impl Default for LineWidth { } } +impl Display for LineWidth { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + std::write!(f, "{}", self.0) + } +} + impl TryFrom for LineWidth { type Error = TryFromIntError; diff --git a/crates/ruff_linter/src/line_width.rs b/crates/ruff_linter/src/line_width.rs index 06fe47c94464b..135937eaf686d 100644 --- a/crates/ruff_linter/src/line_width.rs +++ b/crates/ruff_linter/src/line_width.rs @@ -1,4 +1,5 @@ use std::error::Error; +use std::fmt; use std::hash::Hasher; use std::num::{NonZeroU16, NonZeroU8, ParseIntError}; use std::str::FromStr; @@ -39,6 +40,12 @@ impl Default for LineLength { } } +impl fmt::Display for LineLength { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + impl CacheKey for LineLength { fn cache_key(&self, state: &mut CacheKeyHasher) { state.write_u16(self.0.get()); @@ -248,6 +255,12 @@ impl Default for IndentWidth { } } +impl fmt::Display for IndentWidth { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + impl From for IndentWidth { fn from(tab_size: NonZeroU8) -> Self { Self(tab_size) diff --git a/crates/ruff_linter/src/registry/rule_set.rs b/crates/ruff_linter/src/registry/rule_set.rs index ff6561740d774..7efdbf69f0844 100644 --- a/crates/ruff_linter/src/registry/rule_set.rs +++ b/crates/ruff_linter/src/registry/rule_set.rs @@ -1,6 +1,7 @@ use crate::registry::Rule; +use itertools::Itertools; use ruff_macros::CacheKey; -use std::fmt::{Debug, Formatter}; +use std::fmt::{Debug, Display, Formatter}; use std::iter::FusedIterator; const RULESET_SIZE: usize = 13; @@ -269,6 +270,22 @@ impl Debug for RuleSet { } } +impl Display for RuleSet { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if self.is_empty() { + write!(f, "[]") + } else { + write!( + f, + "[\n\t{}\n]", + self.iter() + .map(|rule| format!("\"{rule:?}\"")) + .join(",\n\t") + ) + } + } +} + impl FromIterator for RuleSet { fn from_iter>(iter: T) -> Self { let mut set = RuleSet::empty(); diff --git a/crates/ruff_linter/src/rules/flake8_annotations/settings.rs b/crates/ruff_linter/src/rules/flake8_annotations/settings.rs index 843d18cd4b61c..f229b628086f6 100644 --- a/crates/ruff_linter/src/rules/flake8_annotations/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_annotations/settings.rs @@ -1,6 +1,8 @@ //! Settings for the `flake-annotations` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, Default, CacheKey)] #[allow(clippy::struct_excessive_bools)] @@ -11,3 +13,20 @@ pub struct Settings { pub allow_star_arg_any: bool, pub ignore_fully_untyped: bool, } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_annotations.", + fields = [ + self.mypy_init_return, + self.suppress_dummy_args, + self.suppress_none_returning, + self.allow_star_arg_any, + self.ignore_fully_untyped + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_bandit/settings.rs b/crates/ruff_linter/src/rules/flake8_bandit/settings.rs index f701916462957..d1a5bb2ed75ae 100644 --- a/crates/ruff_linter/src/rules/flake8_bandit/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_bandit/settings.rs @@ -1,6 +1,8 @@ //! Settings for the `flake8-bandit` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; pub fn default_tmp_dirs() -> Vec { ["/tmp", "/var/tmp", "/dev/shm"] @@ -22,3 +24,17 @@ impl Default for Settings { } } } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_bandit.", + fields = [ + self.hardcoded_tmp_directory | debug, + self.check_typed_exception + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs b/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs index 885860565f686..b545b8d4f744f 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs @@ -1,8 +1,23 @@ //! Settings for the `flake8-bugbear` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, Default, CacheKey)] pub struct Settings { pub extend_immutable_calls: Vec, } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_bugbear.", + fields = [ + self.extend_immutable_calls | debug + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_builtins/settings.rs b/crates/ruff_linter/src/rules/flake8_builtins/settings.rs index 694e4b522c859..9080dea377138 100644 --- a/crates/ruff_linter/src/rules/flake8_builtins/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_builtins/settings.rs @@ -1,8 +1,23 @@ //! Settings for the `flake8-builtins` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, Default, CacheKey)] pub struct Settings { pub builtins_ignorelist: Vec, } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_builtins.", + fields = [ + self.builtins_ignorelist | debug + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/settings.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/settings.rs index 9646cde790e7e..5be8deb011bfa 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/settings.rs @@ -1,8 +1,23 @@ //! Settings for the `flake8-comprehensions` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, Default, CacheKey)] pub struct Settings { pub allow_dict_calls_with_keyword_arguments: bool, } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_comprehensions.", + fields = [ + self.allow_dict_calls_with_keyword_arguments + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_copyright/settings.rs b/crates/ruff_linter/src/rules/flake8_copyright/settings.rs index 0dda17d0edf22..c9da08a5071cd 100644 --- a/crates/ruff_linter/src/rules/flake8_copyright/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_copyright/settings.rs @@ -2,7 +2,9 @@ use once_cell::sync::Lazy; use regex::Regex; +use std::fmt::{Display, Formatter}; +use crate::display_settings; use ruff_macros::CacheKey; #[derive(Debug, CacheKey)] @@ -24,3 +26,19 @@ impl Default for Settings { } } } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_copyright", + fields = [ + self.notice_rgx, + // TODO(jane): remove debug + self.author | debug, + self.min_file_size, + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_errmsg/settings.rs b/crates/ruff_linter/src/rules/flake8_errmsg/settings.rs index d0b82cca605ab..ffb97d93bc4b7 100644 --- a/crates/ruff_linter/src/rules/flake8_errmsg/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_errmsg/settings.rs @@ -1,8 +1,23 @@ //! Settings for the `flake8-errmsg` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, Default, CacheKey)] pub struct Settings { pub max_string_length: usize, } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_errmsg.", + fields = [ + self.max_string_length + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_gettext/settings.rs b/crates/ruff_linter/src/rules/flake8_gettext/settings.rs index 1dd35357d80ee..c23ab2a7904e1 100644 --- a/crates/ruff_linter/src/rules/flake8_gettext/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_gettext/settings.rs @@ -1,4 +1,6 @@ +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, CacheKey)] pub struct Settings { @@ -20,3 +22,16 @@ impl Default for Settings { } } } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_gettext.", + fields = [ + self.functions_names | debug + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/settings.rs b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/settings.rs index 413118fa317cd..250aa29ef289b 100644 --- a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/settings.rs @@ -1,6 +1,8 @@ //! Settings for the `flake8-implicit-str-concat` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, CacheKey)] pub struct Settings { @@ -14,3 +16,16 @@ impl Default for Settings { } } } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_implicit_str_concat.", + fields = [ + self.allow_multiline + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_import_conventions/settings.rs b/crates/ruff_linter/src/rules/flake8_import_conventions/settings.rs index 639a627f091ea..3e4733b240200 100644 --- a/crates/ruff_linter/src/rules/flake8_import_conventions/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_import_conventions/settings.rs @@ -1,7 +1,9 @@ //! Settings for import conventions. use rustc_hash::{FxHashMap, FxHashSet}; +use std::fmt::{Display, Formatter}; +use crate::display_settings; use ruff_macros::CacheKey; const CONVENTIONAL_ALIASES: &[(&str, &str)] = &[ @@ -44,3 +46,18 @@ impl Default for Settings { } } } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_import_conventions", + fields = [ + self.aliases | debug, + self.banned_aliases | debug, + self.banned_from | debug, + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_pytest_style/settings.rs b/crates/ruff_linter/src/rules/flake8_pytest_style/settings.rs index 22231b6981ab1..60da64d656c7c 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/settings.rs @@ -1,7 +1,9 @@ //! Settings for the `flake8-pytest-style` plugin. use std::error::Error; use std::fmt; +use std::fmt::Formatter; +use crate::display_settings; use ruff_macros::CacheKey; use crate::settings::types::IdentifierPattern; @@ -47,6 +49,25 @@ impl Default for Settings { } } +impl fmt::Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_pytest_style.", + fields = [ + self.fixture_parentheses, + self.parametrize_names_type, + self.parametrize_values_type, + self.parametrize_values_row_type, + self.raises_require_match_for | debug, + self.raises_extend_require_match_for | debug, + self.mark_parentheses + ] + } + Ok(()) + } +} + /// Error returned by the [`TryFrom`] implementation of [`Settings`]. #[derive(Debug)] pub enum SettingsError { diff --git a/crates/ruff_linter/src/rules/flake8_quotes/settings.rs b/crates/ruff_linter/src/rules/flake8_quotes/settings.rs index 620fb2e53a8b8..0fddace12cdea 100644 --- a/crates/ruff_linter/src/rules/flake8_quotes/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_quotes/settings.rs @@ -1,7 +1,9 @@ //! Settings for the `flake8-quotes` plugin. use serde::{Deserialize, Serialize}; +use std::fmt::{Display, Formatter}; +use crate::display_settings; use ruff_macros::CacheKey; #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey)] @@ -39,6 +41,22 @@ impl Default for Settings { } } +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_quotes.", + fields = [ + self.inline_quotes, + self.multiline_quotes, + self.docstring_quotes, + self.avoid_escape + ] + } + Ok(()) + } +} + impl Quote { #[must_use] pub const fn opposite(self) -> Self { @@ -56,3 +74,12 @@ impl Quote { } } } + +impl Display for Quote { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Self::Double => write!(f, "double"), + Self::Single => write!(f, "single"), + } + } +} diff --git a/crates/ruff_linter/src/rules/flake8_self/settings.rs b/crates/ruff_linter/src/rules/flake8_self/settings.rs index 5cd083671756d..50d47462a7064 100644 --- a/crates/ruff_linter/src/rules/flake8_self/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_self/settings.rs @@ -1,6 +1,8 @@ //! Settings for the `flake8-self` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; // By default, ignore the `namedtuple` methods and attributes, as well as the // _sunder_ names in Enum, which are underscore-prefixed to prevent conflicts @@ -27,3 +29,16 @@ impl Default for Settings { } } } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_self.", + fields = [ + self.ignore_names | debug + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_tidy_imports/settings.rs b/crates/ruff_linter/src/rules/flake8_tidy_imports/settings.rs index a1267fbc9b8a8..323bfc69b7bc4 100644 --- a/crates/ruff_linter/src/rules/flake8_tidy_imports/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_tidy_imports/settings.rs @@ -1,6 +1,8 @@ use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; +use std::fmt::{Display, Formatter}; +use crate::display_settings; use ruff_macros::CacheKey; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey)] @@ -22,9 +24,33 @@ pub enum Strictness { All, } +impl Display for Strictness { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Self::Parents => write!(f, "\"parents\""), + Self::All => write!(f, "\"all\""), + } + } +} + #[derive(Debug, CacheKey, Default)] pub struct Settings { pub ban_relative_imports: Strictness, pub banned_api: FxHashMap, pub banned_module_level_imports: Vec, } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_tidy_imports.", + fields = [ + self.ban_relative_imports, + self.banned_api | debug, + self.banned_module_level_imports | debug, + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_type_checking/settings.rs b/crates/ruff_linter/src/rules/flake8_type_checking/settings.rs index 16baf1b91edbe..2808a26e4f5ff 100644 --- a/crates/ruff_linter/src/rules/flake8_type_checking/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_type_checking/settings.rs @@ -1,6 +1,8 @@ //! Settings for the `flake8-type-checking` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, CacheKey)] pub struct Settings { @@ -22,3 +24,20 @@ impl Default for Settings { } } } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_type_checking.", + fields = [ + self.strict, + self.exempt_modules | debug, + self.runtime_required_base_classes | debug, + self.runtime_required_decorators | debug, + self.quote_annotations + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/flake8_unused_arguments/settings.rs b/crates/ruff_linter/src/rules/flake8_unused_arguments/settings.rs index 3f413c2a48ab5..d00ca55ba6095 100644 --- a/crates/ruff_linter/src/rules/flake8_unused_arguments/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_unused_arguments/settings.rs @@ -1,8 +1,23 @@ //! Settings for the `flake8-unused-arguments` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, Default, CacheKey)] pub struct Settings { pub ignore_variadic_names: bool, } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.flake8_unused_arguments.", + fields = [ + self.ignore_variadic_names + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/isort/categorize.rs b/crates/ruff_linter/src/rules/isort/categorize.rs index 8ab090645ab62..f9c1bf51928cd 100644 --- a/crates/ruff_linter/src/rules/isort/categorize.rs +++ b/crates/ruff_linter/src/rules/isort/categorize.rs @@ -1,4 +1,6 @@ +use itertools::Itertools; use std::collections::BTreeMap; +use std::fmt; use std::hash::BuildHasherDefault; use std::path::{Path, PathBuf}; use std::{fs, iter}; @@ -378,3 +380,20 @@ impl KnownModules { user_defined } } + +impl fmt::Display for KnownModules { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.known.is_empty() { + write!(f, "[]") + } else { + write!( + f, + "{{\n\t{}\n}}", + self.known + .iter() + .map(|(pattern, import_section)| format!("{pattern} => {import_section:?}")) + .join(", \n\t") + ) + } + } +} diff --git a/crates/ruff_linter/src/rules/isort/settings.rs b/crates/ruff_linter/src/rules/isort/settings.rs index 2a28a3c8b396b..414e54e5dc337 100644 --- a/crates/ruff_linter/src/rules/isort/settings.rs +++ b/crates/ruff_linter/src/rules/isort/settings.rs @@ -3,10 +3,12 @@ use std::collections::BTreeSet; use std::error::Error; use std::fmt; +use std::fmt::{Display, Formatter}; use serde::{Deserialize, Serialize}; use strum::IntoEnumIterator; +use crate::display_settings; use ruff_macros::CacheKey; use crate::rules::isort::categorize::KnownModules; @@ -32,6 +34,15 @@ impl Default for RelativeImportsOrder { } } +impl Display for RelativeImportsOrder { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::ClosestToFurthest => write!(f, "closest_to_furthest"), + Self::FurthestToClosest => write!(f, "furthest_to_closest"), + } + } +} + #[derive(Debug, CacheKey)] #[allow(clippy::struct_excessive_bools)] pub struct Settings { @@ -94,6 +105,43 @@ impl Default for Settings { } } +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.isort.", + fields = [ + self.required_imports | debug, + self.combine_as_imports, + self.force_single_line, + self.force_sort_within_sections, + self.detect_same_package, + self.case_sensitive, + self.force_wrap_aliases, + self.force_to_top | debug, + self.known_modules | debug, // TODO(jane): remove debug + self.order_by_type, + self.relative_imports_order, + self.single_line_exclusions | debug, + self.split_on_trailing_comma, + self.classes | debug, + self.constants | debug, + self.variables | debug, + self.no_lines_before | debug, + self.lines_after_imports, + self.lines_between_types, + self.forced_separate | debug, + self.section_order | debug, + self.no_sections, + self.from_first, + self.length_sort, + self.length_sort_straight + ] + } + Ok(()) + } +} + /// Error returned by the [`TryFrom`] implementation of [`Settings`]. #[derive(Debug)] pub enum SettingsError { diff --git a/crates/ruff_linter/src/rules/mccabe/settings.rs b/crates/ruff_linter/src/rules/mccabe/settings.rs index f0a06b0f15a35..8711e607f54af 100644 --- a/crates/ruff_linter/src/rules/mccabe/settings.rs +++ b/crates/ruff_linter/src/rules/mccabe/settings.rs @@ -1,6 +1,8 @@ //! Settings for the `mccabe` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt::{Display, Formatter}; #[derive(Debug, CacheKey)] pub struct Settings { @@ -16,3 +18,16 @@ impl Default for Settings { } } } + +impl Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.mccabe.", + fields = [ + self.max_complexity + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/pep8_naming/settings.rs b/crates/ruff_linter/src/rules/pep8_naming/settings.rs index 65930f7690927..7c09a23c16be8 100644 --- a/crates/ruff_linter/src/rules/pep8_naming/settings.rs +++ b/crates/ruff_linter/src/rules/pep8_naming/settings.rs @@ -2,7 +2,9 @@ use std::error::Error; use std::fmt; +use std::fmt::Formatter; +use crate::display_settings; use ruff_macros::CacheKey; use crate::settings::types::IdentifierPattern; @@ -44,6 +46,21 @@ impl Default for Settings { } } +impl fmt::Display for Settings { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.pep8_naming.", + fields = [ + self.ignore_names | debug, + self.classmethod_decorators | debug, + self.staticmethod_decorators | debug + ] + } + Ok(()) + } +} + /// Error returned by the [`TryFrom`] implementation of [`Settings`]. #[derive(Debug)] pub enum SettingsError { diff --git a/crates/ruff_linter/src/rules/pycodestyle/settings.rs b/crates/ruff_linter/src/rules/pycodestyle/settings.rs index 7990f6a65646d..7dad02cad5607 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/settings.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/settings.rs @@ -1,6 +1,8 @@ //! Settings for the `pycodestyle` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt; use crate::line_width::LineLength; @@ -10,3 +12,18 @@ pub struct Settings { pub max_doc_length: Option, pub ignore_overlong_task_comments: bool, } + +impl fmt::Display for Settings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.pycodestyle.", + fields = [ + self.max_line_length, + self.max_doc_length | debug, + self.ignore_overlong_task_comments, + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/pydocstyle/settings.rs b/crates/ruff_linter/src/rules/pydocstyle/settings.rs index a8025bdff4578..51187718eeb21 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/settings.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/settings.rs @@ -1,9 +1,11 @@ //! Settings for the `pydocstyle` plugin. use std::collections::BTreeSet; +use std::fmt; use serde::{Deserialize, Serialize}; +use crate::display_settings; use ruff_macros::CacheKey; use crate::registry::Rule; @@ -77,3 +79,18 @@ pub struct Settings { pub ignore_decorators: BTreeSet, pub property_decorators: BTreeSet, } + +impl fmt::Display for Settings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.pydocstyle.", + fields = [ + self.convention | debug, + self.ignore_decorators | debug, + self.property_decorators | debug + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/pyflakes/settings.rs b/crates/ruff_linter/src/rules/pyflakes/settings.rs index d87f93da37669..3cd582eb806e0 100644 --- a/crates/ruff_linter/src/rules/pyflakes/settings.rs +++ b/crates/ruff_linter/src/rules/pyflakes/settings.rs @@ -1,8 +1,23 @@ //! Settings for the `Pyflakes` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt; #[derive(Debug, Default, CacheKey)] pub struct Settings { pub extend_generics: Vec, } + +impl fmt::Display for Settings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.pyflakes.", + fields = [ + self.extend_generics | debug + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/pylint/settings.rs b/crates/ruff_linter/src/rules/pylint/settings.rs index 8ea19cdfaf41d..c4f3d418d9903 100644 --- a/crates/ruff_linter/src/rules/pylint/settings.rs +++ b/crates/ruff_linter/src/rules/pylint/settings.rs @@ -2,7 +2,9 @@ use rustc_hash::FxHashSet; use serde::{Deserialize, Serialize}; +use std::fmt; +use crate::display_settings; use ruff_macros::CacheKey; use ruff_python_ast::{ExprNumberLiteral, LiteralExpressionRef, Number}; @@ -64,3 +66,25 @@ impl Default for Settings { } } } + +impl fmt::Display for Settings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.pylint.", + fields = [ + self.allow_magic_value_types | debug, + self.allow_dunder_method_names | debug, + self.max_args, + self.max_positional_args, + self.max_returns, + self.max_bool_expr, + self.max_branches, + self.max_statements, + self.max_public_methods, + self.max_locals + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/rules/pyupgrade/settings.rs b/crates/ruff_linter/src/rules/pyupgrade/settings.rs index 96f5a80513e70..bf73ea1086358 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/settings.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/settings.rs @@ -1,8 +1,23 @@ //! Settings for the `pyupgrade` plugin. +use crate::display_settings; use ruff_macros::CacheKey; +use std::fmt; #[derive(Debug, Default, CacheKey)] pub struct Settings { pub keep_runtime_typing: bool, } + +impl fmt::Display for Settings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.pyupgrade.", + fields = [ + self.keep_runtime_typing + ] + } + Ok(()) + } +} diff --git a/crates/ruff_linter/src/settings/fix_safety_table.rs b/crates/ruff_linter/src/settings/fix_safety_table.rs index 061b3fe0568e5..ebe93def6a61d 100644 --- a/crates/ruff_linter/src/settings/fix_safety_table.rs +++ b/crates/ruff_linter/src/settings/fix_safety_table.rs @@ -1,4 +1,4 @@ -use std::fmt::Debug; +use std::fmt::{Debug, Display, Formatter}; use ruff_diagnostics::Applicability; use ruff_macros::CacheKey; @@ -6,6 +6,7 @@ use rustc_hash::FxHashMap; use strum::IntoEnumIterator; use crate::{ + display_settings, registry::{Rule, RuleSet}, rule_selector::{PreviewOptions, Specificity}, RuleSelector, @@ -95,6 +96,20 @@ impl FixSafetyTable { } } +impl Display for FixSafetyTable { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.safety_table.", + fields = [ + self.forced_safe, + self.forced_unsafe + ] + } + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/ruff_linter/src/settings/mod.rs b/crates/ruff_linter/src/settings/mod.rs index 66214a3a65201..70944a55d696f 100644 --- a/crates/ruff_linter/src/settings/mod.rs +++ b/crates/ruff_linter/src/settings/mod.rs @@ -2,10 +2,11 @@ //! command-line options. Structure is optimized for internal usage, as opposed //! to external visibility or parsing. +use std::fmt::{Display, Formatter}; use std::path::{Path, PathBuf}; use anyhow::Result; -use globset::{Glob, GlobMatcher}; +use globset::Glob; use once_cell::sync::Lazy; use path_absolutize::path_dedot; use regex::Regex; @@ -15,7 +16,7 @@ use crate::codes::RuleCodePrefix; use ruff_macros::CacheKey; use crate::line_width::LineLength; -use crate::registry::{Linter, Rule, RuleSet}; +use crate::registry::{Linter, Rule}; use crate::rules::{ flake8_annotations, flake8_bandit, flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_copyright, flake8_errmsg, flake8_gettext, flake8_implicit_str_concat, @@ -23,7 +24,9 @@ use crate::rules::{ flake8_tidy_imports, flake8_type_checking, flake8_unused_arguments, isort, mccabe, pep8_naming, pycodestyle, pydocstyle, pyflakes, pylint, pyupgrade, }; -use crate::settings::types::{ExtensionMapping, FilePatternSet, PerFileIgnore, PythonVersion}; +use crate::settings::types::{ + ExtensionMapping, FilePatternSet, PerFileIgnore, PerFileIgnores, PythonVersion, +}; use crate::{codes, RuleSelector}; use super::line_width::IndentWidth; @@ -38,13 +41,34 @@ pub mod flags; pub mod rule_table; pub mod types; +#[macro_export] +macro_rules! display_settings { + (formatter = $fmt:ident, namespace = $namespace:literal, fields = [$($settings:ident.$field:ident $(| $modifier:tt)?),* $(,)?]) => { + { + const _NS: &str = $namespace; + $( + display_settings!(@field $fmt, _NS, $settings.$field $(| $modifier)?); + )* + } + }; + (@field $fmt:ident, $namespace:ident, $settings:ident.$field:ident | debug) => { + writeln!($fmt, "{}{} = {:?}", $namespace, stringify!($field), $settings.$field)?; + }; + (@field $fmt:ident, $namespace:ident, $settings:ident.$field:ident | nested) => { + write!($fmt, "{}", $settings.$field)?; + }; + (@field $fmt:ident, $namespace:ident, $settings:ident.$field:ident) => { + writeln!($fmt, "{}{} = {}", $namespace, stringify!($field), $settings.$field)?; + }; +} + #[derive(Debug, CacheKey)] pub struct LinterSettings { pub exclude: FilePatternSet, pub project_root: PathBuf, pub rules: RuleTable, - pub per_file_ignores: Vec<(GlobMatcher, GlobMatcher, RuleSet)>, + pub per_file_ignores: PerFileIgnores, pub fix_safety: FixSafetyTable, pub target_version: PythonVersion, @@ -93,6 +117,67 @@ pub struct LinterSettings { pub pyupgrade: pyupgrade::settings::Settings, } +impl Display for LinterSettings { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!(f, "# Linter Settings")?; + display_settings! { + formatter = f, + namespace = "linter.", + fields = [ + self.exclude, + self.project_root | debug, + + self.rules | nested, + self.per_file_ignores, + self.fix_safety | nested, + + self.target_version | debug, + self.preview | debug, + self.explicit_preview_rules, + self.extension | debug, + + self.allowed_confusables | debug, + self.builtins | debug, + self.dummy_variable_rgx, + self.external | debug, + self.ignore_init_module_imports, + self.logger_objects | debug, + self.namespace_packages | debug, + self.src | debug, + self.tab_size, + self.line_length, + self.task_tags | debug, + self.typing_modules | debug, + + self.flake8_annotations | nested, + self.flake8_bandit | nested, + self.flake8_bugbear | nested, + self.flake8_builtins | nested, + self.flake8_comprehensions | nested, + self.flake8_copyright | nested, + self.flake8_errmsg | nested, + self.flake8_gettext | nested, + self.flake8_implicit_str_concat | nested, + self.flake8_import_conventions | nested, + self.flake8_pytest_style | nested, + self.flake8_quotes | nested, + self.flake8_self | nested, + self.flake8_tidy_imports | nested, + self.flake8_type_checking | nested, + self.flake8_unused_arguments | nested, + self.isort | nested, + self.mccabe | nested, + self.pep8_naming | nested, + self.pycodestyle | nested, + self.pyflakes | nested, + self.pylint | nested, + self.pyupgrade | nested, + ] + } + Ok(()) + } +} + pub const DEFAULT_SELECTORS: &[RuleSelector] = &[ RuleSelector::Linter(Linter::Pyflakes), // Only include pycodestyle rules that do not overlap with the formatter @@ -152,7 +237,7 @@ impl LinterSettings { logger_objects: vec![], namespace_packages: vec![], - per_file_ignores: vec![], + per_file_ignores: PerFileIgnores::default(), fix_safety: FixSafetyTable::default(), src: vec![path_dedot::CWD.clone()], @@ -206,10 +291,8 @@ impl Default for LinterSettings { } /// Given a list of patterns, create a `GlobSet`. -pub fn resolve_per_file_ignores( - per_file_ignores: Vec, -) -> Result> { - per_file_ignores +pub fn resolve_per_file_ignores(per_file_ignores: Vec) -> Result { + let ignores: Result> = per_file_ignores .into_iter() .map(|per_file_ignore| { // Construct absolute path matcher. @@ -221,5 +304,6 @@ pub fn resolve_per_file_ignores( Ok((absolute, basename, per_file_ignore.rules)) }) - .collect() + .collect(); + Ok(PerFileIgnores::new(ignores?)) } diff --git a/crates/ruff_linter/src/settings/rule_table.rs b/crates/ruff_linter/src/settings/rule_table.rs index 898dcb3f7c76c..395c90d50153f 100644 --- a/crates/ruff_linter/src/settings/rule_table.rs +++ b/crates/ruff_linter/src/settings/rule_table.rs @@ -1,5 +1,6 @@ -use std::fmt::Debug; +use std::fmt::{Debug, Display, Formatter}; +use crate::display_settings; use ruff_macros::CacheKey; use crate::registry::{Rule, RuleSet, RuleSetIterator}; @@ -62,6 +63,20 @@ impl RuleTable { } } +impl Display for RuleTable { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.rules.", + fields = [ + self.enabled, + self.should_fix + ] + } + Ok(()) + } +} + impl FromIterator for RuleTable { fn from_iter>(iter: T) -> Self { let rules = RuleSet::from_iter(iter); diff --git a/crates/ruff_linter/src/settings/types.rs b/crates/ruff_linter/src/settings/types.rs index ed0e83e5c64f7..77fa8658c5284 100644 --- a/crates/ruff_linter/src/settings/types.rs +++ b/crates/ruff_linter/src/settings/types.rs @@ -1,3 +1,4 @@ +use std::fmt::{Display, Formatter}; use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::path::{Path, PathBuf}; @@ -5,7 +6,8 @@ use std::str::FromStr; use std::string::ToString; use anyhow::{bail, Result}; -use globset::{Glob, GlobSet, GlobSetBuilder}; +use globset::{Glob, GlobMatcher, GlobSet, GlobSetBuilder}; +use itertools::Itertools; use pep440_rs::{Version as Pep440Version, VersionSpecifiers}; use rustc_hash::FxHashMap; use serde::{de, Deserialize, Deserializer, Serialize}; @@ -133,6 +135,20 @@ pub enum UnsafeFixes { Enabled, } +impl Display for UnsafeFixes { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Self::Hint => "hint", + Self::Disabled => "disabled", + Self::Enabled => "enabled", + } + ) + } +} + impl From for UnsafeFixes { fn from(value: bool) -> Self { if value { @@ -178,6 +194,19 @@ impl FilePattern { } } +impl Display for FilePattern { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{:?}", + match self { + Self::Builtin(pattern) => pattern, + Self::User(pattern, _) => pattern.as_str(), + } + ) + } +} + impl FromStr for FilePattern { type Err = anyhow::Error; @@ -192,9 +221,14 @@ impl FromStr for FilePattern { pub struct FilePatternSet { set: GlobSet, cache_key: u64, + // This field is only for displaying the internals + // of `set`. + #[allow(clippy::used_underscore_binding)] + _set_internals: Vec, } impl FilePatternSet { + #[allow(clippy::used_underscore_binding)] pub fn try_from_iter(patterns: I) -> Result where I: IntoIterator, @@ -202,7 +236,10 @@ impl FilePatternSet { let mut builder = GlobSetBuilder::new(); let mut hasher = CacheKeyHasher::new(); + let mut _set_internals = vec![]; + for pattern in patterns { + _set_internals.push(pattern.clone()); pattern.cache_key(&mut hasher); pattern.add_to(&mut builder)?; } @@ -212,10 +249,28 @@ impl FilePatternSet { Ok(FilePatternSet { set, cache_key: hasher.finish(), + _set_internals, }) } } +impl Display for FilePatternSet { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if self._set_internals.is_empty() { + write!(f, "[]") + } else { + write!( + f, + "[\n\t{}\n]", + self._set_internals + .iter() + .map(|pattern| format!("{pattern}")) + .join(", \n\t") + ) + } + } +} + impl Deref for FilePatternSet { type Target = GlobSet; @@ -428,6 +483,23 @@ pub enum SerializationFormat { Sarif, } +impl Display for SerializationFormat { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Self::Text => write!(f, "text"), + Self::Json => write!(f, "json"), + Self::JsonLines => write!(f, "json_lines"), + Self::Junit => write!(f, "junit"), + Self::Grouped => write!(f, "grouped"), + Self::Github => write!(f, "github"), + Self::Gitlab => write!(f, "gitlab"), + Self::Pylint => write!(f, "pylint"), + Self::Azure => write!(f, "azure"), + Self::Sarif => write!(f, "sarif"), + } + } +} + impl Default for SerializationFormat { fn default() -> Self { Self::Text @@ -467,3 +539,28 @@ impl Deref for Version { /// [`fnmatch`](https://docs.python.org/3/library/fnmatch.html) for /// pattern matching. pub type IdentifierPattern = glob::Pattern; + +#[derive(Debug, CacheKey, Default)] +pub struct PerFileIgnores { + ignores: Vec<(GlobMatcher, GlobMatcher, RuleSet)>, +} + +impl PerFileIgnores { + pub fn new(ignores: Vec<(GlobMatcher, GlobMatcher, RuleSet)>) -> Self { + Self { ignores } + } +} + +impl Display for PerFileIgnores { + fn fmt(&self, _: &mut Formatter<'_>) -> std::fmt::Result { + Ok(()) + } +} + +impl Deref for PerFileIgnores { + type Target = Vec<(GlobMatcher, GlobMatcher, RuleSet)>; + + fn deref(&self) -> &Self::Target { + &self.ignores + } +} diff --git a/crates/ruff_python_formatter/src/options.rs b/crates/ruff_python_formatter/src/options.rs index 8a7967867afa1..122a9909e943a 100644 --- a/crates/ruff_python_formatter/src/options.rs +++ b/crates/ruff_python_formatter/src/options.rs @@ -2,6 +2,7 @@ use ruff_formatter::printer::{LineEnding, PrinterOptions, SourceMapGeneration}; use ruff_formatter::{FormatOptions, IndentStyle, IndentWidth, LineWidth}; use ruff_macros::CacheKey; use ruff_python_ast::PySourceType; +use std::fmt; use std::path::Path; use std::str::FromStr; @@ -241,6 +242,16 @@ pub enum QuoteStyle { Preserve, } +impl fmt::Display for QuoteStyle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Single => write!(f, "single"), + Self::Double => write!(f, "double"), + Self::Preserve => write!(f, "preserve"), + } + } +} + impl FromStr for QuoteStyle { type Err = &'static str; @@ -277,6 +288,15 @@ impl MagicTrailingComma { } } +impl fmt::Display for MagicTrailingComma { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Respect => write!(f, "respect"), + Self::Ignore => write!(f, "ignore"), + } + } +} + impl FromStr for MagicTrailingComma { type Err = &'static str; @@ -306,6 +326,15 @@ impl PreviewMode { } } +impl fmt::Display for PreviewMode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Disabled => write!(f, "disabled"), + Self::Enabled => write!(f, "enabled"), + } + } +} + #[derive(Copy, Clone, Debug, Eq, PartialEq, Default, CacheKey)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] @@ -323,6 +352,15 @@ impl DocstringCode { } } +impl fmt::Display for DocstringCode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Disabled => write!(f, "disabled"), + Self::Enabled => write!(f, "enabled"), + } + } +} + #[derive(Copy, Clone, Default, Eq, PartialEq, CacheKey)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] @@ -338,8 +376,8 @@ pub enum DocstringCodeLineWidth { Dynamic, } -impl std::fmt::Debug for DocstringCodeLineWidth { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl fmt::Debug for DocstringCodeLineWidth { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { DocstringCodeLineWidth::Fixed(v) => v.value().fmt(f), DocstringCodeLineWidth::Dynamic => "dynamic".fmt(f), @@ -347,6 +385,15 @@ impl std::fmt::Debug for DocstringCodeLineWidth { } } +impl fmt::Display for DocstringCodeLineWidth { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Fixed(width) => width.fmt(f), + Self::Dynamic => write!(f, "dynamic"), + } + } +} + /// Responsible for deserializing the `DocstringCodeLineWidth::Dynamic` /// variant. fn deserialize_docstring_code_line_width_dynamic<'de, D>(d: D) -> Result<(), D::Error> diff --git a/crates/ruff_workspace/src/settings.rs b/crates/ruff_workspace/src/settings.rs index 446cc95173bd0..f77f3f8b603b0 100644 --- a/crates/ruff_workspace/src/settings.rs +++ b/crates/ruff_workspace/src/settings.rs @@ -1,6 +1,7 @@ use path_absolutize::path_dedot; use ruff_cache::cache_dir; use ruff_formatter::{FormatOptions, IndentStyle, IndentWidth, LineWidth}; +use ruff_linter::display_settings; use ruff_linter::settings::types::{FilePattern, FilePatternSet, SerializationFormat, UnsafeFixes}; use ruff_linter::settings::LinterSettings; use ruff_macros::CacheKey; @@ -10,6 +11,7 @@ use ruff_python_formatter::{ QuoteStyle, }; use ruff_source_file::find_newline; +use std::fmt; use std::path::{Path, PathBuf}; #[derive(Debug, CacheKey)] @@ -53,6 +55,30 @@ impl Default for Settings { } } +impl fmt::Display for Settings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + display_settings! { + formatter = f, + namespace = "", + fields = [ + // We want the quotes and lossy UTF8 conversion for this path, so + // using PathBuf's `Debug` formatter suffices. + self.cache_dir | debug, + self.fix, + self.fix_only, + self.output_format, + self.show_fixes, + self.show_source, + self.unsafe_fixes, + self.file_resolver | nested, + self.linter | nested, + self.formatter | nested + ] + } + Ok(()) + } +} + #[derive(Debug, CacheKey)] pub struct FileResolverSettings { pub exclude: FilePatternSet, @@ -64,6 +90,26 @@ pub struct FileResolverSettings { pub project_root: PathBuf, } +impl fmt::Display for FileResolverSettings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "# File Resolver Settings")?; + display_settings! { + formatter = f, + namespace = "file_resolver.", + fields = [ + self.exclude, + self.extend_exclude, + self.force_exclude, + self.include, + self.extend_include, + self.respect_gitignore, + self.project_root | debug, + ] + } + Ok(()) + } +} + pub(crate) static EXCLUDE: &[FilePattern] = &[ FilePattern::Builtin(".bzr"), FilePattern::Builtin(".direnv"), @@ -191,6 +237,30 @@ impl Default for FormatterSettings { } } +impl fmt::Display for FormatterSettings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "# Formatter Settings")?; + display_settings! { + formatter = f, + namespace = "formatter.", + fields = [ + self.exclude, + self.target_version | debug, + self.preview, + self.line_width, + self.line_ending, + self.indent_style, + self.indent_width, + self.quote_style, + self.magic_trailing_comma, + self.docstring_code_format, + self.docstring_code_line_width, + ] + } + Ok(()) + } +} + #[derive( Copy, Clone, Debug, Eq, PartialEq, Default, CacheKey, serde::Serialize, serde::Deserialize, )] @@ -212,3 +282,14 @@ pub enum LineEnding { /// Line endings will be converted to `\n` on Unix and `\r\n` on Windows. Native, } + +impl fmt::Display for LineEnding { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Auto => write!(f, "auto"), + Self::Lf => write!(f, "lf"), + Self::CrLf => write!(f, "crlf"), + Self::Native => write!(f, "native"), + } + } +}