From 4ba3ee334bab99805b16d1347b033f5f84d145fc Mon Sep 17 00:00:00 2001 From: Zanie Date: Tue, 30 Jan 2024 13:49:02 -0600 Subject: [PATCH] Display deprecation warnings for prefix and linter selections with all rules deprecated --- crates/ruff/tests/integration_test.rs | 47 ++++++++++++++++++---- crates/ruff_linter/src/rule_selector.rs | 10 +++++ crates/ruff_workspace/src/configuration.rs | 23 ++++++++--- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/crates/ruff/tests/integration_test.rs b/crates/ruff/tests/integration_test.rs index 68bf81774c..960f23c1b6 100644 --- a/crates/ruff/tests/integration_test.rs +++ b/crates/ruff/tests/integration_test.rs @@ -1146,7 +1146,7 @@ def reciprocal(n): ----- stdout ----- ----- stderr ----- - warning: Rule `TRY200` is deprecated and will be removed in a future release. + warning: The rule `TRY200` is deprecated and will be removed in a future release. "###); } @@ -1173,8 +1173,8 @@ class Foo: Found 2 errors. ----- stderr ----- - warning: Rule `ANN102` is deprecated and will be removed in a future release. - warning: Rule `ANN101` is deprecated and will be removed in a future release. + warning: The rule `ANN102` is deprecated and will be removed in a future release. + warning: The rule `ANN101` is deprecated and will be removed in a future release. "###); } @@ -1182,6 +1182,34 @@ class Foo: fn deprecated_indirect() { // `ANN` includes deprecated rules `ANN101` and `ANN102` but should not warn // since it is not a "direct" selection + let mut cmd = RuffCheck::default().args(["--select", "ANN"]).build(); + assert_cmd_snapshot!(cmd + .pass_stdin(r###" +class Foo: + def a(self): + pass + + @classmethod + def b(cls): + pass +"###), @r###" + success: false + exit_code: 1 + ----- stdout ----- + -:3:9: ANN201 Missing return type annotation for public function `a` + -:3:11: ANN101 Missing type annotation for `self` in method + -:7:9: ANN206 Missing return type annotation for classmethod `b` + -:7:11: ANN102 Missing type annotation for `cls` in classmethod + Found 4 errors. + No fixes available (2 hidden fixes can be enabled with the `--unsafe-fixes` option). + + ----- stderr ----- + "###); +} + +#[test] +fn deprecated_prefix() { + // `ANN1` only includes deprecated rules `ANN101` and `ANN102` so it should warn let mut cmd = RuffCheck::default().args(["--select", "ANN1"]).build(); assert_cmd_snapshot!(cmd .pass_stdin(r###" @@ -1201,6 +1229,7 @@ class Foo: Found 2 errors. ----- stderr ----- + warning: The rule prefix `ANN1` is deprecated and will be removed in a future release. "###); } @@ -1220,7 +1249,7 @@ x = eval(input("Enter a number: ")) Found 1 error. ----- stderr ----- - warning: Rule `PGH001` is deprecated and will be removed in a future release. Use `S307` instead. + warning: The rule `PGH001` is deprecated and will be removed in a future release. Use `S307` instead. "###); } @@ -1290,8 +1319,8 @@ def reciprocal(n): } #[test] -fn deprecated_indirect_redirect_preview_enabled() { - // e.g. `PGH001` is deprecated and redirected and should be off by default in preview. +fn deprecated_linter_preview_enabled() { + // e.g. all the rules in `PGH` are and should fail in preview let mut cmd = RuffCheck::default() .args(["--select", "PGH", "--preview"]) .build(); @@ -1299,11 +1328,13 @@ fn deprecated_indirect_redirect_preview_enabled() { .pass_stdin(r###" x = eval(input("Enter a number: ")) "###), @r###" - success: true - exit_code: 0 + success: false + exit_code: 2 ----- stdout ----- ----- stderr ----- + ruff failed + Cause: Selection of deprecated rule category `PGH` is not allowed when preview mode is enabled. "###); } diff --git a/crates/ruff_linter/src/rule_selector.rs b/crates/ruff_linter/src/rule_selector.rs index 37afac41c3..18a99fe476 100644 --- a/crates/ruff_linter/src/rule_selector.rs +++ b/crates/ruff_linter/src/rule_selector.rs @@ -161,6 +161,16 @@ impl RuleSelector { } } } + + pub fn display_kind(&self) -> &'static str { + match self { + #[allow(deprecated)] + Self::All | Self::T | Self::Nursery | Self::C => "rule selector", + Self::Rule { .. } => "rule", + Self::Prefix { .. } => "rule prefix", + Self::Linter(_) => "rule category", + } + } } impl Serialize for RuleSelector { diff --git a/crates/ruff_workspace/src/configuration.rs b/crates/ruff_workspace/src/configuration.rs index cfa8abd5b4..25f4dbd239 100644 --- a/crates/ruff_workspace/src/configuration.rs +++ b/crates/ruff_workspace/src/configuration.rs @@ -917,12 +917,21 @@ impl LintConfiguration { // Deprecated rules if kind.is_enable() { + if let RuleSelector::Linter(linter) = selector { + if linter.rules().all(|rule| rule.is_deprecated()) { + deprecated_selectors.insert(selector.clone()); + } + } if let RuleSelector::Rule { prefix, redirected_from: None, + } + | RuleSelector::Prefix { + prefix, + redirected_from: _, } = selector { - if prefix.rules().any(|rule| rule.is_deprecated()) { + if prefix.rules().all(|rule| rule.is_deprecated()) { deprecated_selectors.insert(selector.clone()); } } @@ -1019,19 +1028,21 @@ impl LintConfiguration { if preview.mode.is_disabled() { for selection in deprecated_selectors { + let kind = selection.display_kind(); let (prefix, code) = selection.prefix_and_code(); warn_user!( - "Rule `{prefix}{code}` is deprecated and will be removed in a future release.", + "The {kind} `{prefix}{code}` is deprecated and will be removed in a future release.", ); } for (selection, redirected_to) in deprecated_redirected_selectors { + let kind = selection.display_kind(); let (prefix, code) = selection.prefix_and_code(); let (redirect_prefix, redirect_code) = ( redirected_to.linter().common_prefix(), redirected_to.short_code(), ); warn_user!( - "Rule `{prefix}{code}` is deprecated and will be removed in a future release. Use `{redirect_prefix}{redirect_code}` instead.", + "The {kind} `{prefix}{code}` is deprecated and will be removed in a future release. Use `{redirect_prefix}{redirect_code}` instead.", ); } } else { @@ -1049,13 +1060,14 @@ impl LintConfiguration { match deprecated_selectors.as_slice() { [] => (), [(selection, redirect)] => { + let kind = selection.display_kind(); let (prefix, code) = selection.prefix_and_code(); let err = if let Some(redirect) = redirect { let (redirect_prefix, redirect_code) = (redirect.linter().common_prefix(), redirect.short_code()); - anyhow!("Selection of deprecated rule `{prefix}{code}` is not allowed when preview mode is enabled. Use `{redirect_prefix}{redirect_code}` instead.") + anyhow!("Selection of deprecated {kind} `{prefix}{code}` is not allowed when preview mode is enabled. Use `{redirect_prefix}{redirect_code}` instead.") } else { - anyhow!("Selection of deprecated rule `{prefix}{code}` is not allowed when preview mode is enabled.") + anyhow!("Selection of deprecated {kind} `{prefix}{code}` is not allowed when preview mode is enabled.") }; return Err(err); } @@ -1267,6 +1279,7 @@ impl FormatConfiguration { } } } + pub(crate) trait CombinePluginOptions { #[must_use] fn combine(self, other: Self) -> Self;