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")
|
_NotADynamicClass = type("_NotADynamicClass")
|
||||||
|
|
||||||
print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for binding in &*checker.semantic.bindings {
|
for (binding_id, binding) in checker.semantic.bindings.iter_enumerated() {
|
||||||
if checker.enabled(Rule::UnusedVariable) {
|
if checker.enabled(Rule::UnusedVariable) {
|
||||||
if binding.kind.is_bound_exception()
|
if binding.kind.is_bound_exception()
|
||||||
&& binding.is_unused()
|
&& binding.is_unused()
|
||||||
|
|
@ -90,7 +90,8 @@ pub(crate) fn bindings(checker: &mut Checker) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if checker.enabled(Rule::UsedDummyVariable) {
|
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);
|
checker.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use ruff_diagnostics::{Diagnostic, Fix, FixAvailability, Violation};
|
use ruff_diagnostics::{Diagnostic, Fix, FixAvailability, Violation};
|
||||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||||
use ruff_python_ast::helpers::is_dunder;
|
use ruff_python_ast::helpers::is_dunder;
|
||||||
use ruff_python_semantic::{Binding, ScopeId};
|
use ruff_python_semantic::{Binding, BindingId, ScopeId};
|
||||||
use ruff_python_stdlib::{
|
use ruff_python_stdlib::{
|
||||||
builtins::is_python_builtin, identifiers::is_identifier, keyword::is_keyword,
|
builtins::is_python_builtin, identifiers::is_identifier, keyword::is_keyword,
|
||||||
};
|
};
|
||||||
|
|
@ -97,7 +97,11 @@ impl Violation for UsedDummyVariable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RUF052
|
/// 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());
|
let name = binding.name(checker.source());
|
||||||
|
|
||||||
// Ignore `_` and dunder variables
|
// Ignore `_` and dunder variables
|
||||||
|
|
@ -141,6 +145,21 @@ pub(crate) fn used_dummy_variable(checker: &Checker, binding: &Binding) -> Optio
|
||||||
if !scope.kind.is_function() {
|
if !scope.kind.is_function() {
|
||||||
return None;
|
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) {
|
if !checker.settings.dummy_variable_rgx.is_match(name) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,9 @@ RUF052.py:138:5: RUF052 [*] Local dummy variable `_P` is accessed
|
||||||
146 146 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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
|
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 |
|
146 146 |
|
||||||
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
147 |- print(_T, _P, _NT, _E, _NT2, _NT3, _DynamicClass, _NotADynamicClass)
|
||||||
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