mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 06:42:02 +00:00
Implement autofix for E713 and E714 (#804)
This commit is contained in:
parent
2f894e3951
commit
6ffe767252
6 changed files with 145 additions and 57 deletions
|
@ -361,10 +361,10 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/2.9.1/) on PyPI
|
||||||
| ---- | ---- | ------- | --- |
|
| ---- | ---- | ------- | --- |
|
||||||
| E402 | ModuleImportNotAtTopOfFile | Module level import not at top of file | |
|
| E402 | ModuleImportNotAtTopOfFile | Module level import not at top of file | |
|
||||||
| E501 | LineTooLong | Line too long (89 > 88 characters) | |
|
| E501 | LineTooLong | Line too long (89 > 88 characters) | |
|
||||||
| E711 | NoneComparison | Comparison to `None` should be `cond is None` | |
|
| E711 | NoneComparison | Comparison to `None` should be `cond is None` | 🛠 |
|
||||||
| E712 | TrueFalseComparison | Comparison to `True` should be `cond is True` | |
|
| E712 | TrueFalseComparison | Comparison to `True` should be `cond is True` | 🛠 |
|
||||||
| E713 | NotInTest | Test for membership should be `not in` | |
|
| E713 | NotInTest | Test for membership should be `not in` | 🛠 |
|
||||||
| E714 | NotIsTest | Test for object identity should be `is not` | |
|
| E714 | NotIsTest | Test for object identity should be `is not` | 🛠 |
|
||||||
| E721 | TypeComparison | Do not compare types, use `isinstance()` | |
|
| E721 | TypeComparison | Do not compare types, use `isinstance()` | |
|
||||||
| E722 | DoNotUseBareExcept | Do not use bare `except` | |
|
| E722 | DoNotUseBareExcept | Do not use bare `except` | |
|
||||||
| E731 | DoNotAssignLambda | Do not assign a lambda expression, use a def | |
|
| E731 | DoNotAssignLambda | Do not assign a lambda expression, use a def | |
|
||||||
|
|
|
@ -1525,9 +1525,13 @@ where
|
||||||
let check_not_in = self.settings.enabled.contains(&CheckCode::E713);
|
let check_not_in = self.settings.enabled.contains(&CheckCode::E713);
|
||||||
let check_not_is = self.settings.enabled.contains(&CheckCode::E714);
|
let check_not_is = self.settings.enabled.contains(&CheckCode::E714);
|
||||||
if check_not_in || check_not_is {
|
if check_not_in || check_not_is {
|
||||||
self.add_checks(
|
pycodestyle::plugins::not_tests(
|
||||||
pycodestyle::checks::not_tests(op, operand, check_not_in, check_not_is)
|
self,
|
||||||
.into_iter(),
|
expr,
|
||||||
|
op,
|
||||||
|
operand,
|
||||||
|
check_not_in,
|
||||||
|
check_not_is,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
use rustpython_ast::Location;
|
use rustpython_ast::Location;
|
||||||
use rustpython_parser::ast::{Cmpop, Expr, ExprKind, Stmt, Unaryop};
|
use rustpython_parser::ast::{Cmpop, Expr, ExprKind, Stmt};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::checks::{Check, CheckKind};
|
use crate::checks::{Check, CheckKind};
|
||||||
|
@ -59,44 +59,6 @@ pub fn do_not_assign_lambda(target: &Expr, value: &Expr, stmt: &Stmt) -> Option<
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// E713, E714
|
|
||||||
pub fn not_tests(
|
|
||||||
op: &Unaryop,
|
|
||||||
operand: &Expr,
|
|
||||||
check_not_in: bool,
|
|
||||||
check_not_is: bool,
|
|
||||||
) -> Vec<Check> {
|
|
||||||
let mut checks: Vec<Check> = vec![];
|
|
||||||
|
|
||||||
if matches!(op, Unaryop::Not) {
|
|
||||||
if let ExprKind::Compare { ops, .. } = &operand.node {
|
|
||||||
for op in ops {
|
|
||||||
match op {
|
|
||||||
Cmpop::In => {
|
|
||||||
if check_not_in {
|
|
||||||
checks.push(Check::new(
|
|
||||||
CheckKind::NotInTest,
|
|
||||||
Range::from_located(operand),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Cmpop::Is => {
|
|
||||||
if check_not_is {
|
|
||||||
checks.push(Check::new(
|
|
||||||
CheckKind::NotIsTest,
|
|
||||||
Range::from_located(operand),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checks
|
|
||||||
}
|
|
||||||
|
|
||||||
/// E721
|
/// E721
|
||||||
pub fn type_comparison(ops: &[Cmpop], comparators: &[Expr], location: Range) -> Vec<Check> {
|
pub fn type_comparison(ops: &[Cmpop], comparators: &[Expr], location: Range) -> Vec<Check> {
|
||||||
let mut checks: Vec<Check> = vec![];
|
let mut checks: Vec<Check> = vec![];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprKind, Unaryop};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
use crate::autofix::Fix;
|
||||||
|
@ -201,3 +201,62 @@ pub fn literal_comparisons(
|
||||||
|
|
||||||
checker.add_checks(checks.into_iter());
|
checker.add_checks(checks.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// E713, E714
|
||||||
|
pub fn not_tests(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
op: &Unaryop,
|
||||||
|
operand: &Expr,
|
||||||
|
check_not_in: bool,
|
||||||
|
check_not_is: bool,
|
||||||
|
) {
|
||||||
|
if matches!(op, Unaryop::Not) {
|
||||||
|
if let ExprKind::Compare {
|
||||||
|
left,
|
||||||
|
ops,
|
||||||
|
comparators,
|
||||||
|
..
|
||||||
|
} = &operand.node
|
||||||
|
{
|
||||||
|
let should_fix = ops.len() == 1;
|
||||||
|
for op in ops.iter() {
|
||||||
|
match op {
|
||||||
|
Cmpop::In => {
|
||||||
|
if check_not_in {
|
||||||
|
let mut check =
|
||||||
|
Check::new(CheckKind::NotInTest, Range::from_located(operand));
|
||||||
|
if checker.patch() && should_fix {
|
||||||
|
if let Some(content) = compare(left, &[Cmpop::NotIn], comparators) {
|
||||||
|
check.amend(Fix::replacement(
|
||||||
|
content,
|
||||||
|
expr.location,
|
||||||
|
expr.end_location.unwrap(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.add_check(check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Cmpop::Is => {
|
||||||
|
if check_not_is {
|
||||||
|
let mut check =
|
||||||
|
Check::new(CheckKind::NotInTest, Range::from_located(operand));
|
||||||
|
if checker.patch() && should_fix {
|
||||||
|
if let Some(content) = compare(left, &[Cmpop::IsNot], comparators) {
|
||||||
|
check.amend(Fix::replacement(
|
||||||
|
content,
|
||||||
|
expr.location,
|
||||||
|
expr.end_location.unwrap(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.add_check(check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,16 @@ expression: checks
|
||||||
end_location:
|
end_location:
|
||||||
row: 2
|
row: 2
|
||||||
column: 13
|
column: 13
|
||||||
fix: ~
|
fix:
|
||||||
|
patch:
|
||||||
|
content: X not in Y
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 3
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 13
|
||||||
|
applied: false
|
||||||
- kind: NotInTest
|
- kind: NotInTest
|
||||||
location:
|
location:
|
||||||
row: 5
|
row: 5
|
||||||
|
@ -17,7 +26,16 @@ expression: checks
|
||||||
end_location:
|
end_location:
|
||||||
row: 5
|
row: 5
|
||||||
column: 15
|
column: 15
|
||||||
fix: ~
|
fix:
|
||||||
|
patch:
|
||||||
|
content: X.B not in Y
|
||||||
|
location:
|
||||||
|
row: 5
|
||||||
|
column: 3
|
||||||
|
end_location:
|
||||||
|
row: 5
|
||||||
|
column: 15
|
||||||
|
applied: false
|
||||||
- kind: NotInTest
|
- kind: NotInTest
|
||||||
location:
|
location:
|
||||||
row: 8
|
row: 8
|
||||||
|
@ -25,7 +43,16 @@ expression: checks
|
||||||
end_location:
|
end_location:
|
||||||
row: 8
|
row: 8
|
||||||
column: 13
|
column: 13
|
||||||
fix: ~
|
fix:
|
||||||
|
patch:
|
||||||
|
content: X not in Y
|
||||||
|
location:
|
||||||
|
row: 8
|
||||||
|
column: 3
|
||||||
|
end_location:
|
||||||
|
row: 8
|
||||||
|
column: 13
|
||||||
|
applied: false
|
||||||
- kind: NotInTest
|
- kind: NotInTest
|
||||||
location:
|
location:
|
||||||
row: 11
|
row: 11
|
||||||
|
@ -33,7 +60,16 @@ expression: checks
|
||||||
end_location:
|
end_location:
|
||||||
row: 11
|
row: 11
|
||||||
column: 28
|
column: 28
|
||||||
fix: ~
|
fix:
|
||||||
|
patch:
|
||||||
|
content: Y not in Z
|
||||||
|
location:
|
||||||
|
row: 11
|
||||||
|
column: 18
|
||||||
|
end_location:
|
||||||
|
row: 11
|
||||||
|
column: 28
|
||||||
|
applied: false
|
||||||
- kind: NotInTest
|
- kind: NotInTest
|
||||||
location:
|
location:
|
||||||
row: 14
|
row: 14
|
||||||
|
@ -41,5 +77,14 @@ expression: checks
|
||||||
end_location:
|
end_location:
|
||||||
row: 14
|
row: 14
|
||||||
column: 14
|
column: 14
|
||||||
fix: ~
|
fix:
|
||||||
|
patch:
|
||||||
|
content: X not in Y
|
||||||
|
location:
|
||||||
|
row: 14
|
||||||
|
column: 3
|
||||||
|
end_location:
|
||||||
|
row: 14
|
||||||
|
column: 15
|
||||||
|
applied: false
|
||||||
|
|
||||||
|
|
|
@ -2,23 +2,41 @@
|
||||||
source: src/linter.rs
|
source: src/linter.rs
|
||||||
expression: checks
|
expression: checks
|
||||||
---
|
---
|
||||||
- kind: NotIsTest
|
- kind: NotInTest
|
||||||
location:
|
location:
|
||||||
row: 2
|
row: 2
|
||||||
column: 7
|
column: 7
|
||||||
end_location:
|
end_location:
|
||||||
row: 2
|
row: 2
|
||||||
column: 13
|
column: 13
|
||||||
fix: ~
|
fix:
|
||||||
- kind: NotIsTest
|
patch:
|
||||||
|
content: X is not Y
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 3
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 13
|
||||||
|
applied: false
|
||||||
|
- kind: NotInTest
|
||||||
location:
|
location:
|
||||||
row: 5
|
row: 5
|
||||||
column: 7
|
column: 7
|
||||||
end_location:
|
end_location:
|
||||||
row: 5
|
row: 5
|
||||||
column: 15
|
column: 15
|
||||||
fix: ~
|
fix:
|
||||||
- kind: NotIsTest
|
patch:
|
||||||
|
content: X.B is not Y
|
||||||
|
location:
|
||||||
|
row: 5
|
||||||
|
column: 3
|
||||||
|
end_location:
|
||||||
|
row: 5
|
||||||
|
column: 15
|
||||||
|
applied: false
|
||||||
|
- kind: NotInTest
|
||||||
location:
|
location:
|
||||||
row: 8
|
row: 8
|
||||||
column: 7
|
column: 7
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue