mirror of https://github.com/astral-sh/ruff
[`ruff`] Omit diagnostic for shadowed private function parameters in `used-dummy-variable` (`RUF052`) (#15376)
This commit is contained in:
parent
23ad319b55
commit
443bf38565
|
|
@ -145,3 +145,19 @@ def special_calls():
|
|||
_NotADynamicClass = type("_NotADynamicClass")
|
||||
|
||||
print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
|
||||
# Do not emit diagnostic if parameter is private
|
||||
# even if it is later shadowed in the body of the function
|
||||
# see https://github.com/astral-sh/ruff/issues/14968
|
||||
class Node:
|
||||
|
||||
connected: list[Node]
|
||||
|
||||
def recurse(self, *, _seen: set[Node] | None = None):
|
||||
if _seen is None:
|
||||
_seen = set()
|
||||
elif self in _seen:
|
||||
return
|
||||
_seen.add(self)
|
||||
for other in self.connected:
|
||||
other.recurse(_seen=_seen)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ pub(crate) fn bindings(checker: &mut Checker) {
|
|||
return;
|
||||
}
|
||||
|
||||
for binding in &*checker.semantic.bindings {
|
||||
for (binding_id, binding) in checker.semantic.bindings.iter_enumerated() {
|
||||
if checker.enabled(Rule::UnusedVariable) {
|
||||
if binding.kind.is_bound_exception()
|
||||
&& binding.is_unused()
|
||||
|
|
@ -90,7 +90,8 @@ pub(crate) fn bindings(checker: &mut Checker) {
|
|||
}
|
||||
}
|
||||
if checker.enabled(Rule::UsedDummyVariable) {
|
||||
if let Some(diagnostic) = ruff::rules::used_dummy_variable(checker, binding) {
|
||||
if let Some(diagnostic) = ruff::rules::used_dummy_variable(checker, binding, binding_id)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use ruff_diagnostics::{Diagnostic, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||
use ruff_python_ast::helpers::is_dunder;
|
||||
use ruff_python_semantic::{Binding, ScopeId};
|
||||
use ruff_python_semantic::{Binding, BindingId, ScopeId};
|
||||
use ruff_python_stdlib::{
|
||||
builtins::is_python_builtin, identifiers::is_identifier, keyword::is_keyword,
|
||||
};
|
||||
|
|
@ -97,7 +97,11 @@ impl Violation for UsedDummyVariable {
|
|||
}
|
||||
|
||||
/// RUF052
|
||||
pub(crate) fn used_dummy_variable(checker: &Checker, binding: &Binding) -> Option<Diagnostic> {
|
||||
pub(crate) fn used_dummy_variable(
|
||||
checker: &Checker,
|
||||
binding: &Binding,
|
||||
binding_id: BindingId,
|
||||
) -> Option<Diagnostic> {
|
||||
let name = binding.name(checker.source());
|
||||
|
||||
// Ignore `_` and dunder variables
|
||||
|
|
@ -141,6 +145,21 @@ pub(crate) fn used_dummy_variable(checker: &Checker, binding: &Binding) -> Optio
|
|||
if !scope.kind.is_function() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Recall from above that we do not wish to flag "private"
|
||||
// function parameters. The previous early exit ensured
|
||||
// that the binding in hand was not a function parameter.
|
||||
// We now check that, in the body of our function, we are
|
||||
// not looking at a shadowing of a private parameter.
|
||||
//
|
||||
// (Technically this also covers the case in the previous early exit,
|
||||
// but it is more expensive so we keep both.)
|
||||
if scope
|
||||
.shadowed_bindings(binding_id)
|
||||
.any(|shadow_id| semantic.binding(shadow_id).kind.is_argument())
|
||||
{
|
||||
return None;
|
||||
}
|
||||
if !checker.settings.dummy_variable_rgx.is_match(name) {
|
||||
return None;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@ RUF052.py:138:5: RUF052 [*] Local dummy variable `_P` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:139:5: RUF052 [*] Local dummy variable `_T` is accessed
|
||||
|
|
||||
|
|
@ -201,6 +204,9 @@ RUF052.py:139:5: RUF052 [*] Local dummy variable `_T` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:140:5: RUF052 [*] Local dummy variable `_NT` is accessed
|
||||
|
|
||||
|
|
@ -227,6 +233,9 @@ RUF052.py:140:5: RUF052 [*] Local dummy variable `_NT` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:141:5: RUF052 [*] Local dummy variable `_E` is accessed
|
||||
|
|
||||
|
|
@ -252,6 +261,9 @@ RUF052.py:141:5: RUF052 [*] Local dummy variable `_E` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:142:5: RUF052 [*] Local dummy variable `_NT2` is accessed
|
||||
|
|
||||
|
|
@ -276,6 +288,9 @@ RUF052.py:142:5: RUF052 [*] Local dummy variable `_NT2` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, _E, NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:143:5: RUF052 [*] Local dummy variable `_NT3` is accessed
|
||||
|
|
||||
|
|
@ -299,6 +314,9 @@ RUF052.py:143:5: RUF052 [*] Local dummy variable `_NT3` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, _E, _NT2, NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:144:5: RUF052 [*] Local dummy variable `_DynamicClass` is accessed
|
||||
|
|
||||
|
|
@ -320,6 +338,9 @@ RUF052.py:144:5: RUF052 [*] Local dummy variable `_DynamicClass` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, _E, _NT2, _NT3, DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:145:5: RUF052 [*] Local dummy variable `_NotADynamicClass` is accessed
|
||||
|
|
||||
|
|
@ -341,3 +362,6 @@ RUF052.py:145:5: RUF052 [*] Local dummy variable `_NotADynamicClass` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@ RUF052.py:138:5: RUF052 [*] Local dummy variable `_P` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:139:5: RUF052 [*] Local dummy variable `_T` is accessed
|
||||
|
|
||||
|
|
@ -201,6 +204,9 @@ RUF052.py:139:5: RUF052 [*] Local dummy variable `_T` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:140:5: RUF052 [*] Local dummy variable `_NT` is accessed
|
||||
|
|
||||
|
|
@ -227,6 +233,9 @@ RUF052.py:140:5: RUF052 [*] Local dummy variable `_NT` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:141:5: RUF052 [*] Local dummy variable `_E` is accessed
|
||||
|
|
||||
|
|
@ -252,6 +261,9 @@ RUF052.py:141:5: RUF052 [*] Local dummy variable `_E` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:142:5: RUF052 [*] Local dummy variable `_NT2` is accessed
|
||||
|
|
||||
|
|
@ -276,6 +288,9 @@ RUF052.py:142:5: RUF052 [*] Local dummy variable `_NT2` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, _E, NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:143:5: RUF052 [*] Local dummy variable `_NT3` is accessed
|
||||
|
|
||||
|
|
@ -299,6 +314,9 @@ RUF052.py:143:5: RUF052 [*] Local dummy variable `_NT3` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, _E, _NT2, NT3, _DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:144:5: RUF052 [*] Local dummy variable `_DynamicClass` is accessed
|
||||
|
|
||||
|
|
@ -320,6 +338,9 @@ RUF052.py:144:5: RUF052 [*] Local dummy variable `_DynamicClass` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, _E, _NT2, _NT3, DynamicClass, _NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
||||
RUF052.py:145:5: RUF052 [*] Local dummy variable `_NotADynamicClass` is accessed
|
||||
|
|
||||
|
|
@ -341,3 +362,6 @@ RUF052.py:145:5: RUF052 [*] Local dummy variable `_NotADynamicClass` is accessed
|
|||
146 146 |
|
||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||
147 |+ print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, NotADynamicClass)
|
||||
148 148 |
|
||||
149 149 | # Do not emit diagnostic if parameter is private
|
||||
150 150 | # even if it is later shadowed in the body of the function
|
||||
|
|
|
|||
Loading…
Reference in New Issue