feat(W191): add indentation_contains_tabs (#3249)

This commit is contained in:
Carlos Gonçalves 2023-02-27 15:36:03 +00:00 committed by GitHub
parent d285f5c90a
commit e8ba9c9e21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 591 additions and 4 deletions

View file

@ -0,0 +1,145 @@
#: W191
if False:
print # indented with 1 tab
#:
#: W191
y = x == 2 \
or x == 3
#: E101 W191 W504
if (
x == (
3
) or
y == 4):
pass
#: E101 W191
if x == 2 \
or y > 1 \
or x == 3:
pass
#: E101 W191
if x == 2 \
or y > 1 \
or x == 3:
pass
#:
#: E101 W191 W504
if (foo == bar and
baz == bop):
pass
#: E101 W191 W504
if (
foo == bar and
baz == bop
):
pass
#:
#: E101 E101 W191 W191
if start[1] > end_col and not (
over_indent == 4 and indent_next):
return (0, "E121 continuation line over-"
"indented for visual indent")
#:
#: E101 W191
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
#: E101 W191 W504
if ((row < 0 or self.moduleCount <= row or
col < 0 or self.moduleCount <= col)):
raise Exception("%s,%s - %s" % (row, col, self.moduleCount))
#: E101 E101 E101 E101 W191 W191 W191 W191 W191 W191
if bar:
return (
start, 'E121 lines starting with a '
'closing bracket should be indented '
"to match that of the opening "
"bracket's line"
)
#
#: E101 W191 W504
# you want vertical alignment, so use a parens
if ((foo.bar("baz") and
foo.bar("bop")
)):
print "yes"
#: E101 W191 W504
# also ok, but starting to look like LISP
if ((foo.bar("baz") and
foo.bar("bop"))):
print "yes"
#: E101 W191 W504
if (a == 2 or
b == "abc def ghi"
"jkl mno"):
return True
#: E101 W191 W504
if (a == 2 or
b == """abc def ghi
jkl mno"""):
return True
#: W191:2:1 W191:3:1 E101:3:2
if length > options.max_line_length:
return options.max_line_length, \
"E501 line too long (%d characters)" % length
#
#: E101 W191 W191 W504
if os.path.exists(os.path.join(path, PEP8_BIN)):
cmd = ([os.path.join(path, PEP8_BIN)] +
self._pep8_options(targetfile))
#: W191
'''
multiline string with tab in it'''
#: E101 W191
'''multiline string
with tabs
and spaces
'''
#: Okay
'''sometimes, you just need to go nuts in a multiline string
and allow all sorts of crap
like mixed tabs and spaces
or trailing whitespace
or long long long long long long long long long long long long long long long long long lines
''' # nopep8
#: Okay
'''this one
will get no warning
even though the noqa comment is not immediately after the string
''' + foo # noqa
#
#: E101 W191
if foo is None and bar is "bop" and \
blah == 'yeah':
blah = 'yeahnah'
#
#: W191 W191 W191
if True:
foo(
1,
2)
#: W191 W191 W191 W191 W191
def test_keys(self):
"""areas.json - All regions are accounted for."""
expected = set([
u'Norrbotten',
u'V\xe4sterbotten',
])
#: W191
x = [
'abc'
]
#:

View file

@ -8,8 +8,8 @@ use crate::rules::flake8_executable::rules::{
shebang_missing, shebang_newline, shebang_not_executable, shebang_python, shebang_whitespace,
};
use crate::rules::pycodestyle::rules::{
doc_line_too_long, line_too_long, mixed_spaces_and_tabs, no_newline_at_end_of_file,
trailing_whitespace,
doc_line_too_long, indentation_contains_tabs, line_too_long, mixed_spaces_and_tabs,
no_newline_at_end_of_file, trailing_whitespace,
};
use crate::rules::pygrep_hooks::rules::{blanket_noqa, blanket_type_ignore};
use crate::rules::pylint;
@ -45,6 +45,7 @@ pub fn check_physical_lines(
let enforce_trailing_whitespace = settings.rules.enabled(&Rule::TrailingWhitespace);
let enforce_blank_line_contains_whitespace =
settings.rules.enabled(&Rule::BlankLineContainsWhitespace);
let enforce_indentation_contains_tabs = settings.rules.enabled(&Rule::IndentationContainsTabs);
let fix_unnecessary_coding_comment =
autofix.into() && settings.rules.should_fix(&Rule::UTF8EncodingDeclaration);
@ -149,6 +150,12 @@ pub fn check_physical_lines(
diagnostics.push(diagnostic);
}
}
if enforce_indentation_contains_tabs {
if let Some(diagnostic) = indentation_contains_tabs(index, line) {
diagnostics.push(diagnostic);
}
}
}
if enforce_no_newline_at_end_of_file {

View file

@ -74,6 +74,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<Rule> {
(Pycodestyle, "E999") => Rule::SyntaxError,
// pycodestyle warnings
(Pycodestyle, "W191") => Rule::IndentationContainsTabs,
(Pycodestyle, "W291") => Rule::TrailingWhitespace,
(Pycodestyle, "W292") => Rule::NoNewLineAtEndOfFile,
(Pycodestyle, "W293") => Rule::BlankLineContainsWhitespace,

View file

@ -79,6 +79,7 @@ ruff_macros::register_rules!(
rules::pycodestyle::rules::IOError,
rules::pycodestyle::rules::SyntaxError,
// pycodestyle warnings
rules::pycodestyle::rules::IndentationContainsTabs,
rules::pycodestyle::rules::TrailingWhitespace,
rules::pycodestyle::rules::NoNewLineAtEndOfFile,
rules::pycodestyle::rules::BlankLineContainsWhitespace,
@ -803,6 +804,7 @@ impl Rule {
| Rule::ShebangPython
| Rule::ShebangWhitespace
| Rule::TrailingWhitespace
| Rule::IndentationContainsTabs
| Rule::BlankLineContainsWhitespace => &LintSource::PhysicalLines,
Rule::AmbiguousUnicodeCharacterComment
| Rule::AmbiguousUnicodeCharacterDocstring

View file

@ -42,6 +42,7 @@ mod tests {
#[test_case(Rule::NotInTest, Path::new("E713.py"))]
#[test_case(Rule::NotIsTest, Path::new("E714.py"))]
#[test_case(Rule::SyntaxError, Path::new("E999.py"))]
#[test_case(Rule::IndentationContainsTabs, Path::new("W19.py"))]
#[test_case(Rule::TrailingWhitespace, Path::new("W29.py"))]
#[test_case(Rule::TrueFalseComparison, Path::new("E712.py"))]
#[test_case(Rule::TypeComparison, Path::new("E721.py"))]

View file

@ -0,0 +1,34 @@
use ruff_macros::{define_violation, derive_message_formats};
use rustpython_parser::ast::Location;
use crate::ast::types::Range;
use crate::ast::whitespace::leading_space;
use crate::registry::Diagnostic;
use crate::violation::Violation;
define_violation!(
pub struct IndentationContainsTabs;
);
impl Violation for IndentationContainsTabs {
#[derive_message_formats]
fn message(&self) -> String {
format!("Indentation contains tabs")
}
}
/// W191
pub fn indentation_contains_tabs(lineno: usize, line: &str) -> Option<Diagnostic> {
let indent = leading_space(line);
if indent.contains('\t') {
Some(Diagnostic::new(
IndentationContainsTabs,
Range::new(
Location::new(lineno + 1, 0),
Location::new(lineno + 1, indent.chars().count()),
),
))
} else {
None
}
}

View file

@ -21,6 +21,8 @@ pub use indentation::{
NoIndentedBlock, NoIndentedBlockComment, OverIndented, UnexpectedIndentation,
UnexpectedIndentationComment,
};
pub use indentation_contains_tabs::{indentation_contains_tabs, IndentationContainsTabs};
pub use invalid_escape_sequence::{invalid_escape_sequence, InvalidEscapeSequence};
pub use lambda_assignment::{lambda_assignment, LambdaAssignment};
pub use line_too_long::{line_too_long, LineTooLong};
@ -58,6 +60,7 @@ mod errors;
mod extraneous_whitespace;
mod imports;
mod indentation;
mod indentation_contains_tabs;
mod invalid_escape_sequence;
mod lambda_assignment;
mod line_too_long;

View file

@ -0,0 +1,385 @@
---
source: crates/ruff/src/rules/pycodestyle/mod.rs
expression: diagnostics
---
- kind:
IndentationContainsTabs: ~
location:
row: 3
column: 0
end_location:
row: 3
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 9
column: 0
end_location:
row: 9
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 16
column: 0
end_location:
row: 16
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 21
column: 0
end_location:
row: 21
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 26
column: 0
end_location:
row: 26
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 32
column: 0
end_location:
row: 32
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 38
column: 0
end_location:
row: 38
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 44
column: 0
end_location:
row: 44
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 45
column: 0
end_location:
row: 45
column: 9
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 54
column: 0
end_location:
row: 54
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 58
column: 0
end_location:
row: 58
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 61
column: 0
end_location:
row: 61
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 62
column: 0
end_location:
row: 62
column: 5
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 63
column: 0
end_location:
row: 63
column: 5
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 64
column: 0
end_location:
row: 64
column: 5
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 65
column: 0
end_location:
row: 65
column: 5
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 66
column: 0
end_location:
row: 66
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 73
column: 0
end_location:
row: 73
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 78
column: 0
end_location:
row: 78
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 83
column: 0
end_location:
row: 83
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 88
column: 0
end_location:
row: 88
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 91
column: 0
end_location:
row: 91
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 92
column: 0
end_location:
row: 92
column: 5
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 98
column: 0
end_location:
row: 98
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 99
column: 0
end_location:
row: 99
column: 8
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 102
column: 0
end_location:
row: 102
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 105
column: 0
end_location:
row: 105
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 110
column: 0
end_location:
row: 110
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 125
column: 0
end_location:
row: 125
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 131
column: 0
end_location:
row: 131
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 132
column: 0
end_location:
row: 132
column: 2
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 133
column: 0
end_location:
row: 133
column: 2
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 136
column: 0
end_location:
row: 136
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 137
column: 0
end_location:
row: 137
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 138
column: 0
end_location:
row: 138
column: 2
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 139
column: 0
end_location:
row: 139
column: 2
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 140
column: 0
end_location:
row: 140
column: 1
fix: ~
parent: ~
- kind:
IndentationContainsTabs: ~
location:
row: 143
column: 0
end_location:
row: 143
column: 1
fix: ~
parent: ~

View file

@ -56,6 +56,7 @@ mod tests {
Rule::LineTooLong,
Rule::UnusedImport,
Rule::UnusedVariable,
Rule::IndentationContainsTabs,
]),
)?;
assert_yaml_snapshot!(diagnostics);

View file

@ -68,12 +68,12 @@ expression: diagnostics
- kind:
UnusedNOQA:
codes:
unknown:
- W191
unknown: []
disabled:
- F821
unmatched:
- F841
- W191
location:
row: 19
column: 11

View file

@ -470,6 +470,7 @@ mod tests {
Rule::BlankLineContainsWhitespace,
Rule::DocLineTooLong,
Rule::InvalidEscapeSequence,
Rule::IndentationContainsTabs,
]);
assert_eq!(actual, expected);
@ -490,6 +491,7 @@ mod tests {
Rule::BlankLineContainsWhitespace,
Rule::DocLineTooLong,
Rule::InvalidEscapeSequence,
Rule::IndentationContainsTabs,
]);
assert_eq!(actual, expected);
@ -526,6 +528,7 @@ mod tests {
Rule::BlankLineContainsWhitespace,
Rule::DocLineTooLong,
Rule::InvalidEscapeSequence,
Rule::IndentationContainsTabs,
]);
assert_eq!(actual, expected);
@ -563,6 +566,7 @@ mod tests {
Rule::BlankLineContainsWhitespace,
Rule::DocLineTooLong,
Rule::InvalidEscapeSequence,
Rule::IndentationContainsTabs,
]);
assert_eq!(actual, expected);
@ -582,6 +586,7 @@ mod tests {
Rule::TrailingWhitespace,
Rule::BlankLineContainsWhitespace,
Rule::InvalidEscapeSequence,
Rule::IndentationContainsTabs,
]);
assert_eq!(actual, expected);
}

3
ruff.schema.json generated
View file

@ -2123,6 +2123,9 @@
"UP036",
"UP037",
"W",
"W1",
"W19",
"W191",
"W2",
"W29",
"W291",