mirror of https://github.com/astral-sh/ruff
Ignore F841 violations when locals() is in scope (#226)
This commit is contained in:
parent
14806c62ca
commit
afe7a04211
|
|
@ -24,3 +24,8 @@ def g():
|
||||||
(c, d) = bar
|
(c, d) = bar
|
||||||
|
|
||||||
(x, y) = baz = bar
|
(x, y) = baz = bar
|
||||||
|
|
||||||
|
|
||||||
|
def h():
|
||||||
|
locals()
|
||||||
|
x = 1
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use rustpython_parser::ast::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ast::operations::SourceCodeLocator;
|
use crate::ast::operations::SourceCodeLocator;
|
||||||
use crate::ast::types::{Binding, BindingKind, Scope};
|
use crate::ast::types::{Binding, BindingKind, FunctionScope, Scope, ScopeKind};
|
||||||
use crate::autofix::{fixer, fixes};
|
use crate::autofix::{fixer, fixes};
|
||||||
use crate::checks::{Check, CheckKind, Fix, RejectedCmpop};
|
use crate::checks::{Check, CheckKind, Fix, RejectedCmpop};
|
||||||
|
|
||||||
|
|
@ -67,6 +67,13 @@ pub fn check_not_tests(
|
||||||
pub fn check_unused_variables(scope: &Scope) -> Vec<Check> {
|
pub fn check_unused_variables(scope: &Scope) -> Vec<Check> {
|
||||||
let mut checks: Vec<Check> = vec![];
|
let mut checks: Vec<Check> = vec![];
|
||||||
|
|
||||||
|
if matches!(
|
||||||
|
scope.kind,
|
||||||
|
ScopeKind::Function(FunctionScope { uses_locals: true })
|
||||||
|
) {
|
||||||
|
return checks;
|
||||||
|
}
|
||||||
|
|
||||||
for (name, binding) in scope.values.iter() {
|
for (name, binding) in scope.values.iter() {
|
||||||
// TODO(charlie): Ignore if using `locals`.
|
// TODO(charlie): Ignore if using `locals`.
|
||||||
if binding.used.is_none()
|
if binding.used.is_none()
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,15 @@ fn id() -> usize {
|
||||||
COUNTER.fetch_add(1, Ordering::Relaxed)
|
COUNTER.fetch_add(1, Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct FunctionScope {
|
||||||
|
pub uses_locals: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ScopeKind {
|
pub enum ScopeKind {
|
||||||
Class,
|
Class,
|
||||||
Function,
|
Function(FunctionScope),
|
||||||
Generator,
|
Generator,
|
||||||
Module,
|
Module,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use rustpython_parser::parser;
|
||||||
|
|
||||||
use crate::ast::operations::{extract_all_names, SourceCodeLocator};
|
use crate::ast::operations::{extract_all_names, SourceCodeLocator};
|
||||||
use crate::ast::relocate::relocate_expr;
|
use crate::ast::relocate::relocate_expr;
|
||||||
use crate::ast::types::{Binding, BindingKind, Scope, ScopeKind};
|
use crate::ast::types::{Binding, BindingKind, FunctionScope, Scope, ScopeKind};
|
||||||
use crate::ast::visitor::{walk_excepthandler, Visitor};
|
use crate::ast::visitor::{walk_excepthandler, Visitor};
|
||||||
use crate::ast::{checks, operations, visitor};
|
use crate::ast::{checks, operations, visitor};
|
||||||
use crate::autofix::fixer;
|
use crate::autofix::fixer;
|
||||||
|
|
@ -646,6 +646,33 @@ where
|
||||||
self.checks.push(check)
|
self.checks.push(check)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let ExprKind::Name { id, ctx } = &func.node {
|
||||||
|
if id == "locals" && matches!(ctx, ExprContext::Load) {
|
||||||
|
let scope = &mut self.scopes[*(self
|
||||||
|
.scope_stack
|
||||||
|
.last_mut()
|
||||||
|
.expect("No current scope found."))];
|
||||||
|
if matches!(
|
||||||
|
scope.kind,
|
||||||
|
ScopeKind::Function(FunctionScope { uses_locals: false })
|
||||||
|
) {
|
||||||
|
scope.kind = ScopeKind::Function(FunctionScope { uses_locals: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// if id == "locals" {
|
||||||
|
// let scope = &self.scopes
|
||||||
|
// [*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
|
// if matches!(scope.kind, ScopeKind::Function(_)) {
|
||||||
|
// let parent =
|
||||||
|
// self.parents[*(self.parent_stack.last().expect("No parent found."))];
|
||||||
|
// if matches!(parent.node, StmtKind::Call)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
ExprKind::Dict { keys, .. } => {
|
ExprKind::Dict { keys, .. } => {
|
||||||
let check_repeated_literals = self.settings.select.contains(&CheckCode::F601);
|
let check_repeated_literals = self.settings.select.contains(&CheckCode::F601);
|
||||||
|
|
@ -1136,11 +1163,11 @@ impl<'a> Checker<'a> {
|
||||||
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
|
|
||||||
if self.settings.select.contains(&CheckCode::F823)
|
if self.settings.select.contains(&CheckCode::F823)
|
||||||
&& matches!(current.kind, ScopeKind::Function)
|
&& matches!(current.kind, ScopeKind::Function(_))
|
||||||
&& !current.values.contains_key(id)
|
&& !current.values.contains_key(id)
|
||||||
{
|
{
|
||||||
for scope in self.scopes.iter().rev().skip(1) {
|
for scope in self.scopes.iter().rev().skip(1) {
|
||||||
if matches!(scope.kind, ScopeKind::Function | ScopeKind::Module) {
|
if matches!(scope.kind, ScopeKind::Function(_) | ScopeKind::Module) {
|
||||||
if let Some(binding) = scope.values.get(id) {
|
if let Some(binding) = scope.values.get(id) {
|
||||||
if let Some((scope_id, location)) = binding.used {
|
if let Some((scope_id, location)) = binding.used {
|
||||||
if scope_id == current.id {
|
if scope_id == current.id {
|
||||||
|
|
@ -1266,7 +1293,7 @@ impl<'a> Checker<'a> {
|
||||||
while let Some((stmt, scopes, parents)) = self.deferred_functions.pop() {
|
while let Some((stmt, scopes, parents)) = self.deferred_functions.pop() {
|
||||||
self.parent_stack = parents;
|
self.parent_stack = parents;
|
||||||
self.scope_stack = scopes;
|
self.scope_stack = scopes;
|
||||||
self.push_scope(Scope::new(ScopeKind::Function));
|
self.push_scope(Scope::new(ScopeKind::Function(Default::default())));
|
||||||
|
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::FunctionDef { body, args, .. }
|
StmtKind::FunctionDef { body, args, .. }
|
||||||
|
|
@ -1290,7 +1317,7 @@ impl<'a> Checker<'a> {
|
||||||
while let Some((expr, scopes, parents)) = self.deferred_lambdas.pop() {
|
while let Some((expr, scopes, parents)) = self.deferred_lambdas.pop() {
|
||||||
self.parent_stack = parents;
|
self.parent_stack = parents;
|
||||||
self.scope_stack = scopes;
|
self.scope_stack = scopes;
|
||||||
self.push_scope(Scope::new(ScopeKind::Function));
|
self.push_scope(Scope::new(ScopeKind::Function(Default::default())));
|
||||||
|
|
||||||
if let ExprKind::Lambda { args, body } = &expr.node {
|
if let ExprKind::Lambda { args, body } = &expr.node {
|
||||||
self.visit_arguments(args);
|
self.visit_arguments(args);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue