Implement C406 (#363)

This commit is contained in:
Harutaka Kawamura 2022-10-09 00:15:41 +09:00 committed by GitHub
parent 307fa26515
commit 346610c2e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 131 additions and 1 deletions

5
resources/test/fixtures/C406.py vendored Normal file
View File

@ -0,0 +1,5 @@
d1 = dict([(1, 2)])
d2 = dict(((1, 2),))
d3 = dict([])
d4 = dict(())
d5 = dict()

View File

@ -903,6 +903,60 @@ pub fn unnecessary_literal_set(expr: &Expr, func: &Expr, args: &Vec<Expr>) -> Op
None
}
/// Check `dict([(1, 2)])` compliance.
pub fn unnecessary_literal_dict(expr: &Expr, func: &Expr, args: &Vec<Expr>) -> Option<Check> {
if args.len() == 1 {
if let ExprKind::Name { id, .. } = &func.node {
if id == "dict" {
match &args[0].node {
ExprKind::Tuple { elts, .. } => {
if let Some(elt) = elts.first() {
match &elt.node {
// dict((1, 2), ...))
ExprKind::Tuple { elts, .. } if elts.len() == 2 => {
return Some(Check::new(
CheckKind::UnnecessaryLiteralDict("tuple".to_string()),
Range::from_located(expr),
));
}
_ => {}
}
} else {
// dict(())
return Some(Check::new(
CheckKind::UnnecessaryLiteralDict("tuple".to_string()),
Range::from_located(expr),
));
}
}
ExprKind::List { elts, .. } => {
if let Some(elt) = elts.first() {
match &elt.node {
// dict([(1, 2), ...])
ExprKind::Tuple { elts, .. } if elts.len() == 2 => {
return Some(Check::new(
CheckKind::UnnecessaryLiteralDict("list".to_string()),
Range::from_located(expr),
));
}
_ => {}
}
} else {
// dict([])
return Some(Check::new(
CheckKind::UnnecessaryLiteralDict("list".to_string()),
Range::from_located(expr),
));
}
}
_ => {}
}
}
}
}
None
}
// flake8-super
/// Check that `super()` has no args
pub fn check_super_args(

View File

@ -806,6 +806,12 @@ where
};
}
if self.settings.enabled.contains(&CheckCode::C406) {
if let Some(check) = checks::unnecessary_literal_dict(expr, func, args) {
self.checks.push(check);
};
}
// pyupgrade
if self.settings.enabled.contains(&CheckCode::U002)
&& self.settings.target_version >= PythonVersion::Py310

View File

@ -57,7 +57,7 @@ pub const DEFAULT_CHECK_CODES: [CheckCode; 43] = [
CheckCode::F901,
];
pub const ALL_CHECK_CODES: [CheckCode; 61] = [
pub const ALL_CHECK_CODES: [CheckCode; 62] = [
// pycodestyle errors
CheckCode::E402,
CheckCode::E501,
@ -115,6 +115,7 @@ pub const ALL_CHECK_CODES: [CheckCode; 61] = [
CheckCode::C403,
CheckCode::C404,
CheckCode::C405,
CheckCode::C406,
// flake8-super
CheckCode::SPR001,
// flake8-print
@ -189,6 +190,7 @@ pub enum CheckCode {
C403,
C404,
C405,
C406,
// flake8-super
SPR001,
// flake8-print
@ -265,6 +267,8 @@ impl FromStr for CheckCode {
"C402" => Ok(CheckCode::C402),
"C403" => Ok(CheckCode::C403),
"C404" => Ok(CheckCode::C404),
"C405" => Ok(CheckCode::C405),
"C406" => Ok(CheckCode::C406),
// flake8-super
"SPR001" => Ok(CheckCode::SPR001),
// flake8-print
@ -343,6 +347,7 @@ impl CheckCode {
CheckCode::C403 => "C403",
CheckCode::C404 => "C404",
CheckCode::C405 => "C405",
CheckCode::C406 => "C406",
// flake8-super
CheckCode::SPR001 => "SPR001",
// flake8-print
@ -430,6 +435,7 @@ impl CheckCode {
CheckCode::C403 => CheckKind::UnnecessaryListComprehensionSet,
CheckCode::C404 => CheckKind::UnnecessaryListComprehensionDict,
CheckCode::C405 => CheckKind::UnnecessaryLiteralSet("<list/tuple>".to_string()),
CheckCode::C406 => CheckKind::UnnecessaryLiteralDict("<list/tuple>".to_string()),
// flake8-super
CheckCode::SPR001 => CheckKind::SuperCallWithParameters,
// flake8-print
@ -517,6 +523,7 @@ pub enum CheckKind {
UnnecessaryListComprehensionSet,
UnnecessaryListComprehensionDict,
UnnecessaryLiteralSet(String),
UnnecessaryLiteralDict(String),
// flake8-super
SuperCallWithParameters,
// flake8-print
@ -591,6 +598,7 @@ impl CheckKind {
CheckKind::UnnecessaryListComprehensionSet => "UnnecessaryListComprehensionSet",
CheckKind::UnnecessaryListComprehensionDict => "UnnecessaryListComprehensionDict",
CheckKind::UnnecessaryLiteralSet(_) => "UnnecessaryLiteralSet",
CheckKind::UnnecessaryLiteralDict(_) => "UnnecessaryLiteralDict",
// flake8-super
CheckKind::SuperCallWithParameters => "SuperCallWithParameters",
// flake8-print
@ -665,6 +673,7 @@ impl CheckKind {
CheckKind::UnnecessaryListComprehensionSet => &CheckCode::C403,
CheckKind::UnnecessaryListComprehensionDict => &CheckCode::C404,
CheckKind::UnnecessaryLiteralSet(_) => &CheckCode::C405,
CheckKind::UnnecessaryLiteralDict(_) => &CheckCode::C406,
// flake8-super
CheckKind::SuperCallWithParameters => &CheckCode::SPR001,
// flake8-print
@ -842,6 +851,9 @@ impl CheckKind {
CheckKind::UnnecessaryLiteralSet(obj_type) => {
format!("Unnecessary {obj_type} literal - rewrite as a set literal")
}
CheckKind::UnnecessaryLiteralDict(obj_type) => {
format!("Unnecessary {obj_type} literal - rewrite as a dict literal")
}
// flake8-super
CheckKind::SuperCallWithParameters => {
"Use `super()` instead of `super(__class__, self)`".to_string()

View File

@ -858,6 +858,18 @@ mod tests {
Ok(())
}
#[test]
fn c406() -> Result<()> {
let mut checks = check_path(
Path::new("./resources/test/fixtures/C406.py"),
&settings::Settings::for_rule(CheckCode::C406),
&fixer::Mode::Generate,
)?;
checks.sort_by_key(|check| check.location);
insta::assert_yaml_snapshot!(checks);
Ok(())
}
#[test]
fn spr001() -> Result<()> {
let mut checks = check_path(

View File

@ -0,0 +1,41 @@
---
source: src/linter.rs
expression: checks
---
- kind:
UnnecessaryLiteralDict: list
location:
row: 1
column: 6
end_location:
row: 1
column: 20
fix: ~
- kind:
UnnecessaryLiteralDict: tuple
location:
row: 2
column: 6
end_location:
row: 2
column: 21
fix: ~
- kind:
UnnecessaryLiteralDict: list
location:
row: 3
column: 6
end_location:
row: 3
column: 14
fix: ~
- kind:
UnnecessaryLiteralDict: tuple
location:
row: 4
column: 6
end_location:
row: 4
column: 14
fix: ~