Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable autofix for unnecessary-paren-on-raise-exception #2596

Merged
merged 1 commit into from
Feb 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1380,7 +1380,7 @@ For more, see [flake8-raise](https://pypi.org/project/flake8-raise/) on PyPI.

| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| RSE102 | unnecessary-paren-on-raise-exception | Unnecessary parentheses on raised exception | |
| RSE102 | unnecessary-paren-on-raise-exception | Unnecessary parentheses on raised exception | 🛠 |

### flake8-self (SLF)

Expand Down
23 changes: 21 additions & 2 deletions crates/ruff/resources/test/fixtures/flake8_raise/RSE102.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down
27 changes: 27 additions & 0 deletions crates/ruff/src/ast/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Range> {
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.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,47 @@
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};
use crate::violation::AlwaysAutofixableViolation;

define_violation!(
pub struct UnnecessaryParenOnRaiseException;
);
impl Violation for UnnecessaryParenOnRaiseException {
impl AlwaysAutofixableViolation for UnnecessaryParenOnRaiseException {
#[derive_message_formats]
fn message(&self) -> String {
format!("Unnecessary parentheses on raised exception")
}

fn autofix_title(&self) -> String {
format!("Remove unnecessary parentheses")
}
}

/// 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);
}
_ => (),
}
}
Original file line number Diff line number Diff line change
@@ -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: ~