Remove parenthesis lexing in RSE102 (#6732)

## Summary

Now that we have an `Arguments` node, we can just use the range of the
arguments directly to find the parentheses in `raise Error()`.
This commit is contained in:
Charlie Marsh 2023-08-21 16:59:06 -04:00 committed by GitHub
parent b182368008
commit 4678f7dafe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 102 deletions

View File

@ -19,11 +19,20 @@ raise TypeError ()
raise TypeError \ raise TypeError \
() ()
# RSE102
raise TypeError \
();
# RSE102 # RSE102
raise TypeError( raise TypeError(
) )
# RSE102
raise (TypeError) (
)
# RSE102 # RSE102
raise TypeError( raise TypeError(
# Hello, world! # Hello, world!

View File

@ -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_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; 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::checkers::ast::Checker;
use crate::registry::AsRule; 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) { pub(crate) fn unnecessary_paren_on_raise_exception(checker: &mut Checker, expr: &Expr) {
let Expr::Call(ast::ExprCall { let Expr::Call(ast::ExprCall {
func, func,
arguments: arguments,
Arguments {
args,
keywords,
range: _,
},
range: _, range: _,
}) = expr }) = expr
else { else {
return; return;
}; };
if args.is_empty() && keywords.is_empty() { if arguments.is_empty() {
// `raise func()` still requires parentheses; only `raise Class()` does not. // `raise func()` still requires parentheses; only `raise Class()` does not.
if checker if checker
.semantic() .semantic()
@ -81,49 +72,10 @@ pub(crate) fn unnecessary_paren_on_raise_exception(checker: &mut Checker, expr:
return; return;
} }
let range = match_parens(func.end(), checker.locator(), checker.source_type) let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, arguments.range());
.expect("Expected call to include parentheses");
let mut diagnostic = Diagnostic::new(UnnecessaryParenOnRaiseException, range);
if checker.patch(diagnostic.kind.rule()) { 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); 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<TextRange> {
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,
}
}

View File

@ -57,7 +57,7 @@ RSE102.py:16:17: RSE102 [*] Unnecessary parentheses on raised exception
14 14 | 14 14 |
15 15 | # RSE102 15 15 | # RSE102
16 |-raise TypeError () 16 |-raise TypeError ()
16 |+raise TypeError 16 |+raise TypeError
17 17 | 17 17 |
18 18 | # RSE102 18 18 | # RSE102
19 19 | raise TypeError \ 19 19 | raise TypeError \
@ -74,64 +74,109 @@ RSE102.py:20:5: RSE102 [*] Unnecessary parentheses on raised exception
= help: Remove unnecessary parentheses = help: Remove unnecessary parentheses
Fix Fix
16 16 | raise TypeError ()
17 17 | 17 17 |
18 18 | # RSE102 18 18 | # RSE102
19 |-raise TypeError \ 19 19 | raise TypeError \
20 |- () 20 |- ()
19 |+raise TypeError 20 |+
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 | ()
21 21 | 21 21 |
22 22 | # RSE102 22 22 | # RSE102
23 |-raise TypeError( 23 23 | raise TypeError \
24 |-
25 |-)
23 |+raise TypeError
26 24 |
27 25 | # RSE102
28 26 | raise TypeError(
RSE102.py:28:16: RSE102 [*] Unnecessary parentheses on raised exception RSE102.py:24:5: RSE102 [*] Unnecessary parentheses on raised exception
| |
27 | # RSE102 22 | # RSE102
28 | raise TypeError( 23 | raise TypeError \
| ________________^ 24 | ();
29 | | # Hello, world! | ^^ RSE102
30 | | ) 25 |
| |_^ RSE102 26 | # RSE102
31 |
32 | # OK
| |
= help: Remove unnecessary parentheses = help: Remove unnecessary parentheses
Fix Fix
25 25 | ) 21 21 |
26 26 | 22 22 | # RSE102
27 27 | # RSE102 23 23 | raise TypeError \
28 |-raise TypeError( 24 |- ();
29 |- # Hello, world! 24 |+ ;
30 |-) 25 25 |
28 |+raise TypeError 26 26 | # RSE102
31 29 | 27 27 | raise TypeError(
32 30 | # OK
33 31 | raise AssertionError 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