From 651c1aa8d68ec5b5ce809ec9e3c0faf0ddebd699 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 01:02:34 -0800 Subject: [PATCH 01/17] First-pass implementation of `Display` for `ruff_workspace::Settings` - A new utility macro, `display_settings`, has been created to reduce boilerplate for displaying settings fields - `Display` has been implemented on many custom types used in `ruff_workspace::Settings` - `--show-settings` now uses `Display` instead of `Debug` on `ruff_workspace::Settings` Work left to be done: - A lot of formatting for Vec<_> and HashSet<_> types has been stubbed out, using `Debug` as a fallback. There should be a way to add generic formatting support for these types as a modifier in `display_settings`. - Several complex types were also stubbed out and need proper `Display` implementations rather than falling back on `Debug` - An open question needs to be answered: should this output be valid TOML? How important is that? --- crates/ruff_cli/src/commands/show_settings.rs | 2 +- crates/ruff_formatter/src/lib.rs | 13 +++ crates/ruff_linter/src/line_width.rs | 13 +++ crates/ruff_linter/src/registry/rule_set.rs | 19 +++- .../src/rules/flake8_annotations/settings.rs | 19 ++++ .../src/rules/flake8_bandit/settings.rs | 16 +++ .../src/rules/flake8_bugbear/settings.rs | 15 +++ .../src/rules/flake8_builtins/settings.rs | 15 +++ .../rules/flake8_comprehensions/settings.rs | 15 +++ .../src/rules/flake8_copyright/settings.rs | 18 +++ .../src/rules/flake8_errmsg/settings.rs | 15 +++ .../src/rules/flake8_gettext/settings.rs | 15 +++ .../flake8_implicit_str_concat/settings.rs | 15 +++ .../flake8_import_conventions/settings.rs | 17 +++ .../src/rules/flake8_pytest_style/settings.rs | 21 ++++ .../src/rules/flake8_quotes/settings.rs | 27 +++++ .../src/rules/flake8_self/settings.rs | 15 +++ .../src/rules/flake8_tidy_imports/settings.rs | 26 +++++ .../rules/flake8_type_checking/settings.rs | 19 ++++ .../rules/flake8_unused_arguments/settings.rs | 15 +++ .../ruff_linter/src/rules/isort/categorize.rs | 19 ++++ .../ruff_linter/src/rules/isort/settings.rs | 48 ++++++++ .../ruff_linter/src/rules/mccabe/settings.rs | 15 +++ .../src/rules/pep8_naming/settings.rs | 17 +++ .../src/rules/pycodestyle/settings.rs | 17 +++ .../src/rules/pydocstyle/settings.rs | 17 +++ .../src/rules/pyflakes/settings.rs | 15 +++ .../ruff_linter/src/rules/pylint/settings.rs | 24 ++++ .../src/rules/pyupgrade/settings.rs | 15 +++ .../src/settings/fix_safety_table.rs | 17 ++- crates/ruff_linter/src/settings/mod.rs | 104 ++++++++++++++++-- crates/ruff_linter/src/settings/rule_table.rs | 17 ++- crates/ruff_linter/src/settings/types.rs | 99 ++++++++++++++++- crates/ruff_python_formatter/src/options.rs | 51 ++++++++- crates/ruff_workspace/src/settings.rs | 81 ++++++++++++++ 35 files changed, 869 insertions(+), 17 deletions(-) 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"), + } + } +} From 1341d5008b3df82c580928405c558936f16f73fa Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 07:28:50 -0800 Subject: [PATCH 02/17] Use `Display::fmt` directly instead of `write!(f, {}, ...)` --- crates/ruff_formatter/src/lib.rs | 6 +++--- crates/ruff_linter/src/line_width.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ruff_formatter/src/lib.rs b/crates/ruff_formatter/src/lib.rs index 5300f169152c2..d443ec17371c2 100644 --- a/crates/ruff_formatter/src/lib.rs +++ b/crates/ruff_formatter/src/lib.rs @@ -114,9 +114,9 @@ impl Default for IndentWidth { } } -impl fmt::Display for IndentWidth { +impl Display for IndentWidth { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - std::write!(f, "{}", self.0) + Display::fmt(&self.0, f) } } @@ -155,7 +155,7 @@ impl Default for LineWidth { impl Display for LineWidth { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - std::write!(f, "{}", self.0) + Display::fmt(&self.0, f) } } diff --git a/crates/ruff_linter/src/line_width.rs b/crates/ruff_linter/src/line_width.rs index 135937eaf686d..f804fdb2c81b5 100644 --- a/crates/ruff_linter/src/line_width.rs +++ b/crates/ruff_linter/src/line_width.rs @@ -42,7 +42,7 @@ impl Default for LineLength { impl fmt::Display for LineLength { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) + fmt::Display::fmt(&self.0, f) } } @@ -257,7 +257,7 @@ impl Default for IndentWidth { impl fmt::Display for IndentWidth { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) + fmt::Display::fmt(&self.0, f) } } From 415104efa5a575ff8dac54bb43b1e9936e430bcc Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 07:37:23 -0800 Subject: [PATCH 03/17] Make `namespace` an optional parameter for `display_settings` and remove the `.` at the end of each --- .../src/rules/flake8_annotations/settings.rs | 2 +- .../src/rules/flake8_bandit/settings.rs | 2 +- .../src/rules/flake8_bugbear/settings.rs | 2 +- .../src/rules/flake8_builtins/settings.rs | 2 +- .../rules/flake8_comprehensions/settings.rs | 2 +- .../src/rules/flake8_errmsg/settings.rs | 2 +- .../src/rules/flake8_gettext/settings.rs | 2 +- .../flake8_implicit_str_concat/settings.rs | 2 +- .../src/rules/flake8_pytest_style/settings.rs | 2 +- .../src/rules/flake8_quotes/settings.rs | 2 +- .../src/rules/flake8_self/settings.rs | 2 +- .../src/rules/flake8_tidy_imports/settings.rs | 2 +- .../rules/flake8_type_checking/settings.rs | 2 +- .../rules/flake8_unused_arguments/settings.rs | 2 +- .../ruff_linter/src/rules/isort/settings.rs | 2 +- .../ruff_linter/src/rules/mccabe/settings.rs | 2 +- .../src/rules/pep8_naming/settings.rs | 2 +- .../src/rules/pycodestyle/settings.rs | 2 +- .../src/rules/pydocstyle/settings.rs | 2 +- .../src/rules/pyflakes/settings.rs | 2 +- .../ruff_linter/src/rules/pylint/settings.rs | 2 +- .../src/rules/pyupgrade/settings.rs | 2 +- .../src/settings/fix_safety_table.rs | 2 +- crates/ruff_linter/src/settings/mod.rs | 24 ++++++++++++------- crates/ruff_linter/src/settings/rule_table.rs | 2 +- crates/ruff_workspace/src/settings.rs | 5 ++-- 26 files changed, 42 insertions(+), 35 deletions(-) diff --git a/crates/ruff_linter/src/rules/flake8_annotations/settings.rs b/crates/ruff_linter/src/rules/flake8_annotations/settings.rs index f229b628086f6..011cf01f4a926 100644 --- a/crates/ruff_linter/src/rules/flake8_annotations/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_annotations/settings.rs @@ -18,7 +18,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_annotations.", + namespace = "linter.flake8_annotations", fields = [ self.mypy_init_return, self.suppress_dummy_args, diff --git a/crates/ruff_linter/src/rules/flake8_bandit/settings.rs b/crates/ruff_linter/src/rules/flake8_bandit/settings.rs index d1a5bb2ed75ae..d031ea260f376 100644 --- a/crates/ruff_linter/src/rules/flake8_bandit/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_bandit/settings.rs @@ -29,7 +29,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_bandit.", + namespace = "linter.flake8_bandit", fields = [ self.hardcoded_tmp_directory | debug, self.check_typed_exception diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs b/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs index b545b8d4f744f..be58047764222 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs @@ -13,7 +13,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_bugbear.", + namespace = "linter.flake8_bugbear", fields = [ self.extend_immutable_calls | debug ] diff --git a/crates/ruff_linter/src/rules/flake8_builtins/settings.rs b/crates/ruff_linter/src/rules/flake8_builtins/settings.rs index 9080dea377138..12e9831279d59 100644 --- a/crates/ruff_linter/src/rules/flake8_builtins/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_builtins/settings.rs @@ -13,7 +13,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_builtins.", + namespace = "linter.flake8_builtins", fields = [ self.builtins_ignorelist | debug ] diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/settings.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/settings.rs index 5be8deb011bfa..41110886a5d4e 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/settings.rs @@ -13,7 +13,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_comprehensions.", + namespace = "linter.flake8_comprehensions", fields = [ self.allow_dict_calls_with_keyword_arguments ] diff --git a/crates/ruff_linter/src/rules/flake8_errmsg/settings.rs b/crates/ruff_linter/src/rules/flake8_errmsg/settings.rs index ffb97d93bc4b7..ec239435cee07 100644 --- a/crates/ruff_linter/src/rules/flake8_errmsg/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_errmsg/settings.rs @@ -13,7 +13,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_errmsg.", + namespace = "linter.flake8_errmsg", fields = [ self.max_string_length ] diff --git a/crates/ruff_linter/src/rules/flake8_gettext/settings.rs b/crates/ruff_linter/src/rules/flake8_gettext/settings.rs index c23ab2a7904e1..778f0651d5b9f 100644 --- a/crates/ruff_linter/src/rules/flake8_gettext/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_gettext/settings.rs @@ -27,7 +27,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_gettext.", + namespace = "linter.flake8_gettext", fields = [ self.functions_names | debug ] 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 250aa29ef289b..90c6a9a1812fe 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 @@ -21,7 +21,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_implicit_str_concat.", + namespace = "linter.flake8_implicit_str_concat", fields = [ self.allow_multiline ] 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 60da64d656c7c..ae2f3ad59b69f 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/settings.rs @@ -53,7 +53,7 @@ impl fmt::Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_pytest_style.", + namespace = "linter.flake8_pytest_style", fields = [ self.fixture_parentheses, self.parametrize_names_type, diff --git a/crates/ruff_linter/src/rules/flake8_quotes/settings.rs b/crates/ruff_linter/src/rules/flake8_quotes/settings.rs index 0fddace12cdea..a0ddea385c020 100644 --- a/crates/ruff_linter/src/rules/flake8_quotes/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_quotes/settings.rs @@ -45,7 +45,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_quotes.", + namespace = "linter.flake8_quotes", fields = [ self.inline_quotes, self.multiline_quotes, diff --git a/crates/ruff_linter/src/rules/flake8_self/settings.rs b/crates/ruff_linter/src/rules/flake8_self/settings.rs index 50d47462a7064..56355ef2addf4 100644 --- a/crates/ruff_linter/src/rules/flake8_self/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_self/settings.rs @@ -34,7 +34,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_self.", + namespace = "linter.flake8_self", fields = [ self.ignore_names | debug ] 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 323bfc69b7bc4..3c59869ff7bd0 100644 --- a/crates/ruff_linter/src/rules/flake8_tidy_imports/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_tidy_imports/settings.rs @@ -44,7 +44,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_tidy_imports.", + namespace = "linter.flake8_tidy_imports", fields = [ self.ban_relative_imports, self.banned_api | debug, 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 2808a26e4f5ff..3ead966e71c12 100644 --- a/crates/ruff_linter/src/rules/flake8_type_checking/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_type_checking/settings.rs @@ -29,7 +29,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_type_checking.", + namespace = "linter.flake8_type_checking", fields = [ self.strict, self.exempt_modules | debug, 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 d00ca55ba6095..7e13bc6495a9a 100644 --- a/crates/ruff_linter/src/rules/flake8_unused_arguments/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_unused_arguments/settings.rs @@ -13,7 +13,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.flake8_unused_arguments.", + namespace = "linter.flake8_unused_arguments", fields = [ self.ignore_variadic_names ] diff --git a/crates/ruff_linter/src/rules/isort/settings.rs b/crates/ruff_linter/src/rules/isort/settings.rs index 414e54e5dc337..a02004072d49f 100644 --- a/crates/ruff_linter/src/rules/isort/settings.rs +++ b/crates/ruff_linter/src/rules/isort/settings.rs @@ -109,7 +109,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { display_settings! { formatter = f, - namespace = "linter.isort.", + namespace = "linter.isort", fields = [ self.required_imports | debug, self.combine_as_imports, diff --git a/crates/ruff_linter/src/rules/mccabe/settings.rs b/crates/ruff_linter/src/rules/mccabe/settings.rs index 8711e607f54af..65abe3c91d1a0 100644 --- a/crates/ruff_linter/src/rules/mccabe/settings.rs +++ b/crates/ruff_linter/src/rules/mccabe/settings.rs @@ -23,7 +23,7 @@ impl Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.mccabe.", + namespace = "linter.mccabe", fields = [ self.max_complexity ] diff --git a/crates/ruff_linter/src/rules/pep8_naming/settings.rs b/crates/ruff_linter/src/rules/pep8_naming/settings.rs index 7c09a23c16be8..2c689e802b66b 100644 --- a/crates/ruff_linter/src/rules/pep8_naming/settings.rs +++ b/crates/ruff_linter/src/rules/pep8_naming/settings.rs @@ -50,7 +50,7 @@ impl fmt::Display for Settings { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { display_settings! { formatter = f, - namespace = "linter.pep8_naming.", + namespace = "linter.pep8_naming", fields = [ self.ignore_names | debug, self.classmethod_decorators | debug, diff --git a/crates/ruff_linter/src/rules/pycodestyle/settings.rs b/crates/ruff_linter/src/rules/pycodestyle/settings.rs index 7dad02cad5607..43cf37ff69f68 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/settings.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/settings.rs @@ -17,7 +17,7 @@ impl fmt::Display for Settings { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { display_settings! { formatter = f, - namespace = "linter.pycodestyle.", + namespace = "linter.pycodestyle", fields = [ self.max_line_length, self.max_doc_length | debug, diff --git a/crates/ruff_linter/src/rules/pydocstyle/settings.rs b/crates/ruff_linter/src/rules/pydocstyle/settings.rs index 51187718eeb21..a7017de674d8b 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/settings.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/settings.rs @@ -84,7 +84,7 @@ impl fmt::Display for Settings { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { display_settings! { formatter = f, - namespace = "linter.pydocstyle.", + namespace = "linter.pydocstyle", fields = [ self.convention | debug, self.ignore_decorators | debug, diff --git a/crates/ruff_linter/src/rules/pyflakes/settings.rs b/crates/ruff_linter/src/rules/pyflakes/settings.rs index 3cd582eb806e0..b87c9aebf2108 100644 --- a/crates/ruff_linter/src/rules/pyflakes/settings.rs +++ b/crates/ruff_linter/src/rules/pyflakes/settings.rs @@ -13,7 +13,7 @@ impl fmt::Display for Settings { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { display_settings! { formatter = f, - namespace = "linter.pyflakes.", + namespace = "linter.pyflakes", fields = [ self.extend_generics | debug ] diff --git a/crates/ruff_linter/src/rules/pylint/settings.rs b/crates/ruff_linter/src/rules/pylint/settings.rs index c4f3d418d9903..fe1a513cd8b88 100644 --- a/crates/ruff_linter/src/rules/pylint/settings.rs +++ b/crates/ruff_linter/src/rules/pylint/settings.rs @@ -71,7 +71,7 @@ impl fmt::Display for Settings { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { display_settings! { formatter = f, - namespace = "linter.pylint.", + namespace = "linter.pylint", fields = [ self.allow_magic_value_types | debug, self.allow_dunder_method_names | debug, diff --git a/crates/ruff_linter/src/rules/pyupgrade/settings.rs b/crates/ruff_linter/src/rules/pyupgrade/settings.rs index bf73ea1086358..4e228351f3639 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/settings.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/settings.rs @@ -13,7 +13,7 @@ impl fmt::Display for Settings { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { display_settings! { formatter = f, - namespace = "linter.pyupgrade.", + namespace = "linter.pyupgrade", fields = [ self.keep_runtime_typing ] diff --git a/crates/ruff_linter/src/settings/fix_safety_table.rs b/crates/ruff_linter/src/settings/fix_safety_table.rs index ebe93def6a61d..e3b280be0cddc 100644 --- a/crates/ruff_linter/src/settings/fix_safety_table.rs +++ b/crates/ruff_linter/src/settings/fix_safety_table.rs @@ -100,7 +100,7 @@ impl Display for FixSafetyTable { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.safety_table.", + namespace = "linter.safety_table", fields = [ self.forced_safe, self.forced_unsafe diff --git a/crates/ruff_linter/src/settings/mod.rs b/crates/ruff_linter/src/settings/mod.rs index 70944a55d696f..20cf12f916157 100644 --- a/crates/ruff_linter/src/settings/mod.rs +++ b/crates/ruff_linter/src/settings/mod.rs @@ -45,20 +45,28 @@ pub mod types; macro_rules! display_settings { (formatter = $fmt:ident, namespace = $namespace:literal, fields = [$($settings:ident.$field:ident $(| $modifier:tt)?),* $(,)?]) => { { - const _NS: &str = $namespace; + const _PREFIX: &str = concat!($namespace, "."); $( - display_settings!(@field $fmt, _NS, $settings.$field $(| $modifier)?); + display_settings!(@field $fmt, _PREFIX, $settings.$field $(| $modifier)?); )* } }; - (@field $fmt:ident, $namespace:ident, $settings:ident.$field:ident | debug) => { - writeln!($fmt, "{}{} = {:?}", $namespace, stringify!($field), $settings.$field)?; + (formatter = $fmt:ident, fields = [$($settings:ident.$field:ident $(| $modifier:tt)?),* $(,)?]) => { + { + const _PREFIX: &str = ""; + $( + display_settings!(@field $fmt, _PREFIX, $settings.$field $(| $modifier)?); + )* + } + }; + (@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | debug) => { + writeln!($fmt, "{}{} = {:?}", $prefix, stringify!($field), $settings.$field)?; }; - (@field $fmt:ident, $namespace:ident, $settings:ident.$field:ident | nested) => { + (@field $fmt:ident, $prefix: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)?; + (@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident) => { + writeln!($fmt, "{}{} = {}", $prefix, stringify!($field), $settings.$field)?; }; } @@ -122,7 +130,7 @@ impl Display for LinterSettings { writeln!(f, "# Linter Settings")?; display_settings! { formatter = f, - namespace = "linter.", + namespace = "linter", fields = [ self.exclude, self.project_root | debug, diff --git a/crates/ruff_linter/src/settings/rule_table.rs b/crates/ruff_linter/src/settings/rule_table.rs index 395c90d50153f..f6b8482afc71c 100644 --- a/crates/ruff_linter/src/settings/rule_table.rs +++ b/crates/ruff_linter/src/settings/rule_table.rs @@ -67,7 +67,7 @@ impl Display for RuleTable { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { display_settings! { formatter = f, - namespace = "linter.rules.", + namespace = "linter.rules", fields = [ self.enabled, self.should_fix diff --git a/crates/ruff_workspace/src/settings.rs b/crates/ruff_workspace/src/settings.rs index f77f3f8b603b0..8b8e2e7093e4b 100644 --- a/crates/ruff_workspace/src/settings.rs +++ b/crates/ruff_workspace/src/settings.rs @@ -59,7 +59,6 @@ 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. @@ -95,7 +94,7 @@ impl fmt::Display for FileResolverSettings { writeln!(f, "# File Resolver Settings")?; display_settings! { formatter = f, - namespace = "file_resolver.", + namespace = "file_resolver", fields = [ self.exclude, self.extend_exclude, @@ -242,7 +241,7 @@ impl fmt::Display for FormatterSettings { writeln!(f, "# Formatter Settings")?; display_settings! { formatter = f, - namespace = "formatter.", + namespace = "formatter", fields = [ self.exclude, self.target_version | debug, From afe986c7131d25812f22aece48bbc01a468cbf98 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 07:47:52 -0800 Subject: [PATCH 04/17] Eliminate unnessecary allocations in the `Display` implementations of `FilePatternSet` and `RuleSet` --- crates/ruff_linter/src/registry/rule_set.rs | 16 +++++++--------- crates/ruff_linter/src/settings/types.rs | 17 +++++++---------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/crates/ruff_linter/src/registry/rule_set.rs b/crates/ruff_linter/src/registry/rule_set.rs index 7efdbf69f0844..2acc0f4c0e16d 100644 --- a/crates/ruff_linter/src/registry/rule_set.rs +++ b/crates/ruff_linter/src/registry/rule_set.rs @@ -1,5 +1,4 @@ use crate::registry::Rule; -use itertools::Itertools; use ruff_macros::CacheKey; use std::fmt::{Debug, Display, Formatter}; use std::iter::FusedIterator; @@ -273,16 +272,15 @@ impl Debug for RuleSet { impl Display for RuleSet { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if self.is_empty() { - write!(f, "[]") + write!(f, "[]")?; } else { - write!( - f, - "[\n\t{}\n]", - self.iter() - .map(|rule| format!("\"{rule:?}\"")) - .join(",\n\t") - ) + writeln!(f, "[")?; + for rule in self { + writeln!(f, "\t\"{rule:?}\",")?; + } + write!(f, "]")?; } + Ok(()) } } diff --git a/crates/ruff_linter/src/settings/types.rs b/crates/ruff_linter/src/settings/types.rs index 77fa8658c5284..f2b3b2df1f282 100644 --- a/crates/ruff_linter/src/settings/types.rs +++ b/crates/ruff_linter/src/settings/types.rs @@ -7,7 +7,6 @@ use std::string::ToString; use anyhow::{bail, Result}; 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}; @@ -257,17 +256,15 @@ impl FilePatternSet { impl Display for FilePatternSet { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { if self._set_internals.is_empty() { - write!(f, "[]") + write!(f, "[]")?; } else { - write!( - f, - "[\n\t{}\n]", - self._set_internals - .iter() - .map(|pattern| format!("{pattern}")) - .join(", \n\t") - ) + writeln!(f, "[")?; + for pattern in &self._set_internals { + writeln!(f, "\t{pattern},")?; + } + write!(f, "]")?; } + Ok(()) } } From 16dbd8f0f633db36e800173282b0aba80dbc48dc Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 08:17:14 -0800 Subject: [PATCH 05/17] Remove unnessecary allocation from `impl Display for KnownModules` and remove debug formatter for `KnownModules` --- .../ruff_linter/src/rules/isort/categorize.rs | 17 +++++++---------- crates/ruff_linter/src/rules/isort/settings.rs | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/crates/ruff_linter/src/rules/isort/categorize.rs b/crates/ruff_linter/src/rules/isort/categorize.rs index f9c1bf51928cd..ffccbf3781d5a 100644 --- a/crates/ruff_linter/src/rules/isort/categorize.rs +++ b/crates/ruff_linter/src/rules/isort/categorize.rs @@ -1,4 +1,3 @@ -use itertools::Itertools; use std::collections::BTreeMap; use std::fmt; use std::hash::BuildHasherDefault; @@ -384,16 +383,14 @@ impl KnownModules { impl fmt::Display for KnownModules { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.known.is_empty() { - write!(f, "[]") + write!(f, "{{}}")?; } else { - write!( - f, - "{{\n\t{}\n}}", - self.known - .iter() - .map(|(pattern, import_section)| format!("{pattern} => {import_section:?}")) - .join(", \n\t") - ) + writeln!(f, "{{")?; + for (pattern, import_section) in &self.known { + writeln!(f, "\t{pattern} => {import_section:?},")?; + } + write!(f, "}}")?; } + Ok(()) } } diff --git a/crates/ruff_linter/src/rules/isort/settings.rs b/crates/ruff_linter/src/rules/isort/settings.rs index a02004072d49f..4d68da0ecad15 100644 --- a/crates/ruff_linter/src/rules/isort/settings.rs +++ b/crates/ruff_linter/src/rules/isort/settings.rs @@ -119,7 +119,7 @@ impl Display for Settings { self.case_sensitive, self.force_wrap_aliases, self.force_to_top | debug, - self.known_modules | debug, // TODO(jane): remove debug + self.known_modules, self.order_by_type, self.relative_imports_order, self.single_line_exclusions | debug, From e7a6aabb0df486ce0c92af99a1daccfc29d89ce9 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 11:24:21 -0800 Subject: [PATCH 06/17] Implement `array` and `optional` formatting options for `display_settings` --- crates/ruff_linter/src/registry/rule_set.rs | 2 +- .../src/rules/flake8_bandit/settings.rs | 2 +- .../src/rules/flake8_bugbear/settings.rs | 2 +- .../src/rules/flake8_builtins/settings.rs | 2 +- .../src/rules/flake8_copyright/settings.rs | 3 +- .../src/rules/flake8_gettext/settings.rs | 2 +- .../flake8_import_conventions/settings.rs | 2 +- .../src/rules/flake8_pytest_style/settings.rs | 4 +- .../src/rules/flake8_self/settings.rs | 2 +- .../src/rules/flake8_tidy_imports/settings.rs | 2 +- .../rules/flake8_type_checking/settings.rs | 6 +-- .../ruff_linter/src/rules/isort/categorize.rs | 21 ++++++++++ .../ruff_linter/src/rules/isort/settings.rs | 18 ++++----- .../src/rules/pep8_naming/settings.rs | 6 +-- .../src/rules/pycodestyle/settings.rs | 2 +- .../src/rules/pydocstyle/settings.rs | 12 +++++- .../ruff_linter/src/rules/pylint/settings.rs | 16 +++++++- crates/ruff_linter/src/settings/mod.rs | 39 +++++++++++++++---- crates/ruff_linter/src/settings/types.rs | 24 +++++++++++- 19 files changed, 127 insertions(+), 40 deletions(-) diff --git a/crates/ruff_linter/src/registry/rule_set.rs b/crates/ruff_linter/src/registry/rule_set.rs index 2acc0f4c0e16d..6c15feba9a57f 100644 --- a/crates/ruff_linter/src/registry/rule_set.rs +++ b/crates/ruff_linter/src/registry/rule_set.rs @@ -276,7 +276,7 @@ impl Display for RuleSet { } else { writeln!(f, "[")?; for rule in self { - writeln!(f, "\t\"{rule:?}\",")?; + writeln!(f, "\t{rule:?},")?; } write!(f, "]")?; } diff --git a/crates/ruff_linter/src/rules/flake8_bandit/settings.rs b/crates/ruff_linter/src/rules/flake8_bandit/settings.rs index d031ea260f376..17a018a25c64c 100644 --- a/crates/ruff_linter/src/rules/flake8_bandit/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_bandit/settings.rs @@ -31,7 +31,7 @@ impl Display for Settings { formatter = f, namespace = "linter.flake8_bandit", fields = [ - self.hardcoded_tmp_directory | debug, + self.hardcoded_tmp_directory | array, self.check_typed_exception ] } diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs b/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs index be58047764222..03c4d5cdf1d98 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/settings.rs @@ -15,7 +15,7 @@ impl Display for Settings { formatter = f, namespace = "linter.flake8_bugbear", fields = [ - self.extend_immutable_calls | debug + self.extend_immutable_calls | array ] } Ok(()) diff --git a/crates/ruff_linter/src/rules/flake8_builtins/settings.rs b/crates/ruff_linter/src/rules/flake8_builtins/settings.rs index 12e9831279d59..d3fc3a70f74bd 100644 --- a/crates/ruff_linter/src/rules/flake8_builtins/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_builtins/settings.rs @@ -15,7 +15,7 @@ impl Display for Settings { formatter = f, namespace = "linter.flake8_builtins", fields = [ - self.builtins_ignorelist | debug + self.builtins_ignorelist | array ] } Ok(()) diff --git a/crates/ruff_linter/src/rules/flake8_copyright/settings.rs b/crates/ruff_linter/src/rules/flake8_copyright/settings.rs index c9da08a5071cd..9f76e763cf880 100644 --- a/crates/ruff_linter/src/rules/flake8_copyright/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_copyright/settings.rs @@ -34,8 +34,7 @@ impl Display for Settings { namespace = "linter.flake8_copyright", fields = [ self.notice_rgx, - // TODO(jane): remove debug - self.author | debug, + self.author | optional, self.min_file_size, ] } diff --git a/crates/ruff_linter/src/rules/flake8_gettext/settings.rs b/crates/ruff_linter/src/rules/flake8_gettext/settings.rs index 778f0651d5b9f..6e3a6c367cd10 100644 --- a/crates/ruff_linter/src/rules/flake8_gettext/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_gettext/settings.rs @@ -29,7 +29,7 @@ impl Display for Settings { formatter = f, namespace = "linter.flake8_gettext", fields = [ - self.functions_names | debug + self.functions_names | array ] } 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 3e4733b240200..70fe742a20e3e 100644 --- a/crates/ruff_linter/src/rules/flake8_import_conventions/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_import_conventions/settings.rs @@ -55,7 +55,7 @@ impl Display for Settings { fields = [ self.aliases | debug, self.banned_aliases | debug, - self.banned_from | debug, + self.banned_from | array, ] } 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 ae2f3ad59b69f..cab3d2d5a3eed 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/settings.rs @@ -59,8 +59,8 @@ impl fmt::Display for Settings { 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.raises_require_match_for | array, + self.raises_extend_require_match_for | array, self.mark_parentheses ] } diff --git a/crates/ruff_linter/src/rules/flake8_self/settings.rs b/crates/ruff_linter/src/rules/flake8_self/settings.rs index 56355ef2addf4..c59a0ec89d221 100644 --- a/crates/ruff_linter/src/rules/flake8_self/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_self/settings.rs @@ -36,7 +36,7 @@ impl Display for Settings { formatter = f, namespace = "linter.flake8_self", fields = [ - self.ignore_names | debug + self.ignore_names | array ] } 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 3c59869ff7bd0..35d55e2e75b80 100644 --- a/crates/ruff_linter/src/rules/flake8_tidy_imports/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_tidy_imports/settings.rs @@ -48,7 +48,7 @@ impl Display for Settings { fields = [ self.ban_relative_imports, self.banned_api | debug, - self.banned_module_level_imports | debug, + self.banned_module_level_imports | array, ] } 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 3ead966e71c12..fa8214e5b74af 100644 --- a/crates/ruff_linter/src/rules/flake8_type_checking/settings.rs +++ b/crates/ruff_linter/src/rules/flake8_type_checking/settings.rs @@ -32,9 +32,9 @@ impl Display for Settings { namespace = "linter.flake8_type_checking", fields = [ self.strict, - self.exempt_modules | debug, - self.runtime_required_base_classes | debug, - self.runtime_required_decorators | debug, + self.exempt_modules | array, + self.runtime_required_base_classes | array, + self.runtime_required_decorators | array, self.quote_annotations ] } diff --git a/crates/ruff_linter/src/rules/isort/categorize.rs b/crates/ruff_linter/src/rules/isort/categorize.rs index ffccbf3781d5a..c00640ea12ac2 100644 --- a/crates/ruff_linter/src/rules/isort/categorize.rs +++ b/crates/ruff_linter/src/rules/isort/categorize.rs @@ -41,6 +41,18 @@ pub enum ImportType { LocalFolder, } +impl fmt::Display for ImportType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Future => write!(f, "future"), + Self::StandardLibrary => write!(f, "standard_library"), + Self::ThirdParty => write!(f, "third_party"), + Self::FirstParty => write!(f, "first_party"), + Self::LocalFolder => write!(f, "local_folder"), + } + } +} + #[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash, Serialize, Deserialize, CacheKey)] #[serde(untagged)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] @@ -49,6 +61,15 @@ pub enum ImportSection { UserDefined(String), } +impl fmt::Display for ImportSection { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Known(import_type) => write!(f, "known {{ type = {import_type} }}",), + Self::UserDefined(string) => fmt::Debug::fmt(string, f), + } + } +} + #[derive(Debug)] enum Reason<'a> { NonZeroLevel, diff --git a/crates/ruff_linter/src/rules/isort/settings.rs b/crates/ruff_linter/src/rules/isort/settings.rs index 4d68da0ecad15..b5b13363b4c4a 100644 --- a/crates/ruff_linter/src/rules/isort/settings.rs +++ b/crates/ruff_linter/src/rules/isort/settings.rs @@ -111,27 +111,27 @@ impl Display for Settings { formatter = f, namespace = "linter.isort", fields = [ - self.required_imports | debug, + self.required_imports | array, 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.force_to_top | array, self.known_modules, self.order_by_type, self.relative_imports_order, - self.single_line_exclusions | debug, + self.single_line_exclusions | array, self.split_on_trailing_comma, - self.classes | debug, - self.constants | debug, - self.variables | debug, - self.no_lines_before | debug, + self.classes | array, + self.constants | array, + self.variables | array, + self.no_lines_before | array, self.lines_after_imports, self.lines_between_types, - self.forced_separate | debug, - self.section_order | debug, + self.forced_separate | array, + self.section_order | array, self.no_sections, self.from_first, self.length_sort, diff --git a/crates/ruff_linter/src/rules/pep8_naming/settings.rs b/crates/ruff_linter/src/rules/pep8_naming/settings.rs index 2c689e802b66b..1a64557a6d2ad 100644 --- a/crates/ruff_linter/src/rules/pep8_naming/settings.rs +++ b/crates/ruff_linter/src/rules/pep8_naming/settings.rs @@ -52,9 +52,9 @@ impl fmt::Display for Settings { formatter = f, namespace = "linter.pep8_naming", fields = [ - self.ignore_names | debug, - self.classmethod_decorators | debug, - self.staticmethod_decorators | debug + self.ignore_names | array, + self.classmethod_decorators | array, + self.staticmethod_decorators | array ] } Ok(()) diff --git a/crates/ruff_linter/src/rules/pycodestyle/settings.rs b/crates/ruff_linter/src/rules/pycodestyle/settings.rs index 43cf37ff69f68..1ce1d1c029ea6 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/settings.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/settings.rs @@ -20,7 +20,7 @@ impl fmt::Display for Settings { namespace = "linter.pycodestyle", fields = [ self.max_line_length, - self.max_doc_length | debug, + self.max_doc_length | optional, self.ignore_overlong_task_comments, ] } diff --git a/crates/ruff_linter/src/rules/pydocstyle/settings.rs b/crates/ruff_linter/src/rules/pydocstyle/settings.rs index a7017de674d8b..b65172e4102d3 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/settings.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/settings.rs @@ -73,6 +73,16 @@ impl Convention { } } +impl fmt::Display for Convention { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Google => write!(f, "google"), + Self::Numpy => write!(f, "numpy"), + Self::Pep257 => write!(f, "pep257"), + } + } +} + #[derive(Debug, Default, CacheKey)] pub struct Settings { pub convention: Option, @@ -86,7 +96,7 @@ impl fmt::Display for Settings { formatter = f, namespace = "linter.pydocstyle", fields = [ - self.convention | debug, + self.convention | optional, self.ignore_decorators | debug, self.property_decorators | debug ] diff --git a/crates/ruff_linter/src/rules/pylint/settings.rs b/crates/ruff_linter/src/rules/pylint/settings.rs index fe1a513cd8b88..71ff494bf2a7c 100644 --- a/crates/ruff_linter/src/rules/pylint/settings.rs +++ b/crates/ruff_linter/src/rules/pylint/settings.rs @@ -36,6 +36,18 @@ impl ConstantType { } } +impl fmt::Display for ConstantType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Bytes => write!(f, "bytes"), + Self::Complex => write!(f, "complex"), + Self::Float => write!(f, "float"), + Self::Int => write!(f, "int"), + Self::Str => write!(f, "str"), + } + } +} + #[derive(Debug, CacheKey)] pub struct Settings { pub allow_magic_value_types: Vec, @@ -73,8 +85,8 @@ impl fmt::Display for Settings { formatter = f, namespace = "linter.pylint", fields = [ - self.allow_magic_value_types | debug, - self.allow_dunder_method_names | debug, + self.allow_magic_value_types | array, + self.allow_dunder_method_names | array, self.max_args, self.max_positional_args, self.max_returns, diff --git a/crates/ruff_linter/src/settings/mod.rs b/crates/ruff_linter/src/settings/mod.rs index 20cf12f916157..d4e41b548789e 100644 --- a/crates/ruff_linter/src/settings/mod.rs +++ b/crates/ruff_linter/src/settings/mod.rs @@ -65,6 +65,29 @@ macro_rules! display_settings { (@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | nested) => { write!($fmt, "{}", $settings.$field)?; }; + (@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | optional) => { + { + write!($fmt, "{}{} = ", $prefix, stringify!($field))?; + match &$settings.$field { + Some(value) => writeln!($fmt, "{}", value)?, + None => writeln!($fmt, "nil")? + }; + } + }; + (@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | array) => { + { + write!($fmt, "{}{} = ", $prefix, stringify!($field))?; + if $settings.$field.is_empty() { + writeln!($fmt, "[]")?; + } else { + writeln!($fmt, "[")?; + for elem in &$settings.$field { + writeln!($fmt, "\t{elem},")?; + } + writeln!($fmt, "]")?; + } + } + }; (@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident) => { writeln!($fmt, "{}{} = {}", $prefix, stringify!($field), $settings.$field)?; }; @@ -140,22 +163,22 @@ impl Display for LinterSettings { self.fix_safety | nested, self.target_version | debug, - self.preview | debug, + self.preview, self.explicit_preview_rules, - self.extension | debug, + self.extension | nested, - self.allowed_confusables | debug, - self.builtins | debug, + self.allowed_confusables | array, + self.builtins | array, self.dummy_variable_rgx, - self.external | debug, + self.external | array, self.ignore_init_module_imports, - self.logger_objects | debug, + self.logger_objects | array, self.namespace_packages | debug, self.src | debug, self.tab_size, self.line_length, - self.task_tags | debug, - self.typing_modules | debug, + self.task_tags | array, + self.typing_modules | array, self.flake8_annotations | nested, self.flake8_bandit | nested, diff --git a/crates/ruff_linter/src/settings/types.rs b/crates/ruff_linter/src/settings/types.rs index f2b3b2df1f282..a8876fbfa7adf 100644 --- a/crates/ruff_linter/src/settings/types.rs +++ b/crates/ruff_linter/src/settings/types.rs @@ -18,9 +18,9 @@ use ruff_diagnostics::Applicability; use ruff_macros::CacheKey; use ruff_python_ast::PySourceType; -use crate::fs; use crate::registry::RuleSet; use crate::rule_selector::RuleSelector; +use crate::{display_settings, fs}; #[derive( Clone, @@ -122,6 +122,15 @@ impl From for PreviewMode { } } +impl Display for PreviewMode { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Self::Disabled => write!(f, "disabled"), + Self::Enabled => write!(f, "enabled"), + } + } +} + /// Toggle for unsafe fixes. /// `Hint` will not apply unsafe fixes but a message will be shown when they are available. /// `Disabled` will not apply unsafe fixes or show a message. @@ -446,6 +455,19 @@ impl ExtensionMapping { } } +impl Display for ExtensionMapping { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + display_settings! { + formatter = f, + namespace = "linter.extension", + fields = [ + self.mapping | debug + ] + } + Ok(()) + } +} + impl From> for ExtensionMapping { fn from(value: FxHashMap) -> Self { Self { mapping: value } From eb9c1fbf5c984d41730cfa2077d18536cc4efdbc Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 11:44:51 -0800 Subject: [PATCH 07/17] Add `quoted` formatter to `display_settings` and document the `display_settings` macro --- crates/ruff_linter/src/settings/mod.rs | 68 ++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/crates/ruff_linter/src/settings/mod.rs b/crates/ruff_linter/src/settings/mod.rs index d4e41b548789e..fe5d3e3f2692d 100644 --- a/crates/ruff_linter/src/settings/mod.rs +++ b/crates/ruff_linter/src/settings/mod.rs @@ -41,6 +41,71 @@ pub mod flags; pub mod rule_table; pub mod types; +/// `display_settings!` is a macro that can display and format struct fields in a readable, +/// namespaced format. It's particularly useful at generating `Display` implementations +/// for types used in settings. +/// +/// # Example +/// ``` +/// use std::fmt; +/// use ruff_linter::display_settings; +/// #[derive(Default)] +/// struct Settings { +/// option_a: bool, +/// sub_settings: SubSettings, +/// option_b: String, +/// } +/// +/// struct SubSettings { +/// name: String +/// } +/// +/// impl Default for SubSettings { +/// fn default() -> Self { +/// Self { name: "Default Name".into() } +/// } +/// +/// } +/// +/// impl fmt::Display for SubSettings { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// display_settings! { +/// formatter = f, +/// namespace = "sub_settings", +/// fields = [ +/// self.name | quoted +/// ] +/// } +/// Ok(()) +/// } +/// +/// } +/// +/// impl fmt::Display for Settings { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// display_settings! { +/// formatter = f, +/// fields = [ +/// self.option_a, +/// self.sub_settings | nested, +/// self.option_b | quoted, +/// ] +/// } +/// Ok(()) +/// } +/// +/// } +/// +/// const EXPECTED_OUTPUT: &str = r#"option_a = false +/// sub_settings.name = "Default Name" +/// option_b = "" +/// "#; +/// +/// fn main() { +/// let settings = Settings::default(); +/// assert_eq!(format!("{settings}"), EXPECTED_OUTPUT); +/// } +/// ``` #[macro_export] macro_rules! display_settings { (formatter = $fmt:ident, namespace = $namespace:literal, fields = [$($settings:ident.$field:ident $(| $modifier:tt)?),* $(,)?]) => { @@ -62,6 +127,9 @@ macro_rules! display_settings { (@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | debug) => { writeln!($fmt, "{}{} = {:?}", $prefix, stringify!($field), $settings.$field)?; }; + (@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | quoted) => { + writeln!($fmt, "{}{} = \"{}\"", $prefix, stringify!($field), $settings.$field)?; + }; (@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | nested) => { write!($fmt, "{}", $settings.$field)?; }; From 0ce38bc76fb796d261d87c3294f17b8e8f0e0496 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 11:52:34 -0800 Subject: [PATCH 08/17] Properly implement `Display` for `PerFileIgnores` --- crates/ruff_linter/src/settings/types.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/ruff_linter/src/settings/types.rs b/crates/ruff_linter/src/settings/types.rs index a8876fbfa7adf..d9dc33617b66d 100644 --- a/crates/ruff_linter/src/settings/types.rs +++ b/crates/ruff_linter/src/settings/types.rs @@ -571,7 +571,19 @@ impl PerFileIgnores { } impl Display for PerFileIgnores { - fn fmt(&self, _: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if self.is_empty() { + write!(f, "{{}}")?; + } else { + writeln!(f, "{{")?; + for (absolute, basename, rules) in &self.ignores { + writeln!( + f, + "\t{{ absolute = {absolute:#?}, basename = {basename:#?}, rules = {rules} }}," + )?; + } + write!(f, "}}")?; + } Ok(()) } } From 14221b6b13b94b250796bf9c2fb1aa0ab4a75204 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 14:08:23 -0800 Subject: [PATCH 09/17] Set up a snapshot test for the default output of `--show-settings` --- crates/ruff_cli/tests/show_settings.rs | 28 ++ ...ow_settings__display_default_settings.snap | 362 ++++++++++++++++++ 2 files changed, 390 insertions(+) create mode 100644 crates/ruff_cli/tests/show_settings.rs create mode 100644 crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap diff --git a/crates/ruff_cli/tests/show_settings.rs b/crates/ruff_cli/tests/show_settings.rs new file mode 100644 index 0000000000000..9de63e12351b5 --- /dev/null +++ b/crates/ruff_cli/tests/show_settings.rs @@ -0,0 +1,28 @@ +use insta_cmd::{assert_cmd_snapshot, get_cargo_bin}; +use std::path::Path; +use std::process::Command; + +const BIN_NAME: &str = "ruff"; + +#[cfg(not(target_os = "windows"))] +const TEST_FILTERS: &[(&str, &str)] = &[ + ("\"[^\\*\"]*/pyproject.toml", "\"[BASEPATH]/pyproject.toml"), + ("\".*/crates", "\"[BASEPATH]/crates"), + ("\".*/\\.ruff_cache", "\"[BASEPATH]/.ruff_cache"), + ("\".*/ruff\"", "\"[BASEPATH]\""), +]; +#[cfg(target_os = "windows")] +const TEST_FILTERS: &[(&str, &str)] = &[ + (r".*\\resources\\test\\fixtures\\", "[BASEPATH]\\"), + (r#"[^\*"]*\\pyproject.toml"#, "\"[BASEPATH]\\pyproject.toml"), + (r#"".*\\crates"#, "\"[BASEPATH]\\crates"), + (r#"".*\\\.ruff_cache"#, "\"[BASEPATH]\\.ruff_cache"), + (r#"".*\\ruff""#, "\"[BASEPATH]\""), + (r"\\", "/"), +]; + +#[test] +fn display_default_settings() { + insta::with_settings!({ filters => TEST_FILTERS.to_vec() }, { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .args(["check", "--show-settings", "unformatted.py"]).current_dir(Path::new("./resources/test/fixtures"))) } ); +} diff --git a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap new file mode 100644 index 0000000000000..a88eb4e2edde7 --- /dev/null +++ b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap @@ -0,0 +1,362 @@ +--- +source: crates/ruff_cli/tests/show_settings.rs +info: + program: ruff + args: + - check + - "--show-settings" + - unformatted.py +--- +success: true +exit_code: 0 +----- stdout ----- +Resolved settings for: "[BASEPATH]/crates/ruff_cli/resources/test/fixtures/unformatted.py" +Settings path: "[BASEPATH]/pyproject.toml" +cache_dir = "[BASEPATH]/.ruff_cache" +fix = false +fix_only = false +output_format = text +show_fixes = false +show_source = false +unsafe_fixes = hint +# File Resolver Settings +file_resolver.exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".ipynb_checkpoints", + ".mypy_cache", + ".nox", + ".pants.d", + ".pyenv", + ".pytest_cache", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + ".vscode", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "site-packages", + "venv", +] +file_resolver.extend_exclude = [ + "crates/ruff_linter/resources/", + "crates/ruff_python_formatter/resources/", +] +file_resolver.force_exclude = false +file_resolver.include = [ + "*.py", + "*.pyi", + "**/pyproject.toml", +] +file_resolver.extend_include = [] +file_resolver.respect_gitignore = true +file_resolver.project_root = "[BASEPATH]" +# Linter Settings +linter.exclude = [] +linter.project_root = "[BASEPATH]" +linter.rules.enabled = [ + MultipleImportsOnOneLine, + ModuleImportNotAtTopOfFile, + MultipleStatementsOnOneLineColon, + MultipleStatementsOnOneLineSemicolon, + UselessSemicolon, + NoneComparison, + TrueFalseComparison, + NotInTest, + NotIsTest, + TypeComparison, + BareExcept, + LambdaAssignment, + AmbiguousVariableName, + AmbiguousClassName, + AmbiguousFunctionName, + IOError, + SyntaxError, + UnusedImport, + ImportShadowedByLoopVar, + UndefinedLocalWithImportStar, + LateFutureImport, + UndefinedLocalWithImportStarUsage, + UndefinedLocalWithNestedImportStarUsage, + FutureFeatureNotDefined, + PercentFormatInvalidFormat, + PercentFormatExpectedMapping, + PercentFormatExpectedSequence, + PercentFormatExtraNamedArguments, + PercentFormatMissingArgument, + PercentFormatMixedPositionalAndNamed, + PercentFormatPositionalCountMismatch, + PercentFormatStarRequiresSequence, + PercentFormatUnsupportedFormatCharacter, + StringDotFormatInvalidFormat, + StringDotFormatExtraNamedArguments, + StringDotFormatExtraPositionalArguments, + StringDotFormatMissingArguments, + StringDotFormatMixingAutomatic, + FStringMissingPlaceholders, + MultiValueRepeatedKeyLiteral, + MultiValueRepeatedKeyVariable, + ExpressionsInStarAssignment, + MultipleStarredExpressions, + AssertTuple, + IsLiteral, + InvalidPrintSyntax, + IfTuple, + BreakOutsideLoop, + ContinueOutsideLoop, + YieldOutsideFunction, + ReturnOutsideFunction, + DefaultExceptNotLast, + ForwardAnnotationSyntaxError, + RedefinedWhileUnused, + UndefinedName, + UndefinedExport, + UndefinedLocal, + UnusedVariable, + UnusedAnnotation, + RaiseNotImplemented, +] +linter.rules.should_fix = [ + MultipleImportsOnOneLine, + ModuleImportNotAtTopOfFile, + MultipleStatementsOnOneLineColon, + MultipleStatementsOnOneLineSemicolon, + UselessSemicolon, + NoneComparison, + TrueFalseComparison, + NotInTest, + NotIsTest, + TypeComparison, + BareExcept, + LambdaAssignment, + AmbiguousVariableName, + AmbiguousClassName, + AmbiguousFunctionName, + IOError, + SyntaxError, + UnusedImport, + ImportShadowedByLoopVar, + UndefinedLocalWithImportStar, + LateFutureImport, + UndefinedLocalWithImportStarUsage, + UndefinedLocalWithNestedImportStarUsage, + FutureFeatureNotDefined, + PercentFormatInvalidFormat, + PercentFormatExpectedMapping, + PercentFormatExpectedSequence, + PercentFormatExtraNamedArguments, + PercentFormatMissingArgument, + PercentFormatMixedPositionalAndNamed, + PercentFormatPositionalCountMismatch, + PercentFormatStarRequiresSequence, + PercentFormatUnsupportedFormatCharacter, + StringDotFormatInvalidFormat, + StringDotFormatExtraNamedArguments, + StringDotFormatExtraPositionalArguments, + StringDotFormatMissingArguments, + StringDotFormatMixingAutomatic, + FStringMissingPlaceholders, + MultiValueRepeatedKeyLiteral, + MultiValueRepeatedKeyVariable, + ExpressionsInStarAssignment, + MultipleStarredExpressions, + AssertTuple, + IsLiteral, + InvalidPrintSyntax, + IfTuple, + BreakOutsideLoop, + ContinueOutsideLoop, + YieldOutsideFunction, + ReturnOutsideFunction, + DefaultExceptNotLast, + ForwardAnnotationSyntaxError, + RedefinedWhileUnused, + UndefinedName, + UndefinedExport, + UndefinedLocal, + UnusedVariable, + UnusedAnnotation, + RaiseNotImplemented, +] +linter.per_file_ignores = {} +linter.safety_table.forced_safe = [] +linter.safety_table.forced_unsafe = [] +linter.target_version = Py37 +linter.preview = disabled +linter.explicit_preview_rules = false +linter.extension.mapping = {} +linter.allowed_confusables = [] +linter.builtins = [] +linter.dummy_variable_rgx = ^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$ +linter.external = [] +linter.ignore_init_module_imports = false +linter.logger_objects = [] +linter.namespace_packages = [] +linter.src = ["[BASEPATH]"] +linter.tab_size = 4 +linter.line_length = 88 +linter.task_tags = [ + TODO, + FIXME, + XXX, +] +linter.typing_modules = [] +linter.flake8_annotations.mypy_init_return = false +linter.flake8_annotations.suppress_dummy_args = false +linter.flake8_annotations.suppress_none_returning = false +linter.flake8_annotations.allow_star_arg_any = false +linter.flake8_annotations.ignore_fully_untyped = false +linter.flake8_bandit.hardcoded_tmp_directory = [ + /tmp, + /var/tmp, + /dev/shm, +] +linter.flake8_bandit.check_typed_exception = false +linter.flake8_bugbear.extend_immutable_calls = [] +linter.flake8_builtins.builtins_ignorelist = [] +linter.flake8_comprehensions.allow_dict_calls_with_keyword_arguments = false +linter.flake8_copyright.notice_rgx = (?i)Copyright\s+(\(C\)\s+)?\d{4}(-\d{4})* +linter.flake8_copyright.author = nil +linter.flake8_copyright.min_file_size = 0 +linter.flake8_errmsg.max_string_length = 0 +linter.flake8_gettext.functions_names = [ + _, + gettext, + ngettext, +] +linter.flake8_implicit_str_concat.allow_multiline = true +linter.flake8_import_conventions.aliases = {"matplotlib": "mpl", "matplotlib.pyplot": "plt", "pandas": "pd", "seaborn": "sns", "tensorflow": "tf", "networkx": "nx", "plotly.express": "px", "polars": "pl", "numpy": "np", "panel": "pn", "pyarrow": "pa", "altair": "alt", "tkinter": "tk", "holoviews": "hv"} +linter.flake8_import_conventions.banned_aliases = {} +linter.flake8_import_conventions.banned_from = [] +linter.flake8_pytest_style.fixture_parentheses = true +linter.flake8_pytest_style.parametrize_names_type = tuple +linter.flake8_pytest_style.parametrize_values_type = list +linter.flake8_pytest_style.parametrize_values_row_type = tuple +linter.flake8_pytest_style.raises_require_match_for = [ + BaseException, + Exception, + ValueError, + OSError, + IOError, + EnvironmentError, + socket.error, +] +linter.flake8_pytest_style.raises_extend_require_match_for = [] +linter.flake8_pytest_style.mark_parentheses = true +linter.flake8_quotes.inline_quotes = double +linter.flake8_quotes.multiline_quotes = double +linter.flake8_quotes.docstring_quotes = double +linter.flake8_quotes.avoid_escape = true +linter.flake8_self.ignore_names = [ + _make, + _asdict, + _replace, + _fields, + _field_defaults, + _name_, + _value_, +] +linter.flake8_tidy_imports.ban_relative_imports = "parents" +linter.flake8_tidy_imports.banned_api = {} +linter.flake8_tidy_imports.banned_module_level_imports = [] +linter.flake8_type_checking.strict = false +linter.flake8_type_checking.exempt_modules = [ + typing, + typing_extensions, +] +linter.flake8_type_checking.runtime_required_base_classes = [] +linter.flake8_type_checking.runtime_required_decorators = [] +linter.flake8_type_checking.quote_annotations = false +linter.flake8_unused_arguments.ignore_variadic_names = false +linter.isort.required_imports = [] +linter.isort.combine_as_imports = false +linter.isort.force_single_line = false +linter.isort.force_sort_within_sections = false +linter.isort.detect_same_package = true +linter.isort.case_sensitive = false +linter.isort.force_wrap_aliases = false +linter.isort.force_to_top = [] +linter.isort.known_modules = {} +linter.isort.order_by_type = true +linter.isort.relative_imports_order = furthest_to_closest +linter.isort.single_line_exclusions = [] +linter.isort.split_on_trailing_comma = true +linter.isort.classes = [] +linter.isort.constants = [] +linter.isort.variables = [] +linter.isort.no_lines_before = [] +linter.isort.lines_after_imports = -1 +linter.isort.lines_between_types = 0 +linter.isort.forced_separate = [] +linter.isort.section_order = [ + known { type = future }, + known { type = standard_library }, + known { type = third_party }, + known { type = first_party }, + known { type = local_folder }, +] +linter.isort.no_sections = false +linter.isort.from_first = false +linter.isort.length_sort = false +linter.isort.length_sort_straight = false +linter.mccabe.max_complexity = 10 +linter.pep8_naming.ignore_names = [ + setUp, + tearDown, + setUpClass, + tearDownClass, + setUpModule, + tearDownModule, + asyncSetUp, + asyncTearDown, + setUpTestData, + failureException, + longMessage, + maxDiff, +] +linter.pep8_naming.classmethod_decorators = [] +linter.pep8_naming.staticmethod_decorators = [] +linter.pycodestyle.max_line_length = 88 +linter.pycodestyle.max_doc_length = nil +linter.pycodestyle.ignore_overlong_task_comments = false +linter.pyflakes.extend_generics = [] +linter.pylint.allow_magic_value_types = [ + str, + bytes, +] +linter.pylint.allow_dunder_method_names = [] +linter.pylint.max_args = 5 +linter.pylint.max_positional_args = 5 +linter.pylint.max_returns = 6 +linter.pylint.max_bool_expr = 5 +linter.pylint.max_branches = 12 +linter.pylint.max_statements = 50 +linter.pylint.max_public_methods = 20 +linter.pylint.max_locals = 15 +linter.pyupgrade.keep_runtime_typing = false +# Formatter Settings +formatter.exclude = [] +formatter.target_version = Py37 +formatter.preview = disabled +formatter.line_width = 88 +formatter.line_ending = auto +formatter.indent_style = space +formatter.indent_width = 4 +formatter.quote_style = double +formatter.magic_trailing_comma = respect +formatter.docstring_code_format = disabled +formatter.docstring_code_line_width = dynamic + + +----- stderr ----- + From 84a1a2c7d15d815d99019d209be344c3f6759103 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 14:17:42 -0800 Subject: [PATCH 10/17] Remove extraneous newline from stdout for `--show-settings` --- crates/ruff_cli/src/commands/show_settings.rs | 2 +- .../snapshots/show_settings__display_default_settings.snap | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ruff_cli/src/commands/show_settings.rs b/crates/ruff_cli/src/commands/show_settings.rs index 95adb20c0089c..a23f31a4967a2 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}")?; + write!(writer, "{settings}")?; Ok(()) } diff --git a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap index a88eb4e2edde7..1dc3b39553881 100644 --- a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap +++ b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap @@ -357,6 +357,5 @@ formatter.magic_trailing_comma = respect formatter.docstring_code_format = disabled formatter.docstring_code_line_width = dynamic - ----- stderr ----- From 14a8a6ec187fb989a070b11db6cfa6f226c246a0 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 15:16:13 -0800 Subject: [PATCH 11/17] Cleanup snapshot tests --- crates/ruff_cli/tests/show_settings.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/ruff_cli/tests/show_settings.rs b/crates/ruff_cli/tests/show_settings.rs index 9de63e12351b5..e2016e378542b 100644 --- a/crates/ruff_cli/tests/show_settings.rs +++ b/crates/ruff_cli/tests/show_settings.rs @@ -13,16 +13,17 @@ const TEST_FILTERS: &[(&str, &str)] = &[ ]; #[cfg(target_os = "windows")] const TEST_FILTERS: &[(&str, &str)] = &[ - (r".*\\resources\\test\\fixtures\\", "[BASEPATH]\\"), - (r#"[^\*"]*\\pyproject.toml"#, "\"[BASEPATH]\\pyproject.toml"), - (r#"".*\\crates"#, "\"[BASEPATH]\\crates"), - (r#"".*\\\.ruff_cache"#, "\"[BASEPATH]\\.ruff_cache"), + (r#""[^\*"]*\\pyproject.toml"#, "\"[BASEPATH]/pyproject.toml"), + (r#"".*\\crates"#, "\"[BASEPATH]/crates"), + (r#"".*\\\.ruff_cache"#, "\"[BASEPATH]/.ruff_cache"), (r#"".*\\ruff""#, "\"[BASEPATH]\""), - (r"\\", "/"), + (r#"\\+(\w\w|\s|")"#, "/$1"), ]; #[test] fn display_default_settings() { - insta::with_settings!({ filters => TEST_FILTERS.to_vec() }, { assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) - .args(["check", "--show-settings", "unformatted.py"]).current_dir(Path::new("./resources/test/fixtures"))) } ); + insta::with_settings!({ filters => TEST_FILTERS.to_vec() }, { + assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) + .args(["check", "--show-settings", "unformatted.py"]).current_dir(Path::new("./resources/test/fixtures"))); + }); } From 8c82e875f1e1991b81cfcfbaf911d00e044498ed Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 16:31:33 -0800 Subject: [PATCH 12/17] Add top-level comment to `Settings` display --- .../tests/snapshots/show_settings__display_default_settings.snap | 1 + crates/ruff_workspace/src/settings.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap index 1dc3b39553881..132a0bf7fb336 100644 --- a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap +++ b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap @@ -12,6 +12,7 @@ exit_code: 0 ----- stdout ----- Resolved settings for: "[BASEPATH]/crates/ruff_cli/resources/test/fixtures/unformatted.py" Settings path: "[BASEPATH]/pyproject.toml" +# General Settings cache_dir = "[BASEPATH]/.ruff_cache" fix = false fix_only = false diff --git a/crates/ruff_workspace/src/settings.rs b/crates/ruff_workspace/src/settings.rs index 8b8e2e7093e4b..5855ff5da8df9 100644 --- a/crates/ruff_workspace/src/settings.rs +++ b/crates/ruff_workspace/src/settings.rs @@ -57,6 +57,7 @@ impl Default for Settings { impl fmt::Display for Settings { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "# General Settings")?; display_settings! { formatter = f, fields = [ From 5793b604259babfe6d9a1e270ffb53c9d25cc8c8 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Thu, 11 Jan 2024 16:38:58 -0800 Subject: [PATCH 13/17] Make `resolve_per_file_ignores` into an associated function --- crates/ruff_linter/src/rules/ruff/mod.rs | 7 +++---- crates/ruff_linter/src/settings/mod.rs | 24 +--------------------- crates/ruff_linter/src/settings/types.rs | 18 ++++++++++++++-- crates/ruff_workspace/src/configuration.rs | 10 ++++----- 4 files changed, 24 insertions(+), 35 deletions(-) diff --git a/crates/ruff_linter/src/rules/ruff/mod.rs b/crates/ruff_linter/src/rules/ruff/mod.rs index bda96268fdbae..f5584bff250d7 100644 --- a/crates/ruff_linter/src/rules/ruff/mod.rs +++ b/crates/ruff_linter/src/rules/ruff/mod.rs @@ -16,8 +16,7 @@ mod tests { use crate::pyproject_toml::lint_pyproject_toml; use crate::registry::Rule; - use crate::settings::resolve_per_file_ignores; - use crate::settings::types::{PerFileIgnore, PreviewMode, PythonVersion}; + use crate::settings::types::{PerFileIgnore, PerFileIgnores, PreviewMode, PythonVersion}; use crate::test::{test_path, test_resource_path}; use crate::{assert_messages, settings}; @@ -175,7 +174,7 @@ mod tests { let mut settings = settings::LinterSettings::for_rules(vec![Rule::UnusedNOQA, Rule::UnusedImport]); - settings.per_file_ignores = resolve_per_file_ignores(vec![PerFileIgnore::new( + settings.per_file_ignores = PerFileIgnores::resolve(vec![PerFileIgnore::new( "RUF100_2.py".to_string(), &["F401".parse().unwrap()], None, @@ -232,7 +231,7 @@ mod tests { let diagnostics = test_path( Path::new("ruff/ruff_per_file_ignores.py"), &settings::LinterSettings { - per_file_ignores: resolve_per_file_ignores(vec![PerFileIgnore::new( + per_file_ignores: PerFileIgnores::resolve(vec![PerFileIgnore::new( "ruff_per_file_ignores.py".to_string(), &["F401".parse().unwrap(), "RUF100".parse().unwrap()], None, diff --git a/crates/ruff_linter/src/settings/mod.rs b/crates/ruff_linter/src/settings/mod.rs index fe5d3e3f2692d..8a4941c55f3b2 100644 --- a/crates/ruff_linter/src/settings/mod.rs +++ b/crates/ruff_linter/src/settings/mod.rs @@ -5,8 +5,6 @@ use std::fmt::{Display, Formatter}; use std::path::{Path, PathBuf}; -use anyhow::Result; -use globset::Glob; use once_cell::sync::Lazy; use path_absolutize::path_dedot; use regex::Regex; @@ -24,9 +22,7 @@ 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, PerFileIgnores, PythonVersion, -}; +use crate::settings::types::{ExtensionMapping, FilePatternSet, PerFileIgnores, PythonVersion}; use crate::{codes, RuleSelector}; use super::line_width::IndentWidth; @@ -388,21 +384,3 @@ impl Default for LinterSettings { Self::new(path_dedot::CWD.as_path()) } } - -/// Given a list of patterns, create a `GlobSet`. -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. - let absolute = - Glob::new(&per_file_ignore.absolute.to_string_lossy())?.compile_matcher(); - - // Construct basename matcher. - let basename = Glob::new(&per_file_ignore.basename)?.compile_matcher(); - - Ok((absolute, basename, per_file_ignore.rules)) - }) - .collect(); - Ok(PerFileIgnores::new(ignores?)) -} diff --git a/crates/ruff_linter/src/settings/types.rs b/crates/ruff_linter/src/settings/types.rs index d9dc33617b66d..0a2164686fdb1 100644 --- a/crates/ruff_linter/src/settings/types.rs +++ b/crates/ruff_linter/src/settings/types.rs @@ -565,8 +565,22 @@ pub struct PerFileIgnores { } impl PerFileIgnores { - pub fn new(ignores: Vec<(GlobMatcher, GlobMatcher, RuleSet)>) -> Self { - Self { ignores } + /// Given a list of patterns, create a `GlobSet`. + pub fn resolve(per_file_ignores: Vec) -> Result { + let ignores: Result> = per_file_ignores + .into_iter() + .map(|per_file_ignore| { + // Construct absolute path matcher. + let absolute = + Glob::new(&per_file_ignore.absolute.to_string_lossy())?.compile_matcher(); + + // Construct basename matcher. + let basename = Glob::new(&per_file_ignore.basename)?.compile_matcher(); + + Ok((absolute, basename, per_file_ignore.rules)) + }) + .collect(); + Ok(Self { ignores: ignores? }) } } diff --git a/crates/ruff_workspace/src/configuration.rs b/crates/ruff_workspace/src/configuration.rs index b0f5f8bb7cb62..d8d1bede95b27 100644 --- a/crates/ruff_workspace/src/configuration.rs +++ b/crates/ruff_workspace/src/configuration.rs @@ -25,12 +25,10 @@ use ruff_linter::rule_selector::{PreviewOptions, Specificity}; use ruff_linter::rules::pycodestyle; use ruff_linter::settings::rule_table::RuleTable; use ruff_linter::settings::types::{ - ExtensionMapping, FilePattern, FilePatternSet, PerFileIgnore, PreviewMode, PythonVersion, - SerializationFormat, UnsafeFixes, Version, -}; -use ruff_linter::settings::{ - resolve_per_file_ignores, LinterSettings, DEFAULT_SELECTORS, DUMMY_VARIABLE_RGX, TASK_TAGS, + ExtensionMapping, FilePattern, FilePatternSet, PerFileIgnore, PerFileIgnores, PreviewMode, + PythonVersion, SerializationFormat, UnsafeFixes, Version, }; +use ruff_linter::settings::{LinterSettings, DEFAULT_SELECTORS, DUMMY_VARIABLE_RGX, TASK_TAGS}; use ruff_linter::{ fs, warn_user, warn_user_once, warn_user_once_by_id, RuleSelector, RUFF_PKG_VERSION, }; @@ -258,7 +256,7 @@ impl Configuration { line_length, tab_size: self.indent_width.unwrap_or_default(), namespace_packages: self.namespace_packages.unwrap_or_default(), - per_file_ignores: resolve_per_file_ignores( + per_file_ignores: PerFileIgnores::resolve( lint.per_file_ignores .unwrap_or_default() .into_iter() From 142883c3d9266b4359f94d917e919d40d53c4eee Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Fri, 12 Jan 2024 11:02:53 -0800 Subject: [PATCH 14/17] Space out comment headers for settings display --- .../snapshots/show_settings__display_default_settings.snap | 4 ++++ crates/ruff_linter/src/settings/mod.rs | 2 +- crates/ruff_workspace/src/settings.rs | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap index 132a0bf7fb336..294c99089489e 100644 --- a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap +++ b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap @@ -12,6 +12,7 @@ exit_code: 0 ----- stdout ----- Resolved settings for: "[BASEPATH]/crates/ruff_cli/resources/test/fixtures/unformatted.py" Settings path: "[BASEPATH]/pyproject.toml" + # General Settings cache_dir = "[BASEPATH]/.ruff_cache" fix = false @@ -20,6 +21,7 @@ output_format = text show_fixes = false show_source = false unsafe_fixes = hint + # File Resolver Settings file_resolver.exclude = [ ".bzr", @@ -62,6 +64,7 @@ file_resolver.include = [ file_resolver.extend_include = [] file_resolver.respect_gitignore = true file_resolver.project_root = "[BASEPATH]" + # Linter Settings linter.exclude = [] linter.project_root = "[BASEPATH]" @@ -345,6 +348,7 @@ linter.pylint.max_statements = 50 linter.pylint.max_public_methods = 20 linter.pylint.max_locals = 15 linter.pyupgrade.keep_runtime_typing = false + # Formatter Settings formatter.exclude = [] formatter.target_version = Py37 diff --git a/crates/ruff_linter/src/settings/mod.rs b/crates/ruff_linter/src/settings/mod.rs index 8a4941c55f3b2..e4f9cf0cfa08b 100644 --- a/crates/ruff_linter/src/settings/mod.rs +++ b/crates/ruff_linter/src/settings/mod.rs @@ -214,7 +214,7 @@ pub struct LinterSettings { impl Display for LinterSettings { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - writeln!(f, "# Linter Settings")?; + writeln!(f, "\n# Linter Settings")?; display_settings! { formatter = f, namespace = "linter", diff --git a/crates/ruff_workspace/src/settings.rs b/crates/ruff_workspace/src/settings.rs index 5855ff5da8df9..37b22e1d95c0b 100644 --- a/crates/ruff_workspace/src/settings.rs +++ b/crates/ruff_workspace/src/settings.rs @@ -57,7 +57,7 @@ impl Default for Settings { impl fmt::Display for Settings { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "# General Settings")?; + writeln!(f, "\n# General Settings")?; display_settings! { formatter = f, fields = [ @@ -92,7 +92,7 @@ pub struct FileResolverSettings { impl fmt::Display for FileResolverSettings { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "# File Resolver Settings")?; + writeln!(f, "\n# File Resolver Settings")?; display_settings! { formatter = f, namespace = "file_resolver", @@ -239,7 +239,7 @@ impl Default for FormatterSettings { impl fmt::Display for FormatterSettings { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "# Formatter Settings")?; + writeln!(f, "\n# Formatter Settings")?; display_settings! { formatter = f, namespace = "formatter", From b3e3c393ecce5262ad48dcbf37414ea71aa229da Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Fri, 12 Jan 2024 11:05:08 -0800 Subject: [PATCH 15/17] Add Linter Plugins heading to settings display --- .../show_settings__display_default_settings.snap | 2 ++ crates/ruff_linter/src/settings/mod.rs | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap index 294c99089489e..d87720c35e16e 100644 --- a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap +++ b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap @@ -215,6 +215,8 @@ linter.task_tags = [ XXX, ] linter.typing_modules = [] + +# Linter Plugins linter.flake8_annotations.mypy_init_return = false linter.flake8_annotations.suppress_dummy_args = false linter.flake8_annotations.suppress_none_returning = false diff --git a/crates/ruff_linter/src/settings/mod.rs b/crates/ruff_linter/src/settings/mod.rs index e4f9cf0cfa08b..ad994fd6bd94e 100644 --- a/crates/ruff_linter/src/settings/mod.rs +++ b/crates/ruff_linter/src/settings/mod.rs @@ -243,7 +243,13 @@ impl Display for LinterSettings { self.line_length, self.task_tags | array, self.typing_modules | array, - + ] + } + writeln!(f, "\n# Linter Plugins")?; + display_settings! { + formatter = f, + namespace = "linter", + fields = [ self.flake8_annotations | nested, self.flake8_bandit | nested, self.flake8_bugbear | nested, From 27007a147562f4bdb6cfc6f2f002f795ea247a4c Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Fri, 12 Jan 2024 11:06:30 -0800 Subject: [PATCH 16/17] Use 'none' instead of 'nil' when displaying None values in settings --- .../snapshots/show_settings__display_default_settings.snap | 4 ++-- crates/ruff_linter/src/settings/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap index d87720c35e16e..d4a64f69e9522 100644 --- a/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap +++ b/crates/ruff_cli/tests/snapshots/show_settings__display_default_settings.snap @@ -232,7 +232,7 @@ linter.flake8_bugbear.extend_immutable_calls = [] linter.flake8_builtins.builtins_ignorelist = [] linter.flake8_comprehensions.allow_dict_calls_with_keyword_arguments = false linter.flake8_copyright.notice_rgx = (?i)Copyright\s+(\(C\)\s+)?\d{4}(-\d{4})* -linter.flake8_copyright.author = nil +linter.flake8_copyright.author = none linter.flake8_copyright.min_file_size = 0 linter.flake8_errmsg.max_string_length = 0 linter.flake8_gettext.functions_names = [ @@ -333,7 +333,7 @@ linter.pep8_naming.ignore_names = [ linter.pep8_naming.classmethod_decorators = [] linter.pep8_naming.staticmethod_decorators = [] linter.pycodestyle.max_line_length = 88 -linter.pycodestyle.max_doc_length = nil +linter.pycodestyle.max_doc_length = none linter.pycodestyle.ignore_overlong_task_comments = false linter.pyflakes.extend_generics = [] linter.pylint.allow_magic_value_types = [ diff --git a/crates/ruff_linter/src/settings/mod.rs b/crates/ruff_linter/src/settings/mod.rs index ad994fd6bd94e..3cf855a1f1730 100644 --- a/crates/ruff_linter/src/settings/mod.rs +++ b/crates/ruff_linter/src/settings/mod.rs @@ -134,7 +134,7 @@ macro_rules! display_settings { write!($fmt, "{}{} = ", $prefix, stringify!($field))?; match &$settings.$field { Some(value) => writeln!($fmt, "{}", value)?, - None => writeln!($fmt, "nil")? + None => writeln!($fmt, "none")? }; } }; From ba3e00be9afe7458d6733f00ed19c75f83e51c90 Mon Sep 17 00:00:00 2001 From: Jane Lewis Date: Fri, 12 Jan 2024 11:10:54 -0800 Subject: [PATCH 17/17] Explain the order of matchers in `PerFileIgnores` --- crates/ruff_linter/src/settings/types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/ruff_linter/src/settings/types.rs b/crates/ruff_linter/src/settings/types.rs index 0a2164686fdb1..c2876ae1aa904 100644 --- a/crates/ruff_linter/src/settings/types.rs +++ b/crates/ruff_linter/src/settings/types.rs @@ -561,6 +561,7 @@ pub type IdentifierPattern = glob::Pattern; #[derive(Debug, CacheKey, Default)] pub struct PerFileIgnores { + // Ordered as (absolute path matcher, basename matcher, rules) ignores: Vec<(GlobMatcher, GlobMatcher, RuleSet)>, }