mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-03 21:23:45 +00:00
[pycodestyle] Do not trigger E225 and E275 when the next token is a ')' (#10315)
## Summary Fixes #10295. `E225` (`Missing whitespace around operator`) and `E275` (`Missing whitespace after keyword`) try to add a white space even when the next character is a `)` (which is a syntax error in most cases, the exceptions already being handled). This causes `E202` (`Whitespace before close bracket`) to try to remove the added whitespace, resulting in an infinite loop when `E225`/`E275` re-add it. This PR adds an exception in `E225` and `E275` to not trigger in case the next token is a `)`. It is a bit simplistic, but it solves the example given in the issue without introducing a change in behavior (according to the fixtures). ## Test Plan `cargo test` and the `ruff-ecosystem` check were used to check that the PR's changes do not have side-effects. A new fixture was added to check that running the 3 rules on the example given in the issue does not cause ruff to fail to converge.
This commit is contained in:
parent
bc693ea13a
commit
8d73866f70
5 changed files with 44 additions and 1 deletions
1
crates/ruff_linter/resources/test/fixtures/pycodestyle/E2_syntax_error.py
vendored
Normal file
1
crates/ruff_linter/resources/test/fixtures/pycodestyle/E2_syntax_error.py
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
a = (1 or)
|
||||
|
|
@ -148,6 +148,23 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests the compatibility of E2 rules (E202, E225 and E275) on syntactically incorrect code.
|
||||
#[test]
|
||||
fn white_space_syntax_error_compatibility() -> Result<()> {
|
||||
let diagnostics = test_path(
|
||||
Path::new("pycodestyle").join("E2_syntax_error.py"),
|
||||
&settings::LinterSettings {
|
||||
..settings::LinterSettings::for_rules([
|
||||
Rule::MissingWhitespaceAroundOperator,
|
||||
Rule::MissingWhitespaceAfterKeyword,
|
||||
Rule::WhitespaceBeforeCloseBracket,
|
||||
])
|
||||
},
|
||||
)?;
|
||||
assert_messages!(diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Rule::BlankLineBetweenMethods, Path::new("E30.py"))]
|
||||
#[test_case(Rule::BlankLinesTopLevel, Path::new("E30.py"))]
|
||||
#[test_case(Rule::TooManyBlankLines, Path::new("E30.py"))]
|
||||
|
|
|
|||
|
|
@ -59,7 +59,13 @@ pub(crate) fn missing_whitespace_after_keyword(
|
|||
|| tok0_kind == TokenKind::Yield && tok1_kind == TokenKind::Rpar
|
||||
|| matches!(
|
||||
tok1_kind,
|
||||
TokenKind::Colon | TokenKind::Newline | TokenKind::NonLogicalNewline
|
||||
TokenKind::Colon
|
||||
| TokenKind::Newline
|
||||
| TokenKind::NonLogicalNewline
|
||||
// In the event of a syntax error, do not attempt to add a whitespace.
|
||||
| TokenKind::Rpar
|
||||
| TokenKind::Rsqb
|
||||
| TokenKind::Rbrace
|
||||
))
|
||||
&& tok0.end() == tok1.start()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -211,6 +211,21 @@ pub(crate) fn missing_whitespace_around_operator(
|
|||
} else {
|
||||
NeedsSpace::No
|
||||
}
|
||||
} else if tokens.peek().is_some_and(|token| {
|
||||
matches!(
|
||||
token.kind(),
|
||||
TokenKind::Rpar | TokenKind::Rsqb | TokenKind::Rbrace
|
||||
)
|
||||
}) {
|
||||
// There should not be a closing bracket directly after a token, as it is a syntax
|
||||
// error. For example:
|
||||
// ```
|
||||
// 1+)
|
||||
// ```
|
||||
//
|
||||
// However, allow it in order to prevent entering an infinite loop in which E225 adds a
|
||||
// space only for E202 to remove it.
|
||||
NeedsSpace::No
|
||||
} else if is_whitespace_needed(kind) {
|
||||
NeedsSpace::Yes
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue