From c950412c824b0358f3442c3d60961681f1c78a53 Mon Sep 17 00:00:00 2001 From: Zanie Date: Mon, 11 Dec 2023 09:58:54 -0600 Subject: [PATCH] Hide unsafe fix suggestions when explicitly disabled --- crates/ruff_cli/src/printer.rs | 18 +++++------ crates/ruff_cli/tests/integration_test.rs | 38 +++++++++++++++++++++++ crates/ruff_linter/src/settings/types.rs | 11 +++++-- crates/ruff_workspace/src/options.rs | 4 ++- docs/linter.md | 3 ++ ruff.schema.json | 2 +- 6 files changed, 62 insertions(+), 14 deletions(-) diff --git a/crates/ruff_cli/src/printer.rs b/crates/ruff_cli/src/printer.rs index 6f22f37d1608e..228c124d68569 100644 --- a/crates/ruff_cli/src/printer.rs +++ b/crates/ruff_cli/src/printer.rs @@ -125,15 +125,7 @@ impl Printer { if let Some(fixables) = fixables { let fix_prefix = format!("[{}]", "*".cyan()); - if self.unsafe_fixes.is_enabled() { - if fixables.applicable > 0 { - writeln!( - writer, - "{fix_prefix} {} fixable with the --fix option.", - fixables.applicable - )?; - } - } else { + if self.unsafe_fixes.is_hint() { if fixables.applicable > 0 && fixables.unapplicable_unsafe > 0 { let es = if fixables.unapplicable_unsafe == 1 { "" @@ -163,6 +155,14 @@ impl Printer { fixables.unapplicable_unsafe )?; } + } else { + if fixables.applicable > 0 { + writeln!( + writer, + "{fix_prefix} {} fixable with the --fix option.", + fixables.applicable + )?; + } } } } else { diff --git a/crates/ruff_cli/tests/integration_test.rs b/crates/ruff_cli/tests/integration_test.rs index 37c18551c2dbc..1ee634f6c09d3 100644 --- a/crates/ruff_cli/tests/integration_test.rs +++ b/crates/ruff_cli/tests/integration_test.rs @@ -1158,6 +1158,44 @@ fn check_hints_hidden_unsafe_fixes_with_no_safe_fixes() { "###); } +#[test] +fn check_no_hint_for_hidden_unsafe_fixes_when_disabled() { + let mut cmd = RuffCheck::default() + .args(["--select", "F601,UP034", "--no-unsafe-fixes"]) + .build(); + assert_cmd_snapshot!(cmd + .pass_stdin("x = {'a': 1, 'a': 1}\nprint(('foo'))\n"), + @r###" + success: false + exit_code: 1 + ----- stdout ----- + -:1:14: F601 Dictionary key literal `'a'` repeated + -:2:7: UP034 [*] Avoid extraneous parentheses + Found 2 errors. + [*] 1 fixable with the --fix option. + + ----- stderr ----- + "###); +} + +#[test] +fn check_no_hint_for_hidden_unsafe_fixes_with_no_safe_fixes_when_disabled() { + let mut cmd = RuffCheck::default() + .args(["--select", "F601", "--no-unsafe-fixes"]) + .build(); + assert_cmd_snapshot!(cmd + .pass_stdin("x = {'a': 1, 'a': 1}\n"), + @r###" + success: false + exit_code: 1 + ----- stdout ----- + -:1:14: F601 Dictionary key literal `'a'` repeated + Found 1 error. + + ----- stderr ----- + "###); +} + #[test] fn check_shows_unsafe_fixes_with_opt_in() { let mut cmd = RuffCheck::default() diff --git a/crates/ruff_linter/src/settings/types.rs b/crates/ruff_linter/src/settings/types.rs index 8c8d84efb7f34..70ff7a9190f3f 100644 --- a/crates/ruff_linter/src/settings/types.rs +++ b/crates/ruff_linter/src/settings/types.rs @@ -119,16 +119,21 @@ impl From for PreviewMode { } } +/// 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. +/// `Enabled` will apply unsafe fixes. #[derive(Debug, Copy, Clone, CacheKey, Default, PartialEq, Eq, is_macro::Is)] pub enum UnsafeFixes { #[default] + Hint, Disabled, Enabled, } impl From for UnsafeFixes { - fn from(version: bool) -> Self { - if version { + fn from(value: bool) -> Self { + if value { UnsafeFixes::Enabled } else { UnsafeFixes::Disabled @@ -140,7 +145,7 @@ impl UnsafeFixes { pub fn required_applicability(&self) -> Applicability { match self { Self::Enabled => Applicability::Unsafe, - Self::Disabled => Applicability::Safe, + Self::Disabled | Self::Hint => Applicability::Safe, } } } diff --git a/crates/ruff_workspace/src/options.rs b/crates/ruff_workspace/src/options.rs index be92ddcf1634a..10e5c6717696e 100644 --- a/crates/ruff_workspace/src/options.rs +++ b/crates/ruff_workspace/src/options.rs @@ -93,8 +93,10 @@ pub struct Options { pub fix: Option, /// Enable application of unsafe fixes. + /// If excluded, a hint will be displayed when unsafe fixes are available. + /// If set to false, the hint will be hidden. #[option( - default = "false", + default = r#"null"#, value_type = "bool", example = "unsafe-fixes = true" )] diff --git a/docs/linter.md b/docs/linter.md index 01d258d98ccc4..5594789dad49f 100644 --- a/docs/linter.md +++ b/docs/linter.md @@ -203,6 +203,9 @@ ruff check . --unsafe-fixes ruff check . --fix --unsafe-fixes ``` +By default, Ruff will display a hint when unsafe fixes are available but not enabled. The suggestion can be silenced +by setting the [`unsafe-fixes`](settings.md#unsafe-fixes) setting to `false` or using the `--no-unsafe-fixes` flag. + The safety of fixes can be adjusted per rule using the [`extend-safe-fixes`](settings.md#extend-safe-fixes) and [`extend-unsafe-fixes`](settings.md#extend-unsafe-fixes) settings. For example, the following configuration would promote unsafe fixes for `F601` to safe fixes and demote safe fixes for `UP034` to unsafe fixes: diff --git a/ruff.schema.json b/ruff.schema.json index b7ddd6e209602..cbff63adcd807 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -690,7 +690,7 @@ } }, "unsafe-fixes": { - "description": "Enable application of unsafe fixes.", + "description": "Enable application of unsafe fixes. If excluded, a hint will be displayed when unsafe fixes are available. If set to false, the hint will be hidden.", "type": [ "boolean", "null"