diff --git a/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py b/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py index 38cead687f..5ef0b007c3 100644 --- a/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py +++ b/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py @@ -19,11 +19,20 @@ raise TypeError () raise TypeError \ () +# RSE102 +raise TypeError \ + (); + # RSE102 raise TypeError( ) +# RSE102 +raise (TypeError) ( + +) + # RSE102 raise TypeError( # Hello, world! diff --git a/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs b/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs index b1374367c4..bd54d74304 100644 --- a/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs +++ b/crates/ruff/src/rules/flake8_raise/rules/unnecessary_paren_on_raise_exception.rs @@ -1,10 +1,6 @@ -use ruff_python_ast::{self as ast, Arguments, Expr, PySourceType, Ranged}; -use ruff_python_parser::{lexer, AsMode, Tok}; -use ruff_text_size::{TextRange, TextSize}; - use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_source_file::Locator; +use ruff_python_ast::{self as ast, Expr, Ranged}; use crate::checkers::ast::Checker; use crate::registry::AsRule; @@ -49,19 +45,14 @@ impl AlwaysAutofixableViolation for UnnecessaryParenOnRaiseException { pub(crate) fn unnecessary_paren_on_raise_exception(checker: &mut Checker, expr: &Expr) { let Expr::Call(ast::ExprCall { func, - arguments: - Arguments { - args, - keywords, - range: _, - }, + arguments, range: _, }) = expr else { return; }; - if args.is_empty() && keywords.is_empty() { + if arguments.is_empty() { // `raise func()` still requires parentheses; only `raise Class()` does not. if checker .semantic() @@ -81,49 +72,10 @@ pub(crate) fn unnecessary_paren_on_raise_exception(checker: &mut Checker, expr: return; } - let range = match_parens(func.end(), checker.locator(), checker.source_type) - .expect("Expected call to include parentheses"); - let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, range); + let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, arguments.range()); if checker.patch(diagnostic.kind.rule()) { - diagnostic.set_fix(Fix::automatic(Edit::deletion(func.end(), range.end()))); + diagnostic.set_fix(Fix::automatic(Edit::range_deletion(arguments.range()))); } checker.diagnostics.push(diagnostic); } } - -/// Return the range of the first parenthesis pair after a given [`TextSize`]. -fn match_parens( - start: TextSize, - locator: &Locator, - source_type: PySourceType, -) -> Option { - let contents = &locator.contents()[usize::from(start)..]; - - let mut fix_start = None; - let mut fix_end = None; - let mut count = 0u32; - - for (tok, range) in lexer::lex_starts_at(contents, source_type.as_mode(), start).flatten() { - match tok { - Tok::Lpar => { - if count == 0 { - fix_start = Some(range.start()); - } - count = count.saturating_add(1); - } - Tok::Rpar => { - count = count.saturating_sub(1); - if count == 0 { - fix_end = Some(range.end()); - break; - } - } - _ => {} - } - } - - match (fix_start, fix_end) { - (Some(start), Some(end)) => Some(TextRange::new(start, end)), - _ => None, - } -} diff --git a/crates/ruff/src/rules/flake8_raise/snapshots/ruff__rules__flake8_raise__tests__unnecessary-paren-on-raise-exception_RSE102.py.snap b/crates/ruff/src/rules/flake8_raise/snapshots/ruff__rules__flake8_raise__tests__unnecessary-paren-on-raise-exception_RSE102.py.snap index 4f905dd654..61b7f00a95 100644 --- a/crates/ruff/src/rules/flake8_raise/snapshots/ruff__rules__flake8_raise__tests__unnecessary-paren-on-raise-exception_RSE102.py.snap +++ b/crates/ruff/src/rules/flake8_raise/snapshots/ruff__rules__flake8_raise__tests__unnecessary-paren-on-raise-exception_RSE102.py.snap @@ -57,7 +57,7 @@ RSE102.py:16:17: RSE102 [*] Unnecessary parentheses on raised exception 14 14 | 15 15 | # RSE102 16 |-raise TypeError () - 16 |+raise TypeError + 16 |+raise TypeError 17 17 | 18 18 | # RSE102 19 19 | raise TypeError \ @@ -74,64 +74,109 @@ RSE102.py:20:5: RSE102 [*] Unnecessary parentheses on raised exception = help: Remove unnecessary parentheses ℹ Fix -16 16 | raise TypeError () 17 17 | 18 18 | # RSE102 -19 |-raise TypeError \ +19 19 | raise TypeError \ 20 |- () - 19 |+raise TypeError -21 20 | -22 21 | # RSE102 -23 22 | raise TypeError( - -RSE102.py:23:16: RSE102 [*] Unnecessary parentheses on raised exception - | -22 | # RSE102 -23 | raise TypeError( - | ________________^ -24 | | -25 | | ) - | |_^ RSE102 -26 | -27 | # RSE102 - | - = help: Remove unnecessary parentheses - -ℹ Fix -20 20 | () + 20 |+ 21 21 | 22 22 | # RSE102 -23 |-raise TypeError( -24 |- -25 |-) - 23 |+raise TypeError -26 24 | -27 25 | # RSE102 -28 26 | raise TypeError( +23 23 | raise TypeError \ -RSE102.py:28:16: RSE102 [*] Unnecessary parentheses on raised exception +RSE102.py:24:5: RSE102 [*] Unnecessary parentheses on raised exception | -27 | # RSE102 -28 | raise TypeError( - | ________________^ -29 | | # Hello, world! -30 | | ) - | |_^ RSE102 -31 | -32 | # OK +22 | # RSE102 +23 | raise TypeError \ +24 | (); + | ^^ RSE102 +25 | +26 | # RSE102 | = help: Remove unnecessary parentheses ℹ Fix -25 25 | ) -26 26 | -27 27 | # RSE102 -28 |-raise TypeError( -29 |- # Hello, world! -30 |-) - 28 |+raise TypeError -31 29 | -32 30 | # OK -33 31 | raise AssertionError +21 21 | +22 22 | # RSE102 +23 23 | raise TypeError \ +24 |- (); + 24 |+ ; +25 25 | +26 26 | # RSE102 +27 27 | raise TypeError( + +RSE102.py:27:16: RSE102 [*] Unnecessary parentheses on raised exception + | +26 | # RSE102 +27 | raise TypeError( + | ________________^ +28 | | +29 | | ) + | |_^ RSE102 +30 | +31 | # RSE102 + | + = help: Remove unnecessary parentheses + +ℹ Fix +24 24 | (); +25 25 | +26 26 | # RSE102 +27 |-raise TypeError( +28 |- +29 |-) + 27 |+raise TypeError +30 28 | +31 29 | # RSE102 +32 30 | raise (TypeError) ( + +RSE102.py:32:19: RSE102 [*] Unnecessary parentheses on raised exception + | +31 | # RSE102 +32 | raise (TypeError) ( + | ___________________^ +33 | | +34 | | ) + | |_^ RSE102 +35 | +36 | # RSE102 + | + = help: Remove unnecessary parentheses + +ℹ Fix +29 29 | ) +30 30 | +31 31 | # RSE102 +32 |-raise (TypeError) ( +33 |- +34 |-) + 32 |+raise (TypeError) +35 33 | +36 34 | # RSE102 +37 35 | raise TypeError( + +RSE102.py:37:16: RSE102 [*] Unnecessary parentheses on raised exception + | +36 | # RSE102 +37 | raise TypeError( + | ________________^ +38 | | # Hello, world! +39 | | ) + | |_^ RSE102 +40 | +41 | # OK + | + = help: Remove unnecessary parentheses + +ℹ Fix +34 34 | ) +35 35 | +36 36 | # RSE102 +37 |-raise TypeError( +38 |- # Hello, world! +39 |-) + 37 |+raise TypeError +40 38 | +41 39 | # OK +42 40 | raise AssertionError