diff --git a/crates/ruff/src/checkers/ast/analyze/expression.rs b/crates/ruff/src/checkers/ast/analyze/expression.rs index 6c1af752df..2ec42610ee 100644 --- a/crates/ruff/src/checkers/ast/analyze/expression.rs +++ b/crates/ruff/src/checkers/ast/analyze/expression.rs @@ -432,7 +432,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { pyupgrade::rules::deprecated_unittest_alias(checker, func); } if checker.enabled(Rule::SuperCallWithParameters) { - pyupgrade::rules::super_call_with_parameters(checker, expr, func, args); + pyupgrade::rules::super_call_with_parameters(checker, call); } if checker.enabled(Rule::UnnecessaryEncodeUTF8) { pyupgrade::rules::unnecessary_encode_utf8(checker, call); diff --git a/crates/ruff/src/rules/pyupgrade/fixes.rs b/crates/ruff/src/rules/pyupgrade/fixes.rs index 9c9d315db0..648d644f3c 100644 --- a/crates/ruff/src/rules/pyupgrade/fixes.rs +++ b/crates/ruff/src/rules/pyupgrade/fixes.rs @@ -1,17 +1,12 @@ use anyhow::Result; -use libcst_native::ParenthesizableWhitespace; -use ruff_python_ast::{Expr, Ranged}; + +use ruff_python_codegen::Stylist; use ruff_python_parser::{lexer, Mode, Tok}; +use ruff_source_file::Locator; use ruff_text_size::{TextRange, TextSize}; use crate::autofix::codemods::CodegenStylist; -use ruff_diagnostics::Edit; -use ruff_python_codegen::Stylist; -use ruff_source_file::Locator; - -use crate::cst::matchers::{ - match_call_mut, match_expression, match_function_def, match_indented_block, match_statement, -}; +use crate::cst::matchers::{match_function_def, match_indented_block, match_statement}; /// Safely adjust the indentation of the indented block at [`TextRange`]. pub(crate) fn adjust_indentation( @@ -39,29 +34,6 @@ pub(crate) fn adjust_indentation( Ok(module_text) } -/// Generate a fix to remove arguments from a `super` call. -pub(crate) fn remove_super_arguments( - locator: &Locator, - stylist: &Stylist, - expr: &Expr, -) -> Option { - let range = expr.range(); - let contents = locator.slice(range); - - let mut tree = match_expression(contents).ok()?; - - let body = match_call_mut(&mut tree).ok()?; - - body.args = vec![]; - body.whitespace_before_args = ParenthesizableWhitespace::default(); - body.whitespace_after_func = ParenthesizableWhitespace::default(); - - Some(Edit::range_replacement( - tree.codegen_stylist(stylist), - range, - )) -} - /// Remove any imports matching `members` from an import-from statement. pub(crate) fn remove_import_members(contents: &str, members: &[&str]) -> String { let mut names: Vec = vec![]; diff --git a/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs b/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs index d8c6981aa0..8b247f2674 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs @@ -1,11 +1,10 @@ -use ruff_python_ast::{self as ast, Expr, Parameter, ParameterWithDefault, Ranged, Stmt}; - -use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix}; +use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{self as ast, Expr, Parameter, ParameterWithDefault, Ranged, Stmt}; +use ruff_text_size::TextSize; use crate::checkers::ast::Checker; use crate::registry::AsRule; -use crate::rules::pyupgrade::fixes; /// ## What it does /// Checks for `super` calls that pass redundant arguments. @@ -59,25 +58,11 @@ impl AlwaysAutofixableViolation for SuperCallWithParameters { } } -/// Returns `true` if a call is an argumented `super` invocation. -fn is_super_call_with_arguments(func: &Expr, args: &[Expr]) -> bool { - if let Expr::Name(ast::ExprName { id, .. }) = func { - id == "super" && !args.is_empty() - } else { - false - } -} - /// UP008 -pub(crate) fn super_call_with_parameters( - checker: &mut Checker, - expr: &Expr, - func: &Expr, - args: &[Expr], -) { +pub(crate) fn super_call_with_parameters(checker: &mut Checker, call: &ast::ExprCall) { // Only bother going through the super check at all if we're in a `super` call. // (We check this in `super_args` too, so this is just an optimization.) - if !is_super_call_with_arguments(func, args) { + if !is_super_call_with_arguments(call) { return; } let scope = checker.semantic().current_scope(); @@ -92,7 +77,7 @@ pub(crate) fn super_call_with_parameters( // For a `super` invocation to be unnecessary, the first argument needs to match // the enclosing class, and the second argument needs to match the first // argument to the enclosing function. - let [first_arg, second_arg] = args else { + let [first_arg, second_arg] = call.arguments.args.as_slice() else { return; }; @@ -142,13 +127,21 @@ pub(crate) fn super_call_with_parameters( drop(parents); - let mut diagnostic = Diagnostic::new(SuperCallWithParameters, expr.range()); + let mut diagnostic = Diagnostic::new(SuperCallWithParameters, call.arguments.range()); if checker.patch(diagnostic.kind.rule()) { - if let Some(edit) = - fixes::remove_super_arguments(checker.locator(), checker.stylist(), expr) - { - diagnostic.set_fix(Fix::suggested(edit)); - } + diagnostic.set_fix(Fix::suggested(Edit::deletion( + call.arguments.start() + TextSize::new(1), + call.arguments.end() - TextSize::new(1), + ))); } checker.diagnostics.push(diagnostic); } + +/// Returns `true` if a call is an argumented `super` invocation. +fn is_super_call_with_arguments(call: &ast::ExprCall) -> bool { + if let Expr::Name(ast::ExprName { id, .. }) = call.func.as_ref() { + id == "super" && !call.arguments.is_empty() + } else { + false + } +} diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP008.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP008.py.snap index 40458ff41e..afafaf4db3 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP008.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP008.py.snap @@ -1,11 +1,11 @@ --- source: crates/ruff/src/rules/pyupgrade/mod.rs --- -UP008.py:17:18: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:17:23: UP008 [*] Use `super()` instead of `super(__class__, self)` | 16 | def wrong(self): 17 | parent = super(Child, self) # wrong - | ^^^^^^^^^^^^^^^^^^ UP008 + | ^^^^^^^^^^^^^ UP008 18 | super(Child, self).method # wrong 19 | super( | @@ -21,12 +21,12 @@ UP008.py:17:18: UP008 [*] Use `super()` instead of `super(__class__, self)` 19 19 | super( 20 20 | Child, -UP008.py:18:9: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:18:14: UP008 [*] Use `super()` instead of `super(__class__, self)` | 16 | def wrong(self): 17 | parent = super(Child, self) # wrong 18 | super(Child, self).method # wrong - | ^^^^^^^^^^^^^^^^^^ UP008 + | ^^^^^^^^^^^^^ UP008 19 | super( 20 | Child, | @@ -42,12 +42,12 @@ UP008.py:18:9: UP008 [*] Use `super()` instead of `super(__class__, self)` 20 20 | Child, 21 21 | self, -UP008.py:19:9: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:19:14: UP008 [*] Use `super()` instead of `super(__class__, self)` | 17 | parent = super(Child, self) # wrong 18 | super(Child, self).method # wrong 19 | super( - | _________^ + | ______________^ 20 | | Child, 21 | | self, 22 | | ).method() # wrong @@ -68,12 +68,12 @@ UP008.py:19:9: UP008 [*] Use `super()` instead of `super(__class__, self)` 24 21 | 25 22 | class BaseClass: -UP008.py:36:9: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:36:14: UP008 [*] Use `super()` instead of `super(__class__, self)` | 34 | class MyClass(BaseClass): 35 | def normal(self): 36 | super(MyClass, self).f() # can use super() - | ^^^^^^^^^^^^^^^^^^^^ UP008 + | ^^^^^^^^^^^^^^^ UP008 37 | super().f() | = help: Remove `super` parameters @@ -88,11 +88,11 @@ UP008.py:36:9: UP008 [*] Use `super()` instead of `super(__class__, self)` 38 38 | 39 39 | def different_argument(self, other): -UP008.py:50:13: UP008 [*] Use `super()` instead of `super(__class__, self)` +UP008.py:50:18: UP008 [*] Use `super()` instead of `super(__class__, self)` | 49 | def inner_argument(self): 50 | super(MyClass, self).f() # can use super() - | ^^^^^^^^^^^^^^^^^^^^ UP008 + | ^^^^^^^^^^^^^^^ UP008 51 | super().f() | = help: Remove `super` parameters