-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Summary Implements the [redundant-backslash](https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes) rule (E502) from pycodestyle. ## Test Plan New fixture has been added Part of #2402
- Loading branch information
1 parent
fc7139d
commit c746912
Showing
12 changed files
with
475 additions
and
4 deletions.
There are no files selected for viewing
88 changes: 88 additions & 0 deletions
88
crates/ruff_linter/resources/test/fixtures/pycodestyle/E502.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
a = 2 + 2 | ||
|
||
a = (2 + 2) | ||
|
||
a = 2 + \ | ||
3 \ | ||
+ 4 | ||
|
||
a = (3 -\ | ||
2 + \ | ||
7) | ||
|
||
z = 5 + \ | ||
(3 -\ | ||
2 + \ | ||
7) + \ | ||
4 | ||
|
||
b = [2 + | ||
2] | ||
|
||
b = [ | ||
2 + 4 + 5 + \ | ||
44 \ | ||
- 5 | ||
] | ||
|
||
c = (True and | ||
False \ | ||
or False \ | ||
and True \ | ||
) | ||
|
||
c = (True and | ||
False) | ||
|
||
d = True and \ | ||
False or \ | ||
False \ | ||
and not True | ||
|
||
|
||
s = { | ||
'x': 2 + \ | ||
2 | ||
} | ||
|
||
|
||
s = { | ||
'x': 2 + | ||
2 | ||
} | ||
|
||
|
||
x = {2 + 4 \ | ||
+ 3} | ||
|
||
y = ( | ||
2 + 2 # \ | ||
+ 3 # \ | ||
+ 4 \ | ||
+ 3 | ||
) | ||
|
||
|
||
x = """ | ||
(\\ | ||
) | ||
""" | ||
|
||
|
||
("""hello \ | ||
""") | ||
|
||
("hello \ | ||
") | ||
|
||
|
||
x = "abc" \ | ||
"xyz" | ||
|
||
x = ("abc" \ | ||
"xyz") | ||
|
||
|
||
def foo(): | ||
x = (a + \ | ||
2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
crates/ruff_linter/src/rules/pycodestyle/rules/logical_lines/redundant_backslash.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; | ||
use ruff_macros::{derive_message_formats, violation}; | ||
use ruff_python_index::Indexer; | ||
use ruff_python_parser::TokenKind; | ||
use ruff_source_file::Locator; | ||
use ruff_text_size::{Ranged, TextRange, TextSize}; | ||
|
||
use crate::checkers::logical_lines::LogicalLinesContext; | ||
|
||
use super::LogicalLine; | ||
|
||
/// ## What it does | ||
/// Checks for redundant backslashes between brackets. | ||
/// | ||
/// ## Why is this bad? | ||
/// Explicit line joins using a backslash are redundant between brackets. | ||
/// | ||
/// ## Example | ||
/// ```python | ||
/// x = (2 + \ | ||
/// 2) | ||
/// ``` | ||
/// | ||
/// Use instead: | ||
/// ```python | ||
/// x = (2 + | ||
/// 2) | ||
/// ``` | ||
/// | ||
/// [PEP 8]: https://peps.python.org/pep-0008/#maximum-line-length | ||
#[violation] | ||
pub struct RedundantBackslash; | ||
|
||
impl AlwaysFixableViolation for RedundantBackslash { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("Redundant backslash") | ||
} | ||
|
||
fn fix_title(&self) -> String { | ||
"Remove redundant backslash".to_string() | ||
} | ||
} | ||
|
||
/// E502 | ||
pub(crate) fn redundant_backslash( | ||
line: &LogicalLine, | ||
locator: &Locator, | ||
indexer: &Indexer, | ||
context: &mut LogicalLinesContext, | ||
) { | ||
let mut parens = 0; | ||
let continuation_lines = indexer.continuation_line_starts(); | ||
let mut start_index = 0; | ||
|
||
for token in line.tokens() { | ||
match token.kind() { | ||
TokenKind::Lpar | TokenKind::Lsqb | TokenKind::Lbrace => { | ||
if parens == 0 { | ||
let start = locator.line_start(token.start()); | ||
start_index = continuation_lines | ||
.binary_search(&start) | ||
.map_or_else(|err_index| err_index, |ok_index| ok_index); | ||
} | ||
parens += 1; | ||
} | ||
TokenKind::Rpar | TokenKind::Rsqb | TokenKind::Rbrace => { | ||
parens -= 1; | ||
if parens == 0 { | ||
let end = locator.line_start(token.start()); | ||
let end_index = continuation_lines | ||
.binary_search(&end) | ||
.map_or_else(|err_index| err_index, |ok_index| ok_index); | ||
for continuation_line in &continuation_lines[start_index..end_index] { | ||
let backslash_end = locator.line_end(*continuation_line); | ||
let backslash_start = backslash_end - TextSize::new(1); | ||
let mut diagnostic = Diagnostic::new( | ||
RedundantBackslash, | ||
TextRange::new(backslash_start, backslash_end), | ||
); | ||
diagnostic.set_fix(Fix::safe_edit(Edit::deletion( | ||
backslash_start, | ||
backslash_end, | ||
))); | ||
context.push_diagnostic(diagnostic); | ||
} | ||
} | ||
} | ||
_ => continue, | ||
} | ||
} | ||
} |
Oops, something went wrong.