Skip to content

Commit ebd2181

Browse files
authored
Implement unnecessary-direct-lambda-call (#1008)
1 parent 3efa1a0 commit ebd2181

File tree

8 files changed

+77
-2
lines changed

8 files changed

+77
-2
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,8 +751,9 @@ For more, see [Pylint](https://pypi.org/project/pylint/2.15.7/) on PyPI.
751751
752752
| Code | Name | Message | Fix |
753753
| ---- | ---- | ------- | --- |
754-
| PLE1142 | AwaitOutsideAsync | `await` should be used within an async function | |
754+
| PLC3002 | UnnecessaryDirectLambdaCall | Lambda expression called directly. Execute the expression inline instead. | |
755755
| PLR0206 | PropertyWithParameters | Cannot have defined parameters for properties | |
756+
| PLE1142 | AwaitOutsideAsync | `await` should be used within an async function | |
756757
757758
### Ruff-specific rules
758759
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""Test unnecessary direct calls to lambda expressions."""
2+
# pylint: disable=undefined-variable, line-too-long
3+
4+
y = (lambda x: x**2 + 2*x + 1)(a) # [unnecessary-direct-lambda-call]
5+
y = max((lambda x: x**2)(a), (lambda x: x+1)(a)) # [unnecessary-direct-lambda-call,unnecessary-direct-lambda-call]

src/check_ast.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ where
442442
}
443443

444444
if self.settings.enabled.contains(&CheckCode::PLR0206) {
445-
pylint::plugins::property_with_parameters(self, stmt, decorator_list, args)
445+
pylint::plugins::property_with_parameters(self, stmt, decorator_list, args);
446446
}
447447

448448
self.check_builtin_shadowing(name, Range::from_located(stmt), true);
@@ -1712,6 +1712,11 @@ where
17121712
pygrep_hooks::checks::no_eval(self, func);
17131713
}
17141714

1715+
// pylint
1716+
if self.settings.enabled.contains(&CheckCode::PLC3002) {
1717+
pylint::plugins::unnecessary_direct_lambda_call(self, expr, func);
1718+
}
1719+
17151720
// Ruff
17161721
if self.settings.enabled.contains(&CheckCode::RUF101) {
17171722
rules::plugins::convert_exit_to_sys_exit(self, func);

src/checks.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ pub enum CheckCode {
9191
F841,
9292
F901,
9393
// pylint errors
94+
PLC3002,
9495
PLR0206,
9596
PLE1142,
9697
// flake8-builtins
@@ -541,6 +542,7 @@ pub enum CheckKind {
541542
UnusedVariable(String),
542543
YieldOutsideFunction(DeferralKeyword),
543544
// pylint errors
545+
UnnecessaryDirectLambdaCall,
544546
PropertyWithParameters,
545547
AwaitOutsideAsync,
546548
// flake8-builtins
@@ -827,6 +829,7 @@ impl CheckCode {
827829
CheckCode::F841 => CheckKind::UnusedVariable("...".to_string()),
828830
CheckCode::F901 => CheckKind::RaiseNotImplemented,
829831
// pylint errors
832+
CheckCode::PLC3002 => CheckKind::UnnecessaryDirectLambdaCall,
830833
CheckCode::PLR0206 => CheckKind::PropertyWithParameters,
831834
CheckCode::PLE1142 => CheckKind::AwaitOutsideAsync,
832835
// flake8-builtins
@@ -1240,6 +1243,7 @@ impl CheckCode {
12401243
CheckCode::N817 => CheckCategory::PEP8Naming,
12411244
CheckCode::N818 => CheckCategory::PEP8Naming,
12421245
CheckCode::PGH001 => CheckCategory::PygrepHooks,
1246+
CheckCode::PLC3002 => CheckCategory::Pylint,
12431247
CheckCode::PLR0206 => CheckCategory::Pylint,
12441248
CheckCode::PLE1142 => CheckCategory::Pylint,
12451249
CheckCode::Q000 => CheckCategory::Flake8Quotes,
@@ -1354,6 +1358,7 @@ impl CheckKind {
13541358
CheckKind::NoNewLineAtEndOfFile => &CheckCode::W292,
13551359
CheckKind::InvalidEscapeSequence(_) => &CheckCode::W605,
13561360
// pylint errors
1361+
CheckKind::UnnecessaryDirectLambdaCall => &CheckCode::PLC3002,
13571362
CheckKind::PropertyWithParameters => &CheckCode::PLR0206,
13581363
CheckKind::AwaitOutsideAsync => &CheckCode::PLE1142,
13591364
// flake8-builtins
@@ -1728,6 +1733,9 @@ impl CheckKind {
17281733
format!("Invalid escape sequence: '\\{char}'")
17291734
}
17301735
// pylint errors
1736+
CheckKind::UnnecessaryDirectLambdaCall => "Lambda expression called directly. Execute \
1737+
the expression inline instead."
1738+
.to_string(),
17311739
CheckKind::PropertyWithParameters => {
17321740
"Cannot have defined parameters for properties".to_string()
17331741
}

src/checks_gen.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,11 @@ pub enum CheckCodePrefix {
282282
PGH0,
283283
PGH00,
284284
PGH001,
285+
PLC,
286+
PLC3,
287+
PLC30,
288+
PLC300,
289+
PLC3002,
285290
PLE,
286291
PLE1,
287292
PLE11,
@@ -1161,6 +1166,11 @@ impl CheckCodePrefix {
11611166
CheckCodePrefix::PGH0 => vec![CheckCode::PGH001],
11621167
CheckCodePrefix::PGH00 => vec![CheckCode::PGH001],
11631168
CheckCodePrefix::PGH001 => vec![CheckCode::PGH001],
1169+
CheckCodePrefix::PLC => vec![CheckCode::PLC3002],
1170+
CheckCodePrefix::PLC3 => vec![CheckCode::PLC3002],
1171+
CheckCodePrefix::PLC30 => vec![CheckCode::PLC3002],
1172+
CheckCodePrefix::PLC300 => vec![CheckCode::PLC3002],
1173+
CheckCodePrefix::PLC3002 => vec![CheckCode::PLC3002],
11641174
CheckCodePrefix::PLE => vec![CheckCode::PLE1142],
11651175
CheckCodePrefix::PLE1 => vec![CheckCode::PLE1142],
11661176
CheckCodePrefix::PLE11 => vec![CheckCode::PLE1142],
@@ -1637,6 +1647,11 @@ impl CheckCodePrefix {
16371647
CheckCodePrefix::PGH0 => SuffixLength::One,
16381648
CheckCodePrefix::PGH00 => SuffixLength::Two,
16391649
CheckCodePrefix::PGH001 => SuffixLength::Three,
1650+
CheckCodePrefix::PLC => SuffixLength::Zero,
1651+
CheckCodePrefix::PLC3 => SuffixLength::One,
1652+
CheckCodePrefix::PLC30 => SuffixLength::Two,
1653+
CheckCodePrefix::PLC300 => SuffixLength::Three,
1654+
CheckCodePrefix::PLC3002 => SuffixLength::Four,
16401655
CheckCodePrefix::PLE => SuffixLength::Zero,
16411656
CheckCodePrefix::PLE1 => SuffixLength::One,
16421657
CheckCodePrefix::PLE11 => SuffixLength::Two,
@@ -1741,6 +1756,7 @@ pub const CATEGORIES: &[CheckCodePrefix] = &[
17411756
CheckCodePrefix::M,
17421757
CheckCodePrefix::N,
17431758
CheckCodePrefix::PGH,
1759+
CheckCodePrefix::PLC,
17441760
CheckCodePrefix::PLE,
17451761
CheckCodePrefix::PLR,
17461762
CheckCodePrefix::Q,

src/pylint/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod tests {
1111
use crate::linter::test_path;
1212
use crate::Settings;
1313

14+
#[test_case(CheckCode::PLC3002, Path::new("unnecessary_direct_lambda_call.py"); "PLC3002")]
1415
#[test_case(CheckCode::PLR0206, Path::new("property_with_parameters.py"); "PLR0206")]
1516
#[test_case(CheckCode::PLE1142, Path::new("await_outside_async.py"); "PLE1142")]
1617
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {

src/pylint/plugins.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ use crate::check_ast::Checker;
55
use crate::checks::CheckKind;
66
use crate::Check;
77

8+
/// PLC3002
9+
pub fn unnecessary_direct_lambda_call(checker: &mut Checker, expr: &Expr, func: &Expr) {
10+
if let ExprKind::Lambda { .. } = &func.node {
11+
checker.add_check(Check::new(
12+
CheckKind::UnnecessaryDirectLambdaCall,
13+
Range::from_located(expr),
14+
));
15+
}
16+
}
17+
818
/// PLR0206
919
pub fn property_with_parameters(
1020
checker: &mut Checker,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
source: src/pylint/mod.rs
3+
expression: checks
4+
---
5+
- kind: UnnecessaryDirectLambdaCall
6+
location:
7+
row: 4
8+
column: 4
9+
end_location:
10+
row: 4
11+
column: 33
12+
fix: ~
13+
- kind: UnnecessaryDirectLambdaCall
14+
location:
15+
row: 5
16+
column: 8
17+
end_location:
18+
row: 5
19+
column: 27
20+
fix: ~
21+
- kind: UnnecessaryDirectLambdaCall
22+
location:
23+
row: 5
24+
column: 29
25+
end_location:
26+
row: 5
27+
column: 47
28+
fix: ~
29+

0 commit comments

Comments
 (0)