From c38617fa27feff7e9024fbee72354bebc3759b47 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 11 Oct 2023 12:09:47 -0400 Subject: [PATCH] Remove per-diagnostic check for fixability (#7919) ## Summary Throughout the codebase, we have this pattern: ```rust let mut diagnostic = ... if checker.patch(Rule::UnusedVariable) { // Do the fix. } diagnostics.push(diagnostic) ``` This was helpful when we computed fixes lazily; however, we now compute fixes eagerly, and this is _only_ used to ensure that we don't generate fixes for rules marked as unfixable. We often forget to add this, and it leads to bugs in enforcing `--unfixable`. This PR instead removes all of these checks, moving the responsibility of enforcing `--unfixable` up to `check_path`. This is similar to how @zanieb handled the `--extend-unsafe` logic: we post-process the diagnostics to remove any fixes that should be ignored. --- .../src/checkers/ast/analyze/bindings.rs | 11 +- crates/ruff_linter/src/checkers/ast/mod.rs | 5 - .../ruff_linter/src/checkers/logical_lines.rs | 29 +- crates/ruff_linter/src/checkers/noqa.rs | 26 +- .../src/checkers/physical_lines.rs | 6 +- crates/ruff_linter/src/checkers/tokens.rs | 19 +- crates/ruff_linter/src/linter.rs | 7 + .../eradicate/rules/commented_out_code.rs | 9 +- .../flake8_annotations/rules/definition.rs | 24 +- .../flake8_bugbear/rules/assert_false.rs | 11 +- .../rules/duplicate_exceptions.rs | 36 ++- .../rules/getattr_with_constant.rs | 39 ++- .../rules/mutable_argument_default.rs | 23 +- .../redundant_tuple_in_exception_handler.rs | 31 +-- .../rules/setattr_with_constant.rs | 11 +- .../rules/unreliable_callable_check.rs | 15 +- .../rules/unused_loop_control_variable.rs | 33 ++- .../flake8_commas/rules/trailing_commas.rs | 28 +- .../rules/unnecessary_call_around_sorted.rs | 25 +- .../rules/unnecessary_collection_call.rs | 10 +- .../rules/unnecessary_comprehension.rs | 12 +- .../unnecessary_comprehension_any_all.rs | 10 +- .../unnecessary_double_cast_or_process.rs | 20 +- .../rules/unnecessary_generator_dict.rs | 9 +- .../rules/unnecessary_generator_list.rs | 12 +- .../rules/unnecessary_generator_set.rs | 10 +- .../rules/unnecessary_list_call.rs | 12 +- .../unnecessary_list_comprehension_dict.rs | 10 +- .../unnecessary_list_comprehension_set.rs | 10 +- .../rules/unnecessary_literal_dict.rs | 9 +- .../rules/unnecessary_literal_set.rs | 9 +- .../unnecessary_literal_within_dict_call.rs | 14 +- .../unnecessary_literal_within_list_call.rs | 14 +- .../unnecessary_literal_within_tuple_call.rs | 14 +- .../rules/unnecessary_map.rs | 24 +- .../rules/string_in_exception.rs | 69 +++-- .../src/rules/flake8_executable/rules/mod.rs | 4 +- .../rules/shebang_leading_whitespace.rs | 8 +- .../rules/implicit.rs | 7 +- .../rules/unconventional_import_alias.rs | 20 +- .../rules/direct_logger_instantiation.rs | 21 +- .../rules/invalid_get_logger_argument.rs | 13 +- .../flake8_logging/rules/undocumented_warn.rs | 21 +- .../rules/logging_call.rs | 12 +- .../rules/duplicate_class_field_definition.rs | 13 +- .../rules/multiple_starts_ends_with.rs | 165 ++++++------ .../rules/reimplemented_list_builtin.rs | 13 +- .../rules/unnecessary_dict_kwargs.rs | 33 +-- .../flake8_pie/rules/unnecessary_pass.rs | 20 +- .../rules/unnecessary_range_start.rs | 21 +- .../flake8_pyi/rules/any_eq_ne_annotation.rs | 15 +- .../rules/duplicate_union_member.rs | 24 +- .../rules/ellipsis_in_non_empty_class_body.rs | 13 +- .../flake8_pyi/rules/exit_annotations.rs | 13 +- .../flake8_pyi/rules/non_empty_stub_body.rs | 11 +- .../rules/numeric_literal_too_long.rs | 11 +- .../flake8_pyi/rules/pass_in_class_body.rs | 12 +- .../rules/pass_statement_stub_body.rs | 11 +- .../rules/quoted_annotation_in_stub.rs | 11 +- .../rules/flake8_pyi/rules/simple_defaults.rs | 66 ++--- .../rules/str_or_repr_defined_in_stub.rs | 15 +- .../rules/string_or_bytes_too_long.rs | 11 +- .../unaliased_collections_abc_set_import.rs | 16 +- .../rules/unnecessary_literal_union.rs | 12 +- .../flake8_pytest_style/rules/assertion.rs | 65 ++--- .../flake8_pytest_style/rules/fixture.rs | 82 +++--- .../rules/flake8_pytest_style/rules/marks.rs | 10 +- .../flake8_pytest_style/rules/parametrize.rs | 175 ++++++------ .../rules/avoidable_escaped_quote.rs | 78 +++--- .../rules/check_string_quotes.rs | 84 +++--- .../unnecessary_paren_on_raise_exception.rs | 39 ++- .../src/rules/flake8_return/rules/function.rs | 154 +++++------ .../flake8_simplify/rules/ast_bool_op.rs | 205 +++++++------- .../rules/flake8_simplify/rules/ast_expr.rs | 39 ++- .../rules/flake8_simplify/rules/ast_ifexp.rs | 129 +++++---- .../flake8_simplify/rules/ast_unary_op.rs | 95 +++---- .../rules/flake8_simplify/rules/ast_with.rs | 47 ++-- .../flake8_simplify/rules/collapsible_if.rs | 49 ++-- .../if_else_block_instead_of_dict_get.rs | 13 +- .../rules/if_else_block_instead_of_if_exp.rs | 13 +- .../flake8_simplify/rules/key_in_dict.rs | 49 ++-- .../flake8_simplify/rules/needless_bool.rs | 83 +++--- .../rules/reimplemented_builtin.rs | 5 +- .../rules/suppressible_exception.rs | 40 ++- .../flake8_simplify/rules/yoda_conditions.rs | 11 +- .../rules/relative_imports.rs | 14 +- .../src/rules/flake8_todos/rules/todos.rs | 25 +- .../rules/empty_type_checking_block.rs | 17 +- .../runtime_import_in_type_checking_block.rs | 6 +- .../rules/typing_only_runtime_import.rs | 6 +- .../path_constructor_current_directory.rs | 5 +- .../flynt/rules/static_join_to_fstring.rs | 12 +- .../rules/isort/rules/add_required_imports.rs | 15 +- .../src/rules/isort/rules/organize_imports.rs | 12 +- .../rules/numpy/rules/deprecated_function.rs | 21 +- .../numpy/rules/deprecated_type_alias.rs | 23 +- .../pandas_vet/rules/inplace_argument.rs | 39 ++- .../perflint/rules/incorrect_dict_iterator.rs | 41 ++- .../perflint/rules/unnecessary_list_cast.rs | 9 +- .../pycodestyle/rules/compound_statements.rs | 18 +- .../rules/invalid_escape_sequence.rs | 59 ++--- .../pycodestyle/rules/lambda_assignment.rs | 101 ++++--- .../pycodestyle/rules/literal_comparisons.rs | 33 +-- .../logical_lines/extraneous_whitespace.rs | 28 +- .../rules/logical_lines/missing_whitespace.rs | 17 +- .../whitespace_before_parameters.rs | 11 +- .../rules/missing_newline_at_end_of_file.rs | 11 +- .../src/rules/pycodestyle/rules/not_tests.rs | 54 ++-- .../pycodestyle/rules/trailing_whitespace.rs | 22 +- .../pydocstyle/rules/blank_after_summary.rs | 51 ++-- .../rules/blank_before_after_class.rs | 70 +++-- .../rules/blank_before_after_function.rs | 26 +- .../src/rules/pydocstyle/rules/capitalized.rs | 11 +- .../pydocstyle/rules/ends_with_period.rs | 4 +- .../pydocstyle/rules/ends_with_punctuation.rs | 4 +- .../src/rules/pydocstyle/rules/indent.rs | 46 ++-- .../rules/multi_line_summary_start.rs | 90 +++---- .../rules/newline_after_last_paragraph.rs | 41 ++- .../rules/no_surrounding_whitespace.rs | 21 +- .../src/rules/pydocstyle/rules/one_liner.rs | 35 ++- .../src/rules/pydocstyle/rules/sections.rs | 250 ++++++++---------- .../rules/f_string_missing_placeholders.rs | 13 +- .../rules/invalid_literal_comparisons.rs | 41 ++- .../pyflakes/rules/raise_not_implemented.rs | 13 +- .../src/rules/pyflakes/rules/repeated_keys.rs | 84 +++--- .../src/rules/pyflakes/rules/strings.rs | 117 ++++---- .../src/rules/pyflakes/rules/unused_import.rs | 2 +- .../rules/pyflakes/rules/unused_variable.rs | 7 +- .../rules/pylint/rules/iteration_over_set.rs | 22 +- .../rules/pylint/rules/manual_import_from.rs | 31 +-- .../src/rules/pylint/rules/nested_min_max.rs | 30 +-- .../rules/repeated_equality_comparison.rs | 17 +- .../pylint/rules/repeated_isinstance_calls.rs | 12 +- .../src/rules/pylint/rules/sys_exit_alias.rs | 21 +- .../pylint/rules/useless_import_alias.rs | 11 +- .../src/rules/pylint/rules/useless_return.rs | 12 +- ...convert_named_tuple_functional_to_class.rs | 21 +- .../convert_typed_dict_functional_to_class.rs | 23 +- .../pyupgrade/rules/datetime_utc_alias.rs | 21 +- .../rules/deprecated_c_element_tree.rs | 13 +- .../pyupgrade/rules/deprecated_import.rs | 14 +- .../pyupgrade/rules/deprecated_mock_import.rs | 41 ++- .../rules/deprecated_unittest_alias.rs | 11 +- .../pyupgrade/rules/extraneous_parentheses.rs | 19 +- .../src/rules/pyupgrade/rules/f_strings.rs | 10 +- .../rules/pyupgrade/rules/format_literals.rs | 13 +- .../rules/lru_cache_with_maxsize_none.rs | 23 +- .../rules/lru_cache_without_parameters.rs | 5 +- .../rules/pyupgrade/rules/native_literals.rs | 25 +- .../src/rules/pyupgrade/rules/open_alias.rs | 13 +- .../rules/pyupgrade/rules/os_error_alias.rs | 95 ++++--- .../pyupgrade/rules/outdated_version_block.rs | 32 +-- .../rules/printf_string_formatting.rs | 6 +- .../pyupgrade/rules/quoted_annotation.rs | 11 +- .../pyupgrade/rules/redundant_open_modes.rs | 26 +- .../pyupgrade/rules/replace_stdout_stderr.rs | 10 +- .../rules/replace_universal_newlines.rs | 33 ++- .../rules/super_call_with_parameters.rs | 11 +- .../pyupgrade/rules/type_of_primitive.rs | 15 +- .../pyupgrade/rules/typing_text_str_alias.rs | 13 +- .../pyupgrade/rules/unicode_kind_prefix.rs | 11 +- .../rules/unnecessary_builtin_import.rs | 39 ++- .../rules/unnecessary_class_parentheses.rs | 11 +- .../rules/unnecessary_coding_comment.rs | 14 +- .../rules/unnecessary_encode_utf8.rs | 93 +++---- .../rules/unnecessary_future_import.rs | 39 ++- .../rules/unpacked_list_comprehension.rs | 21 +- .../pyupgrade/rules/use_pep585_annotation.rs | 45 ++-- .../pyupgrade/rules/use_pep604_annotation.rs | 5 +- .../pyupgrade/rules/use_pep604_isinstance.rs | 11 +- .../pyupgrade/rules/use_pep695_type_alias.rs | 104 ++++---- .../pyupgrade/rules/useless_metaclass_type.rs | 15 +- .../rules/useless_object_inheritance.rs | 21 +- .../pyupgrade/rules/yield_in_for_loop.rs | 31 +-- .../refurb/rules/check_and_remove_from_set.rs | 13 +- .../rules/refurb/rules/delete_full_slice.rs | 4 +- .../src/rules/refurb/rules/implicit_cwd.rs | 26 +- .../rules/refurb/rules/print_empty_string.rs | 37 ++- .../refurb/rules/reimplemented_starmap.rs | 47 ++-- .../src/rules/refurb/rules/repeated_append.rs | 3 +- .../rules/single_item_membership_test.rs | 27 +- .../src/rules/refurb/rules/slice_copy.rs | 16 +- .../refurb/rules/unnecessary_enumerate.rs | 26 +- .../rules/collection_literal_concatenation.rs | 17 +- .../explicit_f_string_type_conversion.rs | 9 +- .../src/rules/ruff/rules/implicit_optional.rs | 12 +- .../ruff/rules/quadratic_list_summation.rs | 6 +- ...y_iterable_allocation_for_first_element.rs | 11 +- .../rules/tryceratops/rules/verbose_raise.rs | 11 +- 189 files changed, 2433 insertions(+), 3210 deletions(-) diff --git a/crates/ruff_linter/src/checkers/ast/analyze/bindings.rs b/crates/ruff_linter/src/checkers/ast/analyze/bindings.rs index 62dc97dcb6..e7a1f64bae 100644 --- a/crates/ruff_linter/src/checkers/ast/analyze/bindings.rs +++ b/crates/ruff_linter/src/checkers/ast/analyze/bindings.rs @@ -32,15 +32,10 @@ pub(crate) fn bindings(checker: &mut Checker) { }, binding.range(), ); - if checker.patch(Rule::UnusedVariable) { - diagnostic.try_set_fix(|| { - pyflakes::fixes::remove_exception_handler_assignment( - binding, - checker.locator, - ) + diagnostic.try_set_fix(|| { + pyflakes::fixes::remove_exception_handler_assignment(binding, checker.locator) .map(Fix::safe_edit) - }); - } + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/checkers/ast/mod.rs b/crates/ruff_linter/src/checkers/ast/mod.rs index e67a8ce162..26944ce0f0 100644 --- a/crates/ruff_linter/src/checkers/ast/mod.rs +++ b/crates/ruff_linter/src/checkers/ast/mod.rs @@ -143,11 +143,6 @@ impl<'a> Checker<'a> { } impl<'a> Checker<'a> { - /// Return `true` if a patch should be generated for a given [`Rule`]. - pub(crate) fn patch(&self, code: Rule) -> bool { - self.settings.rules.should_fix(code) - } - /// Return `true` if a [`Rule`] is disabled by a `noqa` directive. pub(crate) fn rule_is_ignored(&self, code: Rule, offset: TextSize) -> bool { // TODO(charlie): `noqa` directives are mostly enforced in `check_lines.rs`. diff --git a/crates/ruff_linter/src/checkers/logical_lines.rs b/crates/ruff_linter/src/checkers/logical_lines.rs index c5585c4b93..c216ce2f67 100644 --- a/crates/ruff_linter/src/checkers/logical_lines.rs +++ b/crates/ruff_linter/src/checkers/logical_lines.rs @@ -5,7 +5,7 @@ use ruff_python_parser::TokenKind; use ruff_source_file::Locator; use ruff_text_size::{Ranged, TextRange}; -use crate::registry::{AsRule, Rule}; +use crate::registry::AsRule; use crate::rules::pycodestyle::rules::logical_lines::{ extraneous_whitespace, indentation, missing_whitespace, missing_whitespace_after_keyword, missing_whitespace_around_operator, space_after_comma, space_around_operator, @@ -38,17 +38,6 @@ pub(crate) fn check_logical_lines( ) -> Vec { let mut context = LogicalLinesContext::new(settings); - let should_fix_missing_whitespace = settings.rules.should_fix(Rule::MissingWhitespace); - let should_fix_whitespace_before_parameters = - settings.rules.should_fix(Rule::WhitespaceBeforeParameters); - let should_fix_whitespace_after_open_bracket = - settings.rules.should_fix(Rule::WhitespaceAfterOpenBracket); - let should_fix_whitespace_before_close_bracket = settings - .rules - .should_fix(Rule::WhitespaceBeforeCloseBracket); - let should_fix_whitespace_before_punctuation = - settings.rules.should_fix(Rule::WhitespaceBeforePunctuation); - let mut prev_line = None; let mut prev_indent_level = None; let indent_char = stylist.indentation().as_char(); @@ -58,7 +47,7 @@ pub(crate) fn check_logical_lines( space_around_operator(&line, &mut context); whitespace_around_named_parameter_equals(&line, &mut context); missing_whitespace_around_operator(&line, &mut context); - missing_whitespace(&line, should_fix_missing_whitespace, &mut context); + missing_whitespace(&line, &mut context); } if line.flags().contains(TokenFlags::PUNCTUATION) { space_after_comma(&line, &mut context); @@ -68,13 +57,7 @@ pub(crate) fn check_logical_lines( .flags() .intersects(TokenFlags::OPERATOR | TokenFlags::BRACKET | TokenFlags::PUNCTUATION) { - extraneous_whitespace( - &line, - &mut context, - should_fix_whitespace_after_open_bracket, - should_fix_whitespace_before_close_bracket, - should_fix_whitespace_before_punctuation, - ); + extraneous_whitespace(&line, &mut context); } if line.flags().contains(TokenFlags::KEYWORD) { @@ -87,11 +70,7 @@ pub(crate) fn check_logical_lines( } if line.flags().contains(TokenFlags::BRACKET) { - whitespace_before_parameters( - &line, - should_fix_whitespace_before_parameters, - &mut context, - ); + whitespace_before_parameters(&line, &mut context); } // Extract the indentation level. diff --git a/crates/ruff_linter/src/checkers/noqa.rs b/crates/ruff_linter/src/checkers/noqa.rs index f189ae18a6..fcd86d70fc 100644 --- a/crates/ruff_linter/src/checkers/noqa.rs +++ b/crates/ruff_linter/src/checkers/noqa.rs @@ -109,10 +109,8 @@ pub(crate) fn check_noqa( if line.matches.is_empty() { let mut diagnostic = Diagnostic::new(UnusedNOQA { codes: None }, directive.range()); - if settings.rules.should_fix(diagnostic.kind.rule()) { - diagnostic - .set_fix(Fix::safe_edit(delete_noqa(directive.range(), locator))); - } + diagnostic.set_fix(Fix::safe_edit(delete_noqa(directive.range(), locator))); + diagnostics.push(diagnostic); } } @@ -173,18 +171,14 @@ pub(crate) fn check_noqa( }, directive.range(), ); - if settings.rules.should_fix(diagnostic.kind.rule()) { - if valid_codes.is_empty() { - diagnostic.set_fix(Fix::safe_edit(delete_noqa( - directive.range(), - locator, - ))); - } else { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - format!("# noqa: {}", valid_codes.join(", ")), - directive.range(), - ))); - } + if valid_codes.is_empty() { + diagnostic + .set_fix(Fix::safe_edit(delete_noqa(directive.range(), locator))); + } else { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("# noqa: {}", valid_codes.join(", ")), + directive.range(), + ))); } diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/checkers/physical_lines.rs b/crates/ruff_linter/src/checkers/physical_lines.rs index 8f217193ed..3c1e5d7357 100644 --- a/crates/ruff_linter/src/checkers/physical_lines.rs +++ b/crates/ruff_linter/src/checkers/physical_lines.rs @@ -71,11 +71,7 @@ pub(crate) fn check_physical_lines( } if enforce_no_newline_at_end_of_file { - if let Some(diagnostic) = no_newline_at_end_of_file( - locator, - stylist, - settings.rules.should_fix(Rule::MissingNewlineAtEndOfFile), - ) { + if let Some(diagnostic) = no_newline_at_end_of_file(locator, stylist) { diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/checkers/tokens.rs b/crates/ruff_linter/src/checkers/tokens.rs index 3a057b819d..ad623b9e5b 100644 --- a/crates/ruff_linter/src/checkers/tokens.rs +++ b/crates/ruff_linter/src/checkers/tokens.rs @@ -72,7 +72,7 @@ pub(crate) fn check_tokens( } if settings.rules.enabled(Rule::UTF8EncodingDeclaration) { - pyupgrade::rules::unnecessary_coding_comment(&mut diagnostics, locator, indexer, settings); + pyupgrade::rules::unnecessary_coding_comment(&mut diagnostics, locator, indexer); } if settings.rules.enabled(Rule::InvalidEscapeSequence) { @@ -83,7 +83,6 @@ pub(crate) fn check_tokens( indexer, tok, *range, - settings.rules.should_fix(Rule::InvalidEscapeSequence), ); } } @@ -109,13 +108,7 @@ pub(crate) fn check_tokens( Rule::MultipleStatementsOnOneLineSemicolon, Rule::UselessSemicolon, ]) { - pycodestyle::rules::compound_statements( - &mut diagnostics, - tokens, - locator, - indexer, - settings, - ); + pycodestyle::rules::compound_statements(&mut diagnostics, tokens, locator, indexer); } if settings.rules.enabled(Rule::AvoidableEscapedQuote) && settings.flake8_quotes.avoid_escape { @@ -148,11 +141,11 @@ pub(crate) fn check_tokens( Rule::TrailingCommaOnBareTuple, Rule::ProhibitedTrailingComma, ]) { - flake8_commas::rules::trailing_commas(&mut diagnostics, tokens, locator, settings); + flake8_commas::rules::trailing_commas(&mut diagnostics, tokens, locator); } if settings.rules.enabled(Rule::ExtraneousParentheses) { - pyupgrade::rules::extraneous_parentheses(&mut diagnostics, tokens, locator, settings); + pyupgrade::rules::extraneous_parentheses(&mut diagnostics, tokens, locator); } if is_stub && settings.rules.enabled(Rule::TypeCommentInStub) { @@ -166,7 +159,7 @@ pub(crate) fn check_tokens( Rule::ShebangNotFirstLine, Rule::ShebangMissingPython, ]) { - flake8_executable::rules::from_tokens(tokens, path, locator, settings, &mut diagnostics); + flake8_executable::rules::from_tokens(tokens, path, locator, &mut diagnostics); } if settings.rules.any_enabled(&[ @@ -191,7 +184,7 @@ pub(crate) fn check_tokens( TodoComment::from_comment(comment, *comment_range, i) }) .collect(); - flake8_todos::rules::todos(&mut diagnostics, &todo_comments, locator, indexer, settings); + flake8_todos::rules::todos(&mut diagnostics, &todo_comments, locator, indexer); flake8_fixme::rules::todos(&mut diagnostics, &todo_comments); } diff --git a/crates/ruff_linter/src/linter.rs b/crates/ruff_linter/src/linter.rs index 8f1dd281c1..f12690345c 100644 --- a/crates/ruff_linter/src/linter.rs +++ b/crates/ruff_linter/src/linter.rs @@ -260,6 +260,13 @@ pub fn check_path( } } + // Remove fixes for any rules marked as unfixable. + for diagnostic in &mut diagnostics { + if !settings.rules.should_fix(diagnostic.kind.rule()) { + diagnostic.fix = None; + } + } + // Update fix applicability to account for overrides if !settings.extend_safe_fixes.is_empty() || !settings.extend_unsafe_fixes.is_empty() { for diagnostic in &mut diagnostics { diff --git a/crates/ruff_linter/src/rules/eradicate/rules/commented_out_code.rs b/crates/ruff_linter/src/rules/eradicate/rules/commented_out_code.rs index 86b059621e..6dbe63570f 100644 --- a/crates/ruff_linter/src/rules/eradicate/rules/commented_out_code.rs +++ b/crates/ruff_linter/src/rules/eradicate/rules/commented_out_code.rs @@ -3,7 +3,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_index::Indexer; use ruff_source_file::Locator; -use crate::registry::Rule; use crate::settings::LinterSettings; use super::super::detection::comment_contains_code; @@ -67,11 +66,9 @@ pub(crate) fn commented_out_code( if is_standalone_comment(line) && comment_contains_code(line, &settings.task_tags[..]) { let mut diagnostic = Diagnostic::new(CommentedOutCode, *range); - if settings.rules.should_fix(Rule::CommentedOutCode) { - diagnostic.set_fix(Fix::display_edit(Edit::range_deletion( - locator.full_lines_range(*range), - ))); - } + diagnostic.set_fix(Fix::display_edit(Edit::range_deletion( + locator.full_lines_range(*range), + ))); diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_annotations/rules/definition.rs b/crates/ruff_linter/src/rules/flake8_annotations/rules/definition.rs index a3f72c08d9..1db658efef 100644 --- a/crates/ruff_linter/src/rules/flake8_annotations/rules/definition.rs +++ b/crates/ruff_linter/src/rules/flake8_annotations/rules/definition.rs @@ -11,7 +11,7 @@ use ruff_python_stdlib::typing::simple_magic_return_type; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; use crate::rules::ruff::typing::type_hint_resolves_to_any; /// ## What it does @@ -702,12 +702,10 @@ pub(crate) fn definition( }, function.identifier(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( - " -> None".to_string(), - function.parameters.range().end(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( + " -> None".to_string(), + function.parameters.range().end(), + ))); diagnostics.push(diagnostic); } } @@ -719,13 +717,11 @@ pub(crate) fn definition( }, function.identifier(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(return_type) = simple_magic_return_type(name) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( - format!(" -> {return_type}"), - function.parameters.range().end(), - ))); - } + if let Some(return_type) = simple_magic_return_type(name) { + diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( + format!(" -> {return_type}"), + function.parameters.range().end(), + ))); } diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/rules/assert_false.rs b/crates/ruff_linter/src/rules/flake8_bugbear/rules/assert_false.rs index cdce6bdf60..92c22e01fb 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/rules/assert_false.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/rules/assert_false.rs @@ -6,7 +6,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::helpers::is_const_false; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `assert False`. @@ -75,11 +74,9 @@ pub(crate) fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: } let mut diagnostic = Diagnostic::new(AssertFalse, test.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().stmt(&assertion_error(msg)), - stmt.range(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().stmt(&assertion_error(msg)), + stmt.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs b/crates/ruff_linter/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs index 6059e08aae..8357b6670b 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/rules/duplicate_exceptions.rs @@ -11,7 +11,7 @@ use ruff_python_ast::call_path::CallPath; use crate::checkers::ast::Checker; use crate::fix::edits::pad; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; /// ## What it does /// Checks for `try-except` blocks with duplicate exception handlers. @@ -146,24 +146,22 @@ fn duplicate_handler_exceptions<'a>( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - // Single exceptions don't require parentheses, but since we're _removing_ - // parentheses, insert whitespace as needed. - if let [elt] = unique_elts.as_slice() { - pad( - checker.generator().expr(elt), - expr.range(), - checker.locator(), - ) - } else { - // Multiple exceptions must always be parenthesized. This is done - // manually as the generator never parenthesizes lone tuples. - format!("({})", checker.generator().expr(&type_pattern(unique_elts))) - }, - expr.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + // Single exceptions don't require parentheses, but since we're _removing_ + // parentheses, insert whitespace as needed. + if let [elt] = unique_elts.as_slice() { + pad( + checker.generator().expr(elt), + expr.range(), + checker.locator(), + ) + } else { + // Multiple exceptions must always be parenthesized. This is done + // manually as the generator never parenthesizes lone tuples. + format!("({})", checker.generator().expr(&type_pattern(unique_elts))) + }, + expr.range(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/rules/getattr_with_constant.rs b/crates/ruff_linter/src/rules/flake8_bugbear/rules/getattr_with_constant.rs index b3db6cda81..b9b2624950 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/rules/getattr_with_constant.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/rules/getattr_with_constant.rs @@ -6,7 +6,6 @@ use ruff_python_stdlib::identifiers::{is_identifier, is_mangled_private}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `getattr` that take a constant attribute value as an @@ -85,26 +84,24 @@ pub(crate) fn getattr_with_constant( } let mut diagnostic = Diagnostic::new(GetAttrWithConstant, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - pad( - if matches!( - obj, - Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) - ) && !checker.locator().contains_line_break(obj.range()) - { - format!("{}.{}", checker.locator().slice(obj), value) - } else { - // Defensively parenthesize any other expressions. For example, attribute accesses - // on `int` literals must be parenthesized, e.g., `getattr(1, "real")` becomes - // `(1).real`. The same is true for named expressions and others. - format!("({}).{}", checker.locator().slice(obj), value) - }, - expr.range(), - checker.locator(), - ), + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + pad( + if matches!( + obj, + Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) + ) && !checker.locator().contains_line_break(obj.range()) + { + format!("{}.{}", checker.locator().slice(obj), value) + } else { + // Defensively parenthesize any other expressions. For example, attribute accesses + // on `int` literals must be parenthesized, e.g., `getattr(1, "real")` becomes + // `(1).real`. The same is true for named expressions and others. + format!("({}).{}", checker.locator().slice(obj), value) + }, expr.range(), - ))); - } + checker.locator(), + ), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/rules/mutable_argument_default.rs b/crates/ruff_linter/src/rules/flake8_bugbear/rules/mutable_argument_default.rs index 69afa50b4f..7e4f8a6d5b 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/rules/mutable_argument_default.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/rules/mutable_argument_default.rs @@ -11,7 +11,6 @@ use ruff_source_file::Locator; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of mutable objects as function argument defaults. @@ -110,18 +109,16 @@ pub(crate) fn mutable_argument_default(checker: &mut Checker, function_def: &ast let mut diagnostic = Diagnostic::new(MutableArgumentDefault, default.range()); // If the function body is on the same line as the function def, do not fix - if checker.patch(diagnostic.kind.rule()) { - if let Some(fix) = move_initialization( - function_def, - parameter, - default, - checker.locator(), - checker.stylist(), - checker.indexer(), - checker.generator(), - ) { - diagnostic.set_fix(fix); - } + if let Some(fix) = move_initialization( + function_def, + parameter, + default, + checker.locator(), + checker.stylist(), + checker.indexer(), + checker.generator(), + ) { + diagnostic.set_fix(fix); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs b/crates/ruff_linter/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs index a405acc903..0f0240d6a4 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/rules/redundant_tuple_in_exception_handler.rs @@ -6,7 +6,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix::edits::pad; -use crate::registry::AsRule; /// ## What it does /// Checks for single-element tuples in exception handlers (e.g., @@ -77,23 +76,21 @@ pub(crate) fn redundant_tuple_in_exception_handler( }, type_.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // If there's no space between the `except` and the tuple, we need to insert a space, - // as in: - // ```python - // except(ValueError,): - // ``` - // Otherwise, the output will be invalid syntax, since we're removing a set of - // parentheses. - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - pad( - checker.generator().expr(elt), - type_.range(), - checker.locator(), - ), + // If there's no space between the `except` and the tuple, we need to insert a space, + // as in: + // ```python + // except(ValueError,): + // ``` + // Otherwise, the output will be invalid syntax, since we're removing a set of + // parentheses. + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + pad( + checker.generator().expr(elt), type_.range(), - ))); - } + checker.locator(), + ), + type_.range(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/rules/setattr_with_constant.rs b/crates/ruff_linter/src/rules/flake8_bugbear/rules/setattr_with_constant.rs index b9c7682533..290f3ebc87 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/rules/setattr_with_constant.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/rules/setattr_with_constant.rs @@ -7,7 +7,6 @@ use ruff_python_codegen::Generator; use ruff_python_stdlib::identifiers::{is_identifier, is_mangled_private}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `setattr` that take a constant attribute value as an @@ -108,12 +107,10 @@ pub(crate) fn setattr_with_constant( { if expr == child.as_ref() { let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - assignment(obj, name, value, checker.generator()), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + assignment(obj, name, value, checker.generator()), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs b/crates/ruff_linter/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs index 335cf2f4c0..400f5d31c1 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/rules/unreliable_callable_check.rs @@ -5,7 +5,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `hasattr` to test if an object is callable (e.g., @@ -80,14 +79,12 @@ pub(crate) fn unreliable_callable_check( } let mut diagnostic = Diagnostic::new(UnreliableCallableCheck, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - if id == "hasattr" { - if checker.semantic().is_builtin("callable") { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - format!("callable({})", checker.locator().slice(obj)), - expr.range(), - ))); - } + if id == "hasattr" { + if checker.semantic().is_builtin("callable") { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("callable({})", checker.locator().slice(obj)), + expr.range(), + ))); } } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs b/crates/ruff_linter/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs index 2c950430f8..20e29e179b 100644 --- a/crates/ruff_linter/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs +++ b/crates/ruff_linter/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs @@ -8,7 +8,6 @@ use ruff_python_ast::{helpers, visitor}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; #[derive(Debug, Copy, Clone, PartialEq, Eq, result_like::BoolLike)] enum Certainty { @@ -156,23 +155,21 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, stmt_for: &ast }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(rename) = rename { - if certainty.into() { - // Avoid fixing if the variable, or any future bindings to the variable, are - // used _after_ the loop. - let scope = checker.semantic().current_scope(); - if scope - .get_all(name) - .map(|binding_id| checker.semantic().binding(binding_id)) - .filter(|binding| binding.start() >= expr.start()) - .all(|binding| !binding.is_used()) - { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - rename, - expr.range(), - ))); - } + if let Some(rename) = rename { + if certainty.into() { + // Avoid fixing if the variable, or any future bindings to the variable, are + // used _after_ the loop. + let scope = checker.semantic().current_scope(); + if scope + .get_all(name) + .map(|binding_id| checker.semantic().binding(binding_id)) + .filter(|binding| binding.start() >= expr.start()) + .all(|binding| !binding.is_used()) + { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + rename, + expr.range(), + ))); } } } diff --git a/crates/ruff_linter/src/rules/flake8_commas/rules/trailing_commas.rs b/crates/ruff_linter/src/rules/flake8_commas/rules/trailing_commas.rs index 06f1db53b7..e3fdd58a7e 100644 --- a/crates/ruff_linter/src/rules/flake8_commas/rules/trailing_commas.rs +++ b/crates/ruff_linter/src/rules/flake8_commas/rules/trailing_commas.rs @@ -8,9 +8,6 @@ use ruff_python_parser::Tok; use ruff_source_file::Locator; use ruff_text_size::{Ranged, TextRange}; -use crate::registry::Rule; -use crate::settings::LinterSettings; - /// Simplified token type. #[derive(Copy, Clone, PartialEq, Eq)] enum TokenType { @@ -225,7 +222,6 @@ pub(crate) fn trailing_commas( diagnostics: &mut Vec, tokens: &[LexResult], locator: &Locator, - settings: &LinterSettings, ) { let tokens = tokens .iter() @@ -324,9 +320,7 @@ pub(crate) fn trailing_commas( if comma_prohibited { let comma = prev.spanned.unwrap(); let mut diagnostic = Diagnostic::new(ProhibitedTrailingComma, comma.1); - if settings.rules.should_fix(Rule::ProhibitedTrailingComma) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(diagnostic.range()))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(diagnostic.range()))); diagnostics.push(diagnostic); } @@ -359,17 +353,15 @@ pub(crate) fn trailing_commas( MissingTrailingComma, TextRange::empty(missing_comma.1.end()), ); - if settings.rules.should_fix(Rule::MissingTrailingComma) { - // Create a replacement that includes the final bracket (or other token), - // rather than just inserting a comma at the end. This prevents the UP034 fix - // removing any brackets in the same linter pass - doing both at the same time could - // lead to a syntax error. - let contents = locator.slice(missing_comma.1); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - format!("{contents},"), - missing_comma.1, - ))); - } + // Create a replacement that includes the final bracket (or other token), + // rather than just inserting a comma at the end. This prevents the UP034 fix + // removing any brackets in the same linter pass - doing both at the same time could + // lead to a syntax error. + let contents = locator.slice(missing_comma.1); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("{contents},"), + missing_comma.1, + ))); diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs index 3bdda55712..7117d09991 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs @@ -4,7 +4,7 @@ use ruff_python_ast::{self as ast, Expr}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; /// ## What it does @@ -82,19 +82,14 @@ pub(crate) fn unnecessary_call_around_sorted( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let edit = fixes::fix_unnecessary_call_around_sorted( - expr, - checker.locator(), - checker.stylist(), - )?; - if outer.id == "reversed" { - Ok(Fix::unsafe_edit(edit)) - } else { - Ok(Fix::safe_edit(edit)) - } - }); - } + diagnostic.try_set_fix(|| { + let edit = + fixes::fix_unnecessary_call_around_sorted(expr, checker.locator(), checker.stylist())?; + if outer.id == "reversed" { + Ok(Fix::unsafe_edit(edit)) + } else { + Ok(Fix::safe_edit(edit)) + } + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs index ab66b54b9e..8d40f83506 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs @@ -4,7 +4,7 @@ use ruff_python_ast::{Expr, Keyword}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use crate::rules::flake8_comprehensions::settings::Settings; @@ -86,10 +86,8 @@ pub(crate) fn unnecessary_collection_call( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_collection_call(expr, checker).map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_collection_call(expr, checker).map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs index ff058a6178..f11aa25b63 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs @@ -5,7 +5,7 @@ use ruff_python_ast::{self as ast, Comprehension, Expr}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; /// ## What it does @@ -64,12 +64,10 @@ fn add_diagnostic(checker: &mut Checker, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_comprehension(expr, checker.locator(), checker.stylist()) - .map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_comprehension(expr, checker.locator(), checker.stylist()) + .map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs index aac8345967..9527082ae8 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs @@ -7,7 +7,7 @@ use ruff_python_ast::helpers::any_over_expr; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; /// ## What it does @@ -89,11 +89,9 @@ pub(crate) fn unnecessary_comprehension_any_all( } let mut diagnostic = Diagnostic::new(UnnecessaryComprehensionAnyAll, arg.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_comprehension_any_all(expr, checker.locator(), checker.stylist()) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_comprehension_any_all(expr, checker.locator(), checker.stylist()) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs index 331e2e208a..5bdeca9a57 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs @@ -5,7 +5,7 @@ use ruff_python_ast::{self as ast, Arguments, Expr, Keyword}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; /// ## What it does @@ -130,16 +130,14 @@ pub(crate) fn unnecessary_double_cast_or_process( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_double_cast_or_process( - expr, - checker.locator(), - checker.stylist(), - ) - .map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_double_cast_or_process( + expr, + checker.locator(), + checker.stylist(), + ) + .map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs index 69ac91cbc1..e9be9ad143 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_dict.rs @@ -4,7 +4,7 @@ use ruff_python_ast::{self as ast, Expr, Keyword}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -67,10 +67,7 @@ pub(crate) fn unnecessary_generator_dict( return; } let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorDict, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_generator_dict(expr, checker).map(Fix::unsafe_edit) - }); - } + diagnostic + .try_set_fix(|| fixes::fix_unnecessary_generator_dict(expr, checker).map(Fix::unsafe_edit)); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs index 68dd831a5a..06648ef7b5 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs @@ -5,7 +5,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -60,12 +60,10 @@ pub(crate) fn unnecessary_generator_list( } if let Expr::GeneratorExp(_) = argument { let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorList, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_generator_list(expr, checker.locator(), checker.stylist()) - .map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_generator_list(expr, checker.locator(), checker.stylist()) + .map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs index b27a274ec3..124a838dd2 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs @@ -5,7 +5,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -60,11 +60,9 @@ pub(crate) fn unnecessary_generator_set( } if let Expr::GeneratorExp(_) = argument { let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorSet, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_generator_set(expr, checker).map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_generator_set(expr, checker).map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs index 524078bb1c..587b2754c7 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs @@ -5,7 +5,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -56,11 +56,9 @@ pub(crate) fn unnecessary_list_call( return; } let mut diagnostic = Diagnostic::new(UnnecessaryListCall, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_list_call(expr, checker.locator(), checker.stylist()) - .map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_list_call(expr, checker.locator(), checker.stylist()) + .map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs index 5d22aec86b..90b90afcdd 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs @@ -4,7 +4,7 @@ use ruff_python_ast::{self as ast, Expr, Keyword}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -65,10 +65,8 @@ pub(crate) fn unnecessary_list_comprehension_dict( return; } let mut diagnostic = Diagnostic::new(UnnecessaryListComprehensionDict, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_list_comprehension_dict(expr, checker).map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_list_comprehension_dict(expr, checker).map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs index 6ec1a6cb8f..3e5902ccd5 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs @@ -5,7 +5,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -58,11 +58,9 @@ pub(crate) fn unnecessary_list_comprehension_set( } if argument.is_list_comp_expr() { let mut diagnostic = Diagnostic::new(UnnecessaryListComprehensionSet, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_list_comprehension_set(expr, checker).map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_list_comprehension_set(expr, checker).map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs index 105602a457..26ea9ea0d3 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs @@ -4,7 +4,7 @@ use ruff_python_ast::{self as ast, Expr, Keyword}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -80,10 +80,7 @@ pub(crate) fn unnecessary_literal_dict( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_literal_dict(expr, checker).map(Fix::unsafe_edit) - }); - } + diagnostic + .try_set_fix(|| fixes::fix_unnecessary_literal_dict(expr, checker).map(Fix::unsafe_edit)); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs index 1714b76940..fc4c33a0e8 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs @@ -5,7 +5,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -75,10 +75,7 @@ pub(crate) fn unnecessary_literal_set( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_literal_set(expr, checker).map(Fix::unsafe_edit) - }); - } + diagnostic + .try_set_fix(|| fixes::fix_unnecessary_literal_set(expr, checker).map(Fix::unsafe_edit)); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs index f37739a50d..121ceaf685 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs @@ -7,7 +7,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -91,15 +91,9 @@ pub(crate) fn unnecessary_literal_within_dict_call( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_literal_within_dict_call( - expr, - checker.locator(), - checker.stylist(), - ) + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_literal_within_dict_call(expr, checker.locator(), checker.stylist()) .map(Fix::unsafe_edit) - }); - } + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs index 78f6ddb22d..6cb4596f9f 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs @@ -4,7 +4,7 @@ use ruff_python_ast::{Expr, Keyword}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -93,15 +93,9 @@ pub(crate) fn unnecessary_literal_within_list_call( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_literal_within_list_call( - expr, - checker.locator(), - checker.stylist(), - ) + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_literal_within_list_call(expr, checker.locator(), checker.stylist()) .map(Fix::unsafe_edit) - }); - } + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs index 638740692d..d1600979fa 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs @@ -5,7 +5,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -95,15 +95,9 @@ pub(crate) fn unnecessary_literal_within_tuple_call( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_literal_within_tuple_call( - expr, - checker.locator(), - checker.stylist(), - ) + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_literal_within_tuple_call(expr, checker.locator(), checker.stylist()) .map(Fix::unsafe_edit) - }); - } + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_map.rs b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_map.rs index 5b018439ca..549906f0e7 100644 --- a/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_map.rs +++ b/crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_map.rs @@ -9,7 +9,7 @@ use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Parameters, Stm use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_comprehensions::fixes; use super::helpers; @@ -221,18 +221,16 @@ pub(crate) fn unnecessary_map( }; let mut diagnostic = Diagnostic::new(UnnecessaryMap { object_type }, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - fixes::fix_unnecessary_map( - expr, - parent, - object_type, - checker.locator(), - checker.stylist(), - ) - .map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + fixes::fix_unnecessary_map( + expr, + parent, + object_type, + checker.locator(), + checker.stylist(), + ) + .map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_errmsg/rules/string_in_exception.rs b/crates/ruff_linter/src/rules/flake8_errmsg/rules/string_in_exception.rs index 1a526c4632..06543424f4 100644 --- a/crates/ruff_linter/src/rules/flake8_errmsg/rules/string_in_exception.rs +++ b/crates/ruff_linter/src/rules/flake8_errmsg/rules/string_in_exception.rs @@ -7,7 +7,7 @@ use ruff_python_ast::whitespace; use ruff_python_codegen::{Generator, Stylist}; use crate::checkers::ast::Checker; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; /// ## What it does /// Checks for the use of string literals in exception constructors. @@ -190,30 +190,6 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr if string.len() >= checker.settings.flake8_errmsg.max_string_length { let mut diagnostic = Diagnostic::new(RawStringInException, first.range()); - if checker.patch(diagnostic.kind.rule()) { - if let Some(indentation) = - whitespace::indentation(checker.locator(), stmt) - { - if checker.semantic().is_available("msg") { - diagnostic.set_fix(generate_fix( - stmt, - first, - indentation, - checker.stylist(), - checker.generator(), - )); - } - } - } - checker.diagnostics.push(diagnostic); - } - } - } - // Check for f-strings. - Expr::FString(_) => { - if checker.enabled(Rule::FStringInException) { - let mut diagnostic = Diagnostic::new(FStringInException, first.range()); - if checker.patch(diagnostic.kind.rule()) { if let Some(indentation) = whitespace::indentation(checker.locator(), stmt) { @@ -227,6 +203,25 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr )); } } + checker.diagnostics.push(diagnostic); + } + } + } + // Check for f-strings. + Expr::FString(_) => { + if checker.enabled(Rule::FStringInException) { + let mut diagnostic = Diagnostic::new(FStringInException, first.range()); + if let Some(indentation) = whitespace::indentation(checker.locator(), stmt) + { + if checker.semantic().is_available("msg") { + diagnostic.set_fix(generate_fix( + stmt, + first, + indentation, + checker.stylist(), + checker.generator(), + )); + } } checker.diagnostics.push(diagnostic); } @@ -240,19 +235,17 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr if attr == "format" && value.is_constant_expr() { let mut diagnostic = Diagnostic::new(DotFormatInException, first.range()); - if checker.patch(diagnostic.kind.rule()) { - if let Some(indentation) = - whitespace::indentation(checker.locator(), stmt) - { - if checker.semantic().is_available("msg") { - diagnostic.set_fix(generate_fix( - stmt, - first, - indentation, - checker.stylist(), - checker.generator(), - )); - } + if let Some(indentation) = + whitespace::indentation(checker.locator(), stmt) + { + if checker.semantic().is_available("msg") { + diagnostic.set_fix(generate_fix( + stmt, + first, + indentation, + checker.stylist(), + checker.generator(), + )); } } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/flake8_executable/rules/mod.rs b/crates/ruff_linter/src/rules/flake8_executable/rules/mod.rs index 506a5a63ca..e47e7a4d2c 100644 --- a/crates/ruff_linter/src/rules/flake8_executable/rules/mod.rs +++ b/crates/ruff_linter/src/rules/flake8_executable/rules/mod.rs @@ -12,7 +12,6 @@ pub(crate) use shebang_not_executable::*; pub(crate) use shebang_not_first_line::*; use crate::comments::shebang::ShebangDirective; -use crate::settings::LinterSettings; mod shebang_leading_whitespace; mod shebang_missing_executable_file; @@ -24,7 +23,6 @@ pub(crate) fn from_tokens( tokens: &[LexResult], path: &Path, locator: &Locator, - settings: &LinterSettings, diagnostics: &mut Vec, ) { let mut has_any_shebang = false; @@ -41,7 +39,7 @@ pub(crate) fn from_tokens( diagnostics.push(diagnostic); } - if let Some(diagnostic) = shebang_leading_whitespace(*range, locator, settings) { + if let Some(diagnostic) = shebang_leading_whitespace(*range, locator) { diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_executable/rules/shebang_leading_whitespace.rs b/crates/ruff_linter/src/rules/flake8_executable/rules/shebang_leading_whitespace.rs index 1f16e6a8a1..0aa88beaf1 100644 --- a/crates/ruff_linter/src/rules/flake8_executable/rules/shebang_leading_whitespace.rs +++ b/crates/ruff_linter/src/rules/flake8_executable/rules/shebang_leading_whitespace.rs @@ -5,9 +5,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_trivia::is_python_whitespace; use ruff_source_file::Locator; -use crate::registry::AsRule; -use crate::settings::LinterSettings; - /// ## What it does /// Checks for whitespace before a shebang directive. /// @@ -50,7 +47,6 @@ impl AlwaysFixableViolation for ShebangLeadingWhitespace { pub(crate) fn shebang_leading_whitespace( range: TextRange, locator: &Locator, - settings: &LinterSettings, ) -> Option { // If the shebang is at the beginning of the file, abort. if range.start() == TextSize::from(0) { @@ -68,8 +64,6 @@ pub(crate) fn shebang_leading_whitespace( let prefix = TextRange::up_to(range.start()); let mut diagnostic = Diagnostic::new(ShebangLeadingWhitespace, prefix); - if settings.rules.should_fix(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(prefix))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(prefix))); Some(diagnostic) } diff --git a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/implicit.rs b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/implicit.rs index 489e34545b..38c46e7141 100644 --- a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/implicit.rs +++ b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/implicit.rs @@ -9,7 +9,6 @@ use ruff_python_parser::Tok; use ruff_source_file::Locator; use ruff_text_size::{Ranged, TextRange}; -use crate::registry::AsRule; use crate::settings::LinterSettings; /// ## What it does @@ -137,10 +136,8 @@ pub(crate) fn implicit( TextRange::new(a_range.start(), b_range.end()), ); - if settings.rules.should_fix(diagnostic.kind.rule()) { - if let Some(fix) = concatenate_strings(a_range, b_range, locator) { - diagnostic.set_fix(fix); - } + if let Some(fix) = concatenate_strings(a_range, b_range, locator) { + diagnostic.set_fix(fix); } diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/flake8_import_conventions/rules/unconventional_import_alias.rs b/crates/ruff_linter/src/rules/flake8_import_conventions/rules/unconventional_import_alias.rs index f55446d57b..6399b93883 100644 --- a/crates/ruff_linter/src/rules/flake8_import_conventions/rules/unconventional_import_alias.rs +++ b/crates/ruff_linter/src/rules/flake8_import_conventions/rules/unconventional_import_alias.rs @@ -6,7 +6,7 @@ use ruff_python_semantic::{Binding, Imported}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::renamer::Renamer; /// ## What it does @@ -79,16 +79,14 @@ pub(crate) fn unconventional_import_alias( }, binding.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if !import.is_submodule_import() { - if checker.semantic().is_available(expected_alias) { - diagnostic.try_set_fix(|| { - let scope = &checker.semantic().scopes[binding.scope]; - let (edit, rest) = - Renamer::rename(name, expected_alias, scope, checker.semantic())?; - Ok(Fix::unsafe_edits(edit, rest)) - }); - } + if !import.is_submodule_import() { + if checker.semantic().is_available(expected_alias) { + diagnostic.try_set_fix(|| { + let scope = &checker.semantic().scopes[binding.scope]; + let (edit, rest) = + Renamer::rename(name, expected_alias, scope, checker.semantic())?; + Ok(Fix::unsafe_edits(edit, rest)) + }); } } Some(diagnostic) diff --git a/crates/ruff_linter/src/rules/flake8_logging/rules/direct_logger_instantiation.rs b/crates/ruff_linter/src/rules/flake8_logging/rules/direct_logger_instantiation.rs index c920b676bf..552bee9c4f 100644 --- a/crates/ruff_linter/src/rules/flake8_logging/rules/direct_logger_instantiation.rs +++ b/crates/ruff_linter/src/rules/flake8_logging/rules/direct_logger_instantiation.rs @@ -5,7 +5,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; /// ## What it does /// Checks for direct instantiation of `logging.Logger`, as opposed to using @@ -61,17 +60,15 @@ pub(crate) fn direct_logger_instantiation(checker: &mut Checker, call: &ast::Exp .is_some_and(|call_path| matches!(call_path.as_slice(), ["logging", "Logger"])) { let mut diagnostic = Diagnostic::new(DirectLoggerInstantiation, call.func.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import("logging", "getLogger"), - call.func.start(), - checker.semantic(), - )?; - let reference_edit = Edit::range_replacement(binding, call.func.range()); - Ok(Fix::unsafe_edits(import_edit, [reference_edit])) - }); - } + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import("logging", "getLogger"), + call.func.start(), + checker.semantic(), + )?; + let reference_edit = Edit::range_replacement(binding, call.func.range()); + Ok(Fix::unsafe_edits(import_edit, [reference_edit])) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_logging/rules/invalid_get_logger_argument.rs b/crates/ruff_linter/src/rules/flake8_logging/rules/invalid_get_logger_argument.rs index 38409c04f0..e7d4c8fd2a 100644 --- a/crates/ruff_linter/src/rules/flake8_logging/rules/invalid_get_logger_argument.rs +++ b/crates/ruff_linter/src/rules/flake8_logging/rules/invalid_get_logger_argument.rs @@ -4,7 +4,6 @@ use ruff_python_ast::{self as ast, Expr}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for any usage of `__cached__` and `__file__` as an argument to @@ -80,13 +79,11 @@ pub(crate) fn invalid_get_logger_argument(checker: &mut Checker, call: &ast::Exp } let mut diagnostic = Diagnostic::new(InvalidGetLoggerArgument, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_builtin("__name__") { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - "__name__".to_string(), - expr.range(), - ))); - } + if checker.semantic().is_builtin("__name__") { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + "__name__".to_string(), + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_logging/rules/undocumented_warn.rs b/crates/ruff_linter/src/rules/flake8_logging/rules/undocumented_warn.rs index c3ac765c42..134c4feef7 100644 --- a/crates/ruff_linter/src/rules/flake8_logging/rules/undocumented_warn.rs +++ b/crates/ruff_linter/src/rules/flake8_logging/rules/undocumented_warn.rs @@ -6,7 +6,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `logging.WARN`. @@ -55,17 +54,15 @@ pub(crate) fn undocumented_warn(checker: &mut Checker, expr: &Expr) { .is_some_and(|call_path| matches!(call_path.as_slice(), ["logging", "WARN"])) { let mut diagnostic = Diagnostic::new(UndocumentedWarn, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import("logging", "WARNING"), - expr.start(), - checker.semantic(), - )?; - let reference_edit = Edit::range_replacement(binding, expr.range()); - Ok(Fix::safe_edits(import_edit, [reference_edit])) - }); - } + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import("logging", "WARNING"), + expr.start(), + checker.semantic(), + )?; + let reference_edit = Edit::range_replacement(binding, expr.range()); + Ok(Fix::safe_edits(import_edit, [reference_edit])) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_logging_format/rules/logging_call.rs b/crates/ruff_linter/src/rules/flake8_logging_format/rules/logging_call.rs index 00930d002d..2074f5cc85 100644 --- a/crates/ruff_linter/src/rules/flake8_logging_format/rules/logging_call.rs +++ b/crates/ruff_linter/src/rules/flake8_logging_format/rules/logging_call.rs @@ -5,7 +5,7 @@ use ruff_python_stdlib::logging::LoggingLevel; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; use crate::rules::flake8_logging_format::violations::{ LoggingExcInfo, LoggingExtraAttrClash, LoggingFString, LoggingPercentFormat, LoggingRedundantExcInfo, LoggingStringConcat, LoggingStringFormat, LoggingWarn, @@ -196,12 +196,10 @@ pub(crate) fn logging_call(checker: &mut Checker, call: &ast::ExprCall) { LoggingCallType::LevelCall(LoggingLevel::Warn) ) { let mut diagnostic = Diagnostic::new(LoggingWarn, range); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "warning".to_string(), - range, - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "warning".to_string(), + range, + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_pie/rules/duplicate_class_field_definition.rs b/crates/ruff_linter/src/rules/flake8_pie/rules/duplicate_class_field_definition.rs index cb5bee3d8c..4fa34d1450 100644 --- a/crates/ruff_linter/src/rules/flake8_pie/rules/duplicate_class_field_definition.rs +++ b/crates/ruff_linter/src/rules/flake8_pie/rules/duplicate_class_field_definition.rs @@ -8,7 +8,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix; -use crate::registry::AsRule; /// ## What it does /// Checks for duplicate field definitions in classes. @@ -79,13 +78,11 @@ pub(crate) fn duplicate_class_field_definition(checker: &mut Checker, body: &[St }, stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let edit = - fix::edits::delete_stmt(stmt, Some(stmt), checker.locator(), checker.indexer()); - diagnostic.set_fix(Fix::unsafe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_id(), - ))); - } + let edit = + fix::edits::delete_stmt(stmt, Some(stmt), checker.locator(), checker.indexer()); + diagnostic.set_fix(Fix::unsafe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_id(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_pie/rules/multiple_starts_ends_with.rs b/crates/ruff_linter/src/rules/flake8_pie/rules/multiple_starts_ends_with.rs index 6f6aa16f55..ef4a5ad167 100644 --- a/crates/ruff_linter/src/rules/flake8_pie/rules/multiple_starts_ends_with.rs +++ b/crates/ruff_linter/src/rules/flake8_pie/rules/multiple_starts_ends_with.rs @@ -12,7 +12,6 @@ use ruff_diagnostics::{Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `startswith` or `endswith` calls on the same value with @@ -115,92 +114,90 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let words: Vec<&Expr> = indices + let words: Vec<&Expr> = indices + .iter() + .map(|index| &values[*index]) + .map(|expr| { + let Expr::Call(ast::ExprCall { + func: _, + arguments: + Arguments { + args, + keywords: _, + range: _, + }, + range: _, + }) = expr + else { + unreachable!( + "{}", + format!("Indices should only contain `{attr_name}` calls") + ) + }; + args.get(0) + .unwrap_or_else(|| panic!("`{attr_name}` should have one argument")) + }) + .collect(); + + let node = Expr::Tuple(ast::ExprTuple { + elts: words .iter() - .map(|index| &values[*index]) - .map(|expr| { - let Expr::Call(ast::ExprCall { - func: _, - arguments: - Arguments { - args, - keywords: _, - range: _, - }, - range: _, - }) = expr - else { - unreachable!( - "{}", - format!("Indices should only contain `{attr_name}` calls") - ) - }; - args.get(0) - .unwrap_or_else(|| panic!("`{attr_name}` should have one argument")) + .flat_map(|value| { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = value { + Left(elts.iter()) + } else { + Right(iter::once(*value)) + } }) - .collect(); + .map(Clone::clone) + .collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + let node1 = Expr::Name(ast::ExprName { + id: arg_name.into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + let node2 = Expr::Attribute(ast::ExprAttribute { + value: Box::new(node1), + attr: Identifier::new(attr_name.to_string(), TextRange::default()), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + let node3 = Expr::Call(ast::ExprCall { + func: Box::new(node2), + arguments: Arguments { + args: vec![node], + keywords: vec![], + range: TextRange::default(), + }, + range: TextRange::default(), + }); + let call = node3; - let node = Expr::Tuple(ast::ExprTuple { - elts: words - .iter() - .flat_map(|value| { - if let Expr::Tuple(ast::ExprTuple { elts, .. }) = value { - Left(elts.iter()) - } else { - Right(iter::once(*value)) - } - }) - .map(Clone::clone) - .collect(), - ctx: ExprContext::Load, - range: TextRange::default(), - }); - let node1 = Expr::Name(ast::ExprName { - id: arg_name.into(), - ctx: ExprContext::Load, - range: TextRange::default(), - }); - let node2 = Expr::Attribute(ast::ExprAttribute { - value: Box::new(node1), - attr: Identifier::new(attr_name.to_string(), TextRange::default()), - ctx: ExprContext::Load, - range: TextRange::default(), - }); - let node3 = Expr::Call(ast::ExprCall { - func: Box::new(node2), - arguments: Arguments { - args: vec![node], - keywords: vec![], - range: TextRange::default(), - }, - range: TextRange::default(), - }); - let call = node3; - - // Generate the combined `BoolOp`. - let mut call = Some(call); - let node = Expr::BoolOp(ast::ExprBoolOp { - op: BoolOp::Or, - values: values - .iter() - .enumerate() - .filter_map(|(index, elt)| { - if indices.contains(&index) { - std::mem::take(&mut call) - } else { - Some(elt.clone()) - } - }) - .collect(), - range: TextRange::default(), - }); - let bool_op = node; - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr(&bool_op), - expr.range(), - ))); - } + // Generate the combined `BoolOp`. + let mut call = Some(call); + let node = Expr::BoolOp(ast::ExprBoolOp { + op: BoolOp::Or, + values: values + .iter() + .enumerate() + .filter_map(|(index, elt)| { + if indices.contains(&index) { + std::mem::take(&mut call) + } else { + Some(elt.clone()) + } + }) + .collect(), + range: TextRange::default(), + }); + let bool_op = node; + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&bool_op), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_pie/rules/reimplemented_list_builtin.rs b/crates/ruff_linter/src/rules/flake8_pie/rules/reimplemented_list_builtin.rs index e63d4d7d45..6195d09357 100644 --- a/crates/ruff_linter/src/rules/flake8_pie/rules/reimplemented_list_builtin.rs +++ b/crates/ruff_linter/src/rules/flake8_pie/rules/reimplemented_list_builtin.rs @@ -6,7 +6,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for lambdas that can be replaced with the `list` builtin. @@ -64,13 +63,11 @@ pub(crate) fn reimplemented_list_builtin(checker: &mut Checker, expr: &ExprLambd if let Expr::List(ast::ExprList { elts, .. }) = body.as_ref() { if elts.is_empty() { let mut diagnostic = Diagnostic::new(ReimplementedListBuiltin, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_builtin("list") { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "list".to_string(), - expr.range(), - ))); - } + if checker.semantic().is_builtin("list") { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "list".to_string(), + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_dict_kwargs.rs b/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_dict_kwargs.rs index e26ebcb461..3fa3a60cd4 100644 --- a/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_dict_kwargs.rs +++ b/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_dict_kwargs.rs @@ -8,7 +8,6 @@ use ruff_text_size::Ranged; use ruff_python_stdlib::identifiers::is_identifier; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for unnecessary `dict` kwargs. @@ -68,12 +67,10 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs if matches!(keys.as_slice(), [None]) { let mut diagnostic = Diagnostic::new(UnnecessaryDictKwargs, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - format!("**{}", checker.locator().slice(values[0].range())), - kw.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("**{}", checker.locator().slice(values[0].range())), + kw.range(), + ))); checker.diagnostics.push(diagnostic); continue; @@ -91,18 +88,16 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs let mut diagnostic = Diagnostic::new(UnnecessaryDictKwargs, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - kwargs - .iter() - .zip(values.iter()) - .map(|(kwarg, value)| { - format!("{}={}", kwarg.value, checker.locator().slice(value.range())) - }) - .join(", "), - kw.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + kwargs + .iter() + .zip(values.iter()) + .map(|(kwarg, value)| { + format!("{}={}", kwarg.value, checker.locator().slice(value.range())) + }) + .join(", "), + kw.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_pass.rs b/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_pass.rs index 2f5f9270a8..fe845646a2 100644 --- a/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_pass.rs +++ b/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_pass.rs @@ -8,7 +8,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix; -use crate::registry::AsRule; /// ## What it does /// Checks for unnecessary `pass` statements in functions, classes, and other @@ -63,17 +62,14 @@ pub(crate) fn no_unnecessary_pass(checker: &mut Checker, body: &[Stmt]) { .filter(|stmt| stmt.is_pass_stmt()) .for_each(|stmt| { let mut diagnostic = Diagnostic::new(UnnecessaryPass, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - let edit = - if let Some(index) = trailing_comment_start_offset(stmt, checker.locator()) { - Edit::range_deletion(stmt.range().add_end(index)) - } else { - fix::edits::delete_stmt(stmt, None, checker.locator(), checker.indexer()) - }; - diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_id(), - ))); - } + let edit = if let Some(index) = trailing_comment_start_offset(stmt, checker.locator()) { + Edit::range_deletion(stmt.range().add_end(index)) + } else { + fix::edits::delete_stmt(stmt, None, checker.locator(), checker.indexer()) + }; + diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_id(), + ))); checker.diagnostics.push(diagnostic); }); } diff --git a/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_range_start.rs b/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_range_start.rs index eda96ffb6e..1bc2bd1cf7 100644 --- a/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_range_start.rs +++ b/crates/ruff_linter/src/rules/flake8_pie/rules/unnecessary_range_start.rs @@ -6,7 +6,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix::edits::{remove_argument, Parentheses}; -use crate::registry::AsRule; /// ## What it does /// Checks for `range` calls with an unnecessary `start` argument. @@ -78,16 +77,14 @@ pub(crate) fn unnecessary_range_start(checker: &mut Checker, call: &ast::ExprCal }; let mut diagnostic = Diagnostic::new(UnnecessaryRangeStart, start.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - remove_argument( - &start, - &call.arguments, - Parentheses::Preserve, - checker.locator().contents(), - ) - .map(Fix::safe_edit) - }); - } + diagnostic.try_set_fix(|| { + remove_argument( + &start, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), + ) + .map(Fix::safe_edit) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/any_eq_ne_annotation.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/any_eq_ne_annotation.rs index 1bad7ff3de..a193732226 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/any_eq_ne_annotation.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/any_eq_ne_annotation.rs @@ -5,7 +5,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `__eq__` and `__ne__` implementations that use `typing.Any` as @@ -78,14 +77,12 @@ pub(crate) fn any_eq_ne_annotation(checker: &mut Checker, name: &str, parameters }, annotation.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Ex) `def __eq__(self, obj: Any): ...` - if checker.semantic().is_builtin("object") { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "object".to_string(), - annotation.range(), - ))); - } + // Ex) `def __eq__(self, obj: Any): ...` + if checker.semantic().is_builtin("object") { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "object".to_string(), + annotation.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/duplicate_union_member.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/duplicate_union_member.rs index 6def99c2d7..b12c741620 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/duplicate_union_member.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/duplicate_union_member.rs @@ -3,7 +3,7 @@ use rustc_hash::FxHashSet; use std::collections::HashSet; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_pyi::helpers::traverse_union; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_macros::{derive_message_formats, violation}; @@ -64,19 +64,17 @@ pub(crate) fn duplicate_union_member<'a>(checker: &mut Checker, expr: &'a Expr) }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Delete the "|" character as well as the duplicate value by reconstructing the - // parent without the duplicate. + // Delete the "|" character as well as the duplicate value by reconstructing the + // parent without the duplicate. - // If the parent node is not a `BinOp` we will not perform a fix - if let Some(parent @ Expr::BinOp(ast::ExprBinOp { left, right, .. })) = parent { - // Replace the parent with its non-duplicate child. - let child = if expr == left.as_ref() { right } else { left }; - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - checker.locator().slice(child.as_ref()).to_string(), - parent.range(), - ))); - } + // If the parent node is not a `BinOp` we will not perform a fix + if let Some(parent @ Expr::BinOp(ast::ExprBinOp { left, right, .. })) = parent { + // Replace the parent with its non-duplicate child. + let child = if expr == left.as_ref() { right } else { left }; + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + checker.locator().slice(child.as_ref()).to_string(), + parent.range(), + ))); } diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/ellipsis_in_non_empty_class_body.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/ellipsis_in_non_empty_class_body.rs index 256056bf07..6afb063a4a 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/ellipsis_in_non_empty_class_body.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/ellipsis_in_non_empty_class_body.rs @@ -5,7 +5,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix; -use crate::registry::AsRule; /// ## What it does /// Removes ellipses (`...`) in otherwise non-empty class bodies. @@ -63,13 +62,11 @@ pub(crate) fn ellipsis_in_non_empty_class_body(checker: &mut Checker, body: &[St }) ) { let mut diagnostic = Diagnostic::new(EllipsisInNonEmptyClassBody, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - let edit = - fix::edits::delete_stmt(stmt, Some(stmt), checker.locator(), checker.indexer()); - diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_id(), - ))); - } + let edit = + fix::edits::delete_stmt(stmt, Some(stmt), checker.locator(), checker.indexer()); + diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_id(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/exit_annotations.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/exit_annotations.rs index 79e4781b4b..4e21bb5641 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/exit_annotations.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/exit_annotations.rs @@ -13,7 +13,6 @@ use ruff_python_semantic::SemanticModel; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for incorrect function signatures on `__exit__` and `__aexit__` @@ -175,13 +174,11 @@ fn check_short_args_list(checker: &mut Checker, parameters: &Parameters, func_ki annotation.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_builtin("object") { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "object".to_string(), - annotation.range(), - ))); - } + if checker.semantic().is_builtin("object") { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "object".to_string(), + annotation.range(), + ))); } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/non_empty_stub_body.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/non_empty_stub_body.rs index 9e4174535f..55827e0665 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/non_empty_stub_body.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/non_empty_stub_body.rs @@ -5,7 +5,6 @@ use ruff_python_ast::{self as ast, Expr, Stmt}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::Rule; /// ## What it does /// Checks for non-empty function stub bodies. @@ -69,11 +68,9 @@ pub(crate) fn non_empty_stub_body(checker: &mut Checker, body: &[Stmt]) { } let mut diagnostic = Diagnostic::new(NonEmptyStubBody, stmt.range()); - if checker.patch(Rule::NonEmptyStubBody) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - format!("..."), - stmt.range(), - ))); - }; + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("..."), + stmt.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/numeric_literal_too_long.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/numeric_literal_too_long.rs index 753a668a1c..64092f3035 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/numeric_literal_too_long.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/numeric_literal_too_long.rs @@ -5,7 +5,6 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for numeric literals with a string representation longer than ten @@ -50,11 +49,9 @@ pub(crate) fn numeric_literal_too_long(checker: &mut Checker, expr: &Expr) { } let mut diagnostic = Diagnostic::new(NumericLiteralTooLong, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "...".to_string(), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "...".to_string(), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/pass_in_class_body.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/pass_in_class_body.rs index ee408a712f..1e26b76c6e 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/pass_in_class_body.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/pass_in_class_body.rs @@ -5,7 +5,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix; -use crate::registry::AsRule; /// ## What it does /// Checks for the presence of the `pass` statement within a class body @@ -60,13 +59,10 @@ pub(crate) fn pass_in_class_body(checker: &mut Checker, class_def: &ast::StmtCla } let mut diagnostic = Diagnostic::new(PassInClassBody, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - let edit = - fix::edits::delete_stmt(stmt, Some(stmt), checker.locator(), checker.indexer()); - diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_id(), - ))); - } + let edit = fix::edits::delete_stmt(stmt, Some(stmt), checker.locator(), checker.indexer()); + diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_id(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs index 46a2a83cfa..3e1a0d3a8d 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/pass_statement_stub_body.rs @@ -4,7 +4,6 @@ use ruff_python_ast::Stmt; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::Rule; /// ## What it does /// Checks for `pass` statements in empty stub bodies. @@ -47,11 +46,9 @@ pub(crate) fn pass_statement_stub_body(checker: &mut Checker, body: &[Stmt]) { }; let mut diagnostic = Diagnostic::new(PassStatementStubBody, pass.range()); - if checker.patch(Rule::PassStatementStubBody) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - format!("..."), - pass.range(), - ))); - }; + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("..."), + pass.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/quoted_annotation_in_stub.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/quoted_annotation_in_stub.rs index 1147b6857b..96330f7573 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/quoted_annotation_in_stub.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/quoted_annotation_in_stub.rs @@ -4,7 +4,6 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; -use crate::registry::Rule; /// ## What it does /// Checks for quoted type annotations in stub (`.pyi`) files, which should be avoided. @@ -43,11 +42,9 @@ impl AlwaysFixableViolation for QuotedAnnotationInStub { /// PYI020 pub(crate) fn quoted_annotation_in_stub(checker: &mut Checker, annotation: &str, range: TextRange) { let mut diagnostic = Diagnostic::new(QuotedAnnotationInStub, range); - if checker.patch(Rule::QuotedAnnotationInStub) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - annotation.to_string(), - range, - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + annotation.to_string(), + range, + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/simple_defaults.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/simple_defaults.rs index 73a207b217..dd93d49613 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/simple_defaults.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/simple_defaults.rs @@ -11,7 +11,7 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; + use crate::rules::flake8_pyi::rules::TypingModule; use crate::settings::types::PythonVersion; @@ -534,12 +534,10 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, parameters: ) { let mut diagnostic = Diagnostic::new(TypedArgumentDefaultInStub, default.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "...".to_string(), - default.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "...".to_string(), + default.range(), + ))); checker.diagnostics.push(diagnostic); } @@ -571,12 +569,10 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, parameters: &Param ) { let mut diagnostic = Diagnostic::new(ArgumentDefaultInStub, default.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "...".to_string(), - default.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "...".to_string(), + default.range(), + ))); checker.diagnostics.push(diagnostic); } @@ -606,12 +602,10 @@ pub(crate) fn assignment_default_in_stub(checker: &mut Checker, targets: &[Expr] } let mut diagnostic = Diagnostic::new(AssignmentDefaultInStub, value.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "...".to_string(), - value.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "...".to_string(), + value.range(), + ))); checker.diagnostics.push(diagnostic); } @@ -642,12 +636,10 @@ pub(crate) fn annotated_assignment_default_in_stub( } let mut diagnostic = Diagnostic::new(AssignmentDefaultInStub, value.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "...".to_string(), - value.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "...".to_string(), + value.range(), + ))); checker.diagnostics.push(diagnostic); } @@ -741,18 +733,16 @@ pub(crate) fn type_alias_without_annotation(checker: &mut Checker, value: &Expr, }, target.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import(module.as_str(), "TypeAlias"), - target.start(), - checker.semantic(), - )?; - Ok(Fix::safe_edits( - Edit::range_replacement(format!("{id}: {binding}"), target.range()), - [import_edit], - )) - }); - } + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import(module.as_str(), "TypeAlias"), + target.start(), + checker.semantic(), + )?; + Ok(Fix::safe_edits( + Edit::range_replacement(format!("{id}: {binding}"), target.range()), + [import_edit], + )) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/str_or_repr_defined_in_stub.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/str_or_repr_defined_in_stub.rs index 0babdafe48..ee8a0de530 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/str_or_repr_defined_in_stub.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/str_or_repr_defined_in_stub.rs @@ -8,7 +8,6 @@ use ruff_python_semantic::analyze::visibility::is_abstract; use crate::checkers::ast::Checker; use crate::fix::edits::delete_stmt; -use crate::registry::AsRule; /// ## What it does /// Checks for redundant definitions of `__str__` or `__repr__` in stubs. @@ -95,13 +94,11 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) { }, stmt.identifier(), ); - if checker.patch(diagnostic.kind.rule()) { - let stmt = checker.semantic().current_statement(); - let parent = checker.semantic().current_statement_parent(); - let edit = delete_stmt(stmt, parent, checker.locator(), checker.indexer()); - diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_parent_id(), - ))); - } + let stmt = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); + let edit = delete_stmt(stmt, parent, checker.locator(), checker.indexer()); + diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs index b71c86363d..2ad818501c 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/string_or_bytes_too_long.rs @@ -6,7 +6,6 @@ use ruff_python_ast::helpers::is_docstring_stmt; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for the use of string and bytes literals longer than 50 characters @@ -67,11 +66,9 @@ pub(crate) fn string_or_bytes_too_long(checker: &mut Checker, expr: &Expr) { } let mut diagnostic = Diagnostic::new(StringOrBytesTooLong, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "...".to_string(), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "...".to_string(), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/unaliased_collections_abc_set_import.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/unaliased_collections_abc_set_import.rs index 538dd1716b..79e6ba61a7 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/unaliased_collections_abc_set_import.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/unaliased_collections_abc_set_import.rs @@ -5,7 +5,7 @@ use ruff_python_semantic::{Binding, BindingKind}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::renamer::Renamer; /// ## What it does @@ -65,14 +65,12 @@ pub(crate) fn unaliased_collections_abc_set_import( } let mut diagnostic = Diagnostic::new(UnaliasedCollectionsAbcSetImport, binding.range()); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_available("AbstractSet") { - diagnostic.try_set_fix(|| { - let scope = &checker.semantic().scopes[binding.scope]; - let (edit, rest) = Renamer::rename(name, "AbstractSet", scope, checker.semantic())?; - Ok(Fix::unsafe_edits(edit, rest)) - }); - } + if checker.semantic().is_available("AbstractSet") { + diagnostic.try_set_fix(|| { + let scope = &checker.semantic().scopes[binding.scope]; + let (edit, rest) = Renamer::rename(name, "AbstractSet", scope, checker.semantic())?; + Ok(Fix::unsafe_edits(edit, rest)) + }); } Some(diagnostic) } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs index 1303a2b25b..d0134ad362 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs @@ -4,7 +4,7 @@ use ruff_python_ast::{self as ast, Expr}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_pyi::helpers::traverse_union; /// ## What it does @@ -76,12 +76,10 @@ pub(crate) fn unnecessary_literal_union<'a>(checker: &mut Checker, expr: &'a Exp expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - format!("Literal[{}]", literal_members.join(", ")), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("Literal[{}]", literal_members.join(", ")), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/assertion.rs b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/assertion.rs index 35c0feb57e..1ccc208298 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/assertion.rs +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/assertion.rs @@ -26,7 +26,6 @@ use crate::cst::matchers::match_indented_block; use crate::cst::matchers::match_module; use crate::fix::codemods::CodegenStylist; use crate::importer::ImportRequest; -use crate::registry::AsRule; use super::unittest_assert::UnittestAssert; @@ -284,25 +283,23 @@ pub(crate) fn unittest_assertion( }, func.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // We're converting an expression to a statement, so avoid applying the fix if - // the assertion is part of a larger expression. - if checker.semantic().current_statement().is_expr_stmt() - && checker.semantic().current_expression_parent().is_none() - && !checker.indexer().comment_ranges().intersects(expr.range()) - { - if let Ok(stmt) = unittest_assert.generate_assert(args, keywords) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().stmt(&stmt), - parenthesized_range( - expr.into(), - checker.semantic().current_statement().into(), - checker.indexer().comment_ranges(), - checker.locator().contents(), - ) - .unwrap_or(expr.range()), - ))); - } + // We're converting an expression to a statement, so avoid applying the fix if + // the assertion is part of a larger expression. + if checker.semantic().current_statement().is_expr_stmt() + && checker.semantic().current_expression_parent().is_none() + && !checker.indexer().comment_ranges().intersects(expr.range()) + { + if let Ok(stmt) = unittest_assert.generate_assert(args, keywords) { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().stmt(&stmt), + parenthesized_range( + expr.into(), + checker.semantic().current_statement().into(), + checker.indexer().comment_ranges(), + checker.locator().contents(), + ) + .unwrap_or(expr.range()), + ))); } } Some(diagnostic) @@ -390,9 +387,7 @@ pub(crate) fn unittest_raises_assertion( }, call.func.range(), ); - if checker.patch(diagnostic.kind.rule()) - && !checker.indexer().has_comments(call, checker.locator()) - { + if !checker.indexer().has_comments(call, checker.locator()) { if let Some(args) = to_pytest_raises_args(checker, attr.as_str(), &call.arguments) { diagnostic.try_set_fix(|| { let (import_edit, binding) = checker.importer().get_or_import_symbol( @@ -746,19 +741,17 @@ pub(crate) fn composite_condition( let composite = is_composite_condition(test); if matches!(composite, CompositionKind::Simple | CompositionKind::Mixed) { let mut diagnostic = Diagnostic::new(PytestCompositeAssertion, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - if matches!(composite, CompositionKind::Simple) - && msg.is_none() - && !checker.indexer().comment_ranges().intersects(stmt.range()) - && !checker - .indexer() - .in_multi_statement_line(stmt, checker.locator()) - { - diagnostic.try_set_fix(|| { - fix_composite_condition(stmt, checker.locator(), checker.stylist()) - .map(Fix::unsafe_edit) - }); - } + if matches!(composite, CompositionKind::Simple) + && msg.is_none() + && !checker.indexer().comment_ranges().intersects(stmt.range()) + && !checker + .indexer() + .in_multi_statement_line(stmt, checker.locator()) + { + diagnostic.try_set_fix(|| { + fix_composite_condition(stmt, checker.locator(), checker.stylist()) + .map(Fix::unsafe_edit) + }); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/fixture.rs b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/fixture.rs index 1670401336..58a5553ce1 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/fixture.rs +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/fixture.rs @@ -16,7 +16,7 @@ use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; use super::helpers::{ get_mark_decorators, is_pytest_fixture, is_pytest_yield_fixture, keyword_is_literal, @@ -681,9 +681,7 @@ fn pytest_fixture_parentheses( PytestFixtureIncorrectParenthesesStyle { expected, actual }, decorator.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(fix); - } + diagnostic.set_fix(fix); checker.diagnostics.push(diagnostic); } @@ -727,17 +725,15 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &D if keyword_is_literal(keyword, "function") { let mut diagnostic = Diagnostic::new(PytestExtraneousScopeFunction, keyword.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - edits::remove_argument( - keyword, - arguments, - edits::Parentheses::Preserve, - checker.locator().contents(), - ) - .map(Fix::unsafe_edit) - }); - } + diagnostic.try_set_fix(|| { + edits::remove_argument( + keyword, + arguments, + edits::Parentheses::Preserve, + checker.locator().contents(), + ) + .map(Fix::unsafe_edit) + }); checker.diagnostics.push(diagnostic); } } @@ -819,30 +815,28 @@ fn check_fixture_returns( }, stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let yield_edit = Edit::range_replacement( - "return".to_string(), - TextRange::at(stmt.start(), "yield".text_len()), - ); - let return_type_edit = returns.and_then(|returns| { - let ast::ExprSubscript { value, slice, .. } = returns.as_subscript_expr()?; - let ast::ExprTuple { elts, .. } = slice.as_tuple_expr()?; - let [first, ..] = elts.as_slice() else { - return None; - }; - if !checker.semantic().match_typing_expr(value, "Generator") { - return None; - } - Some(Edit::range_replacement( - checker.generator().expr(first), - returns.range(), - )) - }); - if let Some(return_type_edit) = return_type_edit { - diagnostic.set_fix(Fix::safe_edits(yield_edit, [return_type_edit])); - } else { - diagnostic.set_fix(Fix::safe_edit(yield_edit)); + let yield_edit = Edit::range_replacement( + "return".to_string(), + TextRange::at(stmt.start(), "yield".text_len()), + ); + let return_type_edit = returns.and_then(|returns| { + let ast::ExprSubscript { value, slice, .. } = returns.as_subscript_expr()?; + let ast::ExprTuple { elts, .. } = slice.as_tuple_expr()?; + let [first, ..] = elts.as_slice() else { + return None; + }; + if !checker.semantic().match_typing_expr(value, "Generator") { + return None; } + Some(Edit::range_replacement( + checker.generator().expr(first), + returns.range(), + )) + }); + if let Some(return_type_edit) = return_type_edit { + diagnostic.set_fix(Fix::safe_edits(yield_edit, [return_type_edit])); + } else { + diagnostic.set_fix(Fix::safe_edit(yield_edit)); } checker.diagnostics.push(diagnostic); } @@ -912,10 +906,8 @@ fn check_fixture_marks(checker: &mut Checker, decorators: &[Decorator]) { if *name == "asyncio" { let mut diagnostic = Diagnostic::new(PytestUnnecessaryAsyncioMarkOnFixture, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - let range = checker.locator().full_lines_range(expr.range()); - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(range))); - } + let range = checker.locator().full_lines_range(expr.range()); + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(range))); checker.diagnostics.push(diagnostic); } } @@ -924,10 +916,8 @@ fn check_fixture_marks(checker: &mut Checker, decorators: &[Decorator]) { if *name == "usefixtures" { let mut diagnostic = Diagnostic::new(PytestErroneousUseFixturesOnFixture, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - let line_range = checker.locator().full_lines_range(expr.range()); - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(line_range))); - } + let line_range = checker.locator().full_lines_range(expr.range()); + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(line_range))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/marks.rs b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/marks.rs index 9a4560b84d..51c3bc6e0c 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/marks.rs +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/marks.rs @@ -6,7 +6,7 @@ use ruff_python_ast::call_path::CallPath; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; use super::helpers::get_mark_decorators; @@ -130,9 +130,7 @@ fn pytest_mark_parentheses( }, decorator.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(fix); - } + diagnostic.set_fix(fix); checker.diagnostics.push(diagnostic); } @@ -184,9 +182,7 @@ fn check_useless_usefixtures(checker: &mut Checker, decorator: &Decorator, call_ if !has_parameters { let mut diagnostic = Diagnostic::new(PytestUseFixturesWithoutParameters, decorator.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_deletion(decorator.range()))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_deletion(decorator.range()))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs index d1e00bb72f..bdf63cdef9 100644 --- a/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs +++ b/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs @@ -14,7 +14,7 @@ use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::checkers::ast::Checker; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; use super::super::types; use super::helpers::{is_pytest_parametrize, split_names}; @@ -338,25 +338,23 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { }, name_range, ); - if checker.patch(diagnostic.kind.rule()) { - let node = Expr::Tuple(ast::ExprTuple { - elts: names - .iter() - .map(|name| { - Expr::Constant(ast::ExprConstant { - value: (*name).to_string().into(), - range: TextRange::default(), - }) + let node = Expr::Tuple(ast::ExprTuple { + elts: names + .iter() + .map(|name| { + Expr::Constant(ast::ExprConstant { + value: (*name).to_string().into(), + range: TextRange::default(), }) - .collect(), - ctx: ExprContext::Load, - range: TextRange::default(), - }); - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - format!("({})", checker.generator().expr(&node)), - name_range, - ))); - } + }) + .collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + format!("({})", checker.generator().expr(&node)), + name_range, + ))); checker.diagnostics.push(diagnostic); } types::ParametrizeNameType::List => { @@ -373,25 +371,23 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { }, name_range, ); - if checker.patch(diagnostic.kind.rule()) { - let node = Expr::List(ast::ExprList { - elts: names - .iter() - .map(|name| { - Expr::Constant(ast::ExprConstant { - value: (*name).to_string().into(), - range: TextRange::default(), - }) + let node = Expr::List(ast::ExprList { + elts: names + .iter() + .map(|name| { + Expr::Constant(ast::ExprConstant { + value: (*name).to_string().into(), + range: TextRange::default(), }) - .collect(), - ctx: ExprContext::Load, - range: TextRange::default(), - }); - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr(&node), - name_range, - ))); - } + }) + .collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&node), + name_range, + ))); checker.diagnostics.push(diagnostic); } types::ParametrizeNameType::Csv => {} @@ -413,17 +409,15 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let node = Expr::List(ast::ExprList { - elts: elts.clone(), - ctx: ExprContext::Load, - range: TextRange::default(), - }); - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr(&node), - expr.range(), - ))); - } + let node = Expr::List(ast::ExprList { + elts: elts.clone(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&node), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } types::ParametrizeNameType::Csv => { @@ -433,13 +427,11 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(content) = elts_to_csv(elts, checker.generator()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - content, - expr.range(), - ))); - } + if let Some(content) = elts_to_csv(elts, checker.generator()) { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + content, + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } @@ -461,17 +453,15 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let node = Expr::Tuple(ast::ExprTuple { - elts: elts.clone(), - ctx: ExprContext::Load, - range: TextRange::default(), - }); - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - format!("({})", checker.generator().expr(&node)), - expr.range(), - ))); - } + let node = Expr::Tuple(ast::ExprTuple { + elts: elts.clone(), + ctx: ExprContext::Load, + range: TextRange::default(), + }); + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + format!("({})", checker.generator().expr(&node)), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } types::ParametrizeNameType::Csv => { @@ -481,13 +471,11 @@ fn check_names(checker: &mut Checker, decorator: &Decorator, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(content) = elts_to_csv(elts, checker.generator()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - content, - expr.range(), - ))); - } + if let Some(content) = elts_to_csv(elts, checker.generator()) { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + content, + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } @@ -585,22 +573,19 @@ fn check_duplicates(checker: &mut Checker, values: &Expr) { PytestDuplicateParametrizeTestCases { index: *index }, element.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(prev) = prev { - let values_end = values.range().end() - TextSize::new(1); - let previous_end = trailing_comma(prev, checker.locator().contents()) - .unwrap_or(values_end); - let element_end = trailing_comma(element, checker.locator().contents()) - .unwrap_or(values_end); - let deletion_range = TextRange::new(previous_end, element_end); - if !checker - .indexer() - .comment_ranges() - .intersects(deletion_range) - { - diagnostic - .set_fix(Fix::unsafe_edit(Edit::range_deletion(deletion_range))); - } + if let Some(prev) = prev { + let values_end = values.range().end() - TextSize::new(1); + let previous_end = + trailing_comma(prev, checker.locator().contents()).unwrap_or(values_end); + let element_end = + trailing_comma(element, checker.locator().contents()).unwrap_or(values_end); + let deletion_range = TextRange::new(previous_end, element_end); + if !checker + .indexer() + .comment_ranges() + .intersects(deletion_range) + { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_deletion(deletion_range))); } } checker.diagnostics.push(diagnostic); @@ -618,13 +603,11 @@ fn handle_single_name(checker: &mut Checker, expr: &Expr, value: &Expr) { expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let node = value.clone(); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - checker.generator().expr(&node), - expr.range(), - ))); - } + let node = value.clone(); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + checker.generator().expr(&node), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_quotes/rules/avoidable_escaped_quote.rs b/crates/ruff_linter/src/rules/flake8_quotes/rules/avoidable_escaped_quote.rs index 212817811e..8dae048b12 100644 --- a/crates/ruff_linter/src/rules/flake8_quotes/rules/avoidable_escaped_quote.rs +++ b/crates/ruff_linter/src/rules/flake8_quotes/rules/avoidable_escaped_quote.rs @@ -7,7 +7,7 @@ use ruff_source_file::Locator; use ruff_text_size::TextRange; use crate::lex::docstring_detection::StateMachine; -use crate::registry::AsRule; + use crate::settings::LinterSettings; /// ## What it does @@ -135,18 +135,16 @@ pub(crate) fn avoidable_escaped_quote( && !string_contents.contains(quotes_settings.inline_quotes.opposite().as_char()) { let mut diagnostic = Diagnostic::new(AvoidableEscapedQuote, tok_range); - if settings.rules.should_fix(diagnostic.kind.rule()) { - let fixed_contents = format!( - "{prefix}{quote}{value}{quote}", - prefix = kind.as_str(), - quote = quotes_settings.inline_quotes.opposite().as_char(), - value = unescape_string(string_contents) - ); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - fixed_contents, - tok_range, - ))); - } + let fixed_contents = format!( + "{prefix}{quote}{value}{quote}", + prefix = kind.as_str(), + quote = quotes_settings.inline_quotes.opposite().as_char(), + value = unescape_string(string_contents) + ); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + fixed_contents, + tok_range, + ))); diagnostics.push(diagnostic); } } @@ -192,35 +190,33 @@ pub(crate) fn avoidable_escaped_quote( AvoidableEscapedQuote, TextRange::new(context.start_range.start(), tok_range.end()), ); - if settings.rules.should_fix(diagnostic.kind.rule()) { - let fstring_start_edit = Edit::range_replacement( - // No need for `r`/`R` as we don't perform the checks - // for raw strings. - format!("f{}", quotes_settings.inline_quotes.opposite().as_char()), - context.start_range, - ); - let fstring_middle_and_end_edits = context - .middle_ranges_with_escapes - .iter() - .map(|&range| { - Edit::range_replacement(unescape_string(locator.slice(range)), range) - }) - .chain(std::iter::once( - // `FStringEnd` edit - Edit::range_replacement( - quotes_settings - .inline_quotes - .opposite() - .as_char() - .to_string(), - tok_range, - ), - )); - diagnostic.set_fix(Fix::safe_edits( - fstring_start_edit, - fstring_middle_and_end_edits, + let fstring_start_edit = Edit::range_replacement( + // No need for `r`/`R` as we don't perform the checks + // for raw strings. + format!("f{}", quotes_settings.inline_quotes.opposite().as_char()), + context.start_range, + ); + let fstring_middle_and_end_edits = context + .middle_ranges_with_escapes + .iter() + .map(|&range| { + Edit::range_replacement(unescape_string(locator.slice(range)), range) + }) + .chain(std::iter::once( + // `FStringEnd` edit + Edit::range_replacement( + quotes_settings + .inline_quotes + .opposite() + .as_char() + .to_string(), + tok_range, + ), )); - } + diagnostic.set_fix(Fix::safe_edits( + fstring_start_edit, + fstring_middle_and_end_edits, + )); diagnostics.push(diagnostic); } _ => {} diff --git a/crates/ruff_linter/src/rules/flake8_quotes/rules/check_string_quotes.rs b/crates/ruff_linter/src/rules/flake8_quotes/rules/check_string_quotes.rs index dc00d19b00..641a7eea57 100644 --- a/crates/ruff_linter/src/rules/flake8_quotes/rules/check_string_quotes.rs +++ b/crates/ruff_linter/src/rules/flake8_quotes/rules/check_string_quotes.rs @@ -7,7 +7,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_source_file::Locator; use crate::lex::docstring_detection::StateMachine; -use crate::registry::Rule; + use crate::settings::LinterSettings; use super::super::settings::Quote; @@ -230,21 +230,19 @@ fn docstring(locator: &Locator, range: TextRange, settings: &LinterSettings) -> }, range, ); - if settings.rules.should_fix(Rule::BadQuotesDocstring) { - let quote_count = if trivia.is_multiline { 3 } else { 1 }; - let string_contents = &trivia.raw_text[quote_count..trivia.raw_text.len() - quote_count]; - let quote = good_docstring(quotes_settings.docstring_quotes).repeat(quote_count); - let mut fixed_contents = - String::with_capacity(trivia.prefix.len() + string_contents.len() + quote.len() * 2); - fixed_contents.push_str(trivia.prefix); - fixed_contents.push_str("e); - fixed_contents.push_str(string_contents); - fixed_contents.push_str("e); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - fixed_contents, - range, - ))); - } + let quote_count = if trivia.is_multiline { 3 } else { 1 }; + let string_contents = &trivia.raw_text[quote_count..trivia.raw_text.len() - quote_count]; + let quote = good_docstring(quotes_settings.docstring_quotes).repeat(quote_count); + let mut fixed_contents = + String::with_capacity(trivia.prefix.len() + string_contents.len() + quote.len() * 2); + fixed_contents.push_str(trivia.prefix); + fixed_contents.push_str("e); + fixed_contents.push_str(string_contents); + fixed_contents.push_str("e); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + fixed_contents, + range, + ))); Some(diagnostic) } @@ -307,21 +305,19 @@ fn strings( *range, ); - if settings.rules.should_fix(Rule::BadQuotesMultilineString) { - let string_contents = &trivia.raw_text[3..trivia.raw_text.len() - 3]; - let quote = good_multiline(quotes_settings.multiline_quotes); - let mut fixed_contents = String::with_capacity( - trivia.prefix.len() + string_contents.len() + quote.len() * 2, - ); - fixed_contents.push_str(trivia.prefix); - fixed_contents.push_str(quote); - fixed_contents.push_str(string_contents); - fixed_contents.push_str(quote); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - fixed_contents, - *range, - ))); - } + let string_contents = &trivia.raw_text[3..trivia.raw_text.len() - 3]; + let quote = good_multiline(quotes_settings.multiline_quotes); + let mut fixed_contents = String::with_capacity( + trivia.prefix.len() + string_contents.len() + quote.len() * 2, + ); + fixed_contents.push_str(trivia.prefix); + fixed_contents.push_str(quote); + fixed_contents.push_str(string_contents); + fixed_contents.push_str(quote); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + fixed_contents, + *range, + ))); diagnostics.push(diagnostic); } else if trivia.last_quote_char != quotes_settings.inline_quotes.as_char() // If we're not using the preferred type, only allow use to avoid escapes. @@ -333,20 +329,18 @@ fn strings( }, *range, ); - if settings.rules.should_fix(Rule::BadQuotesInlineString) { - let quote = quotes_settings.inline_quotes.as_char(); - let string_contents = &trivia.raw_text[1..trivia.raw_text.len() - 1]; - let mut fixed_contents = - String::with_capacity(trivia.prefix.len() + string_contents.len() + 2); - fixed_contents.push_str(trivia.prefix); - fixed_contents.push(quote); - fixed_contents.push_str(string_contents); - fixed_contents.push(quote); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - fixed_contents, - *range, - ))); - } + let quote = quotes_settings.inline_quotes.as_char(); + let string_contents = &trivia.raw_text[1..trivia.raw_text.len() - 1]; + let mut fixed_contents = + String::with_capacity(trivia.prefix.len() + string_contents.len() + 2); + fixed_contents.push_str(trivia.prefix); + fixed_contents.push(quote); + fixed_contents.push_str(string_contents); + fixed_contents.push(quote); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + fixed_contents, + *range, + ))); diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs b/crates/ruff_linter/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs index e62ce0387f..d82c00deca 100644 --- a/crates/ruff_linter/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs +++ b/crates/ruff_linter/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs @@ -4,7 +4,6 @@ use ruff_python_ast::{self as ast, Expr}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for unnecessary parentheses on raised exceptions. @@ -74,26 +73,24 @@ pub(crate) fn unnecessary_paren_on_raise_exception(checker: &mut Checker, expr: } let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, arguments.range()); - if checker.patch(diagnostic.kind.rule()) { - // If the arguments are immediately followed by a `from`, insert whitespace to avoid - // a syntax error, as in: - // ```python - // raise IndexError()from ZeroDivisionError - // ``` - if checker - .locator() - .after(arguments.end()) - .chars() - .next() - .is_some_and(char::is_alphanumeric) - { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - " ".to_string(), - arguments.range(), - ))); - } else { - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(arguments.range()))); - } + // If the arguments are immediately followed by a `from`, insert whitespace to avoid + // a syntax error, as in: + // ```python + // raise IndexError()from ZeroDivisionError + // ``` + if checker + .locator() + .after(arguments.end()) + .chars() + .next() + .is_some_and(char::is_alphanumeric) + { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + " ".to_string(), + arguments.range(), + ))); + } else { + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(arguments.range()))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_return/rules/function.rs b/crates/ruff_linter/src/rules/flake8_return/rules/function.rs index d45093a0a2..eed24b12d6 100644 --- a/crates/ruff_linter/src/rules/flake8_return/rules/function.rs +++ b/crates/ruff_linter/src/rules/flake8_return/rules/function.rs @@ -345,12 +345,10 @@ fn unnecessary_return_none(checker: &mut Checker, stack: &Stack) { continue; } let mut diagnostic = Diagnostic::new(UnnecessaryReturnNone, stmt.range); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "return".to_string(), - stmt.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "return".to_string(), + stmt.range(), + ))); checker.diagnostics.push(diagnostic); } } @@ -362,12 +360,10 @@ fn implicit_return_value(checker: &mut Checker, stack: &Stack) { continue; } let mut diagnostic = Diagnostic::new(ImplicitReturnValue, stmt.range); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "return None".to_string(), - stmt.range, - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "return None".to_string(), + stmt.range, + ))); checker.diagnostics.push(diagnostic); } } @@ -409,17 +405,15 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) { None | Some(ast::ElifElseClause { test: Some(_), .. }) ) { let mut diagnostic = Diagnostic::new(ImplicitReturn, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - if let Some(indent) = indentation(checker.locator(), stmt) { - let mut content = String::new(); - content.push_str(checker.stylist().line_ending().as_str()); - content.push_str(indent); - content.push_str("return None"); - diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( - content, - end_of_last_statement(stmt, checker.locator()), - ))); - } + if let Some(indent) = indentation(checker.locator(), stmt) { + let mut content = String::new(); + content.push_str(checker.stylist().line_ending().as_str()); + content.push_str(indent); + content.push_str("return None"); + diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( + content, + end_of_last_statement(stmt, checker.locator()), + ))); } checker.diagnostics.push(diagnostic); } @@ -431,17 +425,15 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) { implicit_return(checker, last_stmt); } else { let mut diagnostic = Diagnostic::new(ImplicitReturn, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - if let Some(indent) = indentation(checker.locator(), stmt) { - let mut content = String::new(); - content.push_str(checker.stylist().line_ending().as_str()); - content.push_str(indent); - content.push_str("return None"); - diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( - content, - end_of_last_statement(stmt, checker.locator()), - ))); - } + if let Some(indent) = indentation(checker.locator(), stmt) { + let mut content = String::new(); + content.push_str(checker.stylist().line_ending().as_str()); + content.push_str(indent); + content.push_str("return None"); + diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( + content, + end_of_last_statement(stmt, checker.locator()), + ))); } checker.diagnostics.push(diagnostic); } @@ -467,17 +459,15 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) { ) => {} _ => { let mut diagnostic = Diagnostic::new(ImplicitReturn, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - if let Some(indent) = indentation(checker.locator(), stmt) { - let mut content = String::new(); - content.push_str(checker.stylist().line_ending().as_str()); - content.push_str(indent); - content.push_str("return None"); - diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( - content, - end_of_last_statement(stmt, checker.locator()), - ))); - } + if let Some(indent) = indentation(checker.locator(), stmt) { + let mut content = String::new(); + content.push_str(checker.stylist().line_ending().as_str()); + content.push_str(indent); + content.push_str("return None"); + diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( + content, + end_of_last_statement(stmt, checker.locator()), + ))); } checker.diagnostics.push(diagnostic); } @@ -529,47 +519,45 @@ fn unnecessary_assign(checker: &mut Checker, stack: &Stack) { }, value.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - // Delete the `return` statement. There's no need to treat this as an isolated - // edit, since we're editing the preceding statement, so no conflicting edit would - // be allowed to remove that preceding statement. - let delete_return = - edits::delete_stmt(stmt, None, checker.locator(), checker.indexer()); + diagnostic.try_set_fix(|| { + // Delete the `return` statement. There's no need to treat this as an isolated + // edit, since we're editing the preceding statement, so no conflicting edit would + // be allowed to remove that preceding statement. + let delete_return = + edits::delete_stmt(stmt, None, checker.locator(), checker.indexer()); - // Replace the `x = 1` statement with `return 1`. - let content = checker.locator().slice(assign); - let equals_index = content - .find('=') - .ok_or(anyhow::anyhow!("expected '=' in assignment statement"))?; - let after_equals = equals_index + 1; + // Replace the `x = 1` statement with `return 1`. + let content = checker.locator().slice(assign); + let equals_index = content + .find('=') + .ok_or(anyhow::anyhow!("expected '=' in assignment statement"))?; + let after_equals = equals_index + 1; - let replace_assign = Edit::range_replacement( - // If necessary, add whitespace after the `return` keyword. - // Ex) Convert `x=y` to `return y` (instead of `returny`). - if content[after_equals..] - .chars() - .next() - .is_some_and(is_python_whitespace) - { - "return".to_string() - } else { - "return ".to_string() - }, - // Replace from the start of the assignment statement to the end of the equals - // sign. - TextRange::new( - assign.start(), - assign - .range() - .start() - .add(TextSize::try_from(after_equals)?), - ), - ); + let replace_assign = Edit::range_replacement( + // If necessary, add whitespace after the `return` keyword. + // Ex) Convert `x=y` to `return y` (instead of `returny`). + if content[after_equals..] + .chars() + .next() + .is_some_and(is_python_whitespace) + { + "return".to_string() + } else { + "return ".to_string() + }, + // Replace from the start of the assignment statement to the end of the equals + // sign. + TextRange::new( + assign.start(), + assign + .range() + .start() + .add(TextSize::try_from(after_equals)?), + ), + ); - Ok(Fix::unsafe_edits(replace_assign, [delete_return])) - }); - } + Ok(Fix::unsafe_edits(replace_assign, [delete_return])) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_bool_op.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_bool_op.rs index 552d260281..7694dd021c 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_bool_op.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_bool_op.rs @@ -15,7 +15,6 @@ use ruff_python_codegen::Generator; use ruff_python_semantic::SemanticModel; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for multiple `isinstance` calls on the same target. @@ -394,78 +393,76 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if !contains_effect(target, |id| checker.semantic().is_builtin(id)) { - // Grab the types used in each duplicate `isinstance` call (e.g., `int` and `str` - // in `isinstance(obj, int) or isinstance(obj, str)`). - let types: Vec<&Expr> = indices + if !contains_effect(target, |id| checker.semantic().is_builtin(id)) { + // Grab the types used in each duplicate `isinstance` call (e.g., `int` and `str` + // in `isinstance(obj, int) or isinstance(obj, str)`). + let types: Vec<&Expr> = indices + .iter() + .map(|index| &values[*index]) + .map(|expr| { + let Expr::Call(ast::ExprCall { + arguments: Arguments { args, .. }, + .. + }) = expr + else { + unreachable!("Indices should only contain `isinstance` calls") + }; + args.get(1).expect("`isinstance` should have two arguments") + }) + .collect(); + + // Generate a single `isinstance` call. + let node = ast::ExprTuple { + // Flatten all the types used across the `isinstance` calls. + elts: types .iter() - .map(|index| &values[*index]) - .map(|expr| { - let Expr::Call(ast::ExprCall { - arguments: Arguments { args, .. }, - .. - }) = expr - else { - unreachable!("Indices should only contain `isinstance` calls") - }; - args.get(1).expect("`isinstance` should have two arguments") + .flat_map(|value| { + if let Expr::Tuple(ast::ExprTuple { elts, .. }) = value { + Left(elts.iter()) + } else { + Right(iter::once(*value)) + } }) - .collect(); + .map(Clone::clone) + .collect(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::ExprName { + id: "isinstance".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node2 = ast::ExprCall { + func: Box::new(node1.into()), + arguments: Arguments { + args: vec![target.clone(), node.into()], + keywords: vec![], + range: TextRange::default(), + }, + range: TextRange::default(), + }; + let call = node2.into(); - // Generate a single `isinstance` call. - let node = ast::ExprTuple { - // Flatten all the types used across the `isinstance` calls. - elts: types - .iter() - .flat_map(|value| { - if let Expr::Tuple(ast::ExprTuple { elts, .. }) = value { - Left(elts.iter()) - } else { - Right(iter::once(*value)) - } - }) - .map(Clone::clone) - .collect(), - ctx: ExprContext::Load, - range: TextRange::default(), - }; - let node1 = ast::ExprName { - id: "isinstance".into(), - ctx: ExprContext::Load, - range: TextRange::default(), - }; - let node2 = ast::ExprCall { - func: Box::new(node1.into()), - arguments: Arguments { - args: vec![target.clone(), node.into()], - keywords: vec![], - range: TextRange::default(), - }, - range: TextRange::default(), - }; - let call = node2.into(); + // Generate the combined `BoolOp`. + let [first, .., last] = indices.as_slice() else { + unreachable!("Indices should have at least two elements") + }; + let before = values.iter().take(*first).cloned(); + let after = values.iter().skip(last + 1).cloned(); + let node = ast::ExprBoolOp { + op: BoolOp::Or, + values: before.chain(iter::once(call)).chain(after).collect(), + range: TextRange::default(), + }; + let bool_op = node.into(); - // Generate the combined `BoolOp`. - let [first, .., last] = indices.as_slice() else { - unreachable!("Indices should have at least two elements") - }; - let before = values.iter().take(*first).cloned(); - let after = values.iter().skip(last + 1).cloned(); - let node = ast::ExprBoolOp { - op: BoolOp::Or, - values: before.chain(iter::once(call)).chain(after).collect(), - range: TextRange::default(), - }; - let bool_op = node.into(); - - // Populate the `Fix`. Replace the _entire_ `BoolOp`. Note that if we have - // multiple duplicates, the fixes will conflict. - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr(&bool_op), - expr.range(), - ))); - } + // Populate the `Fix`. Replace the _entire_ `BoolOp`. Note that if we have + // multiple duplicates, the fixes will conflict. + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&bool_op), + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } @@ -564,29 +561,27 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let unmatched: Vec = values - .iter() - .enumerate() - .filter(|(index, _)| !indices.contains(index)) - .map(|(_, elt)| elt.clone()) - .collect(); - let in_expr = if unmatched.is_empty() { - in_expr - } else { - // Wrap in a `x in (a, b) or ...` boolean operation. - let node = ast::ExprBoolOp { - op: BoolOp::Or, - values: iter::once(in_expr).chain(unmatched).collect(), - range: TextRange::default(), - }; - node.into() + let unmatched: Vec = values + .iter() + .enumerate() + .filter(|(index, _)| !indices.contains(index)) + .map(|(_, elt)| elt.clone()) + .collect(); + let in_expr = if unmatched.is_empty() { + in_expr + } else { + // Wrap in a `x in (a, b) or ...` boolean operation. + let node = ast::ExprBoolOp { + op: BoolOp::Or, + values: iter::once(in_expr).chain(unmatched).collect(), + range: TextRange::default(), }; - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr(&in_expr), - expr.range(), - ))); - } + node.into() + }; + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&in_expr), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } } @@ -638,12 +633,10 @@ pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - "False".to_string(), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + "False".to_string(), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } } @@ -697,12 +690,10 @@ pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - "True".to_string(), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + "True".to_string(), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } } @@ -850,9 +841,7 @@ pub(crate) fn expr_or_true(checker: &mut Checker, expr: &Expr) { }, edit.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(edit)); - } + diagnostic.set_fix(Fix::unsafe_edit(edit)); checker.diagnostics.push(diagnostic); } } @@ -867,9 +856,7 @@ pub(crate) fn expr_and_false(checker: &mut Checker, expr: &Expr) { }, edit.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(edit)); - } + diagnostic.set_fix(Fix::unsafe_edit(edit)); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_expr.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_expr.rs index aa0df1c907..dc3b165b21 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_expr.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_expr.rs @@ -7,7 +7,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::helpers::is_const_none; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Check for environment variables that are not capitalized. @@ -207,21 +206,19 @@ fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) { }, slice.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let node = ast::ExprConstant { - value: ast::Constant::Str(ast::StringConstant { - value: capital_env_var, - unicode: *unicode, - implicit_concatenated: false, - }), - range: TextRange::default(), - }; - let new_env_var = node.into(); - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr(&new_env_var), - slice.range(), - ))); - } + let node = ast::ExprConstant { + value: ast::Constant::Str(ast::StringConstant { + value: capital_env_var, + unicode: *unicode, + implicit_concatenated: false, + }), + range: TextRange::default(), + }; + let new_env_var = node.into(); + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&new_env_var), + slice.range(), + ))); checker.diagnostics.push(diagnostic); } @@ -275,11 +272,9 @@ pub(crate) fn dict_get_with_none_default(checker: &mut Checker, expr: &Expr) { expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - expected, - expr.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + expected, + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_ifexp.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_ifexp.rs index d0518f08be..764253fee0 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_ifexp.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_ifexp.rs @@ -7,7 +7,6 @@ use ruff_python_ast::helpers::{is_const_false, is_const_true}; use ruff_python_ast::parenthesize::parenthesized_range; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `if` expressions that can be replaced with `bool()` calls. @@ -157,48 +156,46 @@ pub(crate) fn if_expr_with_true_false( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if test.is_compare_expr() { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker - .locator() - .slice( - parenthesized_range( - test.into(), - expr.into(), - checker.indexer().comment_ranges(), - checker.locator().contents(), - ) - .unwrap_or(test.range()), + if test.is_compare_expr() { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker + .locator() + .slice( + parenthesized_range( + test.into(), + expr.into(), + checker.indexer().comment_ranges(), + checker.locator().contents(), ) - .to_string(), - expr.range(), - ))); - } else if checker.semantic().is_builtin("bool") { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr( - &ast::ExprCall { - func: Box::new( - ast::ExprName { - id: "bool".into(), - ctx: ExprContext::Load, - range: TextRange::default(), - } - .into(), - ), - arguments: Arguments { - args: vec![test.clone()], - keywords: vec![], + .unwrap_or(test.range()), + ) + .to_string(), + expr.range(), + ))); + } else if checker.semantic().is_builtin("bool") { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr( + &ast::ExprCall { + func: Box::new( + ast::ExprName { + id: "bool".into(), + ctx: ExprContext::Load, range: TextRange::default(), - }, + } + .into(), + ), + arguments: Arguments { + args: vec![test.clone()], + keywords: vec![], range: TextRange::default(), - } - .into(), - ), - expr.range(), - ))); - }; - } + }, + range: TextRange::default(), + } + .into(), + ), + expr.range(), + ))); + }; checker.diagnostics.push(diagnostic); } @@ -215,19 +212,17 @@ pub(crate) fn if_expr_with_false_true( } let mut diagnostic = Diagnostic::new(IfExprWithFalseTrue, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr( - &ast::ExprUnaryOp { - op: UnaryOp::Not, - operand: Box::new(test.clone()), - range: TextRange::default(), - } - .into(), - ), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr( + &ast::ExprUnaryOp { + op: UnaryOp::Not, + operand: Box::new(test.clone()), + range: TextRange::default(), + } + .into(), + ), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } @@ -269,20 +264,18 @@ pub(crate) fn twisted_arms_in_ifexpr( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let node = body.clone(); - let node1 = orelse.clone(); - let node2 = orelse.clone(); - let node3 = ast::ExprIfExp { - test: Box::new(node2), - body: Box::new(node1), - orelse: Box::new(node), - range: TextRange::default(), - }; - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr(&node3.into()), - expr.range(), - ))); - } + let node = body.clone(); + let node1 = orelse.clone(); + let node2 = orelse.clone(); + let node3 = ast::ExprIfExp { + test: Box::new(node2), + body: Box::new(node1), + orelse: Box::new(node), + range: TextRange::default(), + }; + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&node3.into()), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_unary_op.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_unary_op.rs index 96a46b7cd6..8cc58ebda1 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_unary_op.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_unary_op.rs @@ -6,7 +6,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_semantic::ScopeKind; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for negated `==` operators. @@ -175,18 +174,16 @@ pub(crate) fn negation_with_equal_op( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let node = ast::ExprCompare { - left: left.clone(), - ops: vec![CmpOp::NotEq], - comparators: comparators.clone(), - range: TextRange::default(), - }; - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - checker.generator().expr(&node.into()), - expr.range(), - ))); - } + let node = ast::ExprCompare { + left: left.clone(), + ops: vec![CmpOp::NotEq], + comparators: comparators.clone(), + range: TextRange::default(), + }; + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + checker.generator().expr(&node.into()), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } @@ -232,18 +229,16 @@ pub(crate) fn negation_with_not_equal_op( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let node = ast::ExprCompare { - left: left.clone(), - ops: vec![CmpOp::Eq], - comparators: comparators.clone(), - range: TextRange::default(), - }; - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - checker.generator().expr(&node.into()), - expr.range(), - ))); - } + let node = ast::ExprCompare { + left: left.clone(), + ops: vec![CmpOp::Eq], + comparators: comparators.clone(), + range: TextRange::default(), + }; + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + checker.generator().expr(&node.into()), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } @@ -270,32 +265,30 @@ pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: UnaryOp, o }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().in_boolean_test() { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - checker.locator().slice(operand.as_ref()).to_string(), - expr.range(), - ))); - } else if checker.semantic().is_builtin("bool") { - let node = ast::ExprName { - id: "bool".into(), - ctx: ExprContext::Load, - range: TextRange::default(), - }; - let node1 = ast::ExprCall { - func: Box::new(node.into()), - arguments: Arguments { - args: vec![*operand.clone()], - keywords: vec![], - range: TextRange::default(), - }, - range: TextRange::default(), - }; - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - checker.generator().expr(&node1.into()), - expr.range(), - ))); + if checker.semantic().in_boolean_test() { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + checker.locator().slice(operand.as_ref()).to_string(), + expr.range(), + ))); + } else if checker.semantic().is_builtin("bool") { + let node = ast::ExprName { + id: "bool".into(), + ctx: ExprContext::Load, + range: TextRange::default(), }; - } + let node1 = ast::ExprCall { + func: Box::new(node.into()), + arguments: Arguments { + args: vec![*operand.clone()], + keywords: vec![], + range: TextRange::default(), + }, + range: TextRange::default(), + }; + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + checker.generator().expr(&node1.into()), + expr.range(), + ))); + }; checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_with.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_with.rs index d0c5f8e711..7294ccfb87 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_with.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/ast_with.rs @@ -9,7 +9,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits::fits; -use crate::registry::AsRule; use super::fix_with; @@ -124,32 +123,30 @@ pub(crate) fn multiple_with_statements( MultipleWithStatements, TextRange::new(with_stmt.start(), colon.end()), ); - if checker.patch(diagnostic.kind.rule()) { - if !checker - .indexer() - .comment_ranges() - .intersects(TextRange::new(with_stmt.start(), with_stmt.body[0].start())) - { - match fix_with::fix_multiple_with_statements( - checker.locator(), - checker.stylist(), - with_stmt, - ) { - Ok(edit) => { - if edit.content().map_or(true, |content| { - fits( - content, - with_stmt.into(), - checker.locator(), - checker.settings.line_length, - checker.settings.tab_size, - ) - }) { - diagnostic.set_fix(Fix::unsafe_edit(edit)); - } + if !checker + .indexer() + .comment_ranges() + .intersects(TextRange::new(with_stmt.start(), with_stmt.body[0].start())) + { + match fix_with::fix_multiple_with_statements( + checker.locator(), + checker.stylist(), + with_stmt, + ) { + Ok(edit) => { + if edit.content().map_or(true, |content| { + fits( + content, + with_stmt.into(), + checker.locator(), + checker.settings.line_length, + checker.settings.tab_size, + ) + }) { + diagnostic.set_fix(Fix::unsafe_edit(edit)); } - Err(err) => error!("Failed to fix nested with: {err}"), } + Err(err) => error!("Failed to fix nested with: {err}"), } } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/collapsible_if.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/collapsible_if.rs index a6ece32b62..5433a6b98a 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/collapsible_if.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/collapsible_if.rs @@ -18,7 +18,6 @@ use crate::cst::helpers::space; use crate::cst::matchers::{match_function_def, match_if, match_indented_block, match_statement}; use crate::fix::codemods::CodegenStylist; use crate::fix::edits::fits; -use crate::registry::AsRule; /// ## What it does /// Checks for nested `if` statements that can be collapsed into a single `if` @@ -101,33 +100,31 @@ pub(crate) fn nested_if_statements( CollapsibleIf, TextRange::new(nested_if.start(), colon.end()), ); - if checker.patch(diagnostic.kind.rule()) { - // The fixer preserves comments in the nested body, but removes comments between - // the outer and inner if statements. - if !checker - .indexer() - .comment_ranges() - .intersects(TextRange::new( - nested_if.start(), - nested_if.body()[0].start(), - )) - { - match collapse_nested_if(checker.locator(), checker.stylist(), nested_if) { - Ok(edit) => { - if edit.content().map_or(true, |content| { - fits( - content, - (&nested_if).into(), - checker.locator(), - checker.settings.line_length, - checker.settings.tab_size, - ) - }) { - diagnostic.set_fix(Fix::unsafe_edit(edit)); - } + // The fixer preserves comments in the nested body, but removes comments between + // the outer and inner if statements. + if !checker + .indexer() + .comment_ranges() + .intersects(TextRange::new( + nested_if.start(), + nested_if.body()[0].start(), + )) + { + match collapse_nested_if(checker.locator(), checker.stylist(), nested_if) { + Ok(edit) => { + if edit.content().map_or(true, |content| { + fits( + content, + (&nested_if).into(), + checker.locator(), + checker.settings.line_length, + checker.settings.tab_size, + ) + }) { + diagnostic.set_fix(Fix::unsafe_edit(edit)); } - Err(err) => error!("Failed to fix nested if: {err}"), } + Err(err) => error!("Failed to fix nested if: {err}"), } } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/if_else_block_instead_of_dict_get.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/if_else_block_instead_of_dict_get.rs index 71e7a70f6e..820a02d686 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/if_else_block_instead_of_dict_get.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/if_else_block_instead_of_dict_get.rs @@ -9,7 +9,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits::fits; -use crate::registry::AsRule; /// ## What it does /// Checks for `if` statements that can be replaced with `dict.get` calls. @@ -184,13 +183,11 @@ pub(crate) fn use_dict_get_with_default(checker: &mut Checker, stmt_if: &ast::St }, stmt_if.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if !checker.indexer().has_comments(stmt_if, checker.locator()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - contents, - stmt_if.range(), - ))); - } + if !checker.indexer().has_comments(stmt_if, checker.locator()) { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + contents, + stmt_if.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/if_else_block_instead_of_if_exp.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/if_else_block_instead_of_if_exp.rs index a80f6bce95..19bcca6d7e 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/if_else_block_instead_of_if_exp.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/if_else_block_instead_of_if_exp.rs @@ -7,7 +7,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits::fits; -use crate::registry::AsRule; /// ## What it does /// Check for `if`-`else`-blocks that can be replaced with a ternary operator. @@ -143,13 +142,11 @@ pub(crate) fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt) { }, stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if !checker.indexer().has_comments(stmt, checker.locator()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - contents, - stmt.range(), - ))); - } + if !checker.indexer().has_comments(stmt, checker.locator()) { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + contents, + stmt.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/key_in_dict.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/key_in_dict.rs index f3d80a8412..32872db72b 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/key_in_dict.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/key_in_dict.rs @@ -8,7 +8,6 @@ use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer}; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for key-existence checks against `dict.keys()` calls. @@ -109,32 +108,30 @@ fn key_in_dict( }, TextRange::new(left_range.start(), right_range.end()), ); - if checker.patch(diagnostic.kind.rule()) { - // Delete from the start of the dot to the end of the expression. - if let Some(dot) = SimpleTokenizer::starts_at(value.end(), checker.locator().contents()) - .skip_trivia() - .find(|token| token.kind == SimpleTokenKind::Dot) + // Delete from the start of the dot to the end of the expression. + if let Some(dot) = SimpleTokenizer::starts_at(value.end(), checker.locator().contents()) + .skip_trivia() + .find(|token| token.kind == SimpleTokenKind::Dot) + { + // If the `.keys()` is followed by (e.g.) a keyword, we need to insert a space, + // since we're removing parentheses, which could lead to invalid syntax, as in: + // ```python + // if key in foo.keys()and bar: + // ``` + let range = TextRange::new(dot.start(), right.end()); + if checker + .locator() + .after(range.end()) + .chars() + .next() + .is_some_and(|char| char.is_ascii_alphabetic()) { - // If the `.keys()` is followed by (e.g.) a keyword, we need to insert a space, - // since we're removing parentheses, which could lead to invalid syntax, as in: - // ```python - // if key in foo.keys()and bar: - // ``` - let range = TextRange::new(dot.start(), right.end()); - if checker - .locator() - .after(range.end()) - .chars() - .next() - .is_some_and(|char| char.is_ascii_alphabetic()) - { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - " ".to_string(), - range, - ))); - } else { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_deletion(range))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + " ".to_string(), + range, + ))); + } else { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_deletion(range))); } } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/needless_bool.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/needless_bool.rs index 2de933fc8b..a8d8622cfe 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/needless_bool.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/needless_bool.rs @@ -4,7 +4,6 @@ use ruff_python_ast::{self as ast, Arguments, Constant, ElifElseClause, Expr, Ex use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `if` statements that can be replaced with `bool`. @@ -100,49 +99,47 @@ pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) { let condition = checker.generator().expr(if_test); let mut diagnostic = Diagnostic::new(NeedlessBool { condition }, range); - if checker.patch(diagnostic.kind.rule()) { - if matches!(if_return, Bool::True) - && matches!(else_return, Bool::False) - && !checker.indexer().has_comments(&range, checker.locator()) - && (if_test.is_compare_expr() || checker.semantic().is_builtin("bool")) - { - if if_test.is_compare_expr() { - // If the condition is a comparison, we can replace it with the condition. - let node = ast::StmtReturn { - value: Some(Box::new(if_test.clone())), - range: TextRange::default(), - }; - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().stmt(&node.into()), - range, - ))); - } else { - // Otherwise, we need to wrap the condition in a call to `bool`. (We've already - // verified, above, that `bool` is a builtin.) - let node = ast::ExprName { - id: "bool".into(), - ctx: ExprContext::Load, - range: TextRange::default(), - }; - let node1 = ast::ExprCall { - func: Box::new(node.into()), - arguments: Arguments { - args: vec![if_test.clone()], - keywords: vec![], - range: TextRange::default(), - }, - range: TextRange::default(), - }; - let node2 = ast::StmtReturn { - value: Some(Box::new(node1.into())), - range: TextRange::default(), - }; - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().stmt(&node2.into()), - range, - ))); + if matches!(if_return, Bool::True) + && matches!(else_return, Bool::False) + && !checker.indexer().has_comments(&range, checker.locator()) + && (if_test.is_compare_expr() || checker.semantic().is_builtin("bool")) + { + if if_test.is_compare_expr() { + // If the condition is a comparison, we can replace it with the condition. + let node = ast::StmtReturn { + value: Some(Box::new(if_test.clone())), + range: TextRange::default(), }; - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().stmt(&node.into()), + range, + ))); + } else { + // Otherwise, we need to wrap the condition in a call to `bool`. (We've already + // verified, above, that `bool` is a builtin.) + let node = ast::ExprName { + id: "bool".into(), + ctx: ExprContext::Load, + range: TextRange::default(), + }; + let node1 = ast::ExprCall { + func: Box::new(node.into()), + arguments: Arguments { + args: vec![if_test.clone()], + keywords: vec![], + range: TextRange::default(), + }, + range: TextRange::default(), + }; + let node2 = ast::StmtReturn { + value: Some(Box::new(node1.into())), + range: TextRange::default(), + }; + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().stmt(&node2.into()), + range, + ))); + }; } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/reimplemented_builtin.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/reimplemented_builtin.rs index a121235cfe..651b775ddf 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/reimplemented_builtin.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/reimplemented_builtin.rs @@ -11,7 +11,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits::fits; use crate::line_width::LineWidthBuilder; -use crate::registry::AsRule; /// ## What it does /// Checks for `for` loops that can be replaced with a builtin function, like @@ -114,7 +113,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) { }, TextRange::new(stmt.start(), terminal.stmt.end()), ); - if checker.patch(diagnostic.kind.rule()) && checker.semantic().is_builtin("any") { + if checker.semantic().is_builtin("any") { diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement( contents, stmt.start(), @@ -200,7 +199,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) { }, TextRange::new(stmt.start(), terminal.stmt.end()), ); - if checker.patch(diagnostic.kind.rule()) && checker.semantic().is_builtin("all") { + if checker.semantic().is_builtin("all") { diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement( contents, stmt.start(), diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/suppressible_exception.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/suppressible_exception.rs index 0a6d72815a..60d625f565 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/suppressible_exception.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/suppressible_exception.rs @@ -8,7 +8,6 @@ use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; /// ## What it does /// Checks for `try`-`except`-`pass` blocks that can be replaced with the @@ -132,28 +131,25 @@ pub(crate) fn suppressible_exception( }, stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if !checker.indexer().has_comments(stmt, checker.locator()) { - diagnostic.try_set_fix(|| { - // let range = statement_range(stmt, checker.locator(), checker.indexer()); + if !checker.indexer().has_comments(stmt, checker.locator()) { + diagnostic.try_set_fix(|| { + // let range = statement_range(stmt, checker.locator(), checker.indexer()); - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import("contextlib", "suppress"), - stmt.start(), - checker.semantic(), - )?; - let replace_try = Edit::range_replacement( - format!("with {binding}({exception})"), - TextRange::at(stmt.start(), "try".text_len()), - ); - let remove_handler = - Edit::range_deletion(checker.locator().full_lines_range(*range)); - Ok(Fix::unsafe_edits( - import_edit, - [replace_try, remove_handler], - )) - }); - } + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import("contextlib", "suppress"), + stmt.start(), + checker.semantic(), + )?; + let replace_try = Edit::range_replacement( + format!("with {binding}({exception})"), + TextRange::at(stmt.start(), "try".text_len()), + ); + let remove_handler = Edit::range_deletion(checker.locator().full_lines_range(*range)); + Ok(Fix::unsafe_edits( + import_edit, + [replace_try, remove_handler], + )) + }); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_simplify/rules/yoda_conditions.rs b/crates/ruff_linter/src/rules/flake8_simplify/rules/yoda_conditions.rs index 687636e4fe..f58c2f1652 100644 --- a/crates/ruff_linter/src/rules/flake8_simplify/rules/yoda_conditions.rs +++ b/crates/ruff_linter/src/rules/flake8_simplify/rules/yoda_conditions.rs @@ -14,7 +14,6 @@ use crate::cst::helpers::or_space; use crate::cst::matchers::{match_comparison, transform_expression}; use crate::fix::edits::pad; use crate::fix::snippet::SourceCodeSnippet; -use crate::registry::AsRule; /// ## What it does /// Checks for conditions that position a constant on the left-hand side of the @@ -193,12 +192,10 @@ pub(crate) fn yoda_conditions( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - pad(suggestion, expr.range(), checker.locator()), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + pad(suggestion, expr.range(), checker.locator()), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } else { checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/relative_imports.rs b/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/relative_imports.rs index 4e41ec5da7..befbd919de 100644 --- a/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/relative_imports.rs +++ b/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/relative_imports.rs @@ -8,7 +8,7 @@ use ruff_python_codegen::Generator; use ruff_python_stdlib::identifiers::is_identifier; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::flake8_tidy_imports::settings::Strictness; /// ## What it does @@ -124,13 +124,11 @@ pub(crate) fn banned_relative_import( }; if level? > strictness_level { let mut diagnostic = Diagnostic::new(RelativeImports { strictness }, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - if let Some(fix) = - fix_banned_relative_import(stmt, level, module, module_path, checker.generator()) - { - diagnostic.set_fix(fix); - }; - } + if let Some(fix) = + fix_banned_relative_import(stmt, level, module, module_path, checker.generator()) + { + diagnostic.set_fix(fix); + }; Some(diagnostic) } else { None diff --git a/crates/ruff_linter/src/rules/flake8_todos/rules/todos.rs b/crates/ruff_linter/src/rules/flake8_todos/rules/todos.rs index 15b5a2feb2..cbd5a1b2a2 100644 --- a/crates/ruff_linter/src/rules/flake8_todos/rules/todos.rs +++ b/crates/ruff_linter/src/rules/flake8_todos/rules/todos.rs @@ -7,11 +7,7 @@ use ruff_text_size::{TextLen, TextRange, TextSize}; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; -use crate::settings::LinterSettings; -use crate::{ - directives::{TodoComment, TodoDirective, TodoDirectiveKind}, - registry::Rule, -}; +use crate::directives::{TodoComment, TodoDirective, TodoDirectiveKind}; /// ## What it does /// Checks that a TODO comment is labelled with "TODO". @@ -240,7 +236,6 @@ pub(crate) fn todos( todo_comments: &[TodoComment], locator: &Locator, indexer: &Indexer, - settings: &LinterSettings, ) { for todo_comment in todo_comments { let TodoComment { @@ -256,7 +251,7 @@ pub(crate) fn todos( continue; } - directive_errors(diagnostics, directive, settings); + directive_errors(diagnostics, directive); static_errors(diagnostics, content, range, directive); let mut has_issue_link = false; @@ -300,11 +295,7 @@ pub(crate) fn todos( } /// Check that the directive itself is valid. This function modifies `diagnostics` in-place. -fn directive_errors( - diagnostics: &mut Vec, - directive: &TodoDirective, - settings: &LinterSettings, -) { +fn directive_errors(diagnostics: &mut Vec, directive: &TodoDirective) { if directive.content == "TODO" { return; } @@ -318,12 +309,10 @@ fn directive_errors( directive.range, ); - if settings.rules.should_fix(Rule::InvalidTodoCapitalization) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "TODO".to_string(), - directive.range, - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "TODO".to_string(), + directive.range, + ))); diagnostics.push(diagnostic); } else { diff --git a/crates/ruff_linter/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs b/crates/ruff_linter/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs index 1c7a9b7d7a..10ccdd1a9e 100644 --- a/crates/ruff_linter/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs +++ b/crates/ruff_linter/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs @@ -6,7 +6,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix; -use crate::registry::AsRule; /// ## What it does /// Checks for an empty type-checking block. @@ -56,14 +55,12 @@ pub(crate) fn empty_type_checking_block(checker: &mut Checker, stmt: &ast::StmtI } let mut diagnostic = Diagnostic::new(EmptyTypeCheckingBlock, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - // Delete the entire type-checking block. - let stmt = checker.semantic().current_statement(); - let parent = checker.semantic().current_statement_parent(); - let edit = fix::edits::delete_stmt(stmt, parent, checker.locator(), checker.indexer()); - diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_parent_id(), - ))); - } + // Delete the entire type-checking block. + let stmt = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); + let edit = fix::edits::delete_stmt(stmt, parent, checker.locator(), checker.indexer()); + diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs b/crates/ruff_linter/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs index 195ae60a1c..dea0f4007e 100644 --- a/crates/ruff_linter/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs +++ b/crates/ruff_linter/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs @@ -126,11 +126,7 @@ pub(crate) fn runtime_import_in_type_checking_block( // Generate a diagnostic for every import, but share a fix across all imports within the same // statement (excluding those that are ignored). for (node_id, imports) in errors_by_statement { - let fix = if checker.patch(Rule::RuntimeImportInTypeCheckingBlock) { - fix_imports(checker, node_id, &imports).ok() - } else { - None - }; + let fix = fix_imports(checker, node_id, &imports).ok(); for ImportBinding { import, diff --git a/crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs b/crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs index 269d0a7dd0..2b9c39f8cb 100644 --- a/crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs +++ b/crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs @@ -334,11 +334,7 @@ pub(crate) fn typing_only_runtime_import( // Generate a diagnostic for every import, but share a fix across all imports within the same // statement (excluding those that are ignored). for ((node_id, import_type), imports) in errors_by_statement { - let fix = if checker.patch(rule_for(import_type)) { - fix_imports(checker, node_id, &imports).ok() - } else { - None - }; + let fix = fix_imports(checker, node_id, &imports).ok(); for ImportBinding { import, diff --git a/crates/ruff_linter/src/rules/flake8_use_pathlib/rules/path_constructor_current_directory.rs b/crates/ruff_linter/src/rules/flake8_use_pathlib/rules/path_constructor_current_directory.rs index 2937ca3114..b85bba684e 100644 --- a/crates/ruff_linter/src/rules/flake8_use_pathlib/rules/path_constructor_current_directory.rs +++ b/crates/ruff_linter/src/rules/flake8_use_pathlib/rules/path_constructor_current_directory.rs @@ -4,7 +4,6 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `pathlib.Path` objects that are initialized with the current @@ -76,9 +75,7 @@ pub(crate) fn path_constructor_current_directory(checker: &mut Checker, expr: &E if matches!(value.as_str(), "" | ".") { let mut diagnostic = Diagnostic::new(PathConstructorCurrentDirectory, *range); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(*range))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(*range))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flynt/rules/static_join_to_fstring.rs b/crates/ruff_linter/src/rules/flynt/rules/static_join_to_fstring.rs index 3fb276a457..4f4c68c5e7 100644 --- a/crates/ruff_linter/src/rules/flynt/rules/static_join_to_fstring.rs +++ b/crates/ruff_linter/src/rules/flynt/rules/static_join_to_fstring.rs @@ -8,7 +8,7 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::snippet::SourceCodeSnippet; -use crate::registry::AsRule; + use crate::rules::flynt::helpers; /// ## What it does @@ -154,11 +154,9 @@ pub(crate) fn static_join_to_fstring(checker: &mut Checker, expr: &Expr, joiner: }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - pad(contents, expr.range(), checker.locator()), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + pad(contents, expr.range(), checker.locator()), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/isort/rules/add_required_imports.rs b/crates/ruff_linter/src/rules/isort/rules/add_required_imports.rs index 712f7ec9df..4b30dc869e 100644 --- a/crates/ruff_linter/src/rules/isort/rules/add_required_imports.rs +++ b/crates/ruff_linter/src/rules/isort/rules/add_required_imports.rs @@ -11,7 +11,7 @@ use ruff_source_file::Locator; use ruff_text_size::{TextRange, TextSize}; use crate::importer::Importer; -use crate::registry::Rule; + use crate::settings::LinterSettings; /// ## What it does @@ -90,7 +90,6 @@ fn add_required_import( python_ast: &Suite, locator: &Locator, stylist: &Stylist, - settings: &LinterSettings, source_type: PySourceType, ) -> Option { // Don't add imports to semantically-empty files. @@ -116,12 +115,10 @@ fn add_required_import( MissingRequiredImport(required_import.to_string()), TextRange::default(), ); - if settings.rules.should_fix(Rule::MissingRequiredImport) { - diagnostic.set_fix(Fix::safe_edit( - Importer::new(python_ast, locator, stylist) - .add_import(required_import, TextSize::default()), - )); - } + diagnostic.set_fix(Fix::safe_edit( + Importer::new(python_ast, locator, stylist) + .add_import(required_import, TextSize::default()), + )); Some(diagnostic) } @@ -171,7 +168,6 @@ pub(crate) fn add_required_imports( python_ast, locator, stylist, - settings, source_type, ) }) @@ -189,7 +185,6 @@ pub(crate) fn add_required_imports( python_ast, locator, stylist, - settings, source_type, ) }) diff --git a/crates/ruff_linter/src/rules/isort/rules/organize_imports.rs b/crates/ruff_linter/src/rules/isort/rules/organize_imports.rs index f03a1a3d4c..e571271d08 100644 --- a/crates/ruff_linter/src/rules/isort/rules/organize_imports.rs +++ b/crates/ruff_linter/src/rules/isort/rules/organize_imports.rs @@ -13,7 +13,7 @@ use ruff_source_file::{Locator, UniversalNewlines}; use ruff_text_size::{Ranged, TextRange}; use crate::line_width::LineWidthBuilder; -use crate::registry::AsRule; + use crate::settings::LinterSettings; use super::super::block::Block; @@ -138,11 +138,9 @@ pub(crate) fn organize_imports( } let mut diagnostic = Diagnostic::new(UnsortedImports, range); - if settings.rules.should_fix(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - indent(&expected, indentation).to_string(), - range, - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + indent(&expected, indentation).to_string(), + range, + ))); Some(diagnostic) } diff --git a/crates/ruff_linter/src/rules/numpy/rules/deprecated_function.rs b/crates/ruff_linter/src/rules/numpy/rules/deprecated_function.rs index 6339f90f66..7a10671654 100644 --- a/crates/ruff_linter/src/rules/numpy/rules/deprecated_function.rs +++ b/crates/ruff_linter/src/rules/numpy/rules/deprecated_function.rs @@ -5,7 +5,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of deprecated NumPy functions. @@ -76,17 +75,15 @@ pub(crate) fn deprecated_function(checker: &mut Checker, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import_from("numpy", replacement), - expr.start(), - checker.semantic(), - )?; - let replacement_edit = Edit::range_replacement(binding, expr.range()); - Ok(Fix::safe_edits(import_edit, [replacement_edit])) - }); - } + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import_from("numpy", replacement), + expr.start(), + checker.semantic(), + )?; + let replacement_edit = Edit::range_replacement(binding, expr.range()); + Ok(Fix::safe_edits(import_edit, [replacement_edit])) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/numpy/rules/deprecated_type_alias.rs b/crates/ruff_linter/src/rules/numpy/rules/deprecated_type_alias.rs index b62c39b092..265a04d2ff 100644 --- a/crates/ruff_linter/src/rules/numpy/rules/deprecated_type_alias.rs +++ b/crates/ruff_linter/src/rules/numpy/rules/deprecated_type_alias.rs @@ -4,7 +4,6 @@ use ruff_python_ast::Expr; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for deprecated NumPy type aliases. @@ -73,18 +72,16 @@ pub(crate) fn deprecated_type_alias(checker: &mut Checker, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let type_name = match type_name { - "unicode" => "str", - "long" => "int", - _ => type_name, - }; - if checker.semantic().is_builtin(type_name) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - type_name.to_string(), - expr.range(), - ))); - } + let type_name = match type_name { + "unicode" => "str", + "long" => "int", + _ => type_name, + }; + if checker.semantic().is_builtin(type_name) { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + type_name.to_string(), + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pandas_vet/rules/inplace_argument.rs b/crates/ruff_linter/src/rules/pandas_vet/rules/inplace_argument.rs index e3ff3b7f4c..f4924b0a66 100644 --- a/crates/ruff_linter/src/rules/pandas_vet/rules/inplace_argument.rs +++ b/crates/ruff_linter/src/rules/pandas_vet/rules/inplace_argument.rs @@ -9,7 +9,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix::edits::{remove_argument, Parentheses}; -use crate::registry::AsRule; /// ## What it does /// Checks for `inplace=True` usages in `pandas` function and method @@ -71,26 +70,24 @@ pub(crate) fn inplace_argument(checker: &mut Checker, call: &ast::ExprCall) { if arg == "inplace" { if is_const_true(&keyword.value) { let mut diagnostic = Diagnostic::new(PandasUseOfInplaceArgument, keyword.range()); - if checker.patch(diagnostic.kind.rule()) { - // Avoid applying the fix if: - // 1. The keyword argument is followed by a star argument (we can't be certain that - // the star argument _doesn't_ contain an override). - // 2. The call is part of a larger expression (we're converting an expression to a - // statement, and expressions can't contain statements). - let statement = checker.semantic().current_statement(); - if !seen_star - && checker.semantic().current_expression_parent().is_none() - && statement.is_expr_stmt() - { - if let Some(fix) = convert_inplace_argument_to_assignment( - call, - keyword, - statement, - checker.indexer().comment_ranges(), - checker.locator(), - ) { - diagnostic.set_fix(fix); - } + // Avoid applying the fix if: + // 1. The keyword argument is followed by a star argument (we can't be certain that + // the star argument _doesn't_ contain an override). + // 2. The call is part of a larger expression (we're converting an expression to a + // statement, and expressions can't contain statements). + let statement = checker.semantic().current_statement(); + if !seen_star + && checker.semantic().current_expression_parent().is_none() + && statement.is_expr_stmt() + { + if let Some(fix) = convert_inplace_argument_to_assignment( + call, + keyword, + statement, + checker.indexer().comment_ranges(), + checker.locator(), + ) { + diagnostic.set_fix(fix); } } diff --git a/crates/ruff_linter/src/rules/perflint/rules/incorrect_dict_iterator.rs b/crates/ruff_linter/src/rules/perflint/rules/incorrect_dict_iterator.rs index 615aa69dce..829e63e0dd 100644 --- a/crates/ruff_linter/src/rules/perflint/rules/incorrect_dict_iterator.rs +++ b/crates/ruff_linter/src/rules/perflint/rules/incorrect_dict_iterator.rs @@ -8,7 +8,6 @@ use ruff_python_ast::{Arguments, Expr}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `dict.items()` that discard either the key or the value @@ -100,18 +99,16 @@ pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, stmt_for: &ast::Stm }, func.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let replace_attribute = Edit::range_replacement("values".to_string(), attr.range()); - let replace_target = Edit::range_replacement( - pad( - checker.locator().slice(value).to_string(), - stmt_for.target.range(), - checker.locator(), - ), + let replace_attribute = Edit::range_replacement("values".to_string(), attr.range()); + let replace_target = Edit::range_replacement( + pad( + checker.locator().slice(value).to_string(), stmt_for.target.range(), - ); - diagnostic.set_fix(Fix::unsafe_edits(replace_attribute, [replace_target])); - } + checker.locator(), + ), + stmt_for.target.range(), + ); + diagnostic.set_fix(Fix::unsafe_edits(replace_attribute, [replace_target])); checker.diagnostics.push(diagnostic); } (false, true) => { @@ -122,18 +119,16 @@ pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, stmt_for: &ast::Stm }, func.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let replace_attribute = Edit::range_replacement("keys".to_string(), attr.range()); - let replace_target = Edit::range_replacement( - pad( - checker.locator().slice(key).to_string(), - stmt_for.target.range(), - checker.locator(), - ), + let replace_attribute = Edit::range_replacement("keys".to_string(), attr.range()); + let replace_target = Edit::range_replacement( + pad( + checker.locator().slice(key).to_string(), stmt_for.target.range(), - ); - diagnostic.set_fix(Fix::unsafe_edits(replace_attribute, [replace_target])); - } + checker.locator(), + ), + stmt_for.target.range(), + ); + diagnostic.set_fix(Fix::unsafe_edits(replace_attribute, [replace_target])); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/perflint/rules/unnecessary_list_cast.rs b/crates/ruff_linter/src/rules/perflint/rules/unnecessary_list_cast.rs index a259c615db..9769eed8d7 100644 --- a/crates/ruff_linter/src/rules/perflint/rules/unnecessary_list_cast.rs +++ b/crates/ruff_linter/src/rules/perflint/rules/unnecessary_list_cast.rs @@ -5,7 +5,6 @@ use ruff_python_ast::{self as ast, Arguments, Expr}; use ruff_text_size::TextRange; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for explicit casts to `list` on for-loop iterables. @@ -91,9 +90,7 @@ pub(crate) fn unnecessary_list_cast(checker: &mut Checker, iter: &Expr) { .. }) => { let mut diagnostic = Diagnostic::new(UnnecessaryListCast, *list_range); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(remove_cast(*list_range, *iterable_range)); - } + diagnostic.set_fix(remove_cast(*list_range, *iterable_range)); checker.diagnostics.push(diagnostic); } Expr::Name(ast::ExprName { @@ -119,9 +116,7 @@ pub(crate) fn unnecessary_list_cast(checker: &mut Checker, iter: &Expr) { ) { let mut diagnostic = Diagnostic::new(UnnecessaryListCast, *list_range); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(remove_cast(*list_range, *iterable_range)); - } + diagnostic.set_fix(remove_cast(*list_range, *iterable_range)); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/compound_statements.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/compound_statements.rs index 6b56c31cb2..a8c8dd3d28 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/compound_statements.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/compound_statements.rs @@ -8,9 +8,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_index::Indexer; use ruff_source_file::Locator; -use crate::registry::Rule; -use crate::settings::LinterSettings; - /// ## What it does /// Checks for compound statements (multiple statements on the same line). /// @@ -104,7 +101,6 @@ pub(crate) fn compound_statements( lxr: &[LexResult], locator: &Locator, indexer: &Indexer, - settings: &LinterSettings, ) { // Track the last seen instance of a variety of tokens. let mut colon = None; @@ -169,14 +165,12 @@ pub(crate) fn compound_statements( if let Some((start, end)) = semi { let mut diagnostic = Diagnostic::new(UselessSemicolon, TextRange::new(start, end)); - if settings.rules.should_fix(Rule::UselessSemicolon) { - diagnostic.set_fix(Fix::safe_edit(Edit::deletion( - indexer - .preceded_by_continuations(start, locator) - .unwrap_or(start), - end, - ))); - }; + diagnostic.set_fix(Fix::safe_edit(Edit::deletion( + indexer + .preceded_by_continuations(start, locator) + .unwrap_or(start), + end, + ))); diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/invalid_escape_sequence.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/invalid_escape_sequence.rs index 5621b3038e..4a333bdcd5 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/invalid_escape_sequence.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/invalid_escape_sequence.rs @@ -49,7 +49,6 @@ pub(crate) fn invalid_escape_sequence( indexer: &Indexer, token: &Tok, token_range: TextRange, - fix: bool, ) { let token_source_code = match token { Tok::FStringMiddle { value, is_raw } => { @@ -158,37 +157,35 @@ pub(crate) fn invalid_escape_sequence( invalid_escape_sequence.push(Diagnostic::new(InvalidEscapeSequence(next_char), range)); } - if fix { - if contains_valid_escape_sequence { - // Escape with backslash. - for diagnostic in &mut invalid_escape_sequence { - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - r"\".to_string(), - diagnostic.start() + TextSize::from(1), - ))); - } + if contains_valid_escape_sequence { + // Escape with backslash. + for diagnostic in &mut invalid_escape_sequence { + diagnostic.set_fix(Fix::safe_edit(Edit::insertion( + r"\".to_string(), + diagnostic.start() + TextSize::from(1), + ))); + } + } else { + let tok_start = if token.is_f_string_middle() { + // SAFETY: If this is a `FStringMiddle` token, then the indexer + // must have the f-string range. + indexer + .fstring_ranges() + .innermost(token_range.start()) + .unwrap() + .start() } else { - let tok_start = if token.is_f_string_middle() { - // SAFETY: If this is a `FStringMiddle` token, then the indexer - // must have the f-string range. - indexer - .fstring_ranges() - .innermost(token_range.start()) - .unwrap() - .start() - } else { - token_range.start() - }; - // Turn into raw string. - for diagnostic in &mut invalid_escape_sequence { - // If necessary, add a space between any leading keyword (`return`, `yield`, - // `assert`, etc.) and the string. For example, `return"foo"` is valid, but - // `returnr"foo"` is not. - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - pad_start("r".to_string(), tok_start, locator), - tok_start, - ))); - } + token_range.start() + }; + // Turn into raw string. + for diagnostic in &mut invalid_escape_sequence { + // If necessary, add a space between any leading keyword (`return`, `yield`, + // `assert`, etc.) and the string. For example, `return"foo"` is valid, but + // `returnr"foo"` is not. + diagnostic.set_fix(Fix::safe_edit(Edit::insertion( + pad_start("r".to_string(), tok_start, locator), + tok_start, + ))); } } diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/lambda_assignment.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/lambda_assignment.rs index b8f17540dd..03f8ea988f 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/lambda_assignment.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/lambda_assignment.rs @@ -11,7 +11,6 @@ use ruff_python_trivia::{has_leading_content, has_trailing_content, leading_inde use ruff_source_file::UniversalNewlines; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for lambda expressions which are assigned to a variable. @@ -81,61 +80,59 @@ pub(crate) fn lambda_assignment( stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if !has_leading_content(stmt.start(), checker.locator()) - && !has_trailing_content(stmt.end(), checker.locator()) + if !has_leading_content(stmt.start(), checker.locator()) + && !has_trailing_content(stmt.end(), checker.locator()) + { + let first_line = checker.locator().line(stmt.start()); + let indentation = leading_indentation(first_line); + let mut indented = String::new(); + for (idx, line) in function( + id, + parameters.as_deref(), + body, + annotation, + checker.semantic(), + checker.generator(), + ) + .universal_newlines() + .enumerate() { - let first_line = checker.locator().line(stmt.start()); - let indentation = leading_indentation(first_line); - let mut indented = String::new(); - for (idx, line) in function( - id, - parameters.as_deref(), - body, - annotation, - checker.semantic(), - checker.generator(), - ) - .universal_newlines() - .enumerate() - { - if idx == 0 { - indented.push_str(&line); - } else { - indented.push_str(checker.stylist().line_ending().as_str()); - indented.push_str(indentation); - indented.push_str(&line); - } - } - - // If the assignment is in a class body, it might not be safe to replace it because the - // assignment might be carrying a type annotation that will be used by some package like - // dataclasses, which wouldn't consider the rewritten function definition to be - // equivalent. Even if it _doesn't_ have an annotation, rewriting safely would require - // making this a static method. - // See: https://github.com/astral-sh/ruff/issues/3046 - // - // Similarly, if the lambda is shadowing a variable in the current scope, - // rewriting it as a function declaration may break type-checking. - // See: https://github.com/astral-sh/ruff/issues/5421 - if checker.semantic().current_scope().kind.is_class() - || checker - .semantic() - .current_scope() - .get_all(id) - .any(|binding_id| checker.semantic().binding(binding_id).kind.is_annotation()) - { - diagnostic.set_fix(Fix::display_edit(Edit::range_replacement( - indented, - stmt.range(), - ))); + if idx == 0 { + indented.push_str(&line); } else { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - indented, - stmt.range(), - ))); + indented.push_str(checker.stylist().line_ending().as_str()); + indented.push_str(indentation); + indented.push_str(&line); } } + + // If the assignment is in a class body, it might not be safe to replace it because the + // assignment might be carrying a type annotation that will be used by some package like + // dataclasses, which wouldn't consider the rewritten function definition to be + // equivalent. Even if it _doesn't_ have an annotation, rewriting safely would require + // making this a static method. + // See: https://github.com/astral-sh/ruff/issues/3046 + // + // Similarly, if the lambda is shadowing a variable in the current scope, + // rewriting it as a function declaration may break type-checking. + // See: https://github.com/astral-sh/ruff/issues/5421 + if checker.semantic().current_scope().kind.is_class() + || checker + .semantic() + .current_scope() + .get_all(id) + .any(|binding_id| checker.semantic().binding(binding_id).kind.is_annotation()) + { + diagnostic.set_fix(Fix::display_edit(Edit::range_replacement( + indented, + stmt.range(), + ))); + } else { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + indented, + stmt.range(), + ))); + } } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/literal_comparisons.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/literal_comparisons.rs index eb63de1f01..cb8806d919 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/literal_comparisons.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/literal_comparisons.rs @@ -9,7 +9,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::codes::Rule; -use crate::registry::AsRule; #[derive(Debug, PartialEq, Eq, Copy, Clone)] enum EqCmpOp { @@ -153,16 +152,12 @@ pub(crate) fn literal_comparisons(checker: &mut Checker, compare: &ast::ExprComp match op { EqCmpOp::Eq => { let diagnostic = Diagnostic::new(NoneComparison(op), comparator.range()); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(0, CmpOp::Is); - } + bad_ops.insert(0, CmpOp::Is); diagnostics.push(diagnostic); } EqCmpOp::NotEq => { let diagnostic = Diagnostic::new(NoneComparison(op), comparator.range()); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(0, CmpOp::IsNot); - } + bad_ops.insert(0, CmpOp::IsNot); diagnostics.push(diagnostic); } } @@ -180,9 +175,7 @@ pub(crate) fn literal_comparisons(checker: &mut Checker, compare: &ast::ExprComp TrueFalseComparison(*value, op), comparator.range(), ); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(0, CmpOp::Is); - } + bad_ops.insert(0, CmpOp::Is); diagnostics.push(diagnostic); } EqCmpOp::NotEq => { @@ -190,9 +183,7 @@ pub(crate) fn literal_comparisons(checker: &mut Checker, compare: &ast::ExprComp TrueFalseComparison(*value, op), comparator.range(), ); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(0, CmpOp::IsNot); - } + bad_ops.insert(0, CmpOp::IsNot); diagnostics.push(diagnostic); } } @@ -221,16 +212,12 @@ pub(crate) fn literal_comparisons(checker: &mut Checker, compare: &ast::ExprComp match op { EqCmpOp::Eq => { let diagnostic = Diagnostic::new(NoneComparison(op), next.range()); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(index, CmpOp::Is); - } + bad_ops.insert(index, CmpOp::Is); diagnostics.push(diagnostic); } EqCmpOp::NotEq => { let diagnostic = Diagnostic::new(NoneComparison(op), next.range()); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(index, CmpOp::IsNot); - } + bad_ops.insert(index, CmpOp::IsNot); diagnostics.push(diagnostic); } } @@ -246,17 +233,13 @@ pub(crate) fn literal_comparisons(checker: &mut Checker, compare: &ast::ExprComp EqCmpOp::Eq => { let diagnostic = Diagnostic::new(TrueFalseComparison(*value, op), next.range()); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(index, CmpOp::Is); - } + bad_ops.insert(index, CmpOp::Is); diagnostics.push(diagnostic); } EqCmpOp::NotEq => { let diagnostic = Diagnostic::new(TrueFalseComparison(*value, op), next.range()); - if checker.patch(diagnostic.kind.rule()) { - bad_ops.insert(index, CmpOp::IsNot); - } + bad_ops.insert(index, CmpOp::IsNot); diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/extraneous_whitespace.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/extraneous_whitespace.rs index 00f58a807a..c1be325c76 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/extraneous_whitespace.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/extraneous_whitespace.rs @@ -126,13 +126,7 @@ impl AlwaysFixableViolation for WhitespaceBeforePunctuation { } /// E201, E202, E203 -pub(crate) fn extraneous_whitespace( - line: &LogicalLine, - context: &mut LogicalLinesContext, - fix_after_open_bracket: bool, - fix_before_close_bracket: bool, - fix_before_punctuation: bool, -) { +pub(crate) fn extraneous_whitespace(line: &LogicalLine, context: &mut LogicalLinesContext) { let mut prev_token = None; let mut fstrings = 0u32; @@ -161,10 +155,8 @@ pub(crate) fn extraneous_whitespace( WhitespaceAfterOpenBracket { symbol }, TextRange::at(token.end(), trailing_len), ); - if fix_after_open_bracket { - diagnostic - .set_fix(Fix::safe_edit(Edit::range_deletion(diagnostic.range()))); - } + diagnostic + .set_fix(Fix::safe_edit(Edit::range_deletion(diagnostic.range()))); context.push_diagnostic(diagnostic); } } @@ -177,11 +169,8 @@ pub(crate) fn extraneous_whitespace( WhitespaceBeforeCloseBracket { symbol }, TextRange::at(token.start() - offset, offset), ); - if fix_before_close_bracket { - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion( - diagnostic.range(), - ))); - } + diagnostic + .set_fix(Fix::safe_edit(Edit::range_deletion(diagnostic.range()))); context.push_diagnostic(diagnostic); } } @@ -195,11 +184,8 @@ pub(crate) fn extraneous_whitespace( WhitespaceBeforePunctuation { symbol }, TextRange::at(token.start() - offset, offset), ); - if fix_before_punctuation { - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion( - diagnostic.range(), - ))); - } + diagnostic + .set_fix(Fix::safe_edit(Edit::range_deletion(diagnostic.range()))); context.push_diagnostic(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace.rs index e0b1609bd7..6e58faf9c1 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace.rs @@ -53,7 +53,7 @@ impl AlwaysFixableViolation for MissingWhitespace { } /// E231 -pub(crate) fn missing_whitespace(line: &LogicalLine, fix: bool, context: &mut LogicalLinesContext) { +pub(crate) fn missing_whitespace(line: &LogicalLine, context: &mut LogicalLinesContext) { let mut open_parentheses = 0u32; let mut fstrings = 0u32; let mut prev_lsqb = TextSize::default(); @@ -112,15 +112,12 @@ pub(crate) fn missing_whitespace(line: &LogicalLine, fix: bool, context: &mut Lo } } - let kind = MissingWhitespace { token: kind }; - let mut diagnostic = Diagnostic::new(kind, token.range()); - - if fix { - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - " ".to_string(), - token.end(), - ))); - } + let mut diagnostic = + Diagnostic::new(MissingWhitespace { token: kind }, token.range()); + diagnostic.set_fix(Fix::safe_edit(Edit::insertion( + " ".to_string(), + token.end(), + ))); context.push_diagnostic(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/whitespace_before_parameters.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/whitespace_before_parameters.rs index 35e80b1453..0f0dc8763e 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/whitespace_before_parameters.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/whitespace_before_parameters.rs @@ -54,11 +54,7 @@ impl AlwaysFixableViolation for WhitespaceBeforeParameters { } /// E211 -pub(crate) fn whitespace_before_parameters( - line: &LogicalLine, - fix: bool, - context: &mut LogicalLinesContext, -) { +pub(crate) fn whitespace_before_parameters(line: &LogicalLine, context: &mut LogicalLinesContext) { let previous = line.tokens().first().unwrap(); let mut pre_pre_kind: Option = None; @@ -81,10 +77,7 @@ pub(crate) fn whitespace_before_parameters( let kind: WhitespaceBeforeParameters = WhitespaceBeforeParameters { bracket: kind }; let mut diagnostic = Diagnostic::new(kind, TextRange::new(start, end)); - - if fix { - diagnostic.set_fix(Fix::safe_edit(Edit::deletion(start, end))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::deletion(start, end))); context.push_diagnostic(diagnostic); } pre_pre_kind = Some(prev_token); diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/missing_newline_at_end_of_file.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/missing_newline_at_end_of_file.rs index f26eb5e25b..22f9f64ea6 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/missing_newline_at_end_of_file.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/missing_newline_at_end_of_file.rs @@ -39,7 +39,6 @@ impl AlwaysFixableViolation for MissingNewlineAtEndOfFile { pub(crate) fn no_newline_at_end_of_file( locator: &Locator, stylist: &Stylist, - fix: bool, ) -> Option { let source = locator.contents(); @@ -55,12 +54,10 @@ pub(crate) fn no_newline_at_end_of_file( let range = TextRange::empty(locator.contents().text_len()); let mut diagnostic = Diagnostic::new(MissingNewlineAtEndOfFile, range); - if fix { - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - stylist.line_ending().to_string(), - range.start(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::insertion( + stylist.line_ending().to_string(), + range.start(), + ))); return Some(diagnostic); } None diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/not_tests.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/not_tests.rs index 8908050990..c870d2db25 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/not_tests.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/not_tests.rs @@ -6,7 +6,7 @@ use ruff_python_ast::{self as ast, CmpOp, Expr}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; /// ## What it does /// Checks for negative comparison using `not {foo} in {bar}`. @@ -94,46 +94,42 @@ pub(crate) fn not_tests(checker: &mut Checker, unary_op: &ast::ExprUnaryOp) { [CmpOp::In] => { if checker.enabled(Rule::NotInTest) { let mut diagnostic = Diagnostic::new(NotInTest, unary_op.operand.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - pad( - generate_comparison( - left, - &[CmpOp::NotIn], - comparators, - unary_op.into(), - checker.indexer().comment_ranges(), - checker.locator(), - ), - unary_op.range(), + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + pad( + generate_comparison( + left, + &[CmpOp::NotIn], + comparators, + unary_op.into(), + checker.indexer().comment_ranges(), checker.locator(), ), unary_op.range(), - ))); - } + checker.locator(), + ), + unary_op.range(), + ))); checker.diagnostics.push(diagnostic); } } [CmpOp::Is] => { if checker.enabled(Rule::NotIsTest) { let mut diagnostic = Diagnostic::new(NotIsTest, unary_op.operand.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - pad( - generate_comparison( - left, - &[CmpOp::IsNot], - comparators, - unary_op.into(), - checker.indexer().comment_ranges(), - checker.locator(), - ), - unary_op.range(), + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + pad( + generate_comparison( + left, + &[CmpOp::IsNot], + comparators, + unary_op.into(), + checker.indexer().comment_ranges(), checker.locator(), ), unary_op.range(), - ))); - } + checker.locator(), + ), + unary_op.range(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/trailing_whitespace.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/trailing_whitespace.rs index b8416e0644..7df8ee2eb5 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/trailing_whitespace.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/trailing_whitespace.rs @@ -90,23 +90,19 @@ pub(crate) fn trailing_whitespace( if range == line.range() { if settings.rules.enabled(Rule::BlankLineWithWhitespace) { let mut diagnostic = Diagnostic::new(BlankLineWithWhitespace, range); - if settings.rules.should_fix(Rule::BlankLineWithWhitespace) { - // Remove any preceding continuations, to avoid introducing a potential - // syntax error. - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(TextRange::new( - indexer - .preceded_by_continuations(line.start(), locator) - .unwrap_or(range.start()), - range.end(), - )))); - } + // Remove any preceding continuations, to avoid introducing a potential + // syntax error. + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(TextRange::new( + indexer + .preceded_by_continuations(line.start(), locator) + .unwrap_or(range.start()), + range.end(), + )))); return Some(diagnostic); } } else if settings.rules.enabled(Rule::TrailingWhitespace) { let mut diagnostic = Diagnostic::new(TrailingWhitespace, range); - if settings.rules.should_fix(Rule::TrailingWhitespace) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(range))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(range))); return Some(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/blank_after_summary.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/blank_after_summary.rs index c84e2de735..bbd9ee0ab6 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/blank_after_summary.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/blank_after_summary.rs @@ -5,7 +5,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; -use crate::registry::AsRule; /// ## What it does /// Checks for docstring summary lines that are not separated from the docstring @@ -91,35 +90,33 @@ pub(crate) fn blank_after_summary(checker: &mut Checker, docstring: &Docstring) }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if blanks_count > 1 { - let mut lines = UniversalNewlineIterator::with_offset(&body, body.start()); - let mut summary_end = body.start(); + if blanks_count > 1 { + let mut lines = UniversalNewlineIterator::with_offset(&body, body.start()); + let mut summary_end = body.start(); - // Find the "summary" line (defined as the first non-blank line). - for line in lines.by_ref() { - if !line.trim().is_empty() { - summary_end = line.full_end(); - break; - } + // Find the "summary" line (defined as the first non-blank line). + for line in lines.by_ref() { + if !line.trim().is_empty() { + summary_end = line.full_end(); + break; } - - // Find the last blank line - let mut blank_end = summary_end; - for line in lines { - if !line.trim().is_empty() { - blank_end = line.start(); - break; - } - } - - // Insert one blank line after the summary (replacing any existing lines). - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - checker.stylist().line_ending().to_string(), - summary_end, - blank_end, - ))); } + + // Find the last blank line + let mut blank_end = summary_end; + for line in lines { + if !line.trim().is_empty() { + blank_end = line.start(); + break; + } + } + + // Insert one blank line after the summary (replacing any existing lines). + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + checker.stylist().line_ending().to_string(), + summary_end, + blank_end, + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/blank_before_after_class.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/blank_before_after_class.rs index dbfd39fd4c..bd0a1a5c07 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/blank_before_after_class.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/blank_before_after_class.rs @@ -7,7 +7,7 @@ use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; /// ## What it does /// Checks for docstrings on class definitions that are not preceded by a @@ -189,27 +189,23 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr if checker.enabled(Rule::BlankLineBeforeClass) { if blank_lines_before != 0 { let mut diagnostic = Diagnostic::new(BlankLineBeforeClass, docstring.range()); - if checker.patch(diagnostic.kind.rule()) { - // Delete the blank line before the class. - diagnostic.set_fix(Fix::safe_edit(Edit::deletion( - blank_lines_start, - docstring.start() - docstring.indentation.text_len(), - ))); - } + // Delete the blank line before the class. + diagnostic.set_fix(Fix::safe_edit(Edit::deletion( + blank_lines_start, + docstring.start() - docstring.indentation.text_len(), + ))); checker.diagnostics.push(diagnostic); } } if checker.enabled(Rule::OneBlankLineBeforeClass) { if blank_lines_before != 1 { let mut diagnostic = Diagnostic::new(OneBlankLineBeforeClass, docstring.range()); - if checker.patch(diagnostic.kind.rule()) { - // Insert one blank line before the class. - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - checker.stylist().line_ending().to_string(), - blank_lines_start, - docstring.start() - docstring.indentation.text_len(), - ))); - } + // Insert one blank line before the class. + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + checker.stylist().line_ending().to_string(), + blank_lines_start, + docstring.start() - docstring.indentation.text_len(), + ))); checker.diagnostics.push(diagnostic); } } @@ -243,21 +239,19 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr let indentation = indentation_at_offset(docstring.start(), checker.locator()) .expect("Own line docstring must have indentation"); let mut diagnostic = Diagnostic::new(OneBlankLineAfterClass, docstring.range()); - if checker.patch(diagnostic.kind.rule()) { - let line_ending = checker.stylist().line_ending().as_str(); - // We have to trim the whitespace twice, once before the semicolon above and - // once after the semicolon here, or we get invalid indents: - // ```rust - // class Priority: - // """Has priorities""" ; priorities=1 - // ``` - let next_statement = next_statement.trim_whitespace_start(); - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - line_ending.to_string() + line_ending + indentation + next_statement, - replacement_start, - first_line.end(), - ))); - } + let line_ending = checker.stylist().line_ending().as_str(); + // We have to trim the whitespace twice, once before the semicolon above and + // once after the semicolon here, or we get invalid indents: + // ```rust + // class Priority: + // """Has priorities""" ; priorities=1 + // ``` + let next_statement = next_statement.trim_whitespace_start(); + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + line_ending.to_string() + line_ending + indentation + next_statement, + replacement_start, + first_line.end(), + ))); checker.diagnostics.push(diagnostic); return; } else if trailing.starts_with('#') { @@ -280,14 +274,12 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr if blank_lines_after != 1 { let mut diagnostic = Diagnostic::new(OneBlankLineAfterClass, docstring.range()); - if checker.patch(diagnostic.kind.rule()) { - // Insert a blank line before the class (replacing any existing lines). - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - checker.stylist().line_ending().to_string(), - replacement_start, - blank_lines_end, - ))); - } + // Insert a blank line before the class (replacing any existing lines). + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + checker.stylist().line_ending().to_string(), + replacement_start, + blank_lines_end, + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/blank_before_after_function.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/blank_before_after_function.rs index 62151bac7c..25e335e80e 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/blank_before_after_function.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/blank_before_after_function.rs @@ -10,7 +10,7 @@ use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; /// ## What it does /// Checks for docstrings on functions that are separated by one or more blank @@ -132,13 +132,11 @@ pub(crate) fn blank_before_after_function(checker: &mut Checker, docstring: &Doc }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Delete the blank line before the docstring. - diagnostic.set_fix(Fix::safe_edit(Edit::deletion( - blank_lines_start, - docstring.start() - docstring.indentation.text_len(), - ))); - } + // Delete the blank line before the docstring. + diagnostic.set_fix(Fix::safe_edit(Edit::deletion( + blank_lines_start, + docstring.start() - docstring.indentation.text_len(), + ))); checker.diagnostics.push(diagnostic); } } @@ -188,13 +186,11 @@ pub(crate) fn blank_before_after_function(checker: &mut Checker, docstring: &Doc }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Delete the blank line after the docstring. - diagnostic.set_fix(Fix::safe_edit(Edit::deletion( - first_line_end, - blank_lines_end, - ))); - } + // Delete the blank line after the docstring. + diagnostic.set_fix(Fix::safe_edit(Edit::deletion( + first_line_end, + blank_lines_end, + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/capitalized.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/capitalized.rs index 307225917d..e8de2983ab 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/capitalized.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/capitalized.rs @@ -5,7 +5,6 @@ use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; -use crate::registry::AsRule; /// ## What it does /// Checks for docstrings that do not start with a capital letter. @@ -90,12 +89,10 @@ pub(crate) fn capitalized(checker: &mut Checker, docstring: &Docstring) { docstring.expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - capitalized_word, - TextRange::at(body.start(), first_word.text_len()), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + capitalized_word, + TextRange::at(body.start(), first_word.text_len()), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/ends_with_period.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/ends_with_period.rs index cfefdc6353..360a7fccaa 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/ends_with_period.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/ends_with_period.rs @@ -9,7 +9,7 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::sections::SectionKind; use crate::docstrings::Docstring; -use crate::registry::AsRule; + use crate::rules::pydocstyle::helpers::logical_line; /// ## What it does @@ -104,7 +104,7 @@ pub(crate) fn ends_with_period(checker: &mut Checker, docstring: &Docstring) { if !trimmed.ends_with('.') { let mut diagnostic = Diagnostic::new(EndsInPeriod, docstring.range()); // Best-effort fix: avoid adding a period after other punctuation marks. - if checker.patch(diagnostic.kind.rule()) && !trimmed.ends_with([':', ';']) { + if !trimmed.ends_with([':', ';']) { diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( ".".to_string(), line.start() + trimmed.text_len(), diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/ends_with_punctuation.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/ends_with_punctuation.rs index 1b26b8076c..df03f44cc0 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/ends_with_punctuation.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/ends_with_punctuation.rs @@ -9,7 +9,7 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::sections::SectionKind; use crate::docstrings::Docstring; -use crate::registry::AsRule; + use crate::rules::pydocstyle::helpers::logical_line; /// ## What it does @@ -103,7 +103,7 @@ pub(crate) fn ends_with_punctuation(checker: &mut Checker, docstring: &Docstring if !trimmed.ends_with(['.', '!', '?']) { let mut diagnostic = Diagnostic::new(EndsInPunctuation, docstring.range()); // Best-effort fix: avoid adding a period after other punctuation marks. - if checker.patch(diagnostic.kind.rule()) && !trimmed.ends_with([':', ';']) { + if !trimmed.ends_with([':', ';']) { diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion( ".".to_string(), line.start() + trimmed.text_len(), diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/indent.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/indent.rs index 95184df0b6..4ec116cb06 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/indent.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/indent.rs @@ -8,7 +8,7 @@ use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; /// ## What it does /// Checks for docstrings that are indented with tabs. @@ -188,12 +188,10 @@ pub(crate) fn indent(checker: &mut Checker, docstring: &Docstring) { { let mut diagnostic = Diagnostic::new(UnderIndentation, TextRange::empty(line.start())); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - clean_space(docstring.indentation), - TextRange::at(line.start(), line_indent.text_len()), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + clean_space(docstring.indentation), + TextRange::at(line.start(), line_indent.text_len()), + ))); checker.diagnostics.push(diagnostic); } } @@ -229,15 +227,13 @@ pub(crate) fn indent(checker: &mut Checker, docstring: &Docstring) { // enables fix. let mut diagnostic = Diagnostic::new(OverIndentation, TextRange::empty(over_indented.start())); - if checker.patch(diagnostic.kind.rule()) { - let indent = clean_space(docstring.indentation); - let edit = if indent.is_empty() { - Edit::range_deletion(over_indented) - } else { - Edit::range_replacement(indent, over_indented) - }; - diagnostic.set_fix(Fix::safe_edit(edit)); - } + let indent = clean_space(docstring.indentation); + let edit = if indent.is_empty() { + Edit::range_deletion(over_indented) + } else { + Edit::range_replacement(indent, over_indented) + }; + diagnostic.set_fix(Fix::safe_edit(edit)); checker.diagnostics.push(diagnostic); } } @@ -248,16 +244,14 @@ pub(crate) fn indent(checker: &mut Checker, docstring: &Docstring) { if line_indent.len() > docstring.indentation.len() { let mut diagnostic = Diagnostic::new(OverIndentation, TextRange::empty(last.start())); - if checker.patch(diagnostic.kind.rule()) { - let indent = clean_space(docstring.indentation); - let range = TextRange::at(last.start(), line_indent.text_len()); - let edit = if indent.is_empty() { - Edit::range_deletion(range) - } else { - Edit::range_replacement(indent, range) - }; - diagnostic.set_fix(Fix::safe_edit(edit)); - } + let indent = clean_space(docstring.indentation); + let range = TextRange::at(last.start(), line_indent.text_len()); + let edit = if indent.is_empty() { + Edit::range_deletion(range) + } else { + Edit::range_replacement(indent, range) + }; + diagnostic.set_fix(Fix::safe_edit(edit)); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/multi_line_summary_start.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/multi_line_summary_start.rs index 3ef4cd582d..59b618afe7 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/multi_line_summary_start.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/multi_line_summary_start.rs @@ -7,7 +7,7 @@ use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; /// ## What it does /// Checks for docstring summary lines that are not positioned on the first @@ -137,16 +137,14 @@ pub(crate) fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstr if is_triple_quote(&first_line) { if checker.enabled(Rule::MultiLineSummaryFirstLine) { let mut diagnostic = Diagnostic::new(MultiLineSummaryFirstLine, docstring.range()); - if checker.patch(diagnostic.kind.rule()) { - // Delete until first non-whitespace char. - for line in content_lines { - if let Some(end_column) = line.find(|c: char| !c.is_whitespace()) { - diagnostic.set_fix(Fix::safe_edit(Edit::deletion( - first_line.end(), - line.start() + TextSize::try_from(end_column).unwrap(), - ))); - break; - } + // Delete until first non-whitespace char. + for line in content_lines { + if let Some(end_column) = line.find(|c: char| !c.is_whitespace()) { + diagnostic.set_fix(Fix::safe_edit(Edit::deletion( + first_line.end(), + line.start() + TextSize::try_from(end_column).unwrap(), + ))); + break; } } checker.diagnostics.push(diagnostic); @@ -163,46 +161,44 @@ pub(crate) fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstr } else { if checker.enabled(Rule::MultiLineSummarySecondLine) { let mut diagnostic = Diagnostic::new(MultiLineSummarySecondLine, docstring.range()); - if checker.patch(diagnostic.kind.rule()) { - let mut indentation = String::from(docstring.indentation); - let mut fixable = true; - if !indentation.chars().all(char::is_whitespace) { - fixable = false; + let mut indentation = String::from(docstring.indentation); + let mut fixable = true; + if !indentation.chars().all(char::is_whitespace) { + fixable = false; - // If the docstring isn't on its own line, look at the statement indentation, - // and add the default indentation to get the "right" level. - if let Definition::Member(member) = &docstring.definition { - let stmt_line_start = checker.locator().line_start(member.start()); - let stmt_indentation = checker - .locator() - .slice(TextRange::new(stmt_line_start, member.start())); + // If the docstring isn't on its own line, look at the statement indentation, + // and add the default indentation to get the "right" level. + if let Definition::Member(member) = &docstring.definition { + let stmt_line_start = checker.locator().line_start(member.start()); + let stmt_indentation = checker + .locator() + .slice(TextRange::new(stmt_line_start, member.start())); - if stmt_indentation.chars().all(char::is_whitespace) { - indentation.clear(); - indentation.push_str(stmt_indentation); - indentation.push_str(checker.stylist().indentation()); - fixable = true; - } - }; - } + if stmt_indentation.chars().all(char::is_whitespace) { + indentation.clear(); + indentation.push_str(stmt_indentation); + indentation.push_str(checker.stylist().indentation()); + fixable = true; + } + }; + } - if fixable { - let prefix = leading_quote(contents).unwrap(); - // Use replacement instead of insert to trim possible whitespace between leading - // quote and text. - let repl = format!( - "{}{}{}", - checker.stylist().line_ending().as_str(), - indentation, - first_line.strip_prefix(prefix).unwrap().trim_start() - ); + if fixable { + let prefix = leading_quote(contents).unwrap(); + // Use replacement instead of insert to trim possible whitespace between leading + // quote and text. + let repl = format!( + "{}{}{}", + checker.stylist().line_ending().as_str(), + indentation, + first_line.strip_prefix(prefix).unwrap().trim_start() + ); - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - repl, - body.start(), - first_line.end(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + repl, + body.start(), + first_line.end(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs index 0b6155d05c..b318127db9 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs @@ -8,7 +8,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; -use crate::registry::AsRule; /// ## What it does /// Checks for multi-line docstrings whose closing quotes are not on their @@ -81,27 +80,25 @@ pub(crate) fn newline_after_last_paragraph(checker: &mut Checker, docstring: &Do if last_line != "\"\"\"" && last_line != "'''" { let mut diagnostic = Diagnostic::new(NewLineAfterLastParagraph, docstring.range()); - if checker.patch(diagnostic.kind.rule()) { - // Insert a newline just before the end-quote(s). - let num_trailing_quotes = "'''".text_len(); - let num_trailing_spaces: TextSize = last_line - .chars() - .rev() - .skip(usize::from(num_trailing_quotes)) - .take_while(|c| c.is_whitespace()) - .map(TextLen::text_len) - .sum(); - let content = format!( - "{}{}", - checker.stylist().line_ending().as_str(), - clean_space(docstring.indentation) - ); - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - content, - docstring.expr.end() - num_trailing_quotes - num_trailing_spaces, - docstring.expr.end() - num_trailing_quotes, - ))); - } + // Insert a newline just before the end-quote(s). + let num_trailing_quotes = "'''".text_len(); + let num_trailing_spaces: TextSize = last_line + .chars() + .rev() + .skip(usize::from(num_trailing_quotes)) + .take_while(|c| c.is_whitespace()) + .map(TextLen::text_len) + .sum(); + let content = format!( + "{}{}", + checker.stylist().line_ending().as_str(), + clean_space(docstring.indentation) + ); + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + content, + docstring.expr.end() - num_trailing_quotes - num_trailing_spaces, + docstring.expr.end() - num_trailing_quotes, + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs index 174f2ab9f3..5c30438488 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/no_surrounding_whitespace.rs @@ -6,7 +6,7 @@ use ruff_text_size::{TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; -use crate::registry::AsRule; + use crate::rules::pydocstyle::helpers::ends_with_backslash; /// ## What it does @@ -63,17 +63,14 @@ pub(crate) fn no_surrounding_whitespace(checker: &mut Checker, docstring: &Docst return; } let mut diagnostic = Diagnostic::new(SurroundingWhitespace, docstring.range()); - if checker.patch(diagnostic.kind.rule()) { - let quote = docstring.contents.chars().last().unwrap(); - // If removing whitespace would lead to an invalid string of quote - // characters, avoid applying the fix. - if !trimmed.ends_with(quote) && !trimmed.starts_with(quote) && !ends_with_backslash(trimmed) - { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - trimmed.to_string(), - TextRange::at(body.start(), line.text_len()), - ))); - } + let quote = docstring.contents.chars().last().unwrap(); + // If removing whitespace would lead to an invalid string of quote + // characters, avoid applying the fix. + if !trimmed.ends_with(quote) && !trimmed.starts_with(quote) && !ends_with_backslash(trimmed) { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + trimmed.to_string(), + TextRange::at(body.start(), line.text_len()), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/one_liner.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/one_liner.rs index 10ffeddb0e..eac720d20b 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/one_liner.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/one_liner.rs @@ -6,7 +6,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::docstrings::Docstring; -use crate::registry::AsRule; /// ## What it does /// Checks for single-line docstrings that are broken across multiple lines. @@ -65,24 +64,22 @@ pub(crate) fn one_liner(checker: &mut Checker, docstring: &Docstring) { if non_empty_line_count == 1 && line_count > 1 { let mut diagnostic = Diagnostic::new(FitsOnOneLine, docstring.range()); - if checker.patch(diagnostic.kind.rule()) { - if let (Some(leading), Some(trailing)) = ( - leading_quote(docstring.contents), - trailing_quote(docstring.contents), - ) { - // If removing whitespace would lead to an invalid string of quote - // characters, avoid applying the fix. - let body = docstring.body(); - let trimmed = body.trim(); - if trimmed.chars().rev().take_while(|c| *c == '\\').count() % 2 == 0 - && !trimmed.ends_with(trailing.chars().last().unwrap()) - && !trimmed.starts_with(leading.chars().last().unwrap()) - { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - format!("{leading}{trimmed}{trailing}"), - docstring.range(), - ))); - } + if let (Some(leading), Some(trailing)) = ( + leading_quote(docstring.contents), + trailing_quote(docstring.contents), + ) { + // If removing whitespace would lead to an invalid string of quote + // characters, avoid applying the fix. + let body = docstring.body(); + let trimmed = body.trim(); + if trimmed.chars().rev().take_while(|c| *c == '\\').count() % 2 == 0 + && !trimmed.ends_with(trailing.chars().last().unwrap()) + && !trimmed.starts_with(leading.chars().last().unwrap()) + { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + format!("{leading}{trimmed}{trailing}"), + docstring.range(), + ))); } } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs index 008cb9f557..393ce0deac 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs @@ -18,7 +18,7 @@ use crate::checkers::ast::Checker; use crate::docstrings::sections::{SectionContext, SectionContexts, SectionKind}; use crate::docstrings::styles::SectionStyle; use crate::docstrings::Docstring; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; use crate::rules::pydocstyle::settings::Convention; /// ## What it does @@ -1388,12 +1388,9 @@ fn blanks_and_section_underline( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let range = - TextRange::new(context.following_range().start(), blank_lines_end); - // Delete any blank lines between the header and the underline. - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(range))); - } + let range = TextRange::new(context.following_range().start(), blank_lines_end); + // Delete any blank lines between the header and the underline. + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(range))); checker.diagnostics.push(diagnostic); } } @@ -1412,20 +1409,18 @@ fn blanks_and_section_underline( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Replace the existing underline with a line of the appropriate length. - let content = format!( - "{}{}{}", - clean_space(docstring.indentation), - "-".repeat(context.section_name().len()), - checker.stylist().line_ending().as_str() - ); - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - content, - blank_lines_end, - non_blank_line.full_end(), - ))); - }; + // Replace the existing underline with a line of the appropriate length. + let content = format!( + "{}{}{}", + clean_space(docstring.indentation), + "-".repeat(context.section_name().len()), + checker.stylist().line_ending().as_str() + ); + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + content, + blank_lines_end, + non_blank_line.full_end(), + ))); checker.diagnostics.push(diagnostic); } } @@ -1439,19 +1434,17 @@ fn blanks_and_section_underline( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Replace the existing indentation with whitespace of the appropriate length. - let range = TextRange::at( - blank_lines_end, - leading_space.text_len() + TextSize::from(1), - ); - let contents = clean_space(docstring.indentation); - diagnostic.set_fix(Fix::safe_edit(if contents.is_empty() { - Edit::range_deletion(range) - } else { - Edit::range_replacement(contents, range) - })); - }; + // Replace the existing indentation with whitespace of the appropriate length. + let range = TextRange::at( + blank_lines_end, + leading_space.text_len() + TextSize::from(1), + ); + let contents = clean_space(docstring.indentation); + diagnostic.set_fix(Fix::safe_edit(if contents.is_empty() { + Edit::range_deletion(range) + } else { + Edit::range_replacement(contents, range) + })); checker.diagnostics.push(diagnostic); } } @@ -1484,13 +1477,11 @@ fn blanks_and_section_underline( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Delete any blank lines between the header and content. - diagnostic.set_fix(Fix::safe_edit(Edit::deletion( - line_after_dashes.start(), - blank_lines_after_dashes_end, - ))); - } + // Delete any blank lines between the header and content. + diagnostic.set_fix(Fix::safe_edit(Edit::deletion( + line_after_dashes.start(), + blank_lines_after_dashes_end, + ))); checker.diagnostics.push(diagnostic); } } @@ -1516,31 +1507,29 @@ fn blanks_and_section_underline( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Add a dashed line (of the appropriate length) under the section header. - let content = format!( - "{}{}{}", - checker.stylist().line_ending().as_str(), - clean_space(docstring.indentation), - "-".repeat(context.section_name().len()), - ); - if equal_line_found - && non_blank_line.trim_whitespace().len() == context.section_name().len() - { - // If an existing underline is an equal sign line of the appropriate length, - // replace it with a dashed line. - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - content, - context.summary_range().end(), - non_blank_line.end(), - ))); - } else { - // Otherwise, insert a dashed line after the section header. - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - content, - context.summary_range().end(), - ))); - } + // Add a dashed line (of the appropriate length) under the section header. + let content = format!( + "{}{}{}", + checker.stylist().line_ending().as_str(), + clean_space(docstring.indentation), + "-".repeat(context.section_name().len()), + ); + if equal_line_found + && non_blank_line.trim_whitespace().len() == context.section_name().len() + { + // If an existing underline is an equal sign line of the appropriate length, + // replace it with a dashed line. + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + content, + context.summary_range().end(), + non_blank_line.end(), + ))); + } else { + // Otherwise, insert a dashed line after the section header. + diagnostic.set_fix(Fix::safe_edit(Edit::insertion( + content, + context.summary_range().end(), + ))); } checker.diagnostics.push(diagnostic); } @@ -1552,12 +1541,9 @@ fn blanks_and_section_underline( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let range = - TextRange::new(context.following_range().start(), blank_lines_end); - // Delete any blank lines between the header and content. - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(range))); - } + let range = TextRange::new(context.following_range().start(), blank_lines_end); + // Delete any blank lines between the header and content. + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(range))); checker.diagnostics.push(diagnostic); } } @@ -1572,20 +1558,18 @@ fn blanks_and_section_underline( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Add a dashed line (of the appropriate length) under the section header. - let content = format!( - "{}{}{}", - checker.stylist().line_ending().as_str(), - clean_space(docstring.indentation), - "-".repeat(context.section_name().len()), - ); + // Add a dashed line (of the appropriate length) under the section header. + let content = format!( + "{}{}{}", + checker.stylist().line_ending().as_str(), + clean_space(docstring.indentation), + "-".repeat(context.section_name().len()), + ); - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - content, - context.summary_range().end(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::insertion( + content, + context.summary_range().end(), + ))); checker.diagnostics.push(diagnostic); } if checker.enabled(Rule::EmptyDocstringSection) { @@ -1614,15 +1598,13 @@ fn common_section( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Replace the section title with the capitalized variant. This requires - // locating the start and end of the section name. - let section_range = context.section_name_range(); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - capitalized_section_name.to_string(), - section_range, - ))); - } + // Replace the section title with the capitalized variant. This requires + // locating the start and end of the section name. + let section_range = context.section_name_range(); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + capitalized_section_name.to_string(), + section_range, + ))); checker.diagnostics.push(diagnostic); } } @@ -1636,17 +1618,15 @@ fn common_section( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Replace the existing indentation with whitespace of the appropriate length. - let content = clean_space(docstring.indentation); - let fix_range = TextRange::at(context.start(), leading_space.text_len()); + // Replace the existing indentation with whitespace of the appropriate length. + let content = clean_space(docstring.indentation); + let fix_range = TextRange::at(context.start(), leading_space.text_len()); - diagnostic.set_fix(Fix::safe_edit(if content.is_empty() { - Edit::range_deletion(fix_range) - } else { - Edit::range_replacement(content, fix_range) - })); - }; + diagnostic.set_fix(Fix::safe_edit(if content.is_empty() { + Edit::range_deletion(fix_range) + } else { + Edit::range_replacement(content, fix_range) + })); checker.diagnostics.push(diagnostic); } } @@ -1662,13 +1642,11 @@ fn common_section( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Add a newline at the beginning of the next section. - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - line_end.to_string(), - next.start(), - ))); - } + // Add a newline at the beginning of the next section. + diagnostic.set_fix(Fix::safe_edit(Edit::insertion( + line_end.to_string(), + next.start(), + ))); checker.diagnostics.push(diagnostic); } } else { @@ -1679,13 +1657,11 @@ fn common_section( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Add a newline after the section. - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - format!("{}{}", line_end, docstring.indentation), - context.end(), - ))); - } + // Add a newline after the section. + diagnostic.set_fix(Fix::safe_edit(Edit::insertion( + format!("{}{}", line_end, docstring.indentation), + context.end(), + ))); checker.diagnostics.push(diagnostic); } } @@ -1702,13 +1678,11 @@ fn common_section( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Add a blank line before the section. - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - line_end.to_string(), - context.start(), - ))); - } + // Add a blank line before the section. + diagnostic.set_fix(Fix::safe_edit(Edit::insertion( + line_end.to_string(), + context.start(), + ))); checker.diagnostics.push(diagnostic); } } @@ -1898,13 +1872,11 @@ fn numpy_section( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let section_range = context.section_name_range(); - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(TextRange::at( - section_range.end(), - suffix.text_len(), - )))); - } + let section_range = context.section_name_range(); + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(TextRange::at( + section_range.end(), + suffix.text_len(), + )))); checker.diagnostics.push(diagnostic); } @@ -1934,14 +1906,12 @@ fn google_section( }, docstring.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // Replace the suffix. - let section_name_range = context.section_name_range(); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - ":".to_string(), - TextRange::at(section_name_range.end(), suffix.text_len()), - ))); - } + // Replace the suffix. + let section_name_range = context.section_name_range(); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + ":".to_string(), + TextRange::at(section_name_range.end(), suffix.text_len()), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyflakes/rules/f_string_missing_placeholders.rs b/crates/ruff_linter/src/rules/pyflakes/rules/f_string_missing_placeholders.rs index 68be85f793..448959149e 100644 --- a/crates/ruff_linter/src/rules/pyflakes/rules/f_string_missing_placeholders.rs +++ b/crates/ruff_linter/src/rules/pyflakes/rules/f_string_missing_placeholders.rs @@ -6,7 +6,6 @@ use ruff_source_file::Locator; use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for f-strings that do not contain any placeholder expressions. @@ -108,13 +107,11 @@ pub(crate) fn f_string_missing_placeholders(fstring: &ast::ExprFString, checker: fstring_prefix_and_tok_range(fstring, checker.locator(), checker.source_type) { let mut diagnostic = Diagnostic::new(FStringMissingPlaceholders, tok_range); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(convert_f_string_to_regular_string( - prefix_range, - tok_range, - checker.locator(), - )); - } + diagnostic.set_fix(convert_f_string_to_regular_string( + prefix_range, + tok_range, + checker.locator(), + )); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyflakes/rules/invalid_literal_comparisons.rs b/crates/ruff_linter/src/rules/pyflakes/rules/invalid_literal_comparisons.rs index 2946624936..1f8e85ad9d 100644 --- a/crates/ruff_linter/src/rules/pyflakes/rules/invalid_literal_comparisons.rs +++ b/crates/ruff_linter/src/rules/pyflakes/rules/invalid_literal_comparisons.rs @@ -8,7 +8,6 @@ use ruff_python_parser::locate_cmp_ops; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `is` and `is not` comparisons against constant literals, like @@ -85,30 +84,26 @@ pub(crate) fn invalid_literal_comparison( || helpers::is_constant_non_singleton(right)) { let mut diagnostic = Diagnostic::new(IsLiteral { cmp_op: op.into() }, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - if lazy_located.is_none() { - lazy_located = Some(locate_cmp_ops(expr, checker.locator().contents())); - } - if let Some(located_op) = - lazy_located.as_ref().and_then(|located| located.get(index)) - { - assert_eq!(located_op.op, *op); - if let Some(content) = match located_op.op { - CmpOp::Is => Some("==".to_string()), - CmpOp::IsNot => Some("!=".to_string()), - node => { - error!("Failed to fix invalid comparison: {node:?}"); - None - } - } { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - content, - located_op.range + expr.start(), - ))); + if lazy_located.is_none() { + lazy_located = Some(locate_cmp_ops(expr, checker.locator().contents())); + } + if let Some(located_op) = lazy_located.as_ref().and_then(|located| located.get(index)) { + assert_eq!(located_op.op, *op); + if let Some(content) = match located_op.op { + CmpOp::Is => Some("==".to_string()), + CmpOp::IsNot => Some("!=".to_string()), + node => { + error!("Failed to fix invalid comparison: {node:?}"); + None } - } else { - error!("Failed to fix invalid comparison due to missing op"); + } { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + content, + located_op.range + expr.start(), + ))); } + } else { + error!("Failed to fix invalid comparison due to missing op"); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyflakes/rules/raise_not_implemented.rs b/crates/ruff_linter/src/rules/pyflakes/rules/raise_not_implemented.rs index 7eeeedb755..3a48fe902f 100644 --- a/crates/ruff_linter/src/rules/pyflakes/rules/raise_not_implemented.rs +++ b/crates/ruff_linter/src/rules/pyflakes/rules/raise_not_implemented.rs @@ -5,7 +5,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `raise` statements that raise `NotImplemented`. @@ -76,13 +75,11 @@ pub(crate) fn raise_not_implemented(checker: &mut Checker, expr: &Expr) { return; }; let mut diagnostic = Diagnostic::new(RaiseNotImplemented, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_builtin("NotImplementedError") { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "NotImplementedError".to_string(), - expr.range(), - ))); - } + if checker.semantic().is_builtin("NotImplementedError") { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "NotImplementedError".to_string(), + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyflakes/rules/repeated_keys.rs b/crates/ruff_linter/src/rules/pyflakes/rules/repeated_keys.rs index fcdc3ebc5c..1d8fa4daad 100644 --- a/crates/ruff_linter/src/rules/pyflakes/rules/repeated_keys.rs +++ b/crates/ruff_linter/src/rules/pyflakes/rules/repeated_keys.rs @@ -11,7 +11,7 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix::snippet::SourceCodeSnippet; -use crate::registry::{AsRule, Rule}; +use crate::registry::Rule; /// ## What it does /// Checks for dictionary literals that associate multiple values with the @@ -157,27 +157,25 @@ pub(crate) fn repeated_keys(checker: &mut Checker, dict: &ast::ExprDict) { }, key.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if !seen_values.insert(comparable_value) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::deletion( - parenthesized_range( - (&dict.values[i - 1]).into(), - dict.into(), - checker.indexer().comment_ranges(), - checker.locator().contents(), - ) - .unwrap_or(dict.values[i - 1].range()) - .end(), - parenthesized_range( - (&dict.values[i]).into(), - dict.into(), - checker.indexer().comment_ranges(), - checker.locator().contents(), - ) - .unwrap_or(dict.values[i].range()) - .end(), - ))); - } + if !seen_values.insert(comparable_value) { + diagnostic.set_fix(Fix::unsafe_edit(Edit::deletion( + parenthesized_range( + (&dict.values[i - 1]).into(), + dict.into(), + checker.indexer().comment_ranges(), + checker.locator().contents(), + ) + .unwrap_or(dict.values[i - 1].range()) + .end(), + parenthesized_range( + (&dict.values[i]).into(), + dict.into(), + checker.indexer().comment_ranges(), + checker.locator().contents(), + ) + .unwrap_or(dict.values[i].range()) + .end(), + ))); } checker.diagnostics.push(diagnostic); } @@ -190,28 +188,26 @@ pub(crate) fn repeated_keys(checker: &mut Checker, dict: &ast::ExprDict) { }, key.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let comparable_value: ComparableExpr = (&dict.values[i]).into(); - if !seen_values.insert(comparable_value) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::deletion( - parenthesized_range( - (&dict.values[i - 1]).into(), - dict.into(), - checker.indexer().comment_ranges(), - checker.locator().contents(), - ) - .unwrap_or(dict.values[i - 1].range()) - .end(), - parenthesized_range( - (&dict.values[i]).into(), - dict.into(), - checker.indexer().comment_ranges(), - checker.locator().contents(), - ) - .unwrap_or(dict.values[i].range()) - .end(), - ))); - } + let comparable_value: ComparableExpr = (&dict.values[i]).into(); + if !seen_values.insert(comparable_value) { + diagnostic.set_fix(Fix::unsafe_edit(Edit::deletion( + parenthesized_range( + (&dict.values[i - 1]).into(), + dict.into(), + checker.indexer().comment_ranges(), + checker.locator().contents(), + ) + .unwrap_or(dict.values[i - 1].range()) + .end(), + parenthesized_range( + (&dict.values[i]).into(), + dict.into(), + checker.indexer().comment_ranges(), + checker.locator().contents(), + ) + .unwrap_or(dict.values[i].range()) + .end(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyflakes/rules/strings.rs b/crates/ruff_linter/src/rules/pyflakes/rules/strings.rs index bac1deda27..317c5692ea 100644 --- a/crates/ruff_linter/src/rules/pyflakes/rules/strings.rs +++ b/crates/ruff_linter/src/rules/pyflakes/rules/strings.rs @@ -8,7 +8,6 @@ use ruff_python_ast::{self as ast, Constant, Expr, Identifier, Keyword}; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; use super::super::cformat::CFormatSummary; use super::super::fixes::{ @@ -609,18 +608,16 @@ pub(crate) fn percent_format_extra_named_arguments( PercentFormatExtraNamedArguments { missing: names }, location, ); - if checker.patch(diagnostic.kind.rule()) { - let indexes: Vec = missing.iter().map(|(index, _)| *index).collect(); - diagnostic.try_set_fix(|| { - let edit = remove_unused_format_arguments_from_dict( - &indexes, - dict, - checker.locator(), - checker.stylist(), - )?; - Ok(Fix::safe_edit(edit)) - }); - } + let indexes: Vec = missing.iter().map(|(index, _)| *index).collect(); + diagnostic.try_set_fix(|| { + let edit = remove_unused_format_arguments_from_dict( + &indexes, + dict, + checker.locator(), + checker.stylist(), + )?; + Ok(Fix::safe_edit(edit)) + }); checker.diagnostics.push(diagnostic); } @@ -776,18 +773,16 @@ pub(crate) fn string_dot_format_extra_named_arguments( StringDotFormatExtraNamedArguments { missing: names }, call.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let indexes: Vec = missing.iter().map(|(index, _)| *index).collect(); - diagnostic.try_set_fix(|| { - let edit = remove_unused_keyword_arguments_from_format_call( - &indexes, - call, - checker.locator(), - checker.stylist(), - )?; - Ok(Fix::safe_edit(edit)) - }); - } + let indexes: Vec = missing.iter().map(|(index, _)| *index).collect(); + diagnostic.try_set_fix(|| { + let edit = remove_unused_keyword_arguments_from_format_call( + &indexes, + call, + checker.locator(), + checker.stylist(), + )?; + Ok(Fix::safe_edit(edit)) + }); checker.diagnostics.push(diagnostic); } @@ -798,6 +793,31 @@ pub(crate) fn string_dot_format_extra_positional_arguments( summary: &FormatSummary, args: &[Expr], ) { + // We can only fix if the positional arguments we're removing don't require re-indexing + // the format string itself. For example, we can't fix `"{1}{2}".format(0, 1, 2)"`, since + // this requires changing the format string to `"{0}{1}"`. But we can fix + // `"{0}{1}".format(0, 1, 2)`, since this only requires modifying the call arguments. + fn is_contiguous_from_end(indexes: &[usize], target: &[T]) -> bool { + if indexes.is_empty() { + return true; + } + + let mut expected_index = target.len() - 1; + for &index in indexes.iter().rev() { + if index != expected_index { + return false; + } + + if expected_index == 0 { + break; + } + + expected_index -= 1; + } + + true + } + let missing: Vec = args .iter() .enumerate() @@ -820,44 +840,19 @@ pub(crate) fn string_dot_format_extra_positional_arguments( }, call.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // We can only fix if the positional arguments we're removing don't require re-indexing - // the format string itself. For example, we can't fix `"{1}{2}".format(0, 1, 2)"`, since - // this requires changing the format string to `"{0}{1}"`. But we can fix - // `"{0}{1}".format(0, 1, 2)`, since this only requires modifying the call arguments. - fn is_contiguous_from_end(indexes: &[usize], target: &[T]) -> bool { - if indexes.is_empty() { - return true; - } - let mut expected_index = target.len() - 1; - for &index in indexes.iter().rev() { - if index != expected_index { - return false; - } - - if expected_index == 0 { - break; - } - - expected_index -= 1; - } - - true - } - - if is_contiguous_from_end(&missing, args) { - diagnostic.try_set_fix(|| { - let edit = remove_unused_positional_arguments_from_format_call( - &missing, - call, - checker.locator(), - checker.stylist(), - )?; - Ok(Fix::safe_edit(edit)) - }); - } + if is_contiguous_from_end(&missing, args) { + diagnostic.try_set_fix(|| { + let edit = remove_unused_positional_arguments_from_format_call( + &missing, + call, + checker.locator(), + checker.stylist(), + )?; + Ok(Fix::safe_edit(edit)) + }); } + checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs b/crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs index 91ddb22629..158e45183e 100644 --- a/crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs +++ b/crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs @@ -154,7 +154,7 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut exceptions.intersects(Exceptions::MODULE_NOT_FOUND_ERROR | Exceptions::IMPORT_ERROR); let multiple = imports.len() > 1; - let fix = if !in_init && !in_except_handler && checker.patch(Rule::UnusedImport) { + let fix = if !in_init && !in_except_handler { fix_imports(checker, node_id, &imports).ok() } else { None diff --git a/crates/ruff_linter/src/rules/pyflakes/rules/unused_variable.rs b/crates/ruff_linter/src/rules/pyflakes/rules/unused_variable.rs index 54c69c409c..b72bb5372f 100644 --- a/crates/ruff_linter/src/rules/pyflakes/rules/unused_variable.rs +++ b/crates/ruff_linter/src/rules/pyflakes/rules/unused_variable.rs @@ -12,7 +12,6 @@ use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::checkers::ast::Checker; use crate::fix::edits::delete_stmt; -use crate::registry::AsRule; /// ## What it does /// Checks for the presence of unused variables in function scopes. @@ -344,10 +343,8 @@ pub(crate) fn unused_variable(checker: &Checker, scope: &Scope, diagnostics: &mu }, binding.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(fix) = remove_unused_variable(binding, checker) { - diagnostic.set_fix(fix); - } + if let Some(fix) = remove_unused_variable(binding, checker) { + diagnostic.set_fix(fix); } diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pylint/rules/iteration_over_set.rs b/crates/ruff_linter/src/rules/pylint/rules/iteration_over_set.rs index 0a85ff3d5c..98146923b5 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/iteration_over_set.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/iteration_over_set.rs @@ -5,7 +5,7 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::{Ranged, TextRange}; -use crate::{checkers::ast::Checker, registry::AsRule}; +use crate::checkers::ast::Checker; /// ## What it does /// Checks for iterations over `set` literals. @@ -54,17 +54,15 @@ pub(crate) fn iteration_over_set(checker: &mut Checker, expr: &Expr) { let mut diagnostic = Diagnostic::new(IterationOverSet, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - let tuple = checker.generator().expr(&Expr::Tuple(ast::ExprTuple { - elts: elts.clone(), - ctx: ExprContext::Store, - range: TextRange::default(), - })); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - format!("({tuple})"), - expr.range(), - ))); - } + let tuple = checker.generator().expr(&Expr::Tuple(ast::ExprTuple { + elts: elts.clone(), + ctx: ExprContext::Store, + range: TextRange::default(), + })); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("({tuple})"), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pylint/rules/manual_import_from.rs b/crates/ruff_linter/src/rules/pylint/rules/manual_import_from.rs index 4df7f5a6ff..4898c9b310 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/manual_import_from.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/manual_import_from.rs @@ -5,7 +5,6 @@ use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for submodule imports that are aliased to the submodule name. @@ -71,23 +70,21 @@ pub(crate) fn manual_from_import( }, alias.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if names.len() == 1 { - let node = ast::StmtImportFrom { - module: Some(Identifier::new(module.to_string(), TextRange::default())), - names: vec![Alias { - name: asname.clone(), - asname: None, - range: TextRange::default(), - }], - level: Some(0), + if names.len() == 1 { + let node = ast::StmtImportFrom { + module: Some(Identifier::new(module.to_string(), TextRange::default())), + names: vec![Alias { + name: asname.clone(), + asname: None, range: TextRange::default(), - }; - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - checker.generator().stmt(&node.into()), - stmt.range(), - ))); - } + }], + level: Some(0), + range: TextRange::default(), + }; + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + checker.generator().stmt(&node.into()), + stmt.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pylint/rules/nested_min_max.rs b/crates/ruff_linter/src/rules/pylint/rules/nested_min_max.rs index fe2f91ec56..3911b55be2 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/nested_min_max.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/nested_min_max.rs @@ -5,7 +5,7 @@ use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_semantic::SemanticModel; -use crate::{checkers::ast::Checker, registry::AsRule}; +use crate::checkers::ast::Checker; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub(crate) enum MinMax { @@ -160,22 +160,20 @@ pub(crate) fn nested_min_max( MinMax::try_from_call(func.as_ref(), keywords.as_ref(), checker.semantic()) == Some(min_max) }) { let mut diagnostic = Diagnostic::new(NestedMinMax { func: min_max }, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - if !checker.indexer().has_comments(expr, checker.locator()) { - let flattened_expr = Expr::Call(ast::ExprCall { - func: Box::new(func.clone()), - arguments: Arguments { - args: collect_nested_args(min_max, args, checker.semantic()), - keywords: keywords.to_owned(), - range: TextRange::default(), - }, + if !checker.indexer().has_comments(expr, checker.locator()) { + let flattened_expr = Expr::Call(ast::ExprCall { + func: Box::new(func.clone()), + arguments: Arguments { + args: collect_nested_args(min_max, args, checker.semantic()), + keywords: keywords.to_owned(), range: TextRange::default(), - }); - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr(&flattened_expr), - expr.range(), - ))); - } + }, + range: TextRange::default(), + }); + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&flattened_expr), + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pylint/rules/repeated_equality_comparison.rs b/crates/ruff_linter/src/rules/pylint/rules/repeated_equality_comparison.rs index 13d6b4c43f..d3077539c8 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/repeated_equality_comparison.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/repeated_equality_comparison.rs @@ -1,10 +1,10 @@ use std::hash::BuildHasherDefault; use std::ops::Deref; -use ast::ExprContext; use itertools::{any, Itertools}; use rustc_hash::FxHashMap; +use ast::ExprContext; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::comparable::ComparableExpr; @@ -15,7 +15,6 @@ use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::checkers::ast::Checker; use crate::fix::snippet::SourceCodeSnippet; -use crate::registry::AsRule; /// ## What it does /// Checks for repeated equality comparisons that can rewritten as a membership @@ -133,8 +132,8 @@ pub(crate) fn repeated_equality_comparison(checker: &mut Checker, bool_op: &ast: bool_op.range(), ); - if checker.patch(diagnostic.kind.rule()) { - let content = checker.generator().expr(&Expr::Compare(ast::ExprCompare { + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&Expr::Compare(ast::ExprCompare { left: Box::new(value.as_expr().clone()), ops: match bool_op.op { BoolOp::Or => vec![CmpOp::In], @@ -146,13 +145,9 @@ pub(crate) fn repeated_equality_comparison(checker: &mut Checker, bool_op: &ast: ctx: ExprContext::Load, })], range: bool_op.range(), - })); - - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - content, - bool_op.range(), - ))); - } + })), + bool_op.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pylint/rules/repeated_isinstance_calls.rs b/crates/ruff_linter/src/rules/pylint/rules/repeated_isinstance_calls.rs index d3a0ca14dc..4ede23df5c 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/repeated_isinstance_calls.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/repeated_isinstance_calls.rs @@ -10,7 +10,7 @@ use ruff_python_ast::hashable::HashableExpr; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::settings::types::PythonVersion; /// ## What it does @@ -133,12 +133,10 @@ pub(crate) fn repeated_isinstance_calls( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - pad(call, expr.range(), checker.locator()), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + pad(call, expr.range(), checker.locator()), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pylint/rules/sys_exit_alias.rs b/crates/ruff_linter/src/rules/pylint/rules/sys_exit_alias.rs index f8a637822d..894cda0c15 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/sys_exit_alias.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/sys_exit_alias.rs @@ -6,7 +6,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of the `exit()` and `quit()`. @@ -77,16 +76,14 @@ pub(crate) fn sys_exit_alias(checker: &mut Checker, func: &Expr) { }, func.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import("sys", "exit"), - func.start(), - checker.semantic(), - )?; - let reference_edit = Edit::range_replacement(binding, func.range()); - Ok(Fix::unsafe_edits(import_edit, [reference_edit])) - }); - } + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import("sys", "exit"), + func.start(), + checker.semantic(), + )?; + let reference_edit = Edit::range_replacement(binding, func.range()); + Ok(Fix::unsafe_edits(import_edit, [reference_edit])) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pylint/rules/useless_import_alias.rs b/crates/ruff_linter/src/rules/pylint/rules/useless_import_alias.rs index 125d442a72..f86314a3a2 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/useless_import_alias.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/useless_import_alias.rs @@ -5,7 +5,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for import aliases that do not rename the original package. @@ -49,11 +48,9 @@ pub(crate) fn useless_import_alias(checker: &mut Checker, alias: &Alias) { } let mut diagnostic = Diagnostic::new(UselessImportAlias, alias.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - asname.to_string(), - alias.range(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + asname.to_string(), + alias.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pylint/rules/useless_return.rs b/crates/ruff_linter/src/rules/pylint/rules/useless_return.rs index 3536f201d3..1221cf7eaa 100644 --- a/crates/ruff_linter/src/rules/pylint/rules/useless_return.rs +++ b/crates/ruff_linter/src/rules/pylint/rules/useless_return.rs @@ -8,7 +8,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix; -use crate::registry::AsRule; /// ## What it does /// Checks for functions that end with an unnecessary `return` or @@ -103,12 +102,9 @@ pub(crate) fn useless_return( } let mut diagnostic = Diagnostic::new(UselessReturn, last_stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - let edit = - fix::edits::delete_stmt(last_stmt, Some(stmt), checker.locator(), checker.indexer()); - diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_id(), - ))); - } + let edit = fix::edits::delete_stmt(last_stmt, Some(stmt), checker.locator(), checker.indexer()); + diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_id(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs index 506b6bb2d9..27e1ef79c0 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs @@ -12,7 +12,6 @@ use ruff_python_stdlib::identifiers::is_identifier; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `NamedTuple` declarations that use functional syntax. @@ -114,17 +113,15 @@ pub(crate) fn convert_named_tuple_functional_to_class( }, stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // TODO(charlie): Preserve indentation, to remove the first-column requirement. - if checker.locator().is_at_start_of_line(stmt.start()) { - diagnostic.set_fix(convert_to_class( - stmt, - typename, - fields, - base_class, - checker.generator(), - )); - } + // TODO(charlie): Preserve indentation, to remove the first-column requirement. + if checker.locator().is_at_start_of_line(stmt.start()) { + diagnostic.set_fix(convert_to_class( + stmt, + typename, + fields, + base_class, + checker.generator(), + )); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs index 9701efe37b..462ea9ceab 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs @@ -10,7 +10,6 @@ use ruff_python_stdlib::identifiers::is_identifier; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `TypedDict` declarations that use functional syntax. @@ -84,18 +83,16 @@ pub(crate) fn convert_typed_dict_functional_to_class( }, stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - // TODO(charlie): Preserve indentation, to remove the first-column requirement. - if checker.locator().is_at_start_of_line(stmt.start()) { - diagnostic.set_fix(convert_to_class( - stmt, - class_name, - body, - total_keyword, - base_class, - checker.generator(), - )); - } + // TODO(charlie): Preserve indentation, to remove the first-column requirement. + if checker.locator().is_at_start_of_line(stmt.start()) { + diagnostic.set_fix(convert_to_class( + stmt, + class_name, + body, + total_keyword, + base_class, + checker.generator(), + )); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/datetime_utc_alias.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/datetime_utc_alias.rs index e37d564e3e..c4325f9651 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/datetime_utc_alias.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/datetime_utc_alias.rs @@ -6,7 +6,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `datetime.timezone.utc`. @@ -58,17 +57,15 @@ pub(crate) fn datetime_utc_alias(checker: &mut Checker, expr: &Expr) { .is_some_and(|call_path| matches!(call_path.as_slice(), ["datetime", "timezone", "utc"])) { let mut diagnostic = Diagnostic::new(DatetimeTimezoneUTC, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import_from("datetime", "UTC"), - expr.start(), - checker.semantic(), - )?; - let reference_edit = Edit::range_replacement(binding, expr.range()); - Ok(Fix::safe_edits(import_edit, [reference_edit])) - }); - } + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import_from("datetime", "UTC"), + expr.start(), + checker.semantic(), + )?; + let reference_edit = Edit::range_replacement(binding, expr.range()); + Ok(Fix::safe_edits(import_edit, [reference_edit])) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs index d8f7e99237..55d338c66a 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_c_element_tree.rs @@ -4,7 +4,6 @@ use ruff_python_ast::{self as ast, Stmt}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of the `xml.etree.cElementTree` module. @@ -44,13 +43,11 @@ where T: Ranged, { let mut diagnostic = Diagnostic::new(DeprecatedCElementTree, node.range()); - if checker.patch(diagnostic.kind.rule()) { - let contents = checker.locator().slice(node); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - contents.replacen("cElementTree", "ElementTree", 1), - node.range(), - ))); - } + let contents = checker.locator().slice(node); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + contents.replacen("cElementTree", "ElementTree", 1), + node.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_import.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_import.rs index b713ca2395..91374d639c 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_import.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_import.rs @@ -9,7 +9,7 @@ use ruff_source_file::Locator; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::Rule; + use crate::rules::pyupgrade::fixes; use crate::settings::types::PythonVersion; @@ -630,13 +630,11 @@ pub(crate) fn deprecated_import( }, stmt.range(), ); - if checker.patch(Rule::DeprecatedImport) { - if let Some(content) = fix { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - content, - stmt.range(), - ))); - } + if let Some(content) = fix { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + content, + stmt.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_mock_import.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_mock_import.rs index bb8a11ccb0..aed0ff2907 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_mock_import.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_mock_import.rs @@ -17,7 +17,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::cst::matchers::{match_import, match_import_from, match_statement}; -use crate::registry::{AsRule, Rule}; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub(crate) enum MockReference { @@ -261,12 +260,10 @@ pub(crate) fn deprecated_mock_attribute(checker: &mut Checker, expr: &Expr) { }, value.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "mock".to_string(), - value.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "mock".to_string(), + value.range(), + ))); checker.diagnostics.push(diagnostic); } } @@ -282,17 +279,13 @@ pub(crate) fn deprecated_mock_import(checker: &mut Checker, stmt: &Stmt) { .any(|name| &name.name == "mock" || &name.name == "mock.mock") { // Generate the fix, if needed, which is shared between all `mock` imports. - let content = if checker.patch(Rule::DeprecatedMockImport) { - if let Some(indent) = indentation(checker.locator(), stmt) { - match format_import(stmt, indent, checker.locator(), checker.stylist()) { - Ok(content) => Some(content), - Err(e) => { - error!("Failed to rewrite `mock` import: {e}"); - None - } + let content = if let Some(indent) = indentation(checker.locator(), stmt) { + match format_import(stmt, indent, checker.locator(), checker.stylist()) { + Ok(content) => Some(content), + Err(e) => { + error!("Failed to rewrite `mock` import: {e}"); + None } - } else { - None } } else { None @@ -334,14 +327,12 @@ pub(crate) fn deprecated_mock_import(checker: &mut Checker, stmt: &Stmt) { }, stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(indent) = indentation(checker.locator(), stmt) { - diagnostic.try_set_fix(|| { - format_import_from(stmt, indent, checker.locator(), checker.stylist()) - .map(|content| Edit::range_replacement(content, stmt.range())) - .map(Fix::safe_edit) - }); - } + if let Some(indent) = indentation(checker.locator(), stmt) { + diagnostic.try_set_fix(|| { + format_import_from(stmt, indent, checker.locator(), checker.stylist()) + .map(|content| Edit::range_replacement(content, stmt.range())) + .map(Fix::safe_edit) + }); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs index 794f0cd62a..58250d43a2 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_unittest_alias.rs @@ -7,7 +7,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of deprecated methods from the `unittest` module. @@ -99,11 +98,9 @@ pub(crate) fn deprecated_unittest_alias(checker: &mut Checker, expr: &Expr) { }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - format!("self.{target}"), - expr.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("self.{target}"), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/extraneous_parentheses.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/extraneous_parentheses.rs index 76a356f1d4..621412d20c 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/extraneous_parentheses.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/extraneous_parentheses.rs @@ -6,9 +6,6 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_source_file::Locator; -use crate::registry::Rule; -use crate::settings::LinterSettings; - /// ## What it does /// Checks for extraneous parentheses. /// @@ -137,7 +134,6 @@ pub(crate) fn extraneous_parentheses( diagnostics: &mut Vec, tokens: &[LexResult], locator: &Locator, - settings: &LinterSettings, ) { let mut i = 0; while i < tokens.len() { @@ -154,15 +150,12 @@ pub(crate) fn extraneous_parentheses( ExtraneousParentheses, TextRange::new(start_range.start(), end_range.end()), ); - if settings.rules.should_fix(Rule::ExtraneousParentheses) { - let contents = - locator.slice(TextRange::new(start_range.start(), end_range.end())); - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - contents[1..contents.len() - 1].to_string(), - start_range.start(), - end_range.end(), - ))); - } + let contents = locator.slice(TextRange::new(start_range.start(), end_range.end())); + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + contents[1..contents.len() - 1].to_string(), + start_range.start(), + end_range.end(), + ))); diagnostics.push(diagnostic); } else { i += 1; diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/f_strings.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/f_strings.rs index 10783a0495..290a7cd552 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/f_strings.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/f_strings.rs @@ -17,7 +17,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits::fits_or_shrinks; -use crate::registry::AsRule; use crate::rules::pyflakes::format::FormatSummary; use crate::rules::pyupgrade::helpers::curly_escape; @@ -433,11 +432,10 @@ pub(crate) fn f_strings( // 0, # 0 // ) // ``` - if checker.patch(diagnostic.kind.rule()) - && !checker - .indexer() - .comment_ranges() - .intersects(call.arguments.range()) + if !checker + .indexer() + .comment_ranges() + .intersects(call.arguments.range()) { diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( contents, diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/format_literals.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/format_literals.rs index 23b688cb14..ab6753f0c8 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/format_literals.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/format_literals.rs @@ -15,7 +15,7 @@ use crate::cst::matchers::{ match_attribute, match_call_mut, match_expression, transform_expression_text, }; use crate::fix::codemods::CodegenStylist; -use crate::registry::AsRule; + use crate::rules::pyflakes::format::FormatSummary; /// ## What it does @@ -113,13 +113,10 @@ pub(crate) fn format_literals( }; let mut diagnostic = Diagnostic::new(FormatLiterals, call.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - generate_call(call, arguments, checker.locator(), checker.stylist()).map(|suggestion| { - Fix::unsafe_edit(Edit::range_replacement(suggestion, call.range())) - }) - }); - } + diagnostic.try_set_fix(|| { + generate_call(call, arguments, checker.locator(), checker.stylist()) + .map(|suggestion| Fix::unsafe_edit(Edit::range_replacement(suggestion, call.range()))) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs index 95bf867b28..837a7bafdf 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs @@ -7,7 +7,6 @@ use ruff_python_ast::helpers::is_const_none; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `functools.lru_cache` that set `maxsize=None`. @@ -91,18 +90,16 @@ pub(crate) fn lru_cache_with_maxsize_none(checker: &mut Checker, decorator_list: LRUCacheWithMaxsizeNone, TextRange::new(func.end(), decorator.end()), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import("functools", "cache"), - decorator.start(), - checker.semantic(), - )?; - let reference_edit = - Edit::range_replacement(binding, decorator.expression.range()); - Ok(Fix::safe_edits(import_edit, [reference_edit])) - }); - } + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import("functools", "cache"), + decorator.start(), + checker.semantic(), + )?; + let reference_edit = + Edit::range_replacement(binding, decorator.expression.range()); + Ok(Fix::safe_edits(import_edit, [reference_edit])) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs index 5f7a0dc5df..00c53bfc61 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs @@ -4,7 +4,6 @@ use ruff_python_ast::{self as ast, Decorator, Expr}; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for unnecessary parentheses on `functools.lru_cache` decorators. @@ -77,9 +76,7 @@ pub(crate) fn lru_cache_without_parameters(checker: &mut Checker, decorator_list LRUCacheWithoutParameters, TextRange::new(func.end(), decorator.end()), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(arguments.range()))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(arguments.range()))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs index 867225c746..7f67285144 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs @@ -7,7 +7,6 @@ use ruff_python_ast::{self as ast, Constant, Expr}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; #[derive(Debug, PartialEq, Eq, Copy, Clone)] enum LiteralType { @@ -182,14 +181,12 @@ pub(crate) fn native_literals( return; } - if checker.patch(diagnostic.kind.rule()) { - let constant = Constant::from(literal_type); - let content = checker.generator().constant(&constant); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - content, - call.range(), - ))); - } + let constant = Constant::from(literal_type); + let content = checker.generator().constant(&constant); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + content, + call.range(), + ))); checker.diagnostics.push(diagnostic); } Some(arg) => { @@ -222,12 +219,10 @@ pub(crate) fn native_literals( }; let mut diagnostic = Diagnostic::new(NativeLiterals { literal_type }, call.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - content, - call.range(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + content, + call.range(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/open_alias.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/open_alias.rs index 14aba7b278..1809b4cea4 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/open_alias.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/open_alias.rs @@ -5,7 +5,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `io.open`. @@ -54,13 +53,11 @@ pub(crate) fn open_alias(checker: &mut Checker, expr: &Expr, func: &Expr) { .is_some_and(|call_path| matches!(call_path.as_slice(), ["io", "open"])) { let mut diagnostic = Diagnostic::new(OpenAlias, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_builtin("open") { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "open".to_string(), - func.range(), - ))); - } + if checker.semantic().is_builtin("open") { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "open".to_string(), + func.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/os_error_alias.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/os_error_alias.rs index a90383c4ac..8477e775b7 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/os_error_alias.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/os_error_alias.rs @@ -8,7 +8,6 @@ use ruff_python_ast::call_path::compose_call_path; use ruff_python_semantic::SemanticModel; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of exceptions that alias `OSError`. @@ -81,13 +80,11 @@ fn atom_diagnostic(checker: &mut Checker, target: &Expr) { }, target.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_builtin("OSError") { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "OSError".to_string(), - target.range(), - ))); - } + if checker.semantic().is_builtin("OSError") { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "OSError".to_string(), + target.range(), + ))); } checker.diagnostics.push(diagnostic); } @@ -95,51 +92,49 @@ fn atom_diagnostic(checker: &mut Checker, target: &Expr) { /// Create a [`Diagnostic`] for a tuple of expressions. fn tuple_diagnostic(checker: &mut Checker, tuple: &ast::ExprTuple, aliases: &[&Expr]) { let mut diagnostic = Diagnostic::new(OSErrorAlias { name: None }, tuple.range()); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_builtin("OSError") { - // Filter out any `OSErrors` aliases. - let mut remaining: Vec = tuple - .elts - .iter() - .filter_map(|elt| { - if aliases.contains(&elt) { - None - } else { - Some(elt.clone()) - } - }) - .collect(); + if checker.semantic().is_builtin("OSError") { + // Filter out any `OSErrors` aliases. + let mut remaining: Vec = tuple + .elts + .iter() + .filter_map(|elt| { + if aliases.contains(&elt) { + None + } else { + Some(elt.clone()) + } + }) + .collect(); - // If `OSError` itself isn't already in the tuple, add it. - if tuple - .elts - .iter() - .all(|elt| !is_os_error(elt, checker.semantic())) - { - let node = ast::ExprName { - id: "OSError".into(), - ctx: ExprContext::Load, - range: TextRange::default(), - }; - remaining.insert(0, node.into()); - } - - let content = if remaining.len() == 1 { - "OSError".to_string() - } else { - let node = ast::ExprTuple { - elts: remaining, - ctx: ExprContext::Load, - range: TextRange::default(), - }; - format!("({})", checker.generator().expr(&node.into())) + // If `OSError` itself isn't already in the tuple, add it. + if tuple + .elts + .iter() + .all(|elt| !is_os_error(elt, checker.semantic())) + { + let node = ast::ExprName { + id: "OSError".into(), + ctx: ExprContext::Load, + range: TextRange::default(), }; - - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - pad(content, tuple.range(), checker.locator()), - tuple.range(), - ))); + remaining.insert(0, node.into()); } + + let content = if remaining.len() == 1 { + "OSError".to_string() + } else { + let node = ast::ExprTuple { + elts: remaining, + ctx: ExprContext::Load, + range: TextRange::default(), + }; + format!("({})", checker.generator().expr(&node.into())) + }; + + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + pad(content, tuple.range(), checker.locator()), + tuple.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs index 07cb766e11..bfaee87a73 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs @@ -10,7 +10,7 @@ use ruff_text_size::{Ranged, TextLen, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits::delete_stmt; -use crate::registry::AsRule; + use crate::rules::pyupgrade::fixes::adjust_indentation; use crate::settings::types::PythonVersion; @@ -118,12 +118,8 @@ pub(crate) fn outdated_version_block(checker: &mut Checker, stmt_if: &StmtIf) { }, branch.test.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(fix) = - fix_always_false_branch(checker, stmt_if, &branch) - { - diagnostic.set_fix(fix); - } + if let Some(fix) = fix_always_false_branch(checker, stmt_if, &branch) { + diagnostic.set_fix(fix); } checker.diagnostics.push(diagnostic); } @@ -151,11 +147,8 @@ pub(crate) fn outdated_version_block(checker: &mut Checker, stmt_if: &StmtIf) { }, branch.test.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(fix) = fix_always_true_branch(checker, stmt_if, &branch) - { - diagnostic.set_fix(fix); - } + if let Some(fix) = fix_always_true_branch(checker, stmt_if, &branch) { + diagnostic.set_fix(fix); } checker.diagnostics.push(diagnostic); } @@ -184,12 +177,8 @@ pub(crate) fn outdated_version_block(checker: &mut Checker, stmt_if: &StmtIf) { }, branch.test.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(fix) = - fix_always_false_branch(checker, stmt_if, &branch) - { - diagnostic.set_fix(fix); - } + if let Some(fix) = fix_always_false_branch(checker, stmt_if, &branch) { + diagnostic.set_fix(fix); } checker.diagnostics.push(diagnostic); } @@ -200,11 +189,8 @@ pub(crate) fn outdated_version_block(checker: &mut Checker, stmt_if: &StmtIf) { }, branch.test.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(fix) = fix_always_true_branch(checker, stmt_if, &branch) - { - diagnostic.set_fix(fix); - } + if let Some(fix) = fix_always_true_branch(checker, stmt_if, &branch) { + diagnostic.set_fix(fix); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/printf_string_formatting.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/printf_string_formatting.rs index 4ae29c36df..89b4a67778 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/printf_string_formatting.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/printf_string_formatting.rs @@ -15,7 +15,7 @@ use ruff_source_file::Locator; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::pyupgrade::helpers::curly_escape; /// ## What it does @@ -495,9 +495,7 @@ pub(crate) fn printf_string_formatting(checker: &mut Checker, expr: &Expr, right // 0, # 0 // ) // ``` - if checker.patch(diagnostic.kind.rule()) - && !checker.indexer().comment_ranges().intersects(right.range()) - { + if !checker.indexer().comment_ranges().intersects(right.range()) { diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( contents, expr.range(), diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/quoted_annotation.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/quoted_annotation.rs index a6cadaa490..2a94d946a3 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/quoted_annotation.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/quoted_annotation.rs @@ -4,7 +4,6 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use crate::checkers::ast::Checker; -use crate::registry::Rule; /// ## What it does /// Checks for the presence of unnecessary quotes in type annotations. @@ -53,11 +52,9 @@ impl AlwaysFixableViolation for QuotedAnnotation { /// UP037 pub(crate) fn quoted_annotation(checker: &mut Checker, annotation: &str, range: TextRange) { let mut diagnostic = Diagnostic::new(QuotedAnnotation, range); - if checker.patch(Rule::QuotedAnnotation) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - annotation.to_string(), - range, - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + annotation.to_string(), + range, + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/redundant_open_modes.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/redundant_open_modes.rs index 91e856738a..52356297c7 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/redundant_open_modes.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/redundant_open_modes.rs @@ -11,7 +11,6 @@ use ruff_source_file::Locator; use ruff_text_size::{Ranged, TextSize}; use crate::checkers::ast::Checker; -use crate::registry::Rule; /// ## What it does /// Checks for redundant `open` mode parameters. @@ -87,7 +86,6 @@ pub(crate) fn redundant_open_modes(checker: &mut Checker, call: &ast::ExprCall) &keyword.value, mode.replacement_value(), checker.locator(), - checker.patch(Rule::RedundantOpenModes), checker.source_type, )); } @@ -107,7 +105,6 @@ pub(crate) fn redundant_open_modes(checker: &mut Checker, call: &ast::ExprCall) mode_param, mode.replacement_value(), checker.locator(), - checker.patch(Rule::RedundantOpenModes), checker.source_type, )); } @@ -174,7 +171,6 @@ fn create_check( mode_param: &Expr, replacement_value: Option<&str>, locator: &Locator, - patch: bool, source_type: PySourceType, ) -> Diagnostic { let mut diagnostic = Diagnostic::new( @@ -183,18 +179,18 @@ fn create_check( }, expr.range(), ); - if patch { - if let Some(content) = replacement_value { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - content.to_string(), - mode_param.range(), - ))); - } else { - diagnostic.try_set_fix(|| { - create_remove_param_fix(locator, expr, mode_param, source_type).map(Fix::safe_edit) - }); - } + + if let Some(content) = replacement_value { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + content.to_string(), + mode_param.range(), + ))); + } else { + diagnostic.try_set_fix(|| { + create_remove_param_fix(locator, expr, mode_param, source_type).map(Fix::safe_edit) + }); } + diagnostic } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/replace_stdout_stderr.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/replace_stdout_stderr.rs index 2fa6261f51..ff08e4e851 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/replace_stdout_stderr.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/replace_stdout_stderr.rs @@ -7,7 +7,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix::edits::{remove_argument, Parentheses}; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `subprocess.run` that send `stdout` and `stderr` to a @@ -81,12 +80,9 @@ pub(crate) fn replace_stdout_stderr(checker: &mut Checker, call: &ast::ExprCall) } let mut diagnostic = Diagnostic::new(ReplaceStdoutStderr, call.range()); - if checker.patch(diagnostic.kind.rule()) { - if call.arguments.find_keyword("capture_output").is_none() { - diagnostic.try_set_fix(|| { - generate_fix(stdout, stderr, call, checker.locator().contents()) - }); - } + if call.arguments.find_keyword("capture_output").is_none() { + diagnostic + .try_set_fix(|| generate_fix(stdout, stderr, call, checker.locator().contents())); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/replace_universal_newlines.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/replace_universal_newlines.rs index 7d14c5b2e0..9e97481dba 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/replace_universal_newlines.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/replace_universal_newlines.rs @@ -5,7 +5,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix::edits::{remove_argument, Parentheses}; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `subprocess.run` that set the `universal_newlines` @@ -65,23 +64,21 @@ pub(crate) fn replace_universal_newlines(checker: &mut Checker, call: &ast::Expr let mut diagnostic = Diagnostic::new(ReplaceUniversalNewlines, arg.range()); - if checker.patch(diagnostic.kind.rule()) { - if call.arguments.find_keyword("text").is_some() { - diagnostic.try_set_fix(|| { - remove_argument( - kwarg, - &call.arguments, - Parentheses::Preserve, - checker.locator().contents(), - ) - .map(Fix::safe_edit) - }); - } else { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "text".to_string(), - arg.range(), - ))); - } + if call.arguments.find_keyword("text").is_some() { + diagnostic.try_set_fix(|| { + remove_argument( + kwarg, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), + ) + .map(Fix::safe_edit) + }); + } else { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "text".to_string(), + arg.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/super_call_with_parameters.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/super_call_with_parameters.rs index dc0df1ec34..c8af446f4a 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/super_call_with_parameters.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/super_call_with_parameters.rs @@ -4,7 +4,6 @@ use ruff_python_ast::{self as ast, Expr, Parameter, ParameterWithDefault, Stmt}; use ruff_text_size::{Ranged, TextSize}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `super` calls that pass redundant arguments. @@ -128,12 +127,10 @@ pub(crate) fn super_call_with_parameters(checker: &mut Checker, call: &ast::Expr drop(parents); let mut diagnostic = Diagnostic::new(SuperCallWithParameters, call.arguments.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::deletion( - call.arguments.start() + TextSize::new(1), - call.arguments.end() - TextSize::new(1), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::deletion( + call.arguments.start() + TextSize::new(1), + call.arguments.end() - TextSize::new(1), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/type_of_primitive.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/type_of_primitive.rs index 080aa8fe81..f65ce23ff2 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/type_of_primitive.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/type_of_primitive.rs @@ -6,7 +6,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; use super::super::types::Primitive; @@ -73,14 +72,12 @@ pub(crate) fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, return; }; let mut diagnostic = Diagnostic::new(TypeOfPrimitive { primitive }, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - let builtin = primitive.builtin(); - if checker.semantic().is_builtin(&builtin) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - pad(primitive.builtin(), expr.range(), checker.locator()), - expr.range(), - ))); - } + let builtin = primitive.builtin(); + if checker.semantic().is_builtin(&builtin) { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + pad(primitive.builtin(), expr.range(), checker.locator()), + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/typing_text_str_alias.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/typing_text_str_alias.rs index f804261abc..86d9e6b28b 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/typing_text_str_alias.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/typing_text_str_alias.rs @@ -5,7 +5,6 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `typing.Text`. @@ -53,13 +52,11 @@ pub(crate) fn typing_text_str_alias(checker: &mut Checker, expr: &Expr) { .is_some_and(|call_path| matches!(call_path.as_slice(), ["typing", "Text"])) { let mut diagnostic = Diagnostic::new(TypingTextStrAlias, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - if checker.semantic().is_builtin("str") { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - "str".to_string(), - expr.range(), - ))); - } + if checker.semantic().is_builtin("str") { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + "str".to_string(), + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/unicode_kind_prefix.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/unicode_kind_prefix.rs index 12677b429a..20fcbf08a5 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/unicode_kind_prefix.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/unicode_kind_prefix.rs @@ -4,7 +4,6 @@ use ruff_python_ast::Expr; use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of the Unicode kind prefix (`u`) in strings. @@ -43,12 +42,10 @@ impl AlwaysFixableViolation for UnicodeKindPrefix { pub(crate) fn unicode_kind_prefix(checker: &mut Checker, expr: &Expr, is_unicode: bool) { if is_unicode { let mut diagnostic = Diagnostic::new(UnicodeKindPrefix, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(TextRange::at( - expr.start(), - TextSize::from(1), - )))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(TextRange::at( + expr.start(), + TextSize::from(1), + )))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs index 2190f9a4b5..ccb7d12c35 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs @@ -7,7 +7,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix; -use crate::registry::AsRule; /// ## What it does /// Checks for unnecessary imports of builtins. @@ -121,25 +120,23 @@ pub(crate) fn unnecessary_builtin_import( }, stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let statement = checker.semantic().current_statement(); - let parent = checker.semantic().current_statement_parent(); - let edit = fix::edits::remove_unused_imports( - unused_imports - .iter() - .map(|alias| &alias.name) - .map(ruff_python_ast::Identifier::as_str), - statement, - parent, - checker.locator(), - checker.stylist(), - checker.indexer(), - )?; - Ok(Fix::unsafe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_parent_id(), - ))) - }); - } + diagnostic.try_set_fix(|| { + let statement = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); + let edit = fix::edits::remove_unused_imports( + unused_imports + .iter() + .map(|alias| &alias.name) + .map(ruff_python_ast::Identifier::as_str), + statement, + parent, + checker.locator(), + checker.stylist(), + checker.indexer(), + )?; + Ok(Fix::unsafe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_class_parentheses.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_class_parentheses.rs index fa9db452df..fdb3612d2b 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_class_parentheses.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_class_parentheses.rs @@ -4,7 +4,6 @@ use ruff_python_ast::{self as ast}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for class definitions that include unnecessary parentheses after @@ -50,11 +49,9 @@ pub(crate) fn unnecessary_class_parentheses(checker: &mut Checker, class_def: &a } let mut diagnostic = Diagnostic::new(UnnecessaryClassParentheses, arguments.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::deletion( - arguments.start(), - arguments.end(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::deletion( + arguments.start(), + arguments.end(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_coding_comment.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_coding_comment.rs index 54f86ad125..46ed24c176 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_coding_comment.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_coding_comment.rs @@ -7,9 +7,6 @@ use ruff_python_index::Indexer; use ruff_source_file::Locator; use ruff_text_size::{Ranged, TextRange}; -use crate::registry::AsRule; -use crate::settings::LinterSettings; - /// ## What it does /// Checks for unnecessary UTF-8 encoding declarations. /// @@ -52,7 +49,6 @@ pub(crate) fn unnecessary_coding_comment( diagnostics: &mut Vec, locator: &Locator, indexer: &Indexer, - settings: &LinterSettings, ) { // The coding comment must be on one of the first two lines. Since each comment spans at least // one line, we only need to check the first two comments at most. @@ -91,12 +87,10 @@ pub(crate) fn unnecessary_coding_comment( } let mut diagnostic = Diagnostic::new(UTF8EncodingDeclaration, *comment_range); - if settings.rules.should_fix(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::deletion( - line_range.start(), - line_range.end(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::deletion( + line_range.start(), + line_range.end(), + ))); diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs index 02a6385f21..9cc79ce4da 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_encode_utf8.rs @@ -7,7 +7,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits::{pad, remove_argument, Parentheses}; -use crate::registry::Rule; /// ## What it does /// Checks for unnecessary calls to `encode` as UTF-8. @@ -177,13 +176,11 @@ pub(crate) fn unnecessary_encode_utf8(checker: &mut Checker, call: &ast::ExprCal }, call.range(), ); - if checker.patch(Rule::UnnecessaryEncodeUTF8) { - diagnostic.set_fix(replace_with_bytes_literal( - checker.locator(), - call, - checker.source_type, - )); - } + diagnostic.set_fix(replace_with_bytes_literal( + checker.locator(), + call, + checker.source_type, + )); checker.diagnostics.push(diagnostic); } else if let EncodingArg::Keyword(kwarg) = encoding_arg { // Ex) Convert `"unicode text©".encode(encoding="utf-8")` to @@ -194,17 +191,15 @@ pub(crate) fn unnecessary_encode_utf8(checker: &mut Checker, call: &ast::ExprCal }, call.range(), ); - if checker.patch(Rule::UnnecessaryEncodeUTF8) { - diagnostic.try_set_fix(|| { - remove_argument( - kwarg, - &call.arguments, - Parentheses::Preserve, - checker.locator().contents(), - ) - .map(Fix::safe_edit) - }); - } + diagnostic.try_set_fix(|| { + remove_argument( + kwarg, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), + ) + .map(Fix::safe_edit) + }); checker.diagnostics.push(diagnostic); } else if let EncodingArg::Positional(arg) = encoding_arg { // Ex) Convert `"unicode text©".encode("utf-8")` to `"unicode text©".encode()`. @@ -214,17 +209,15 @@ pub(crate) fn unnecessary_encode_utf8(checker: &mut Checker, call: &ast::ExprCal }, call.range(), ); - if checker.patch(Rule::UnnecessaryEncodeUTF8) { - diagnostic.try_set_fix(|| { - remove_argument( - arg, - &call.arguments, - Parentheses::Preserve, - checker.locator().contents(), - ) - .map(Fix::safe_edit) - }); - } + diagnostic.try_set_fix(|| { + remove_argument( + arg, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), + ) + .map(Fix::safe_edit) + }); checker.diagnostics.push(diagnostic); } } @@ -241,17 +234,15 @@ pub(crate) fn unnecessary_encode_utf8(checker: &mut Checker, call: &ast::ExprCal }, call.range(), ); - if checker.patch(Rule::UnnecessaryEncodeUTF8) { - diagnostic.try_set_fix(|| { - remove_argument( - kwarg, - &call.arguments, - Parentheses::Preserve, - checker.locator().contents(), - ) - .map(Fix::safe_edit) - }); - } + diagnostic.try_set_fix(|| { + remove_argument( + kwarg, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), + ) + .map(Fix::safe_edit) + }); checker.diagnostics.push(diagnostic); } else if let EncodingArg::Positional(arg) = encoding_arg { // Ex) Convert `f"unicode text©".encode("utf-8")` to `f"unicode text©".encode()`. @@ -261,17 +252,15 @@ pub(crate) fn unnecessary_encode_utf8(checker: &mut Checker, call: &ast::ExprCal }, call.range(), ); - if checker.patch(Rule::UnnecessaryEncodeUTF8) { - diagnostic.try_set_fix(|| { - remove_argument( - arg, - &call.arguments, - Parentheses::Preserve, - checker.locator().contents(), - ) - .map(Fix::safe_edit) - }); - } + diagnostic.try_set_fix(|| { + remove_argument( + arg, + &call.arguments, + Parentheses::Preserve, + checker.locator().contents(), + ) + .map(Fix::safe_edit) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_future_import.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_future_import.rs index a191027e89..c713a04673 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_future_import.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/unnecessary_future_import.rs @@ -7,7 +7,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix; -use crate::registry::AsRule; /// ## What it does /// Checks for unnecessary `__future__` imports. @@ -110,25 +109,23 @@ pub(crate) fn unnecessary_future_import(checker: &mut Checker, stmt: &Stmt, name stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let statement = checker.semantic().current_statement(); - let parent = checker.semantic().current_statement_parent(); - let edit = fix::edits::remove_unused_imports( - unused_imports - .iter() - .map(|alias| &alias.name) - .map(ruff_python_ast::Identifier::as_str), - statement, - parent, - checker.locator(), - checker.stylist(), - checker.indexer(), - )?; - Ok(Fix::safe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_parent_id(), - ))) - }); - } + diagnostic.try_set_fix(|| { + let statement = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); + let edit = fix::edits::remove_unused_imports( + unused_imports + .iter() + .map(|alias| &alias.name) + .map(ruff_python_ast::Identifier::as_str), + statement, + parent, + checker.locator(), + checker.stylist(), + checker.indexer(), + )?; + Ok(Fix::safe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs index d195c0bd3c..383b28114e 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/unpacked_list_comprehension.rs @@ -6,7 +6,6 @@ use ruff_python_ast::helpers::any_over_expr; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for list comprehensions that are immediately unpacked. @@ -67,18 +66,16 @@ pub(crate) fn unpacked_list_comprehension(checker: &mut Checker, targets: &[Expr } let mut diagnostic = Diagnostic::new(UnpackedListComprehension, value.range()); - if checker.patch(diagnostic.kind.rule()) { - let existing = checker.locator().slice(value); + let existing = checker.locator().slice(value); - let mut content = String::with_capacity(existing.len()); - content.push('('); - content.push_str(&existing[1..existing.len() - 1]); - content.push(')'); - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - content, - value.range(), - ))); - } + let mut content = String::with_capacity(existing.len()); + content.push('('); + content.push_str(&existing[1..existing.len() - 1]); + content.push(')'); + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + content, + value.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep585_annotation.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep585_annotation.rs index 5da988cbdf..3b91cd6504 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep585_annotation.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep585_annotation.rs @@ -8,7 +8,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; /// ## What it does /// Checks for the use of generics that can be replaced with standard library @@ -86,31 +85,29 @@ pub(crate) fn use_pep585_annotation( }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if !checker.semantic().in_complex_string_type_definition() { - match replacement { - ModuleMember::BuiltIn(name) => { - // Built-in type, like `list`. - if checker.semantic().is_builtin(name) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - (*name).to_string(), - expr.range(), - ))); - } - } - ModuleMember::Member(module, member) => { - // Imported type, like `collections.deque`. - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import_from(module, member), - expr.start(), - checker.semantic(), - )?; - let reference_edit = Edit::range_replacement(binding, expr.range()); - Ok(Fix::unsafe_edits(import_edit, [reference_edit])) - }); + if !checker.semantic().in_complex_string_type_definition() { + match replacement { + ModuleMember::BuiltIn(name) => { + // Built-in type, like `list`. + if checker.semantic().is_builtin(name) { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + (*name).to_string(), + expr.range(), + ))); } } + ModuleMember::Member(module, member) => { + // Imported type, like `collections.deque`. + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import_from(module, member), + expr.start(), + checker.semantic(), + )?; + let reference_edit = Edit::range_replacement(binding, expr.range()); + Ok(Fix::unsafe_edits(import_edit, [reference_edit])) + }); + } } } checker.diagnostics.push(diagnostic); diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_annotation.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_annotation.rs index b070ac6c69..3e3666d39a 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_annotation.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_annotation.rs @@ -6,7 +6,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits::pad; -use crate::registry::AsRule; /// ## What it does /// Check for type annotations that can be rewritten based on [PEP 604] syntax. @@ -73,7 +72,7 @@ pub(crate) fn use_pep604_annotation( match operator { Pep604Operator::Optional => { let mut diagnostic = Diagnostic::new(NonPEP604Annotation, expr.range()); - if fixable && checker.patch(diagnostic.kind.rule()) { + if fixable { match slice { Expr::Tuple(_) => { // Invalid type annotation. @@ -94,7 +93,7 @@ pub(crate) fn use_pep604_annotation( } Pep604Operator::Union => { let mut diagnostic = Diagnostic::new(NonPEP604Annotation, expr.range()); - if fixable && checker.patch(diagnostic.kind.rule()) { + if fixable { match slice { Expr::Slice(_) => { // Invalid type annotation. diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_isinstance.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_isinstance.rs index 4849dda185..550987f839 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_isinstance.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_isinstance.rs @@ -6,7 +6,6 @@ use ruff_python_ast::{self as ast, Expr, Operator}; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; -use crate::registry::AsRule; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub(crate) enum CallKind { @@ -120,12 +119,10 @@ pub(crate) fn use_pep604_isinstance( } let mut diagnostic = Diagnostic::new(NonPEP604Isinstance { kind }, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - checker.generator().expr(&union(elts)), - types.range(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + checker.generator().expr(&union(elts)), + types.range(), + ))); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep695_type_alias.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep695_type_alias.rs index 22dd94d9ba..4e81b2e961 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep695_type_alias.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/use_pep695_type_alias.rs @@ -11,7 +11,7 @@ use ruff_python_semantic::SemanticModel; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; -use crate::{registry::AsRule, settings::types::PythonVersion}; +use crate::settings::types::PythonVersion; /// ## What it does /// Checks for use of `TypeAlias` annotation for declaring type aliases. @@ -94,64 +94,60 @@ pub(crate) fn non_pep695_type_alias(checker: &mut Checker, stmt: &StmtAnnAssign) // TODO(zanie): We should check for generic type variables used in the value and define them // as type params instead let mut diagnostic = Diagnostic::new(NonPEP695TypeAlias { name: name.clone() }, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - let mut visitor = TypeVarReferenceVisitor { - vars: vec![], - semantic: checker.semantic(), - }; - visitor.visit_expr(value); + let mut visitor = TypeVarReferenceVisitor { + vars: vec![], + semantic: checker.semantic(), + }; + visitor.visit_expr(value); - let type_params = if visitor.vars.is_empty() { - None - } else { - Some(ast::TypeParams { - range: TextRange::default(), - type_params: visitor - .vars - .into_iter() - .map(|TypeVar { name, restriction }| { - TypeParam::TypeVar(TypeParamTypeVar { - range: TextRange::default(), - name: Identifier::new(name.id.clone(), TextRange::default()), - bound: match restriction { - Some(TypeVarRestriction::Bound(bound)) => { - Some(Box::new(bound.clone())) - } - Some(TypeVarRestriction::Constraint(constraints)) => { - Some(Box::new(Expr::Tuple(ast::ExprTuple { - range: TextRange::default(), - elts: constraints.into_iter().cloned().collect(), - ctx: ast::ExprContext::Load, - }))) - } - None => None, - }, - }) + let type_params = if visitor.vars.is_empty() { + None + } else { + Some(ast::TypeParams { + range: TextRange::default(), + type_params: visitor + .vars + .into_iter() + .map(|TypeVar { name, restriction }| { + TypeParam::TypeVar(TypeParamTypeVar { + range: TextRange::default(), + name: Identifier::new(name.id.clone(), TextRange::default()), + bound: match restriction { + Some(TypeVarRestriction::Bound(bound)) => Some(Box::new(bound.clone())), + Some(TypeVarRestriction::Constraint(constraints)) => { + Some(Box::new(Expr::Tuple(ast::ExprTuple { + range: TextRange::default(), + elts: constraints.into_iter().cloned().collect(), + ctx: ast::ExprContext::Load, + }))) + } + None => None, + }, }) - .collect(), - }) - }; + }) + .collect(), + }) + }; - let edit = Edit::range_replacement( - checker.generator().stmt(&Stmt::from(StmtTypeAlias { - range: TextRange::default(), - name: target.clone(), - type_params, - value: value.clone(), - })), - stmt.range(), - ); + let edit = Edit::range_replacement( + checker.generator().stmt(&Stmt::from(StmtTypeAlias { + range: TextRange::default(), + name: target.clone(), + type_params, + value: value.clone(), + })), + stmt.range(), + ); - // The fix is only safe in a type stub because new-style aliases have different runtime behavior - // See https://github.com/astral-sh/ruff/issues/6434 - let fix = if checker.source_type.is_stub() { - Fix::safe_edit(edit) - } else { - Fix::unsafe_edit(edit) - }; + // The fix is only safe in a type stub because new-style aliases have different runtime behavior + // See https://github.com/astral-sh/ruff/issues/6434 + let fix = if checker.source_type.is_stub() { + Fix::safe_edit(edit) + } else { + Fix::unsafe_edit(edit) + }; - diagnostic.set_fix(fix); - } + diagnostic.set_fix(fix); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/useless_metaclass_type.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/useless_metaclass_type.rs index 0b635353a3..612c94644c 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/useless_metaclass_type.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/useless_metaclass_type.rs @@ -6,7 +6,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix; -use crate::registry::AsRule; /// ## What it does /// Checks for the use of `__metaclass__ = type` in class definitions. @@ -63,13 +62,11 @@ pub(crate) fn useless_metaclass_type( } let mut diagnostic = Diagnostic::new(UselessMetaclassType, stmt.range()); - if checker.patch(diagnostic.kind.rule()) { - let stmt = checker.semantic().current_statement(); - let parent = checker.semantic().current_statement_parent(); - let edit = fix::edits::delete_stmt(stmt, parent, checker.locator(), checker.indexer()); - diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( - checker.semantic().current_statement_parent_id(), - ))); - } + let stmt = checker.semantic().current_statement(); + let parent = checker.semantic().current_statement_parent(); + let edit = fix::edits::delete_stmt(stmt, parent, checker.locator(), checker.indexer()); + diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation( + checker.semantic().current_statement_parent_id(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/useless_object_inheritance.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/useless_object_inheritance.rs index dfd5d878a4..83f9a417e8 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/useless_object_inheritance.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/useless_object_inheritance.rs @@ -5,7 +5,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix::edits::{remove_argument, Parentheses}; -use crate::registry::AsRule; /// ## What it does /// Checks for classes that inherit from `object`. @@ -68,17 +67,15 @@ pub(crate) fn useless_object_inheritance(checker: &mut Checker, class_def: &ast: }, base.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - remove_argument( - base, - arguments, - Parentheses::Remove, - checker.locator().contents(), - ) - .map(Fix::safe_edit) - }); - } + diagnostic.try_set_fix(|| { + remove_argument( + base, + arguments, + Parentheses::Remove, + checker.locator().contents(), + ) + .map(Fix::safe_edit) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/yield_in_for_loop.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/yield_in_for_loop.rs index 8cbd87ae5c..6325cc9fd2 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/yield_in_for_loop.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/yield_in_for_loop.rs @@ -5,7 +5,6 @@ use ruff_python_ast::{self as ast, Expr, Stmt}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `for` loops that can be replaced with `yield from` expressions. @@ -103,22 +102,20 @@ pub(crate) fn yield_in_for_loop(checker: &mut Checker, stmt_for: &ast::StmtFor) } let mut diagnostic = Diagnostic::new(YieldInForLoop, stmt_for.range()); - if checker.patch(diagnostic.kind.rule()) { - let contents = checker.locator().slice( - parenthesized_range( - iter.as_ref().into(), - stmt_for.into(), - checker.indexer().comment_ranges(), - checker.locator().contents(), - ) - .unwrap_or(iter.range()), - ); - let contents = format!("yield from {contents}"); - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - contents, - stmt_for.range(), - ))); - } + let contents = checker.locator().slice( + parenthesized_range( + iter.as_ref().into(), + stmt_for.into(), + checker.indexer().comment_ranges(), + checker.locator().contents(), + ) + .unwrap_or(iter.range()), + ); + let contents = format!("yield from {contents}"); + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + contents, + stmt_for.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/refurb/rules/check_and_remove_from_set.rs b/crates/ruff_linter/src/rules/refurb/rules/check_and_remove_from_set.rs index 785d1981c8..083c9a05e0 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/check_and_remove_from_set.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/check_and_remove_from_set.rs @@ -9,7 +9,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::snippet::SourceCodeSnippet; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `set.remove` that can be replaced with `set.discard`. @@ -112,13 +111,11 @@ pub(crate) fn check_and_remove_from_set(checker: &mut Checker, if_stmt: &ast::St }, if_stmt.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement( - make_suggestion(check_set, check_element, checker.generator()), - if_stmt.start(), - if_stmt.end(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement( + make_suggestion(check_set, check_element, checker.generator()), + if_stmt.start(), + if_stmt.end(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/refurb/rules/delete_full_slice.rs b/crates/ruff_linter/src/rules/refurb/rules/delete_full_slice.rs index 931723b721..c7ce2b218c 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/delete_full_slice.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/delete_full_slice.rs @@ -6,7 +6,7 @@ use ruff_python_semantic::{Binding, SemanticModel}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::refurb::helpers::generate_method_call; /// ## What it does @@ -69,7 +69,7 @@ pub(crate) fn delete_full_slice(checker: &mut Checker, delete: &ast::StmtDelete) let mut diagnostic = Diagnostic::new(DeleteFullSlice, delete.range); // Fix is only supported for single-target deletions. - if checker.patch(diagnostic.kind.rule()) && delete.targets.len() == 1 { + if delete.targets.len() == 1 { let replacement = generate_method_call(name, "clear", checker.generator()); diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement( replacement, diff --git a/crates/ruff_linter/src/rules/refurb/rules/implicit_cwd.rs b/crates/ruff_linter/src/rules/refurb/rules/implicit_cwd.rs index 35317cef41..a4cf83d557 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/implicit_cwd.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/implicit_cwd.rs @@ -3,7 +3,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::{self as ast, Constant, Expr, ExprAttribute, ExprCall}; use ruff_text_size::Ranged; -use crate::{checkers::ast::Checker, importer::ImportRequest, registry::AsRule}; +use crate::{checkers::ast::Checker, importer::ImportRequest}; /// ## What it does /// Checks for current-directory lookups using `Path().resolve()`. @@ -88,19 +88,17 @@ pub(crate) fn no_implicit_cwd(checker: &mut Checker, call: &ExprCall) { let mut diagnostic = Diagnostic::new(ImplicitCwd, call.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import("pathlib", "Path"), - call.start(), - checker.semantic(), - )?; - Ok(Fix::unsafe_edits( - Edit::range_replacement(format!("{binding}.cwd()"), call.range()), - [import_edit], - )) - }); - } + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import("pathlib", "Path"), + call.start(), + checker.semantic(), + )?; + Ok(Fix::unsafe_edits( + Edit::range_replacement(format!("{binding}.cwd()"), call.range()), + [import_edit], + )) + }); checker .diagnostics diff --git a/crates/ruff_linter/src/rules/refurb/rules/print_empty_string.rs b/crates/ruff_linter/src/rules/refurb/rules/print_empty_string.rs index d267c48042..e450cf3098 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/print_empty_string.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/print_empty_string.rs @@ -5,7 +5,6 @@ use ruff_python_codegen::Generator; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for `print` calls with an empty string as the only positional @@ -87,13 +86,11 @@ pub(crate) fn print_empty_string(checker: &mut Checker, call: &ast::ExprCall) { let mut diagnostic = Diagnostic::new(PrintEmptyString { reason }, call.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - generate_suggestion(call, Separator::Remove, checker.generator()), - call.start(), - call.end(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + generate_suggestion(call, Separator::Remove, checker.generator()), + call.start(), + call.end(), + ))); checker.diagnostics.push(diagnostic); } @@ -109,13 +106,11 @@ pub(crate) fn print_empty_string(checker: &mut Checker, call: &ast::ExprCall) { call.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - generate_suggestion(call, Separator::Remove, checker.generator()), - call.start(), - call.end(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + generate_suggestion(call, Separator::Remove, checker.generator()), + call.start(), + call.end(), + ))); checker.diagnostics.push(diagnostic); } @@ -174,13 +169,11 @@ pub(crate) fn print_empty_string(checker: &mut Checker, call: &ast::ExprCall) { call.range(), ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - generate_suggestion(call, separator, checker.generator()), - call.start(), - call.end(), - ))); - } + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + generate_suggestion(call, separator, checker.generator()), + call.start(), + call.end(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/refurb/rules/reimplemented_starmap.rs b/crates/ruff_linter/src/rules/refurb/rules/reimplemented_starmap.rs index 674ac5fa0d..8f380a187b 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/reimplemented_starmap.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/reimplemented_starmap.rs @@ -7,7 +7,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; /// ## What it does /// Checks for generator expressions, list and set comprehensions that can @@ -136,30 +135,28 @@ pub(crate) fn reimplemented_starmap(checker: &mut Checker, target: &StarmapCandi } let mut diagnostic = Diagnostic::new(ReimplementedStarmap, target.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - // Try importing `starmap` from `itertools`. - // - // It is not required to be `itertools.starmap`, though. The user might've already - // imported it. Maybe even under a different name. So, we should use that name - // for fix construction. - let (import_edit, starmap_name) = checker.importer().get_or_import_symbol( - &ImportRequest::import_from("itertools", "starmap"), - target.start(), - checker.semantic(), - )?; - // The actual fix suggestion depends on what type of expression we were looking at. - // - // - For generator expressions, we use `starmap` call directly. - // - For list and set comprehensions, we'd want to wrap it with `list` and `set` - // correspondingly. - let main_edit = Edit::range_replacement( - target.try_make_suggestion(starmap_name, &comprehension.iter, func, checker)?, - target.range(), - ); - Ok(Fix::safe_edits(import_edit, [main_edit])) - }); - } + diagnostic.try_set_fix(|| { + // Try importing `starmap` from `itertools`. + // + // It is not required to be `itertools.starmap`, though. The user might've already + // imported it. Maybe even under a different name. So, we should use that name + // for fix construction. + let (import_edit, starmap_name) = checker.importer().get_or_import_symbol( + &ImportRequest::import_from("itertools", "starmap"), + target.start(), + checker.semantic(), + )?; + // The actual fix suggestion depends on what type of expression we were looking at. + // + // - For generator expressions, we use `starmap` call directly. + // - For list and set comprehensions, we'd want to wrap it with `list` and `set` + // correspondingly. + let main_edit = Edit::range_replacement( + target.try_make_suggestion(starmap_name, &comprehension.iter, func, checker)?, + target.range(), + ); + Ok(Fix::safe_edits(import_edit, [main_edit])) + }); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/refurb/rules/repeated_append.rs b/crates/ruff_linter/src/rules/refurb/rules/repeated_append.rs index d68502798a..7ca2ab2acc 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/repeated_append.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/repeated_append.rs @@ -11,7 +11,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::snippet::SourceCodeSnippet; -use crate::registry::AsRule; /// ## What it does /// Checks for consecutive calls to `append`. @@ -107,7 +106,7 @@ pub(crate) fn repeated_append(checker: &mut Checker, stmt: &Stmt) { // We only suggest a fix when all appends in a group are clumped together. If they're // non-consecutive, fixing them is much more difficult. - if checker.patch(diagnostic.kind.rule()) && group.is_consecutive { + if group.is_consecutive { diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement( replacement, group.start(), diff --git a/crates/ruff_linter/src/rules/refurb/rules/single_item_membership_test.rs b/crates/ruff_linter/src/rules/refurb/rules/single_item_membership_test.rs index 10ba36daa6..8e828942bf 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/single_item_membership_test.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/single_item_membership_test.rs @@ -7,7 +7,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::fix::edits::pad; -use crate::registry::AsRule; /// ## What it does /// Checks for membership tests against single-item containers. @@ -78,23 +77,21 @@ pub(crate) fn single_item_membership_test( let mut diagnostic = Diagnostic::new(SingleItemMembershipTest { membership_test }, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( - pad( - generate_comparison( - left, - &[membership_test.replacement_op()], - &[item.clone()], - expr.into(), - checker.indexer().comment_ranges(), - checker.locator(), - ), - expr.range(), + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + pad( + generate_comparison( + left, + &[membership_test.replacement_op()], + &[item.clone()], + expr.into(), + checker.indexer().comment_ranges(), checker.locator(), ), expr.range(), - ))); - } + checker.locator(), + ), + expr.range(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/refurb/rules/slice_copy.rs b/crates/ruff_linter/src/rules/refurb/rules/slice_copy.rs index 591fb8f57e..3d4e6a203d 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/slice_copy.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/slice_copy.rs @@ -6,7 +6,7 @@ use ruff_python_semantic::{Binding, SemanticModel}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; + use crate::rules::refurb::helpers::generate_method_call; /// ## What it does @@ -61,14 +61,12 @@ pub(crate) fn slice_copy(checker: &mut Checker, subscript: &ast::ExprSubscript) return; }; let mut diagnostic = Diagnostic::new(SliceCopy, subscript.range()); - if checker.patch(diagnostic.kind.rule()) { - let replacement = generate_method_call(name, "copy", checker.generator()); - diagnostic.set_fix(Fix::safe_edit(Edit::replacement( - replacement, - subscript.start(), - subscript.end(), - ))); - } + let replacement = generate_method_call(name, "copy", checker.generator()); + diagnostic.set_fix(Fix::safe_edit(Edit::replacement( + replacement, + subscript.start(), + subscript.end(), + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/refurb/rules/unnecessary_enumerate.rs b/crates/ruff_linter/src/rules/refurb/rules/unnecessary_enumerate.rs index 09bb5f0616..b5652ec02b 100644 --- a/crates/ruff_linter/src/rules/refurb/rules/unnecessary_enumerate.rs +++ b/crates/ruff_linter/src/rules/refurb/rules/unnecessary_enumerate.rs @@ -11,7 +11,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::edits::pad; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `enumerate` that discard either the index or the value @@ -139,18 +138,16 @@ pub(crate) fn unnecessary_enumerate(checker: &mut Checker, stmt_for: &ast::StmtF ); // The index is unused, so replace with `for value in sequence`. - if checker.patch(diagnostic.kind.rule()) { - let replace_iter = Edit::range_replacement(sequence.into(), stmt_for.iter.range()); - let replace_target = Edit::range_replacement( - pad( - checker.locator().slice(value).to_string(), - stmt_for.target.range(), - checker.locator(), - ), + let replace_iter = Edit::range_replacement(sequence.into(), stmt_for.iter.range()); + let replace_target = Edit::range_replacement( + pad( + checker.locator().slice(value).to_string(), stmt_for.target.range(), - ); - diagnostic.set_fix(Fix::unsafe_edits(replace_iter, [replace_target])); - } + checker.locator(), + ), + stmt_for.target.range(), + ); + diagnostic.set_fix(Fix::unsafe_edits(replace_iter, [replace_target])); checker.diagnostics.push(diagnostic); } @@ -182,10 +179,7 @@ pub(crate) fn unnecessary_enumerate(checker: &mut Checker, stmt_for: &ast::StmtF }, func.range(), ); - if checker.patch(diagnostic.kind.rule()) - && checker.semantic().is_builtin("range") - && checker.semantic().is_builtin("len") - { + if checker.semantic().is_builtin("range") && checker.semantic().is_builtin("len") { // If the `start` argument is set to something other than the `range` default, // there's no clear fix. let start = arguments.find_argument("start", 1); diff --git a/crates/ruff_linter/src/rules/ruff/rules/collection_literal_concatenation.rs b/crates/ruff_linter/src/rules/ruff/rules/collection_literal_concatenation.rs index 1c602215ea..263ff68dc9 100644 --- a/crates/ruff_linter/src/rules/ruff/rules/collection_literal_concatenation.rs +++ b/crates/ruff_linter/src/rules/ruff/rules/collection_literal_concatenation.rs @@ -5,7 +5,6 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::fix::snippet::SourceCodeSnippet; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of the `+` operator to concatenate collections. @@ -198,15 +197,13 @@ pub(crate) fn collection_literal_concatenation(checker: &mut Checker, expr: &Exp }, expr.range(), ); - if checker.patch(diagnostic.kind.rule()) { - if !checker.indexer().has_comments(expr, checker.locator()) { - // This suggestion could be unsafe if the non-literal expression in the - // expression has overridden the `__add__` (or `__radd__`) magic methods. - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - contents, - expr.range(), - ))); - } + if !checker.indexer().has_comments(expr, checker.locator()) { + // This suggestion could be unsafe if the non-literal expression in the + // expression has overridden the `__add__` (or `__radd__`) magic methods. + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + contents, + expr.range(), + ))); } checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/ruff/rules/explicit_f_string_type_conversion.rs b/crates/ruff_linter/src/rules/ruff/rules/explicit_f_string_type_conversion.rs index b9d8985ce4..1931270157 100644 --- a/crates/ruff_linter/src/rules/ruff/rules/explicit_f_string_type_conversion.rs +++ b/crates/ruff_linter/src/rules/ruff/rules/explicit_f_string_type_conversion.rs @@ -12,7 +12,6 @@ use ruff_text_size::Ranged; use crate::checkers::ast::Checker; use crate::cst::matchers::{match_call_mut, match_name, transform_expression}; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `str()`, `repr()`, and `ascii()` as explicit type @@ -123,11 +122,9 @@ pub(crate) fn explicit_f_string_type_conversion( } let mut diagnostic = Diagnostic::new(ExplicitFStringTypeConversion, value.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| { - convert_call_to_conversion_flag(expr, index, checker.locator(), checker.stylist()) - }); - } + diagnostic.try_set_fix(|| { + convert_call_to_conversion_flag(expr, index, checker.locator(), checker.stylist()) + }); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/ruff/rules/implicit_optional.rs b/crates/ruff_linter/src/rules/ruff/rules/implicit_optional.rs index b3d721e90e..287ee0fbc1 100644 --- a/crates/ruff_linter/src/rules/ruff/rules/implicit_optional.rs +++ b/crates/ruff_linter/src/rules/ruff/rules/implicit_optional.rs @@ -11,7 +11,7 @@ use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::registry::AsRule; + use crate::settings::types::PythonVersion; use super::super::typing::type_hint_explicitly_allows_none; @@ -205,10 +205,8 @@ pub(crate) fn implicit_optional(checker: &mut Checker, parameters: &Parameters) let mut diagnostic = Diagnostic::new(ImplicitOptional { conversion_type }, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - if kind.is_simple() { - diagnostic.try_set_fix(|| generate_fix(checker, conversion_type, expr)); - } + if kind.is_simple() { + diagnostic.try_set_fix(|| generate_fix(checker, conversion_type, expr)); } checker.diagnostics.push(diagnostic); } @@ -226,9 +224,7 @@ pub(crate) fn implicit_optional(checker: &mut Checker, parameters: &Parameters) let mut diagnostic = Diagnostic::new(ImplicitOptional { conversion_type }, expr.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.try_set_fix(|| generate_fix(checker, conversion_type, expr)); - } + diagnostic.try_set_fix(|| generate_fix(checker, conversion_type, expr)); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/ruff/rules/quadratic_list_summation.rs b/crates/ruff_linter/src/rules/ruff/rules/quadratic_list_summation.rs index b5c9dc294f..9fe896d28d 100644 --- a/crates/ruff_linter/src/rules/ruff/rules/quadratic_list_summation.rs +++ b/crates/ruff_linter/src/rules/ruff/rules/quadratic_list_summation.rs @@ -9,8 +9,8 @@ use ruff_python_ast::{self as ast, Arguments, Expr}; use ruff_python_semantic::SemanticModel; use ruff_text_size::Ranged; +use crate::checkers::ast::Checker; use crate::importer::ImportRequest; -use crate::{checkers::ast::Checker, registry::Rule}; /// ## What it does /// Checks for the use of `sum()` to flatten lists of lists, which has @@ -82,9 +82,7 @@ pub(crate) fn quadratic_list_summation(checker: &mut Checker, call: &ast::ExprCa }; let mut diagnostic = Diagnostic::new(QuadraticListSummation, *range); - if checker.patch(Rule::QuadraticListSummation) { - diagnostic.try_set_fix(|| convert_to_reduce(iterable, call, checker)); - } + diagnostic.try_set_fix(|| convert_to_reduce(iterable, call, checker)); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs b/crates/ruff_linter/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs index 6c5265fadc..fc5b0a88b2 100644 --- a/crates/ruff_linter/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs +++ b/crates/ruff_linter/src/rules/ruff/rules/unnecessary_iterable_allocation_for_first_element.rs @@ -9,7 +9,6 @@ use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::checkers::ast::Checker; use crate::fix::snippet::SourceCodeSnippet; -use crate::registry::AsRule; /// ## What it does /// Checks for uses of `list(...)[0]` that can be replaced with @@ -97,12 +96,10 @@ pub(crate) fn unnecessary_iterable_allocation_for_first_element( *range, ); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - format!("next({iterable})"), - *range, - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + format!("next({iterable})"), + *range, + ))); checker.diagnostics.push(diagnostic); } diff --git a/crates/ruff_linter/src/rules/tryceratops/rules/verbose_raise.rs b/crates/ruff_linter/src/rules/tryceratops/rules/verbose_raise.rs index 702e416257..bfe623a0a0 100644 --- a/crates/ruff_linter/src/rules/tryceratops/rules/verbose_raise.rs +++ b/crates/ruff_linter/src/rules/tryceratops/rules/verbose_raise.rs @@ -6,7 +6,6 @@ use ruff_python_ast::statement_visitor::{walk_stmt, StatementVisitor}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; -use crate::registry::AsRule; /// ## What it does /// Checks for needless exception names in `raise` statements. @@ -96,12 +95,10 @@ pub(crate) fn verbose_raise(checker: &mut Checker, handlers: &[ExceptHandler]) { if let Expr::Name(ast::ExprName { id, .. }) = exc.as_ref() { if id == exception_name.as_str() { let mut diagnostic = Diagnostic::new(VerboseRaise, exc.range()); - if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( - "raise".to_string(), - raise.range(), - ))); - } + diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement( + "raise".to_string(), + raise.range(), + ))); checker.diagnostics.push(diagnostic); } }