mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 02:38:25 +00:00
Implement E241 and E242 (tab/multiple ws after commas) (#6094)
## Summary This PR implements pycodestyle's E241 (tab after comma) and E242 (multiple whitespace after comma) lints. These are marked as nursery rules like many other pycodestyle rules. Refs #2402 ## Test Plan E24.py copied from pycodestyle.
This commit is contained in:
parent
1418ee62f8
commit
3d54d31cd9
10 changed files with 151 additions and 3 deletions
13
crates/ruff/resources/test/fixtures/pycodestyle/E24.py
vendored
Normal file
13
crates/ruff/resources/test/fixtures/pycodestyle/E24.py
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
#: E241
|
||||
a = (1, 2)
|
||||
#: Okay
|
||||
b = (1, 20)
|
||||
#: E242
|
||||
a = (1, 2) # tab before 2
|
||||
#: Okay
|
||||
b = (1, 20) # space before 20
|
||||
#: E241 E241 E241
|
||||
# issue 135
|
||||
more_spaces = [a, b,
|
||||
ef, +h,
|
||||
c, -d]
|
|
@ -9,9 +9,9 @@ use ruff_source_file::Locator;
|
|||
use crate::registry::{AsRule, Rule};
|
||||
use crate::rules::pycodestyle::rules::logical_lines::{
|
||||
extraneous_whitespace, indentation, missing_whitespace, missing_whitespace_after_keyword,
|
||||
missing_whitespace_around_operator, space_around_operator, whitespace_around_keywords,
|
||||
whitespace_around_named_parameter_equals, whitespace_before_comment,
|
||||
whitespace_before_parameters, LogicalLines, TokenFlags,
|
||||
missing_whitespace_around_operator, space_after_comma, space_around_operator,
|
||||
whitespace_around_keywords, whitespace_around_named_parameter_equals,
|
||||
whitespace_before_comment, whitespace_before_parameters, LogicalLines, TokenFlags,
|
||||
};
|
||||
use crate::settings::Settings;
|
||||
|
||||
|
@ -61,6 +61,9 @@ pub(crate) fn check_logical_lines(
|
|||
missing_whitespace_around_operator(&line, &mut context);
|
||||
missing_whitespace(&line, should_fix_missing_whitespace, &mut context);
|
||||
}
|
||||
if line.flags().contains(TokenFlags::PUNCTUATION) {
|
||||
space_after_comma(&line, &mut context);
|
||||
}
|
||||
|
||||
if line
|
||||
.flags()
|
||||
|
|
|
@ -84,6 +84,8 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Pycodestyle, "E227") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespaceAroundBitwiseOrShiftOperator),
|
||||
(Pycodestyle, "E228") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespaceAroundModuloOperator),
|
||||
(Pycodestyle, "E231") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespace),
|
||||
(Pycodestyle, "E241") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MultipleSpacesAfterComma),
|
||||
(Pycodestyle, "E242") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::TabAfterComma),
|
||||
(Pycodestyle, "E251") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::UnexpectedSpacesAroundKeywordParameterEquals),
|
||||
(Pycodestyle, "E252") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespaceAroundParameterEquals),
|
||||
(Pycodestyle, "E261") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::TooFewSpacesBeforeInlineComment),
|
||||
|
|
|
@ -303,6 +303,7 @@ impl Rule {
|
|||
| Rule::MissingWhitespaceAroundOperator
|
||||
| Rule::MissingWhitespaceAroundParameterEquals
|
||||
| Rule::MultipleLeadingHashesForBlockComment
|
||||
| Rule::MultipleSpacesAfterComma
|
||||
| Rule::MultipleSpacesAfterKeyword
|
||||
| Rule::MultipleSpacesAfterOperator
|
||||
| Rule::MultipleSpacesBeforeKeyword
|
||||
|
@ -312,6 +313,7 @@ impl Rule {
|
|||
| Rule::NoSpaceAfterBlockComment
|
||||
| Rule::NoSpaceAfterInlineComment
|
||||
| Rule::OverIndented
|
||||
| Rule::TabAfterComma
|
||||
| Rule::TabAfterKeyword
|
||||
| Rule::TabAfterOperator
|
||||
| Rule::TabBeforeKeyword
|
||||
|
|
|
@ -70,6 +70,7 @@ mod tests {
|
|||
#[test_case(Rule::IndentationWithInvalidMultiple, Path::new("E11.py"))]
|
||||
#[test_case(Rule::IndentationWithInvalidMultipleComment, Path::new("E11.py"))]
|
||||
#[test_case(Rule::MultipleLeadingHashesForBlockComment, Path::new("E26.py"))]
|
||||
#[test_case(Rule::MultipleSpacesAfterComma, Path::new("E24.py"))]
|
||||
#[test_case(Rule::MultipleSpacesAfterKeyword, Path::new("E27.py"))]
|
||||
#[test_case(Rule::MultipleSpacesAfterOperator, Path::new("E22.py"))]
|
||||
#[test_case(Rule::MultipleSpacesBeforeKeyword, Path::new("E27.py"))]
|
||||
|
@ -80,6 +81,7 @@ mod tests {
|
|||
#[test_case(Rule::NoSpaceAfterBlockComment, Path::new("E26.py"))]
|
||||
#[test_case(Rule::NoSpaceAfterInlineComment, Path::new("E26.py"))]
|
||||
#[test_case(Rule::OverIndented, Path::new("E11.py"))]
|
||||
#[test_case(Rule::TabAfterComma, Path::new("E24.py"))]
|
||||
#[test_case(Rule::TabAfterKeyword, Path::new("E27.py"))]
|
||||
#[test_case(Rule::TabAfterOperator, Path::new("E22.py"))]
|
||||
#[test_case(Rule::TabBeforeKeyword, Path::new("E27.py"))]
|
||||
|
|
|
@ -120,6 +120,57 @@ impl Violation for MultipleSpacesAfterOperator {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for extraneous tabs after a comma.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Commas should be followed by one space, never tabs.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// a = 4,\t5
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// a = 4, 3
|
||||
/// ```
|
||||
///
|
||||
#[violation]
|
||||
pub struct TabAfterComma;
|
||||
|
||||
impl Violation for TabAfterComma {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Tab after comma")
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for extraneous whitespace after a comma.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// According to the `black` code style, commas should be followed by a single space.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// a = 4, 5
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// a = 4, 5
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct MultipleSpacesAfterComma;
|
||||
|
||||
impl Violation for MultipleSpacesAfterComma {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Multiple spaces after comma")
|
||||
}
|
||||
}
|
||||
|
||||
/// E221, E222, E223, E224
|
||||
pub(crate) fn space_around_operator(line: &LogicalLine, context: &mut LogicalLinesContext) {
|
||||
let mut after_operator = false;
|
||||
|
@ -161,6 +212,23 @@ pub(crate) fn space_around_operator(line: &LogicalLine, context: &mut LogicalLin
|
|||
}
|
||||
}
|
||||
|
||||
/// E241, E242
|
||||
pub(crate) fn space_after_comma(line: &LogicalLine, context: &mut LogicalLinesContext) {
|
||||
for token in line.tokens() {
|
||||
if matches!(token.kind(), TokenKind::Comma) {
|
||||
match line.trailing_whitespace(token) {
|
||||
(Whitespace::Tab, len) => {
|
||||
context.push(TabAfterComma, TextRange::at(token.end(), len));
|
||||
}
|
||||
(Whitespace::Many, len) => {
|
||||
context.push(MultipleSpacesAfterComma, TextRange::at(token.end(), len));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fn is_operator_token(token: TokenKind) -> bool {
|
||||
matches!(
|
||||
token,
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
source: crates/ruff/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E24.py:2:8: E241 Multiple spaces after comma
|
||||
|
|
||||
1 | #: E241
|
||||
2 | a = (1, 2)
|
||||
| ^^ E241
|
||||
3 | #: Okay
|
||||
4 | b = (1, 20)
|
||||
|
|
||||
|
||||
E24.py:11:18: E241 Multiple spaces after comma
|
||||
|
|
||||
9 | #: E241 E241 E241
|
||||
10 | # issue 135
|
||||
11 | more_spaces = [a, b,
|
||||
| ^^^^ E241
|
||||
12 | ef, +h,
|
||||
13 | c, -d]
|
||||
|
|
||||
|
||||
E24.py:12:19: E241 Multiple spaces after comma
|
||||
|
|
||||
10 | # issue 135
|
||||
11 | more_spaces = [a, b,
|
||||
12 | ef, +h,
|
||||
| ^^ E241
|
||||
13 | c, -d]
|
||||
|
|
||||
|
||||
E24.py:13:18: E241 Multiple spaces after comma
|
||||
|
|
||||
11 | more_spaces = [a, b,
|
||||
12 | ef, +h,
|
||||
13 | c, -d]
|
||||
| ^^^ E241
|
||||
|
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
source: crates/ruff/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
E24.py:6:8: E242 Tab after comma
|
||||
|
|
||||
4 | b = (1, 20)
|
||||
5 | #: E242
|
||||
6 | a = (1, 2) # tab before 2
|
||||
| ^ E242
|
||||
7 | #: Okay
|
||||
8 | b = (1, 20) # space before 20
|
||||
|
|
||||
|
||||
|
2
ruff.schema.json
generated
2
ruff.schema.json
generated
|
@ -1869,6 +1869,8 @@
|
|||
"E227",
|
||||
"E228",
|
||||
"E231",
|
||||
"E241",
|
||||
"E242",
|
||||
"E251",
|
||||
"E252",
|
||||
"E261",
|
||||
|
|
|
@ -43,6 +43,7 @@ KNOWN_FORMATTING_VIOLATIONS = [
|
|||
"missing-whitespace-around-operator",
|
||||
"multi-line-implicit-string-concatenation",
|
||||
"multiple-leading-hashes-for-block-comment",
|
||||
"multiple-spaces-after-comma",
|
||||
"multiple-spaces-after-keyword",
|
||||
"multiple-spaces-after-operator",
|
||||
"multiple-spaces-before-keyword",
|
||||
|
@ -81,6 +82,7 @@ KNOWN_PARSE_ERRORS = [
|
|||
"missing-newline-at-end-of-file",
|
||||
"mixed-spaces-and-tabs",
|
||||
"no-indented-block",
|
||||
"tab-after-comma",
|
||||
"tab-after-keyword",
|
||||
"tab-after-operator",
|
||||
"tab-before-keyword",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue