mirror of https://github.com/astral-sh/ruff
[`pylint`] Add `named_expr_without_context` (`W0131`) (#4531)
This commit is contained in:
parent
a9ed8d5391
commit
fe8e2bb237
|
|
@ -0,0 +1,19 @@
|
|||
# Errors
|
||||
(a := 42)
|
||||
if True:
|
||||
(b := 1)
|
||||
|
||||
|
||||
class Foo:
|
||||
(c := 1)
|
||||
|
||||
|
||||
# OK
|
||||
if a := 42:
|
||||
print("Success")
|
||||
|
||||
a = 0
|
||||
while (a := a + 1) < 10:
|
||||
print("Correct")
|
||||
|
||||
a = (b := 1)
|
||||
|
|
@ -1895,6 +1895,9 @@ where
|
|||
if self.settings.rules.enabled(Rule::InvalidMockAccess) {
|
||||
pygrep_hooks::rules::uncalled_mock_method(self, value);
|
||||
}
|
||||
if self.settings.rules.enabled(Rule::NamedExprWithoutContext) {
|
||||
pylint::rules::named_expr_without_context(self, value);
|
||||
}
|
||||
if self.settings.rules.enabled(Rule::AsyncioDanglingTask) {
|
||||
if let Some(diagnostic) = ruff::rules::asyncio_dangling_task(value, |expr| {
|
||||
self.ctx.resolve_call_path(expr)
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Pylint, "R5501") => (RuleGroup::Unspecified, Rule::CollapsibleElseIf),
|
||||
(Pylint, "W0120") => (RuleGroup::Unspecified, Rule::UselessElseOnLoop),
|
||||
(Pylint, "W0129") => (RuleGroup::Unspecified, Rule::AssertOnStringLiteral),
|
||||
(Pylint, "W0131") => (RuleGroup::Unspecified, Rule::NamedExprWithoutContext),
|
||||
(Pylint, "W0406") => (RuleGroup::Unspecified, Rule::ImportSelf),
|
||||
(Pylint, "W0602") => (RuleGroup::Unspecified, Rule::GlobalVariableNotAssigned),
|
||||
(Pylint, "W0603") => (RuleGroup::Unspecified, Rule::GlobalStatement),
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ ruff_macros::register_rules!(
|
|||
rules::pylint::rules::NestedMinMax,
|
||||
rules::pylint::rules::DuplicateValue,
|
||||
rules::pylint::rules::DuplicateBases,
|
||||
rules::pylint::rules::NamedExprWithoutContext,
|
||||
// flake8-async
|
||||
rules::flake8_async::rules::BlockingHttpCallInAsyncFunction,
|
||||
rules::flake8_async::rules::OpenSleepOrSubprocessInAsyncFunction,
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ mod tests {
|
|||
#[test_case(Rule::LoggingTooFewArgs, Path::new("logging_too_few_args.py"); "PLE1206")]
|
||||
#[test_case(Rule::LoggingTooManyArgs, Path::new("logging_too_many_args.py"); "PLE1205")]
|
||||
#[test_case(Rule::MagicValueComparison, Path::new("magic_value_comparison.py"); "PLR2004")]
|
||||
#[test_case(Rule::NamedExprWithoutContext, Path::new("named_expr_without_context.py"); "PLW0131")]
|
||||
#[test_case(Rule::NonlocalWithoutBinding, Path::new("nonlocal_without_binding.py"); "PLE0117")]
|
||||
#[test_case(Rule::PropertyWithParameters, Path::new("property_with_parameters.py"); "PLR0206")]
|
||||
#[test_case(Rule::RedefinedLoopName, Path::new("redefined_loop_name.py"); "PLW2901")]
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ pub(crate) use load_before_global_declaration::{
|
|||
pub(crate) use logging::{logging_call, LoggingTooFewArgs, LoggingTooManyArgs};
|
||||
pub(crate) use magic_value_comparison::{magic_value_comparison, MagicValueComparison};
|
||||
pub(crate) use manual_import_from::{manual_from_import, ManualFromImport};
|
||||
pub(crate) use named_expr_without_context::{named_expr_without_context, NamedExprWithoutContext};
|
||||
pub(crate) use nested_min_max::{nested_min_max, NestedMinMax};
|
||||
pub(crate) use nonlocal_without_binding::NonlocalWithoutBinding;
|
||||
pub(crate) use property_with_parameters::{property_with_parameters, PropertyWithParameters};
|
||||
|
|
@ -73,6 +74,7 @@ mod load_before_global_declaration;
|
|||
mod logging;
|
||||
mod magic_value_comparison;
|
||||
mod manual_import_from;
|
||||
mod named_expr_without_context;
|
||||
mod nested_min_max;
|
||||
mod nonlocal_without_binding;
|
||||
mod property_with_parameters;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
use rustpython_parser::ast::{self, Expr};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for usages of named expressions (e.g., `a := 42`) that can be
|
||||
/// replaced by regular assignment statements (e.g., `a = 42`).
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// While a top-level named expression is syntactically and semantically valid,
|
||||
/// it's less clear than a regular assignment statement. Named expressions are
|
||||
/// intended to be used in comprehensions and generator expressions, where
|
||||
/// assignment statements are not allowed.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// (a := 42)
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// a = 42
|
||||
/// ```
|
||||
#[violation]
|
||||
pub struct NamedExprWithoutContext;
|
||||
|
||||
impl Violation for NamedExprWithoutContext {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Named expression used without context")
|
||||
}
|
||||
}
|
||||
|
||||
/// PLW0131
|
||||
pub(crate) fn named_expr_without_context(checker: &mut Checker, value: &Expr) {
|
||||
if let Expr::NamedExpr(ast::ExprNamedExpr { range, .. }) = value {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(NamedExprWithoutContext, *range));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
source: crates/ruff/src/rules/pylint/mod.rs
|
||||
---
|
||||
named_expr_without_context.py:2:2: PLW0131 Named expression used without context
|
||||
|
|
||||
2 | # Errors
|
||||
3 | (a := 42)
|
||||
| ^^^^^^^ PLW0131
|
||||
4 | if True:
|
||||
5 | (b := 1)
|
||||
|
|
||||
|
||||
named_expr_without_context.py:4:6: PLW0131 Named expression used without context
|
||||
|
|
||||
4 | (a := 42)
|
||||
5 | if True:
|
||||
6 | (b := 1)
|
||||
| ^^^^^^ PLW0131
|
||||
|
|
||||
|
||||
named_expr_without_context.py:8:6: PLW0131 Named expression used without context
|
||||
|
|
||||
8 | class Foo:
|
||||
9 | (c := 1)
|
||||
| ^^^^^^ PLW0131
|
||||
|
|
||||
|
||||
|
||||
|
|
@ -2078,6 +2078,7 @@
|
|||
"PLW0129",
|
||||
"PLW013",
|
||||
"PLW0130",
|
||||
"PLW0131",
|
||||
"PLW04",
|
||||
"PLW040",
|
||||
"PLW0406",
|
||||
|
|
|
|||
Loading…
Reference in New Issue