mirror of https://github.com/astral-sh/ruff
Implement C415 (#371)
This commit is contained in:
parent
129e2b6ad3
commit
bbe0220c72
|
|
@ -1926,6 +1926,7 @@ dependencies = [
|
||||||
"libcst",
|
"libcst",
|
||||||
"log",
|
"log",
|
||||||
"notify",
|
"notify",
|
||||||
|
"num-bigint",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"path-absolutize",
|
"path-absolutize",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ update-informer = { version = "0.5.0", default_features = false, features = ["py
|
||||||
walkdir = { version = "2.3.2" }
|
walkdir = { version = "2.3.2" }
|
||||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||||
strum_macros = "0.24.3"
|
strum_macros = "0.24.3"
|
||||||
|
num-bigint = "0.4.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
insta = { version = "1.19.1", features = ["yaml"] }
|
insta = { version = "1.19.1", features = ["yaml"] }
|
||||||
|
|
|
||||||
|
|
@ -286,6 +286,7 @@ The 🛠 emoji indicates that a rule is automatically fixable by the `--fix` com
|
||||||
| C405 | UnnecessaryLiteralSet | Unnecessary <list/tuple> literal - rewrite as a set literal | | |
|
| C405 | UnnecessaryLiteralSet | Unnecessary <list/tuple> literal - rewrite as a set literal | | |
|
||||||
| C406 | UnnecessaryLiteralDict | Unnecessary <list/tuple> literal - rewrite as a dict literal | | |
|
| C406 | UnnecessaryLiteralDict | Unnecessary <list/tuple> literal - rewrite as a dict literal | | |
|
||||||
| C408 | UnnecessaryCollectionCall | Unnecessary <dict/list/tuple> call - rewrite as a literal | | |
|
| C408 | UnnecessaryCollectionCall | Unnecessary <dict/list/tuple> call - rewrite as a literal | | |
|
||||||
|
| C415 | UnnecessarySubscriptReversal | Unnecessary subscript reversal of iterable within <reversed/set/sorted>() | | |
|
||||||
| SPR001 | SuperCallWithParameters | Use `super()` instead of `super(__class__, self)` | | 🛠 |
|
| SPR001 | SuperCallWithParameters | Use `super()` instead of `super(__class__, self)` | | 🛠 |
|
||||||
| T201 | PrintFound | `print` found | | 🛠 |
|
| T201 | PrintFound | `print` found | | 🛠 |
|
||||||
| T203 | PPrintFound | `pprint` found | | 🛠 |
|
| T203 | PPrintFound | `pprint` found | | 🛠 |
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
lst = [2, 1, 3]
|
||||||
|
a = set(lst[::-1])
|
||||||
|
b = reversed(lst[::-1])
|
||||||
|
c = sorted(lst[::-1])
|
||||||
|
d = sorted(lst[::-1], reverse=True)
|
||||||
|
e = set(lst[2:-1])
|
||||||
|
f = set(lst[:1:-1])
|
||||||
|
g = set(lst[::1])
|
||||||
|
h = set(lst[::-2])
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
|
use num_bigint::BigInt;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rustpython_parser::ast::{
|
use rustpython_parser::ast::{
|
||||||
Arg, ArgData, Arguments, Cmpop, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprKind,
|
Arg, ArgData, Arguments, Cmpop, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprKind,
|
||||||
|
|
@ -985,6 +986,44 @@ pub fn unnecessary_collection_call(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unnecessary_subscript_reversal(expr: &Expr, func: &Expr, args: &[Expr]) -> Option<Check> {
|
||||||
|
if let Some(first_arg) = args.first() {
|
||||||
|
if let ExprKind::Name { id, .. } = &func.node {
|
||||||
|
if id == "set" || id == "sorted" || id == "reversed" {
|
||||||
|
if let ExprKind::Subscript { slice, .. } = &first_arg.node {
|
||||||
|
if let ExprKind::Slice { lower, upper, step } = &slice.node {
|
||||||
|
if lower.is_none() && upper.is_none() {
|
||||||
|
if let Some(step) = step {
|
||||||
|
if let ExprKind::UnaryOp {
|
||||||
|
op: Unaryop::USub,
|
||||||
|
operand,
|
||||||
|
} = &step.node
|
||||||
|
{
|
||||||
|
if let ExprKind::Constant {
|
||||||
|
value: Constant::Int(val),
|
||||||
|
..
|
||||||
|
} = &operand.node
|
||||||
|
{
|
||||||
|
if *val == BigInt::from(1) {
|
||||||
|
return Some(Check::new(
|
||||||
|
CheckKind::UnnecessarySubscriptReversal(
|
||||||
|
id.to_string(),
|
||||||
|
),
|
||||||
|
Range::from_located(expr),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
// flake8-super
|
// flake8-super
|
||||||
/// Check that `super()` has no args
|
/// Check that `super()` has no args
|
||||||
pub fn check_super_args(
|
pub fn check_super_args(
|
||||||
|
|
|
||||||
|
|
@ -783,6 +783,12 @@ where
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.settings.enabled.contains(&CheckCode::C415) {
|
||||||
|
if let Some(check) = checks::unnecessary_subscript_reversal(expr, func, args) {
|
||||||
|
self.checks.push(check);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
if self.settings.enabled.contains(&CheckCode::U002)
|
if self.settings.enabled.contains(&CheckCode::U002)
|
||||||
&& self.settings.target_version >= PythonVersion::Py310
|
&& self.settings.target_version >= PythonVersion::Py310
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ pub enum CheckCode {
|
||||||
C405,
|
C405,
|
||||||
C406,
|
C406,
|
||||||
C408,
|
C408,
|
||||||
|
C415,
|
||||||
// flake8-super
|
// flake8-super
|
||||||
SPR001,
|
SPR001,
|
||||||
// flake8-print
|
// flake8-print
|
||||||
|
|
@ -219,6 +220,7 @@ pub enum CheckKind {
|
||||||
UnnecessaryLiteralSet(String),
|
UnnecessaryLiteralSet(String),
|
||||||
UnnecessaryLiteralDict(String),
|
UnnecessaryLiteralDict(String),
|
||||||
UnnecessaryCollectionCall(String),
|
UnnecessaryCollectionCall(String),
|
||||||
|
UnnecessarySubscriptReversal(String),
|
||||||
// flake8-super
|
// flake8-super
|
||||||
SuperCallWithParameters,
|
SuperCallWithParameters,
|
||||||
// flake8-print
|
// flake8-print
|
||||||
|
|
@ -312,6 +314,9 @@ impl CheckCode {
|
||||||
CheckCode::C408 => {
|
CheckCode::C408 => {
|
||||||
CheckKind::UnnecessaryCollectionCall("<dict/list/tuple>".to_string())
|
CheckKind::UnnecessaryCollectionCall("<dict/list/tuple>".to_string())
|
||||||
}
|
}
|
||||||
|
CheckCode::C415 => {
|
||||||
|
CheckKind::UnnecessarySubscriptReversal("<reversed/set/sorted>".to_string())
|
||||||
|
}
|
||||||
// flake8-super
|
// flake8-super
|
||||||
CheckCode::SPR001 => CheckKind::SuperCallWithParameters,
|
CheckCode::SPR001 => CheckKind::SuperCallWithParameters,
|
||||||
// flake8-print
|
// flake8-print
|
||||||
|
|
@ -393,6 +398,7 @@ impl CheckKind {
|
||||||
CheckKind::UnnecessaryLiteralSet(_) => &CheckCode::C405,
|
CheckKind::UnnecessaryLiteralSet(_) => &CheckCode::C405,
|
||||||
CheckKind::UnnecessaryLiteralDict(_) => &CheckCode::C406,
|
CheckKind::UnnecessaryLiteralDict(_) => &CheckCode::C406,
|
||||||
CheckKind::UnnecessaryCollectionCall(_) => &CheckCode::C408,
|
CheckKind::UnnecessaryCollectionCall(_) => &CheckCode::C408,
|
||||||
|
CheckKind::UnnecessarySubscriptReversal(_) => &CheckCode::C415,
|
||||||
// flake8-super
|
// flake8-super
|
||||||
CheckKind::SuperCallWithParameters => &CheckCode::SPR001,
|
CheckKind::SuperCallWithParameters => &CheckCode::SPR001,
|
||||||
// flake8-print
|
// flake8-print
|
||||||
|
|
@ -579,6 +585,9 @@ impl CheckKind {
|
||||||
CheckKind::UnnecessaryCollectionCall(obj_type) => {
|
CheckKind::UnnecessaryCollectionCall(obj_type) => {
|
||||||
format!("Unnecessary {obj_type} call - rewrite as a literal")
|
format!("Unnecessary {obj_type} call - rewrite as a literal")
|
||||||
}
|
}
|
||||||
|
CheckKind::UnnecessarySubscriptReversal(func) => {
|
||||||
|
format!("Unnecessary subscript reversal of iterable within {func}()")
|
||||||
|
}
|
||||||
// flake8-super
|
// flake8-super
|
||||||
CheckKind::SuperCallWithParameters => {
|
CheckKind::SuperCallWithParameters => {
|
||||||
"Use `super()` instead of `super(__class__, self)`".to_string()
|
"Use `super()` instead of `super(__class__, self)`".to_string()
|
||||||
|
|
|
||||||
|
|
@ -894,6 +894,18 @@ mod tests {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn c415() -> Result<()> {
|
||||||
|
let mut checks = check_path(
|
||||||
|
Path::new("./resources/test/fixtures/C415.py"),
|
||||||
|
&settings::Settings::for_rule(CheckCode::C415),
|
||||||
|
&fixer::Mode::Generate,
|
||||||
|
)?;
|
||||||
|
checks.sort_by_key(|check| check.location);
|
||||||
|
insta::assert_yaml_snapshot!(checks);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn spr001() -> Result<()> {
|
fn spr001() -> Result<()> {
|
||||||
let mut checks = check_path(
|
let mut checks = check_path(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
source: src/linter.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
UnnecessarySubscriptReversal: set
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 19
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
UnnecessarySubscriptReversal: reversed
|
||||||
|
location:
|
||||||
|
row: 3
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 24
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
UnnecessarySubscriptReversal: sorted
|
||||||
|
location:
|
||||||
|
row: 4
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 4
|
||||||
|
column: 22
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
UnnecessarySubscriptReversal: sorted
|
||||||
|
location:
|
||||||
|
row: 5
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 5
|
||||||
|
column: 36
|
||||||
|
fix: ~
|
||||||
|
|
||||||
Loading…
Reference in New Issue