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
|
||||
|
||||
(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::types::{Binding, BindingKind, Scope};
|
||||
use crate::ast::types::{Binding, BindingKind, FunctionScope, Scope, ScopeKind};
|
||||
use crate::autofix::{fixer, fixes};
|
||||
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> {
|
||||
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() {
|
||||
// TODO(charlie): Ignore if using `locals`.
|
||||
if binding.used.is_none()
|
||||
|
|
|
|||
|
|
@ -8,10 +8,15 @@ fn id() -> usize {
|
|||
COUNTER.fetch_add(1, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct FunctionScope {
|
||||
pub uses_locals: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ScopeKind {
|
||||
Class,
|
||||
Function,
|
||||
Function(FunctionScope),
|
||||
Generator,
|
||||
Module,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustpython_parser::parser;
|
|||
|
||||
use crate::ast::operations::{extract_all_names, SourceCodeLocator};
|
||||
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::{checks, operations, visitor};
|
||||
use crate::autofix::fixer;
|
||||
|
|
@ -646,6 +646,33 @@ where
|
|||
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, .. } => {
|
||||
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."))];
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F823)
|
||||
&& matches!(current.kind, ScopeKind::Function)
|
||||
&& matches!(current.kind, ScopeKind::Function(_))
|
||||
&& !current.values.contains_key(id)
|
||||
{
|
||||
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((scope_id, location)) = binding.used {
|
||||
if scope_id == current.id {
|
||||
|
|
@ -1266,7 +1293,7 @@ impl<'a> Checker<'a> {
|
|||
while let Some((stmt, scopes, parents)) = self.deferred_functions.pop() {
|
||||
self.parent_stack = parents;
|
||||
self.scope_stack = scopes;
|
||||
self.push_scope(Scope::new(ScopeKind::Function));
|
||||
self.push_scope(Scope::new(ScopeKind::Function(Default::default())));
|
||||
|
||||
match &stmt.node {
|
||||
StmtKind::FunctionDef { body, args, .. }
|
||||
|
|
@ -1290,7 +1317,7 @@ impl<'a> Checker<'a> {
|
|||
while let Some((expr, scopes, parents)) = self.deferred_lambdas.pop() {
|
||||
self.parent_stack = parents;
|
||||
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 {
|
||||
self.visit_arguments(args);
|
||||
|
|
|
|||
Loading…
Reference in New Issue