From f9ffa80833f07fdb2a6afa4a2b5c404134e70b68 Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Sun, 10 Mar 2024 00:29:50 +0900 Subject: [PATCH 1/5] fix: do not trigger E225 and E275 when the next token is a ')' Fixes #10295. --- .../logical_lines/missing_whitespace_after_keyword.rs | 5 ++++- .../logical_lines/missing_whitespace_around_operator.rs | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs index 7aa8cfc24764a..9c7b3df7811a2 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs @@ -59,7 +59,10 @@ 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 + | TokenKind::Rpar // In case of a syntax error, do not attempt to add a whitespace. )) && tok0.end() == tok1.start() { diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs index c5432802ccd26..bcedfe3d7fa31 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs @@ -159,7 +159,13 @@ pub(crate) fn missing_whitespace_around_operator( while let Some(token) = tokens.next() { let kind = token.kind(); - if kind.is_trivia() { + // There should not be a ")" directly after a token, as it is a syntax error. However if that happens, + // allow it in order to prevent entering a loop where E225 adds a space only for E202 to remove it. + if kind.is_trivia() + || tokens + .peek() + .is_some_and(|token| token.kind() == TokenKind::Rpar) + { continue; } From 918b311f9512f9553e3ba103d46e55d3f49d3714 Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Sun, 10 Mar 2024 01:09:58 +0900 Subject: [PATCH 2/5] add fixture. --- .../fixtures/pycodestyle/E20_syntax_error.py | 1 + crates/ruff_linter/src/rules/pycodestyle/mod.rs | 17 +++++++++++++++++ ..._white_space_syntax_error_compatibility.snap | 4 ++++ 3 files changed, 22 insertions(+) create mode 100644 crates/ruff_linter/resources/test/fixtures/pycodestyle/E20_syntax_error.py create mode 100644 crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__white_space_syntax_error_compatibility.snap diff --git a/crates/ruff_linter/resources/test/fixtures/pycodestyle/E20_syntax_error.py b/crates/ruff_linter/resources/test/fixtures/pycodestyle/E20_syntax_error.py new file mode 100644 index 0000000000000..34c9579d58cc2 --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/pycodestyle/E20_syntax_error.py @@ -0,0 +1 @@ +a = (1 or) diff --git a/crates/ruff_linter/src/rules/pycodestyle/mod.rs b/crates/ruff_linter/src/rules/pycodestyle/mod.rs index a6d850f862aef..5b716b08d88bd 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/mod.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/mod.rs @@ -148,6 +148,23 @@ mod tests { Ok(()) } + /// Tests the compatibility of E202, E225 and E275. + #[test] + fn white_space_syntax_error_compatibility() -> Result<()> { + let diagnostics = test_path( + Path::new("pycodestyle").join("E20_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"))] diff --git a/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__white_space_syntax_error_compatibility.snap b/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__white_space_syntax_error_compatibility.snap new file mode 100644 index 0000000000000..6dcc4546f11f9 --- /dev/null +++ b/crates/ruff_linter/src/rules/pycodestyle/snapshots/ruff_linter__rules__pycodestyle__tests__white_space_syntax_error_compatibility.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff_linter/src/rules/pycodestyle/mod.rs +--- + From 7e879185136db58420d15d1fe67b59909231debd Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Sun, 10 Mar 2024 10:58:09 +0900 Subject: [PATCH 3/5] move E225 ) skip case. --- .../missing_whitespace_around_operator.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs index bcedfe3d7fa31..26e619ddaf27d 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs @@ -159,13 +159,7 @@ pub(crate) fn missing_whitespace_around_operator( while let Some(token) = tokens.next() { let kind = token.kind(); - // There should not be a ")" directly after a token, as it is a syntax error. However if that happens, - // allow it in order to prevent entering a loop where E225 adds a space only for E202 to remove it. - if kind.is_trivia() - || tokens - .peek() - .is_some_and(|token| token.kind() == TokenKind::Rpar) - { + if kind.is_trivia() { continue; } @@ -217,6 +211,13 @@ pub(crate) fn missing_whitespace_around_operator( } else { NeedsSpace::No } + } else if tokens + .peek() + .is_some_and(|token| token.kind() == TokenKind::Rpar) + { + // There should not be a ")" directly after a token, as it is a syntax error. However if that happens, + // allow it in order to prevent entering a loop where E225 adds a space only for E202 to remove it. + NeedsSpace::No } else if is_whitespace_needed(kind) { NeedsSpace::Yes } else { From 04e7f680ae9d7d89be5377964037a35c03325cea Mon Sep 17 00:00:00 2001 From: Hoel Bagard Date: Sun, 10 Mar 2024 11:22:35 +0900 Subject: [PATCH 4/5] E20 -> E2 --- .../pycodestyle/{E20_syntax_error.py => E2_syntax_error.py} | 0 crates/ruff_linter/src/rules/pycodestyle/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename crates/ruff_linter/resources/test/fixtures/pycodestyle/{E20_syntax_error.py => E2_syntax_error.py} (100%) diff --git a/crates/ruff_linter/resources/test/fixtures/pycodestyle/E20_syntax_error.py b/crates/ruff_linter/resources/test/fixtures/pycodestyle/E2_syntax_error.py similarity index 100% rename from crates/ruff_linter/resources/test/fixtures/pycodestyle/E20_syntax_error.py rename to crates/ruff_linter/resources/test/fixtures/pycodestyle/E2_syntax_error.py diff --git a/crates/ruff_linter/src/rules/pycodestyle/mod.rs b/crates/ruff_linter/src/rules/pycodestyle/mod.rs index 5b716b08d88bd..156fde4924b48 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/mod.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/mod.rs @@ -148,11 +148,11 @@ mod tests { Ok(()) } - /// Tests the compatibility of E202, E225 and E275. + /// 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("E20_syntax_error.py"), + Path::new("pycodestyle").join("E2_syntax_error.py"), &settings::LinterSettings { ..settings::LinterSettings::for_rules([ Rule::MissingWhitespaceAroundOperator, From 667e3852e4615e202c8087ef7ce9b0357ab27424 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 11 Mar 2024 17:15:10 -0400 Subject: [PATCH 5/5] Add other bracket kinds --- .../missing_whitespace_after_keyword.rs | 5 ++++- .../missing_whitespace_around_operator.rs | 20 +++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs index 9c7b3df7811a2..296d9514bda6e 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_after_keyword.rs @@ -62,7 +62,10 @@ pub(crate) fn missing_whitespace_after_keyword( TokenKind::Colon | TokenKind::Newline | TokenKind::NonLogicalNewline - | TokenKind::Rpar // In case of a syntax error, do not attempt to add a whitespace. + // In the event of a syntax error, do not attempt to add a whitespace. + | TokenKind::Rpar + | TokenKind::Rsqb + | TokenKind::Rbrace )) && tok0.end() == tok1.start() { diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs index 26e619ddaf27d..fd182648caec3 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/missing_whitespace_around_operator.rs @@ -211,12 +211,20 @@ pub(crate) fn missing_whitespace_around_operator( } else { NeedsSpace::No } - } else if tokens - .peek() - .is_some_and(|token| token.kind() == TokenKind::Rpar) - { - // There should not be a ")" directly after a token, as it is a syntax error. However if that happens, - // allow it in order to prevent entering a loop where E225 adds a space only for E202 to remove it. + } 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