mirror of https://github.com/astral-sh/ruff
Move flake8-comprehensions violations to rule files (#2477)
This commit is contained in:
parent
f5fd6f59ea
commit
aa85c81280
|
|
@ -130,22 +130,22 @@ ruff_macros::define_rule_mapping!(
|
||||||
// flake8-blind-except
|
// flake8-blind-except
|
||||||
BLE001 => violations::BlindExcept,
|
BLE001 => violations::BlindExcept,
|
||||||
// flake8-comprehensions
|
// flake8-comprehensions
|
||||||
C400 => violations::UnnecessaryGeneratorList,
|
C400 => rules::flake8_comprehensions::rules::UnnecessaryGeneratorList,
|
||||||
C401 => violations::UnnecessaryGeneratorSet,
|
C401 => rules::flake8_comprehensions::rules::UnnecessaryGeneratorSet,
|
||||||
C402 => violations::UnnecessaryGeneratorDict,
|
C402 => rules::flake8_comprehensions::rules::UnnecessaryGeneratorDict,
|
||||||
C403 => violations::UnnecessaryListComprehensionSet,
|
C403 => rules::flake8_comprehensions::rules::UnnecessaryListComprehensionSet,
|
||||||
C404 => violations::UnnecessaryListComprehensionDict,
|
C404 => rules::flake8_comprehensions::rules::UnnecessaryListComprehensionDict,
|
||||||
C405 => violations::UnnecessaryLiteralSet,
|
C405 => rules::flake8_comprehensions::rules::UnnecessaryLiteralSet,
|
||||||
C406 => violations::UnnecessaryLiteralDict,
|
C406 => rules::flake8_comprehensions::rules::UnnecessaryLiteralDict,
|
||||||
C408 => violations::UnnecessaryCollectionCall,
|
C408 => rules::flake8_comprehensions::rules::UnnecessaryCollectionCall,
|
||||||
C409 => violations::UnnecessaryLiteralWithinTupleCall,
|
C409 => rules::flake8_comprehensions::rules::UnnecessaryLiteralWithinTupleCall,
|
||||||
C410 => violations::UnnecessaryLiteralWithinListCall,
|
C410 => rules::flake8_comprehensions::rules::UnnecessaryLiteralWithinListCall,
|
||||||
C411 => violations::UnnecessaryListCall,
|
C411 => rules::flake8_comprehensions::rules::UnnecessaryListCall,
|
||||||
C413 => violations::UnnecessaryCallAroundSorted,
|
C413 => rules::flake8_comprehensions::rules::UnnecessaryCallAroundSorted,
|
||||||
C414 => violations::UnnecessaryDoubleCastOrProcess,
|
C414 => rules::flake8_comprehensions::rules::UnnecessaryDoubleCastOrProcess,
|
||||||
C415 => violations::UnnecessarySubscriptReversal,
|
C415 => rules::flake8_comprehensions::rules::UnnecessarySubscriptReversal,
|
||||||
C416 => violations::UnnecessaryComprehension,
|
C416 => rules::flake8_comprehensions::rules::UnnecessaryComprehension,
|
||||||
C417 => violations::UnnecessaryMap,
|
C417 => rules::flake8_comprehensions::rules::UnnecessaryMap,
|
||||||
// flake8-debugger
|
// flake8-debugger
|
||||||
T100 => violations::Debugger,
|
T100 => violations::Debugger,
|
||||||
// mccabe
|
// mccabe
|
||||||
|
|
|
||||||
|
|
@ -1,728 +0,0 @@
|
||||||
use log::error;
|
|
||||||
use num_bigint::BigInt;
|
|
||||||
use rustpython_ast::{Comprehension, Constant, Expr, ExprKind, Keyword, Unaryop};
|
|
||||||
|
|
||||||
use super::fixes;
|
|
||||||
use crate::ast::types::Range;
|
|
||||||
use crate::checkers::ast::Checker;
|
|
||||||
use crate::registry::Diagnostic;
|
|
||||||
use crate::violations;
|
|
||||||
|
|
||||||
fn function_name(func: &Expr) -> Option<&str> {
|
|
||||||
if let ExprKind::Name { id, .. } = &func.node {
|
|
||||||
Some(id)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn exactly_one_argument_with_matching_function<'a>(
|
|
||||||
name: &str,
|
|
||||||
func: &Expr,
|
|
||||||
args: &'a [Expr],
|
|
||||||
keywords: &[Keyword],
|
|
||||||
) -> Option<&'a ExprKind> {
|
|
||||||
if !keywords.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if args.len() != 1 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if function_name(func)? != name {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(&args[0].node)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn first_argument_with_matching_function<'a>(
|
|
||||||
name: &str,
|
|
||||||
func: &Expr,
|
|
||||||
args: &'a [Expr],
|
|
||||||
) -> Option<&'a ExprKind> {
|
|
||||||
if function_name(func)? == name {
|
|
||||||
Some(&args.first()?.node)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C400 (`list(generator)`)
|
|
||||||
pub fn unnecessary_generator_list(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
keywords: &[Keyword],
|
|
||||||
) {
|
|
||||||
let Some(argument) = exactly_one_argument_with_matching_function("list", func, args, keywords) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin("list") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if let ExprKind::GeneratorExp { .. } = argument {
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryGeneratorList,
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_generator_list(checker.locator, checker.stylist, expr) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C401 (`set(generator)`)
|
|
||||||
pub fn unnecessary_generator_set(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
keywords: &[Keyword],
|
|
||||||
) {
|
|
||||||
let Some(argument) = exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin("set") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if let ExprKind::GeneratorExp { .. } = argument {
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryGeneratorSet,
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_generator_set(checker.locator, checker.stylist, expr) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C402 (`dict((x, y) for x, y in iterable)`)
|
|
||||||
pub fn unnecessary_generator_dict(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
keywords: &[Keyword],
|
|
||||||
) {
|
|
||||||
let Some(argument) = exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if let ExprKind::GeneratorExp { elt, .. } = argument {
|
|
||||||
match &elt.node {
|
|
||||||
ExprKind::Tuple { elts, .. } if elts.len() == 2 => {
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryGeneratorDict,
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_generator_dict(
|
|
||||||
checker.locator,
|
|
||||||
checker.stylist,
|
|
||||||
expr,
|
|
||||||
) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C403 (`set([...])`)
|
|
||||||
pub fn unnecessary_list_comprehension_set(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
keywords: &[Keyword],
|
|
||||||
) {
|
|
||||||
let Some(argument) = exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin("set") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if let ExprKind::ListComp { .. } = &argument {
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryListComprehensionSet,
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_list_comprehension_set(
|
|
||||||
checker.locator,
|
|
||||||
checker.stylist,
|
|
||||||
expr,
|
|
||||||
) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C404 (`dict([...])`)
|
|
||||||
pub fn unnecessary_list_comprehension_dict(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
keywords: &[Keyword],
|
|
||||||
) {
|
|
||||||
let Some(argument) = exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin("dict") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let ExprKind::ListComp { elt, .. } = &argument else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let ExprKind::Tuple { elts, .. } = &elt.node else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if elts.len() != 2 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryListComprehensionDict,
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_list_comprehension_dict(checker.locator, checker.stylist, expr)
|
|
||||||
{
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C405 (`set([1, 2])`)
|
|
||||||
pub fn unnecessary_literal_set(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
keywords: &[Keyword],
|
|
||||||
) {
|
|
||||||
let Some(argument) = exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin("set") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let kind = match argument {
|
|
||||||
ExprKind::List { .. } => "list",
|
|
||||||
ExprKind::Tuple { .. } => "tuple",
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryLiteralSet {
|
|
||||||
obj_type: kind.to_string(),
|
|
||||||
},
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_literal_set(checker.locator, checker.stylist, expr) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C406 (`dict([(1, 2)])`)
|
|
||||||
pub fn unnecessary_literal_dict(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
keywords: &[Keyword],
|
|
||||||
) {
|
|
||||||
let Some(argument) = exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin("dict") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let (kind, elts) = match argument {
|
|
||||||
ExprKind::Tuple { elts, .. } => ("tuple", elts),
|
|
||||||
ExprKind::List { elts, .. } => ("list", elts),
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
// Accept `dict((1, 2), ...))` `dict([(1, 2), ...])`.
|
|
||||||
if !elts
|
|
||||||
.iter()
|
|
||||||
.all(|elt| matches!(&elt.node, ExprKind::Tuple { elts, .. } if elts.len() == 2))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryLiteralDict {
|
|
||||||
obj_type: kind.to_string(),
|
|
||||||
},
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_literal_dict(checker.locator, checker.stylist, expr) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C408
|
|
||||||
pub fn unnecessary_collection_call(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
keywords: &[Keyword],
|
|
||||||
) {
|
|
||||||
if !args.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let Some(id) = function_name(func) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
match id {
|
|
||||||
"dict" if keywords.is_empty() || keywords.iter().all(|kw| kw.node.arg.is_some()) => {
|
|
||||||
// `dict()` or `dict(a=1)` (as opposed to `dict(**a)`)
|
|
||||||
}
|
|
||||||
"list" | "tuple" => {
|
|
||||||
// `list()` or `tuple()`
|
|
||||||
}
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
if !checker.is_builtin(id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryCollectionCall {
|
|
||||||
obj_type: id.to_string(),
|
|
||||||
},
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_collection_call(checker.locator, checker.stylist, expr) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C409
|
|
||||||
pub fn unnecessary_literal_within_tuple_call(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
) {
|
|
||||||
let Some(argument) = first_argument_with_matching_function("tuple", func, args) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin("tuple") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let argument_kind = match argument {
|
|
||||||
ExprKind::Tuple { .. } => "tuple",
|
|
||||||
ExprKind::List { .. } => "list",
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryLiteralWithinTupleCall {
|
|
||||||
literal: argument_kind.to_string(),
|
|
||||||
},
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_literal_within_tuple_call(
|
|
||||||
checker.locator,
|
|
||||||
checker.stylist,
|
|
||||||
expr,
|
|
||||||
) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C410
|
|
||||||
pub fn unnecessary_literal_within_list_call(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
) {
|
|
||||||
let Some(argument) = first_argument_with_matching_function("list", func, args) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin("list") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let argument_kind = match argument {
|
|
||||||
ExprKind::Tuple { .. } => "tuple",
|
|
||||||
ExprKind::List { .. } => "list",
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryLiteralWithinListCall {
|
|
||||||
literal: argument_kind.to_string(),
|
|
||||||
},
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_literal_within_list_call(
|
|
||||||
checker.locator,
|
|
||||||
checker.stylist,
|
|
||||||
expr,
|
|
||||||
) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C411
|
|
||||||
pub fn unnecessary_list_call(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
|
||||||
let Some(argument) = first_argument_with_matching_function("list", func, args) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin("list") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if !matches!(argument, ExprKind::ListComp { .. }) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut diagnostic =
|
|
||||||
Diagnostic::new(violations::UnnecessaryListCall, Range::from_located(expr));
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_list_call(checker.locator, checker.stylist, expr) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C413
|
|
||||||
pub fn unnecessary_call_around_sorted(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
) {
|
|
||||||
let Some(outer) = function_name(func) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !(outer == "list" || outer == "reversed") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let Some(arg) = args.first() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let ExprKind::Call { func, .. } = &arg.node else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let Some(inner) = function_name(func) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if inner != "sorted" {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if !checker.is_builtin(inner) || !checker.is_builtin(outer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryCallAroundSorted {
|
|
||||||
func: outer.to_string(),
|
|
||||||
},
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_call_around_sorted(checker.locator, checker.stylist, expr) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C414
|
|
||||||
pub fn unnecessary_double_cast_or_process(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
) {
|
|
||||||
fn diagnostic(inner: &str, outer: &str, location: Range) -> Diagnostic {
|
|
||||||
Diagnostic::new(
|
|
||||||
violations::UnnecessaryDoubleCastOrProcess {
|
|
||||||
inner: inner.to_string(),
|
|
||||||
outer: outer.to_string(),
|
|
||||||
},
|
|
||||||
location,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(outer) = function_name(func) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !(outer == "list"
|
|
||||||
|| outer == "tuple"
|
|
||||||
|| outer == "set"
|
|
||||||
|| outer == "reversed"
|
|
||||||
|| outer == "sorted")
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let Some(arg) = args.first() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let ExprKind::Call { func, .. } = &arg.node else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let Some(inner) = function_name(func) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !checker.is_builtin(inner) || !checker.is_builtin(outer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ex) set(tuple(...))
|
|
||||||
if (outer == "set" || outer == "sorted")
|
|
||||||
&& (inner == "list" || inner == "tuple" || inner == "reversed" || inner == "sorted")
|
|
||||||
{
|
|
||||||
checker
|
|
||||||
.diagnostics
|
|
||||||
.push(diagnostic(inner, outer, Range::from_located(expr)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ex) list(tuple(...))
|
|
||||||
if (outer == "list" || outer == "tuple") && (inner == "list" || inner == "tuple") {
|
|
||||||
checker
|
|
||||||
.diagnostics
|
|
||||||
.push(diagnostic(inner, outer, Range::from_located(expr)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ex) set(set(...))
|
|
||||||
if outer == "set" && inner == "set" {
|
|
||||||
checker
|
|
||||||
.diagnostics
|
|
||||||
.push(diagnostic(inner, outer, Range::from_located(expr)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C415
|
|
||||||
pub fn unnecessary_subscript_reversal(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
func: &Expr,
|
|
||||||
args: &[Expr],
|
|
||||||
) {
|
|
||||||
let Some(first_arg) = args.first() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let Some(id) = function_name(func) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if !(id == "set" || id == "sorted" || id == "reversed") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if !checker.is_builtin(id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let ExprKind::Subscript { slice, .. } = &first_arg.node else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let ExprKind::Slice { lower, upper, step } = &slice.node else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if lower.is_some() || upper.is_some() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let Some(step) = step.as_ref() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let ExprKind::UnaryOp {
|
|
||||||
op: Unaryop::USub,
|
|
||||||
operand,
|
|
||||||
} = &step.node else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let ExprKind::Constant {
|
|
||||||
value: Constant::Int(val),
|
|
||||||
..
|
|
||||||
} = &operand.node else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if *val != BigInt::from(1) {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
|
||||||
violations::UnnecessarySubscriptReversal {
|
|
||||||
func: id.to_string(),
|
|
||||||
},
|
|
||||||
Range::from_located(expr),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C416
|
|
||||||
pub fn unnecessary_comprehension(
|
|
||||||
checker: &mut Checker,
|
|
||||||
expr: &Expr,
|
|
||||||
elt: &Expr,
|
|
||||||
generators: &[Comprehension],
|
|
||||||
) {
|
|
||||||
if generators.len() != 1 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let generator = &generators[0];
|
|
||||||
if !(generator.ifs.is_empty() && generator.is_async == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let Some(elt_id) = function_name(elt) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(target_id) = function_name(&generator.target) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if elt_id != target_id {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let id = match &expr.node {
|
|
||||||
ExprKind::ListComp { .. } => "list",
|
|
||||||
ExprKind::SetComp { .. } => "set",
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
if !checker.is_builtin(id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
|
||||||
violations::UnnecessaryComprehension {
|
|
||||||
obj_type: id.to_string(),
|
|
||||||
},
|
|
||||||
Range::from_located(expr),
|
|
||||||
);
|
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
|
||||||
match fixes::fix_unnecessary_comprehension(checker.locator, checker.stylist, expr) {
|
|
||||||
Ok(fix) => {
|
|
||||||
diagnostic.amend(fix);
|
|
||||||
}
|
|
||||||
Err(e) => error!("Failed to generate fix: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
checker.diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C417
|
|
||||||
pub fn unnecessary_map(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
|
||||||
fn diagnostic(kind: &str, location: Range) -> Diagnostic {
|
|
||||||
Diagnostic::new(
|
|
||||||
violations::UnnecessaryMap {
|
|
||||||
obj_type: kind.to_string(),
|
|
||||||
},
|
|
||||||
location,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(id) = function_name(func) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
match id {
|
|
||||||
"map" => {
|
|
||||||
if !checker.is_builtin(id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.len() == 2 && matches!(&args[0].node, ExprKind::Lambda { .. }) {
|
|
||||||
checker
|
|
||||||
.diagnostics
|
|
||||||
.push(diagnostic("generator", Range::from_located(expr)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"list" | "set" => {
|
|
||||||
if !checker.is_builtin(id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(arg) = args.first() {
|
|
||||||
if let ExprKind::Call { func, args, .. } = &arg.node {
|
|
||||||
let Some(argument) = first_argument_with_matching_function("map", func, args) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if let ExprKind::Lambda { .. } = argument {
|
|
||||||
checker
|
|
||||||
.diagnostics
|
|
||||||
.push(diagnostic(id, Range::from_located(expr)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"dict" => {
|
|
||||||
if !checker.is_builtin(id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.len() == 1 {
|
|
||||||
if let ExprKind::Call { func, args, .. } = &args[0].node {
|
|
||||||
let Some(argument) = first_argument_with_matching_function("map", func, args) else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if let ExprKind::Lambda { body, .. } = &argument {
|
|
||||||
if matches!(&body.node, ExprKind::Tuple { elts, .. } | ExprKind::List { elts, .. } if elts.len() == 2)
|
|
||||||
{
|
|
||||||
checker
|
|
||||||
.diagnostics
|
|
||||||
.push(diagnostic(id, Range::from_located(expr)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
use rustpython_ast::{Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
|
pub fn function_name(func: &Expr) -> Option<&str> {
|
||||||
|
if let ExprKind::Name { id, .. } = &func.node {
|
||||||
|
Some(id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exactly_one_argument_with_matching_function<'a>(
|
||||||
|
name: &str,
|
||||||
|
func: &Expr,
|
||||||
|
args: &'a [Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) -> Option<&'a ExprKind> {
|
||||||
|
if !keywords.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if args.len() != 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if function_name(func)? != name {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(&args[0].node)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn first_argument_with_matching_function<'a>(
|
||||||
|
name: &str,
|
||||||
|
func: &Expr,
|
||||||
|
args: &'a [Expr],
|
||||||
|
) -> Option<&'a ExprKind> {
|
||||||
|
if function_name(func)? == name {
|
||||||
|
Some(&args.first()?.node)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
mod helpers;
|
||||||
|
mod unnecessary_call_around_sorted;
|
||||||
|
mod unnecessary_collection_call;
|
||||||
|
mod unnecessary_comprehension;
|
||||||
|
mod unnecessary_double_cast_or_process;
|
||||||
|
mod unnecessary_generator_dict;
|
||||||
|
mod unnecessary_generator_list;
|
||||||
|
mod unnecessary_generator_set;
|
||||||
|
mod unnecessary_list_call;
|
||||||
|
mod unnecessary_list_comprehension_dict;
|
||||||
|
mod unnecessary_list_comprehension_set;
|
||||||
|
mod unnecessary_literal_dict;
|
||||||
|
mod unnecessary_literal_set;
|
||||||
|
mod unnecessary_literal_within_list_call;
|
||||||
|
mod unnecessary_literal_within_tuple_call;
|
||||||
|
mod unnecessary_map;
|
||||||
|
mod unnecessary_subscript_reversal;
|
||||||
|
|
||||||
|
pub use unnecessary_call_around_sorted::{
|
||||||
|
unnecessary_call_around_sorted, UnnecessaryCallAroundSorted,
|
||||||
|
};
|
||||||
|
pub use unnecessary_collection_call::{unnecessary_collection_call, UnnecessaryCollectionCall};
|
||||||
|
pub use unnecessary_comprehension::{unnecessary_comprehension, UnnecessaryComprehension};
|
||||||
|
pub use unnecessary_double_cast_or_process::{
|
||||||
|
unnecessary_double_cast_or_process, UnnecessaryDoubleCastOrProcess,
|
||||||
|
};
|
||||||
|
pub use unnecessary_generator_dict::{unnecessary_generator_dict, UnnecessaryGeneratorDict};
|
||||||
|
pub use unnecessary_generator_list::{unnecessary_generator_list, UnnecessaryGeneratorList};
|
||||||
|
pub use unnecessary_generator_set::{unnecessary_generator_set, UnnecessaryGeneratorSet};
|
||||||
|
pub use unnecessary_list_call::{unnecessary_list_call, UnnecessaryListCall};
|
||||||
|
pub use unnecessary_list_comprehension_dict::{
|
||||||
|
unnecessary_list_comprehension_dict, UnnecessaryListComprehensionDict,
|
||||||
|
};
|
||||||
|
pub use unnecessary_list_comprehension_set::{
|
||||||
|
unnecessary_list_comprehension_set, UnnecessaryListComprehensionSet,
|
||||||
|
};
|
||||||
|
pub use unnecessary_literal_dict::{unnecessary_literal_dict, UnnecessaryLiteralDict};
|
||||||
|
pub use unnecessary_literal_set::{unnecessary_literal_set, UnnecessaryLiteralSet};
|
||||||
|
pub use unnecessary_literal_within_list_call::{
|
||||||
|
unnecessary_literal_within_list_call, UnnecessaryLiteralWithinListCall,
|
||||||
|
};
|
||||||
|
pub use unnecessary_literal_within_tuple_call::{
|
||||||
|
unnecessary_literal_within_tuple_call, UnnecessaryLiteralWithinTupleCall,
|
||||||
|
};
|
||||||
|
pub use unnecessary_map::{unnecessary_map, UnnecessaryMap};
|
||||||
|
pub use unnecessary_subscript_reversal::{
|
||||||
|
unnecessary_subscript_reversal, UnnecessarySubscriptReversal,
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryCallAroundSorted {
|
||||||
|
pub func: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryCallAroundSorted {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessaryCallAroundSorted { func } = self;
|
||||||
|
format!("Unnecessary `{func}` call around `sorted()`")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
let UnnecessaryCallAroundSorted { func } = self;
|
||||||
|
format!("Remove unnecessary `{func}` call")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C413
|
||||||
|
pub fn unnecessary_call_around_sorted(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
) {
|
||||||
|
let Some(outer) = helpers::function_name(func) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !(outer == "list" || outer == "reversed") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(arg) = args.first() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ExprKind::Call { func, .. } = &arg.node else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(inner) = helpers::function_name(func) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if inner != "sorted" {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !checker.is_builtin(inner) || !checker.is_builtin(outer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
UnnecessaryCallAroundSorted {
|
||||||
|
func: outer.to_string(),
|
||||||
|
},
|
||||||
|
Range::from_located(expr),
|
||||||
|
);
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_call_around_sorted(checker.locator, checker.stylist, expr) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, Keyword};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryCollectionCall {
|
||||||
|
pub obj_type: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryCollectionCall {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessaryCollectionCall { obj_type } = self;
|
||||||
|
format!("Unnecessary `{obj_type}` call (rewrite as a literal)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Rewrite as a literal".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C408
|
||||||
|
pub fn unnecessary_collection_call(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) {
|
||||||
|
if !args.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(id) = helpers::function_name(func) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
match id {
|
||||||
|
"dict" if keywords.is_empty() || keywords.iter().all(|kw| kw.node.arg.is_some()) => {
|
||||||
|
// `dict()` or `dict(a=1)` (as opposed to `dict(**a)`)
|
||||||
|
}
|
||||||
|
"list" | "tuple" => {
|
||||||
|
// `list()` or `tuple()`
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
if !checker.is_builtin(id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
UnnecessaryCollectionCall {
|
||||||
|
obj_type: id.to_string(),
|
||||||
|
},
|
||||||
|
Range::from_located(expr),
|
||||||
|
);
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_collection_call(checker.locator, checker.stylist, expr) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Comprehension, Expr, ExprKind};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryComprehension {
|
||||||
|
pub obj_type: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryComprehension {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessaryComprehension { obj_type } = self;
|
||||||
|
format!("Unnecessary `{obj_type}` comprehension (rewrite using `{obj_type}()`)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
let UnnecessaryComprehension { obj_type } = self;
|
||||||
|
format!("Rewrite using `{obj_type}()`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C416
|
||||||
|
pub fn unnecessary_comprehension(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
elt: &Expr,
|
||||||
|
generators: &[Comprehension],
|
||||||
|
) {
|
||||||
|
if generators.len() != 1 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let generator = &generators[0];
|
||||||
|
if !(generator.ifs.is_empty() && generator.is_async == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(elt_id) = helpers::function_name(elt) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(target_id) = helpers::function_name(&generator.target) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if elt_id != target_id {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let id = match &expr.node {
|
||||||
|
ExprKind::ListComp { .. } => "list",
|
||||||
|
ExprKind::SetComp { .. } => "set",
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
if !checker.is_builtin(id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
UnnecessaryComprehension {
|
||||||
|
obj_type: id.to_string(),
|
||||||
|
},
|
||||||
|
Range::from_located(expr),
|
||||||
|
);
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_comprehension(checker.locator, checker.stylist, expr) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
|
||||||
|
use crate::violation::Violation;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryDoubleCastOrProcess {
|
||||||
|
pub inner: String,
|
||||||
|
pub outer: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl Violation for UnnecessaryDoubleCastOrProcess {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessaryDoubleCastOrProcess { inner, outer } = self;
|
||||||
|
format!("Unnecessary `{inner}` call within `{outer}()`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C414
|
||||||
|
pub fn unnecessary_double_cast_or_process(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
) {
|
||||||
|
fn diagnostic(inner: &str, outer: &str, location: Range) -> Diagnostic {
|
||||||
|
Diagnostic::new(
|
||||||
|
UnnecessaryDoubleCastOrProcess {
|
||||||
|
inner: inner.to_string(),
|
||||||
|
outer: outer.to_string(),
|
||||||
|
},
|
||||||
|
location,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(outer) = helpers::function_name(func) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !(outer == "list"
|
||||||
|
|| outer == "tuple"
|
||||||
|
|| outer == "set"
|
||||||
|
|| outer == "reversed"
|
||||||
|
|| outer == "sorted")
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(arg) = args.first() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ExprKind::Call { func, .. } = &arg.node else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(inner) = helpers::function_name(func) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin(inner) || !checker.is_builtin(outer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ex) set(tuple(...))
|
||||||
|
if (outer == "set" || outer == "sorted")
|
||||||
|
&& (inner == "list" || inner == "tuple" || inner == "reversed" || inner == "sorted")
|
||||||
|
{
|
||||||
|
checker
|
||||||
|
.diagnostics
|
||||||
|
.push(diagnostic(inner, outer, Range::from_located(expr)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ex) list(tuple(...))
|
||||||
|
if (outer == "list" || outer == "tuple") && (inner == "list" || inner == "tuple") {
|
||||||
|
checker
|
||||||
|
.diagnostics
|
||||||
|
.push(diagnostic(inner, outer, Range::from_located(expr)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ex) set(set(...))
|
||||||
|
if outer == "set" && inner == "set" {
|
||||||
|
checker
|
||||||
|
.diagnostics
|
||||||
|
.push(diagnostic(inner, outer, Range::from_located(expr)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryGeneratorDict;
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryGeneratorDict {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("Unnecessary generator (rewrite as a `dict` comprehension)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Rewrite as a `dict` comprehension".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C402 (`dict((x, y) for x, y in iterable)`)
|
||||||
|
pub fn unnecessary_generator_dict(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) {
|
||||||
|
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if let ExprKind::GeneratorExp { elt, .. } = argument {
|
||||||
|
match &elt.node {
|
||||||
|
ExprKind::Tuple { elts, .. } if elts.len() == 2 => {
|
||||||
|
let mut diagnostic =
|
||||||
|
Diagnostic::new(UnnecessaryGeneratorDict, Range::from_located(expr));
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_generator_dict(
|
||||||
|
checker.locator,
|
||||||
|
checker.stylist,
|
||||||
|
expr,
|
||||||
|
) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryGeneratorList;
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryGeneratorList {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("Unnecessary generator (rewrite as a `list` comprehension)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Rewrite as a `list` comprehension".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C400 (`list(generator)`)
|
||||||
|
pub fn unnecessary_generator_list(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) {
|
||||||
|
let Some(argument) = helpers::exactly_one_argument_with_matching_function("list", func, args, keywords) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin("list") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let ExprKind::GeneratorExp { .. } = argument {
|
||||||
|
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorList, Range::from_located(expr));
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_generator_list(checker.locator, checker.stylist, expr) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryGeneratorSet;
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryGeneratorSet {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("Unnecessary generator (rewrite as a `set` comprehension)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Rewrite as a `set` comprehension".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C401 (`set(generator)`)
|
||||||
|
pub fn unnecessary_generator_set(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) {
|
||||||
|
let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin("set") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let ExprKind::GeneratorExp { .. } = argument {
|
||||||
|
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorSet, Range::from_located(expr));
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_generator_set(checker.locator, checker.stylist, expr) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryListCall;
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryListCall {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("Unnecessary `list` call (remove the outer call to `list()`)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Remove outer `list` call".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C411
|
||||||
|
pub fn unnecessary_list_call(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||||
|
let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin("list") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !matches!(argument, ExprKind::ListComp { .. }) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut diagnostic = Diagnostic::new(UnnecessaryListCall, Range::from_located(expr));
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_list_call(checker.locator, checker.stylist, expr) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryListComprehensionDict;
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryListComprehensionDict {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("Unnecessary `list` comprehension (rewrite as a `dict` comprehension)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Rewrite as a `dict` comprehension".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C404 (`dict([...])`)
|
||||||
|
pub fn unnecessary_list_comprehension_dict(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) {
|
||||||
|
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin("dict") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ExprKind::ListComp { elt, .. } = &argument else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ExprKind::Tuple { elts, .. } = &elt.node else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if elts.len() != 2 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut diagnostic =
|
||||||
|
Diagnostic::new(UnnecessaryListComprehensionDict, Range::from_located(expr));
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_list_comprehension_dict(checker.locator, checker.stylist, expr)
|
||||||
|
{
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryListComprehensionSet;
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryListComprehensionSet {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!("Unnecessary `list` comprehension (rewrite as a `set` comprehension)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Rewrite as a `set` comprehension".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C403 (`set([...])`)
|
||||||
|
pub fn unnecessary_list_comprehension_set(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) {
|
||||||
|
let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin("set") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let ExprKind::ListComp { .. } = &argument {
|
||||||
|
let mut diagnostic =
|
||||||
|
Diagnostic::new(UnnecessaryListComprehensionSet, Range::from_located(expr));
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_list_comprehension_set(
|
||||||
|
checker.locator,
|
||||||
|
checker.stylist,
|
||||||
|
expr,
|
||||||
|
) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryLiteralDict {
|
||||||
|
pub obj_type: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryLiteralDict {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessaryLiteralDict { obj_type } = self;
|
||||||
|
format!("Unnecessary `{obj_type}` literal (rewrite as a `dict` literal)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Rewrite as a `dict` literal".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C406 (`dict([(1, 2)])`)
|
||||||
|
pub fn unnecessary_literal_dict(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) {
|
||||||
|
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin("dict") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let (kind, elts) = match argument {
|
||||||
|
ExprKind::Tuple { elts, .. } => ("tuple", elts),
|
||||||
|
ExprKind::List { elts, .. } => ("list", elts),
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
// Accept `dict((1, 2), ...))` `dict([(1, 2), ...])`.
|
||||||
|
if !elts
|
||||||
|
.iter()
|
||||||
|
.all(|elt| matches!(&elt.node, ExprKind::Tuple { elts, .. } if elts.len() == 2))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
UnnecessaryLiteralDict {
|
||||||
|
obj_type: kind.to_string(),
|
||||||
|
},
|
||||||
|
Range::from_located(expr),
|
||||||
|
);
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_literal_dict(checker.locator, checker.stylist, expr) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryLiteralSet {
|
||||||
|
pub obj_type: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryLiteralSet {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessaryLiteralSet { obj_type } = self;
|
||||||
|
format!("Unnecessary `{obj_type}` literal (rewrite as a `set` literal)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
"Rewrite as a `set` literal".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C405 (`set([1, 2])`)
|
||||||
|
pub fn unnecessary_literal_set(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
keywords: &[Keyword],
|
||||||
|
) {
|
||||||
|
let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin("set") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let kind = match argument {
|
||||||
|
ExprKind::List { .. } => "list",
|
||||||
|
ExprKind::Tuple { .. } => "tuple",
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
UnnecessaryLiteralSet {
|
||||||
|
obj_type: kind.to_string(),
|
||||||
|
},
|
||||||
|
Range::from_located(expr),
|
||||||
|
);
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_literal_set(checker.locator, checker.stylist, expr) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryLiteralWithinListCall {
|
||||||
|
pub literal: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryLiteralWithinListCall {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessaryLiteralWithinListCall { literal } = self;
|
||||||
|
if literal == "list" {
|
||||||
|
format!(
|
||||||
|
"Unnecessary `{literal}` literal passed to `list()` (remove the outer call to \
|
||||||
|
`list()`)"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"Unnecessary `{literal}` literal passed to `list()` (rewrite as a `list` literal)"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
let UnnecessaryLiteralWithinListCall { literal } = self;
|
||||||
|
{
|
||||||
|
if literal == "list" {
|
||||||
|
"Remove outer `list` call".to_string()
|
||||||
|
} else {
|
||||||
|
"Rewrite as a `list` literal".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C410
|
||||||
|
pub fn unnecessary_literal_within_list_call(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
) {
|
||||||
|
let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin("list") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let argument_kind = match argument {
|
||||||
|
ExprKind::Tuple { .. } => "tuple",
|
||||||
|
ExprKind::List { .. } => "list",
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
UnnecessaryLiteralWithinListCall {
|
||||||
|
literal: argument_kind.to_string(),
|
||||||
|
},
|
||||||
|
Range::from_located(expr),
|
||||||
|
);
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_literal_within_list_call(
|
||||||
|
checker.locator,
|
||||||
|
checker.stylist,
|
||||||
|
expr,
|
||||||
|
) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::rules::flake8_comprehensions::fixes;
|
||||||
|
use crate::violation::AlwaysAutofixableViolation;
|
||||||
|
use log::error;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryLiteralWithinTupleCall {
|
||||||
|
pub literal: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl AlwaysAutofixableViolation for UnnecessaryLiteralWithinTupleCall {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessaryLiteralWithinTupleCall { literal } = self;
|
||||||
|
if literal == "list" {
|
||||||
|
format!(
|
||||||
|
"Unnecessary `{literal}` literal passed to `tuple()` (rewrite as a `tuple` \
|
||||||
|
literal)"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"Unnecessary `{literal}` literal passed to `tuple()` (remove the outer call to \
|
||||||
|
`tuple()`)"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn autofix_title(&self) -> String {
|
||||||
|
let UnnecessaryLiteralWithinTupleCall { literal } = self;
|
||||||
|
{
|
||||||
|
if literal == "list" {
|
||||||
|
"Rewrite as a `tuple` literal".to_string()
|
||||||
|
} else {
|
||||||
|
"Remove outer `tuple` call".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C409
|
||||||
|
pub fn unnecessary_literal_within_tuple_call(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
) {
|
||||||
|
let Some(argument) = helpers::first_argument_with_matching_function("tuple", func, args) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !checker.is_builtin("tuple") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let argument_kind = match argument {
|
||||||
|
ExprKind::Tuple { .. } => "tuple",
|
||||||
|
ExprKind::List { .. } => "list",
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
UnnecessaryLiteralWithinTupleCall {
|
||||||
|
literal: argument_kind.to_string(),
|
||||||
|
},
|
||||||
|
Range::from_located(expr),
|
||||||
|
);
|
||||||
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
match fixes::fix_unnecessary_literal_within_tuple_call(
|
||||||
|
checker.locator,
|
||||||
|
checker.stylist,
|
||||||
|
expr,
|
||||||
|
) {
|
||||||
|
Ok(fix) => {
|
||||||
|
diagnostic.amend(fix);
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to generate fix: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checker.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
|
||||||
|
use crate::violation::Violation;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessaryMap {
|
||||||
|
pub obj_type: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl Violation for UnnecessaryMap {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessaryMap { obj_type } = self;
|
||||||
|
if obj_type == "generator" {
|
||||||
|
format!("Unnecessary `map` usage (rewrite using a generator expression)")
|
||||||
|
} else {
|
||||||
|
format!("Unnecessary `map` usage (rewrite using a `{obj_type}` comprehension)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C417
|
||||||
|
pub fn unnecessary_map(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||||
|
fn diagnostic(kind: &str, location: Range) -> Diagnostic {
|
||||||
|
Diagnostic::new(
|
||||||
|
UnnecessaryMap {
|
||||||
|
obj_type: kind.to_string(),
|
||||||
|
},
|
||||||
|
location,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(id) = helpers::function_name(func) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
match id {
|
||||||
|
"map" => {
|
||||||
|
if !checker.is_builtin(id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.len() == 2 && matches!(&args[0].node, ExprKind::Lambda { .. }) {
|
||||||
|
checker
|
||||||
|
.diagnostics
|
||||||
|
.push(diagnostic("generator", Range::from_located(expr)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"list" | "set" => {
|
||||||
|
if !checker.is_builtin(id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(arg) = args.first() {
|
||||||
|
if let ExprKind::Call { func, args, .. } = &arg.node {
|
||||||
|
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if let ExprKind::Lambda { .. } = argument {
|
||||||
|
checker
|
||||||
|
.diagnostics
|
||||||
|
.push(diagnostic(id, Range::from_located(expr)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"dict" => {
|
||||||
|
if !checker.is_builtin(id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.len() == 1 {
|
||||||
|
if let ExprKind::Call { func, args, .. } = &args[0].node {
|
||||||
|
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if let ExprKind::Lambda { body, .. } = &argument {
|
||||||
|
if matches!(&body.node, ExprKind::Tuple { elts, .. } | ExprKind::List { elts, .. } if elts.len() == 2)
|
||||||
|
{
|
||||||
|
checker
|
||||||
|
.diagnostics
|
||||||
|
.push(diagnostic(id, Range::from_located(expr)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
use super::helpers;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
|
||||||
|
use crate::violation::Violation;
|
||||||
|
use num_bigint::BigInt;
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
use rustpython_ast::{Constant, Expr, ExprKind, Unaryop};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct UnnecessarySubscriptReversal {
|
||||||
|
pub func: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl Violation for UnnecessarySubscriptReversal {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let UnnecessarySubscriptReversal { func } = self;
|
||||||
|
format!("Unnecessary subscript reversal of iterable within `{func}()`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// C415
|
||||||
|
pub fn unnecessary_subscript_reversal(
|
||||||
|
checker: &mut Checker,
|
||||||
|
expr: &Expr,
|
||||||
|
func: &Expr,
|
||||||
|
args: &[Expr],
|
||||||
|
) {
|
||||||
|
let Some(first_arg) = args.first() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(id) = helpers::function_name(func) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if !(id == "set" || id == "sorted" || id == "reversed") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !checker.is_builtin(id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ExprKind::Subscript { slice, .. } = &first_arg.node else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ExprKind::Slice { lower, upper, step } = &slice.node else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if lower.is_some() || upper.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(step) = step.as_ref() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ExprKind::UnaryOp {
|
||||||
|
op: Unaryop::USub,
|
||||||
|
operand,
|
||||||
|
} = &step.node else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let ExprKind::Constant {
|
||||||
|
value: Constant::Int(val),
|
||||||
|
..
|
||||||
|
} = &operand.node else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if *val != BigInt::from(1) {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
|
UnnecessarySubscriptReversal {
|
||||||
|
func: id.to_string(),
|
||||||
|
},
|
||||||
|
Range::from_located(expr),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
@ -1396,290 +1396,6 @@ impl Violation for BlindExcept {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// flake8-comprehensions
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryGeneratorList;
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryGeneratorList {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("Unnecessary generator (rewrite as a `list` comprehension)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Rewrite as a `list` comprehension".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryGeneratorSet;
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryGeneratorSet {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("Unnecessary generator (rewrite as a `set` comprehension)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Rewrite as a `set` comprehension".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryGeneratorDict;
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryGeneratorDict {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("Unnecessary generator (rewrite as a `dict` comprehension)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Rewrite as a `dict` comprehension".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryListComprehensionSet;
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryListComprehensionSet {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("Unnecessary `list` comprehension (rewrite as a `set` comprehension)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Rewrite as a `set` comprehension".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryListComprehensionDict;
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryListComprehensionDict {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("Unnecessary `list` comprehension (rewrite as a `dict` comprehension)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Rewrite as a `dict` comprehension".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryLiteralSet {
|
|
||||||
pub obj_type: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryLiteralSet {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessaryLiteralSet { obj_type } = self;
|
|
||||||
format!("Unnecessary `{obj_type}` literal (rewrite as a `set` literal)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Rewrite as a `set` literal".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryLiteralDict {
|
|
||||||
pub obj_type: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryLiteralDict {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessaryLiteralDict { obj_type } = self;
|
|
||||||
format!("Unnecessary `{obj_type}` literal (rewrite as a `dict` literal)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Rewrite as a `dict` literal".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryCollectionCall {
|
|
||||||
pub obj_type: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryCollectionCall {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessaryCollectionCall { obj_type } = self;
|
|
||||||
format!("Unnecessary `{obj_type}` call (rewrite as a literal)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Rewrite as a literal".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryLiteralWithinTupleCall {
|
|
||||||
pub literal: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryLiteralWithinTupleCall {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessaryLiteralWithinTupleCall { literal } = self;
|
|
||||||
if literal == "list" {
|
|
||||||
format!(
|
|
||||||
"Unnecessary `{literal}` literal passed to `tuple()` (rewrite as a `tuple` \
|
|
||||||
literal)"
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
"Unnecessary `{literal}` literal passed to `tuple()` (remove the outer call to \
|
|
||||||
`tuple()`)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
let UnnecessaryLiteralWithinTupleCall { literal } = self;
|
|
||||||
{
|
|
||||||
if literal == "list" {
|
|
||||||
"Rewrite as a `tuple` literal".to_string()
|
|
||||||
} else {
|
|
||||||
"Remove outer `tuple` call".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryLiteralWithinListCall {
|
|
||||||
pub literal: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryLiteralWithinListCall {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessaryLiteralWithinListCall { literal } = self;
|
|
||||||
if literal == "list" {
|
|
||||||
format!(
|
|
||||||
"Unnecessary `{literal}` literal passed to `list()` (remove the outer call to \
|
|
||||||
`list()`)"
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
"Unnecessary `{literal}` literal passed to `list()` (rewrite as a `list` literal)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
let UnnecessaryLiteralWithinListCall { literal } = self;
|
|
||||||
{
|
|
||||||
if literal == "list" {
|
|
||||||
"Remove outer `list` call".to_string()
|
|
||||||
} else {
|
|
||||||
"Rewrite as a `list` literal".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryListCall;
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryListCall {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("Unnecessary `list` call (remove the outer call to `list()`)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
"Remove outer `list` call".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryCallAroundSorted {
|
|
||||||
pub func: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryCallAroundSorted {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessaryCallAroundSorted { func } = self;
|
|
||||||
format!("Unnecessary `{func}` call around `sorted()`")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
let UnnecessaryCallAroundSorted { func } = self;
|
|
||||||
format!("Remove unnecessary `{func}` call")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryDoubleCastOrProcess {
|
|
||||||
pub inner: String,
|
|
||||||
pub outer: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl Violation for UnnecessaryDoubleCastOrProcess {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessaryDoubleCastOrProcess { inner, outer } = self;
|
|
||||||
format!("Unnecessary `{inner}` call within `{outer}()`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessarySubscriptReversal {
|
|
||||||
pub func: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl Violation for UnnecessarySubscriptReversal {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessarySubscriptReversal { func } = self;
|
|
||||||
format!("Unnecessary subscript reversal of iterable within `{func}()`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryComprehension {
|
|
||||||
pub obj_type: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl AlwaysAutofixableViolation for UnnecessaryComprehension {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessaryComprehension { obj_type } = self;
|
|
||||||
format!("Unnecessary `{obj_type}` comprehension (rewrite using `{obj_type}()`)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn autofix_title(&self) -> String {
|
|
||||||
let UnnecessaryComprehension { obj_type } = self;
|
|
||||||
format!("Rewrite using `{obj_type}()`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
define_violation!(
|
|
||||||
pub struct UnnecessaryMap {
|
|
||||||
pub obj_type: String,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
impl Violation for UnnecessaryMap {
|
|
||||||
#[derive_message_formats]
|
|
||||||
fn message(&self) -> String {
|
|
||||||
let UnnecessaryMap { obj_type } = self;
|
|
||||||
if obj_type == "generator" {
|
|
||||||
format!("Unnecessary `map` usage (rewrite using a generator expression)")
|
|
||||||
} else {
|
|
||||||
format!("Unnecessary `map` usage (rewrite using a `{obj_type}` comprehension)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// flake8-debugger
|
// flake8-debugger
|
||||||
|
|
||||||
define_violation!(
|
define_violation!(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue