From 409c417527f16c0ea32db7b3848c7bc323b5a1d2 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 5 Feb 2023 17:54:33 -0500 Subject: [PATCH] Enable autofix for unnecessary-paren-on-raise-exception --- .../test/fixtures/flake8_raise/RSE102.py | 23 +++- crates/ruff/src/ast/helpers.rs | 27 +++++ .../unnecessary_paren_on_raise_exception.rs | 30 +++-- ...ry-paren-on-raise-exception_RSE102.py.snap | 106 ++++++++++++++++-- 4 files changed, 166 insertions(+), 20 deletions(-) diff --git a/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py b/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py index ba377a856b2e17..aa80fa51452ac1 100644 --- a/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py +++ b/crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py @@ -1,14 +1,33 @@ try: y = 6 + "7" except TypeError: - raise ValueError() # RSE102 + # RSE102 + raise ValueError() try: x = 1 / 0 except ZeroDivisionError: raise -raise TypeError() # RSE102 +# RSE102 +raise TypeError() + +# RSE102 +raise TypeError () + +# RSE102 +raise TypeError \ + () + +# RSE102 +raise TypeError( + +) + +# RSE102 +raise TypeError( + # Hello, world! +) raise AssertionError diff --git a/crates/ruff/src/ast/helpers.rs b/crates/ruff/src/ast/helpers.rs index 1a0af0bf578cd0..4cb3af82f4b560 100644 --- a/crates/ruff/src/ast/helpers.rs +++ b/crates/ruff/src/ast/helpers.rs @@ -755,6 +755,33 @@ pub fn count_trailing_lines(stmt: &Stmt, locator: &Locator) -> usize { .count() } +/// Return the range of the first parenthesis pair after a given [`Location`]. +pub fn match_parens(start: Location, locator: &Locator) -> Option { + let contents = locator.slice_source_code_at(start); + let mut fix_start = None; + let mut fix_end = None; + let mut count: usize = 0; + for (start, tok, end) in lexer::make_tokenizer_located(contents, start).flatten() { + if matches!(tok, Tok::Lpar) { + if count == 0 { + fix_start = Some(start); + } + count += 1; + } + if matches!(tok, Tok::Rpar) { + count -= 1; + if count == 0 { + fix_end = Some(end); + break; + } + } + } + match (fix_start, fix_end) { + (Some(start), Some(end)) => Some(Range::new(start, end)), + _ => None, + } +} + /// Return the appropriate visual `Range` for any message that spans a `Stmt`. /// Specifically, this method returns the range of a function or class name, /// rather than that of the entire function or class body. 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 40f26e98475c8c..9eef2be5e6da52 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,11 +1,13 @@ +use rustpython_ast::{Expr, ExprKind}; + use ruff_macros::derive_message_formats; -use crate::ast::types::Range; +use crate::ast::helpers::match_parens; use crate::checkers::ast::Checker; use crate::define_violation; +use crate::fix::Fix; use crate::registry::Diagnostic; use crate::violation::Violation; -use rustpython_ast::{Expr, ExprKind}; define_violation!( pub struct UnnecessaryParenOnRaiseException; @@ -19,13 +21,23 @@ impl Violation for UnnecessaryParenOnRaiseException { /// RSE102 pub fn unnecessary_paren_on_raise_exception(checker: &mut Checker, expr: &Expr) { - match &expr.node { - ExprKind::Call { args, keywords, .. } if args.is_empty() && keywords.is_empty() => { - checker.diagnostics.push(Diagnostic::new( - UnnecessaryParenOnRaiseException, - Range::from_located(expr), - )); + if let ExprKind::Call { + func, + args, + keywords, + } = &expr.node + { + if args.is_empty() && keywords.is_empty() { + let range = match_parens(func.end_location.unwrap(), checker.locator) + .expect("Expected call to include parentheses"); + let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, range); + if checker.patch(&diagnostic.kind.rule()) { + diagnostic.amend(Fix::deletion( + func.end_location.unwrap(), + range.end_location, + )); + } + checker.diagnostics.push(diagnostic); } - _ => (), } } 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 c023452f3bf5e6..4dfa58fdd1219a 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 @@ -1,25 +1,113 @@ --- -source: src/rules/flake8_raise/mod.rs +source: crates/ruff/src/rules/flake8_raise/mod.rs expression: diagnostics --- - kind: UnnecessaryParenOnRaiseException: ~ location: - row: 4 - column: 10 + row: 5 + column: 20 end_location: - row: 4 + row: 5 column: 22 - fix: ~ + fix: + content: + - "" + location: + row: 5 + column: 20 + end_location: + row: 5 + column: 22 parent: ~ - kind: UnnecessaryParenOnRaiseException: ~ location: - row: 11 - column: 6 + row: 13 + column: 15 end_location: - row: 11 + row: 13 column: 17 - fix: ~ + fix: + content: + - "" + location: + row: 13 + column: 15 + end_location: + row: 13 + column: 17 + parent: ~ +- kind: + UnnecessaryParenOnRaiseException: ~ + location: + row: 16 + column: 16 + end_location: + row: 16 + column: 18 + fix: + content: + - "" + location: + row: 16 + column: 15 + end_location: + row: 16 + column: 18 + parent: ~ +- kind: + UnnecessaryParenOnRaiseException: ~ + location: + row: 20 + column: 4 + end_location: + row: 20 + column: 6 + fix: + content: + - "" + location: + row: 19 + column: 15 + end_location: + row: 20 + column: 6 + parent: ~ +- kind: + UnnecessaryParenOnRaiseException: ~ + location: + row: 23 + column: 15 + end_location: + row: 25 + column: 1 + fix: + content: + - "" + location: + row: 23 + column: 15 + end_location: + row: 25 + column: 1 + parent: ~ +- kind: + UnnecessaryParenOnRaiseException: ~ + location: + row: 28 + column: 15 + end_location: + row: 30 + column: 1 + fix: + content: + - "" + location: + row: 28 + column: 15 + end_location: + row: 30 + column: 1 parent: ~