mirror of https://github.com/astral-sh/ruff
Try to fix
This commit is contained in:
parent
7be26dafe9
commit
3c41b33023
|
|
@ -1,50 +1,50 @@
|
||||||
# def get_name():
|
def get_name():
|
||||||
# return self.name
|
return self.name
|
||||||
#
|
|
||||||
#
|
|
||||||
# def get_name():
|
def get_name():
|
||||||
# return (self.name,)
|
return (self.name,)
|
||||||
#
|
|
||||||
#
|
|
||||||
# def get_name():
|
def get_name():
|
||||||
# del self.name
|
del self.name
|
||||||
#
|
|
||||||
#
|
|
||||||
# def get_name(self):
|
def get_name(self):
|
||||||
# return self.name
|
return self.name
|
||||||
#
|
|
||||||
#
|
|
||||||
# x = list()
|
x = list()
|
||||||
#
|
|
||||||
#
|
|
||||||
# def randdec(maxprec, maxexp):
|
def randdec(maxprec, maxexp):
|
||||||
# return numeric_string(maxprec, maxexp)
|
return numeric_string(maxprec, maxexp)
|
||||||
#
|
|
||||||
#
|
|
||||||
# def ternary_optarg(prec, exp_range, itr):
|
def ternary_optarg(prec, exp_range, itr):
|
||||||
# for _ in range(100):
|
for _ in range(100):
|
||||||
# a = randdec(prec, 2 * exp_range)
|
a = randdec(prec, 2 * exp_range)
|
||||||
# b = randdec(prec, 2 * exp_range)
|
b = randdec(prec, 2 * exp_range)
|
||||||
# c = randdec(prec, 2 * exp_range)
|
c = randdec(prec, 2 * exp_range)
|
||||||
# yield a, b, c, None
|
yield a, b, c, None
|
||||||
# yield a, b, c, None, None
|
yield a, b, c, None, None
|
||||||
#
|
|
||||||
#
|
|
||||||
# class Foo:
|
class Foo:
|
||||||
# CLASS_VAR = 1
|
CLASS_VAR = 1
|
||||||
# REFERENCES_CLASS_VAR = {"CLASS_VAR": CLASS_VAR}
|
REFERENCES_CLASS_VAR = {"CLASS_VAR": CLASS_VAR}
|
||||||
# ANNOTATED_CLASS_VAR: int = 2
|
ANNOTATED_CLASS_VAR: int = 2
|
||||||
#
|
|
||||||
|
|
||||||
class Class:
|
class Class:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Class
|
Class
|
||||||
|
|
||||||
#
|
|
||||||
# try:
|
try:
|
||||||
# x = 1 / 0
|
x = 1 / 0
|
||||||
# except Exception as e:
|
except Exception as e:
|
||||||
# print(e)
|
print(e)
|
||||||
#
|
|
||||||
#
|
|
||||||
# y: int = 1
|
y: int = 1
|
||||||
|
|
|
||||||
350
src/check_ast.rs
350
src/check_ast.rs
|
|
@ -17,20 +17,26 @@ use crate::settings::Settings;
|
||||||
use crate::visitor::{walk_excepthandler, Visitor};
|
use crate::visitor::{walk_excepthandler, Visitor};
|
||||||
use crate::{autofix, fixer, visitor};
|
use crate::{autofix, fixer, visitor};
|
||||||
|
|
||||||
|
pub const GLOBAL_SCOPE_INDEX: usize = 0;
|
||||||
|
|
||||||
struct Checker<'a> {
|
struct Checker<'a> {
|
||||||
|
// Input data.
|
||||||
locator: SourceCodeLocator<'a>,
|
locator: SourceCodeLocator<'a>,
|
||||||
settings: &'a Settings,
|
settings: &'a Settings,
|
||||||
autofix: &'a autofix::Mode,
|
autofix: &'a autofix::Mode,
|
||||||
path: &'a str,
|
path: &'a str,
|
||||||
|
// Computed checks.
|
||||||
checks: Vec<Check>,
|
checks: Vec<Check>,
|
||||||
|
// Scope tracking: retain all scopes, along with a stack of indexes to track which scopes are
|
||||||
|
// active.
|
||||||
scopes: Vec<Scope>,
|
scopes: Vec<Scope>,
|
||||||
dead_scopes: Vec<Scope>,
|
scope_stack: Vec<usize>,
|
||||||
|
parents: Vec<&'a Stmt>,
|
||||||
|
dead_scopes: Vec<usize>,
|
||||||
deferred_annotations: Vec<&'a str>,
|
deferred_annotations: Vec<&'a str>,
|
||||||
// I think I need to track the list of scope indexes...
|
deferred_functions: Vec<(&'a Stmt, Vec<usize>)>,
|
||||||
// And then store all scopes.
|
deferred_lambdas: Vec<(&'a Expr, Vec<usize>)>,
|
||||||
// And track the current scope stack by index?
|
// Derivative state.
|
||||||
deferred_functions: Vec<(&'a Stmt, &'a [Scope])>,
|
|
||||||
stack: Vec<&'a Stmt>,
|
|
||||||
in_f_string: bool,
|
in_f_string: bool,
|
||||||
in_annotation: bool,
|
in_annotation: bool,
|
||||||
seen_non_import: bool,
|
seen_non_import: bool,
|
||||||
|
|
@ -50,11 +56,13 @@ impl<'a> Checker<'a> {
|
||||||
path,
|
path,
|
||||||
locator: SourceCodeLocator::new(content),
|
locator: SourceCodeLocator::new(content),
|
||||||
checks: vec![],
|
checks: vec![],
|
||||||
|
scope_stack: vec![],
|
||||||
scopes: vec![],
|
scopes: vec![],
|
||||||
dead_scopes: vec![],
|
dead_scopes: vec![],
|
||||||
deferred_annotations: vec![],
|
deferred_annotations: vec![],
|
||||||
deferred_functions: vec![],
|
deferred_functions: vec![],
|
||||||
stack: vec![],
|
deferred_lambdas: vec![],
|
||||||
|
parents: vec![],
|
||||||
in_f_string: false,
|
in_f_string: false,
|
||||||
in_annotation: false,
|
in_annotation: false,
|
||||||
seen_non_import: false,
|
seen_non_import: false,
|
||||||
|
|
@ -82,17 +90,20 @@ where
|
||||||
'b: 'a,
|
'b: 'a,
|
||||||
{
|
{
|
||||||
fn visit_stmt(&mut self, stmt: &'b Stmt) {
|
fn visit_stmt(&mut self, stmt: &'b Stmt) {
|
||||||
self.stack.push(stmt);
|
self.parents.push(stmt);
|
||||||
|
|
||||||
|
// Pre-visit.
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::Global { names } | StmtKind::Nonlocal { names } => {
|
StmtKind::Global { names } | StmtKind::Nonlocal { names } => {
|
||||||
// TODO(charlie): Handle doctests.
|
// TODO(charlie): Handle doctests.
|
||||||
let global_scope_index = 0;
|
let global_scope_id = self.scopes[GLOBAL_SCOPE_INDEX].id;
|
||||||
let global_scope_id = self.scopes[global_scope_index].id;
|
|
||||||
let current_scope_id = self.scopes.last().expect("No current scope found.").id;
|
let current_scope =
|
||||||
|
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
|
let current_scope_id = current_scope.id;
|
||||||
if current_scope_id != global_scope_id {
|
if current_scope_id != global_scope_id {
|
||||||
for name in names {
|
for name in names {
|
||||||
for scope in self.scopes.iter_mut().skip(global_scope_index + 1) {
|
for scope in self.scopes.iter_mut().skip(GLOBAL_SCOPE_INDEX + 1) {
|
||||||
scope.values.insert(
|
scope.values.insert(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
Binding {
|
Binding {
|
||||||
|
|
@ -118,7 +129,7 @@ where
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
for expr in decorator_list {
|
for expr in decorator_list {
|
||||||
self.visit_expr(expr, Some(stmt));
|
self.visit_expr(expr);
|
||||||
}
|
}
|
||||||
for expr in returns {
|
for expr in returns {
|
||||||
self.visit_annotation(expr);
|
self.visit_annotation(expr);
|
||||||
|
|
@ -131,10 +142,6 @@ where
|
||||||
location: stmt.location,
|
location: stmt.location,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
self.deferred_functions.push((stmt, &self.scopes));
|
|
||||||
|
|
||||||
// self.push_scope(Scope::new(ScopeKind::Function));
|
|
||||||
}
|
}
|
||||||
StmtKind::Return { .. } => {
|
StmtKind::Return { .. } => {
|
||||||
if self
|
if self
|
||||||
|
|
@ -142,8 +149,8 @@ where
|
||||||
.select
|
.select
|
||||||
.contains(CheckKind::ReturnOutsideFunction.code())
|
.contains(CheckKind::ReturnOutsideFunction.code())
|
||||||
{
|
{
|
||||||
if let Some(scope) = self.scopes.last() {
|
if let Some(scope_index) = self.scope_stack.last().cloned() {
|
||||||
match scope.kind {
|
match self.scopes[scope_index].kind {
|
||||||
ScopeKind::Class | ScopeKind::Module => {
|
ScopeKind::Class | ScopeKind::Module => {
|
||||||
self.checks.push(Check::new(
|
self.checks.push(Check::new(
|
||||||
CheckKind::ReturnOutsideFunction,
|
CheckKind::ReturnOutsideFunction,
|
||||||
|
|
@ -166,7 +173,8 @@ where
|
||||||
for expr in bases {
|
for expr in bases {
|
||||||
if let ExprKind::Name { id, .. } = &expr.node {
|
if let ExprKind::Name { id, .. } = &expr.node {
|
||||||
if id == "object" {
|
if id == "object" {
|
||||||
let scope = self.scopes.last().expect("No current scope found.");
|
let scope = &self.scopes
|
||||||
|
[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
match scope.values.get(id) {
|
match scope.values.get(id) {
|
||||||
None
|
None
|
||||||
| Some(Binding {
|
| Some(Binding {
|
||||||
|
|
@ -201,13 +209,13 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
for expr in bases {
|
for expr in bases {
|
||||||
self.visit_expr(expr, Some(stmt))
|
self.visit_expr(expr)
|
||||||
}
|
}
|
||||||
for keyword in keywords {
|
for keyword in keywords {
|
||||||
self.visit_keyword(keyword)
|
self.visit_keyword(keyword)
|
||||||
}
|
}
|
||||||
for expr in decorator_list {
|
for expr in decorator_list {
|
||||||
self.visit_expr(expr, Some(stmt))
|
self.visit_expr(expr)
|
||||||
}
|
}
|
||||||
self.push_scope(Scope::new(ScopeKind::Class))
|
self.push_scope(Scope::new(ScopeKind::Class))
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +294,13 @@ where
|
||||||
name,
|
name,
|
||||||
Binding {
|
Binding {
|
||||||
kind: BindingKind::FutureImportation,
|
kind: BindingKind::FutureImportation,
|
||||||
used: Some(self.scopes.last().expect("No current scope found.").id),
|
used: Some(
|
||||||
|
self.scopes[*(self
|
||||||
|
.scope_stack
|
||||||
|
.last()
|
||||||
|
.expect("No current scope found."))]
|
||||||
|
.id,
|
||||||
|
),
|
||||||
location: stmt.location,
|
location: stmt.location,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -441,41 +455,23 @@ where
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
visitor::walk_stmt(self, stmt);
|
// Recurse.
|
||||||
|
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::ClassDef { .. } => {
|
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. } => {
|
||||||
if let Some(scope) = self.scopes.pop() {
|
self.deferred_functions
|
||||||
self.dead_scopes.push(scope);
|
.push((stmt, self.scope_stack.clone()));
|
||||||
|
}
|
||||||
|
StmtKind::ClassDef { body, .. } => {
|
||||||
|
for stmt in body {
|
||||||
|
self.visit_stmt(stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. } => {
|
_ => visitor::walk_stmt(self, stmt),
|
||||||
// let scope = self.scopes.last().expect("No current scope found.");
|
|
||||||
// for (name, binding) in scope.values.iter() {
|
|
||||||
// // TODO(charlie): Ignore if using `locals`.
|
|
||||||
// if self.settings.select.contains(&CheckCode::F841)
|
|
||||||
// && binding.used.is_none()
|
|
||||||
// && name != "_"
|
|
||||||
// && name != "__tracebackhide__"
|
|
||||||
// && name != "__traceback_info__"
|
|
||||||
// && name != "__traceback_supplement__"
|
|
||||||
// && matches!(binding.kind, BindingKind::Assignment)
|
|
||||||
// {
|
|
||||||
// self.checks.push(Check::new(
|
|
||||||
// CheckKind::UnusedVariable(name.to_string()),
|
|
||||||
// binding.location,
|
|
||||||
// ));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if let Some(scope) = self.scopes.pop() {
|
|
||||||
// self.dead_scopes.push(scope);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
_ => {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Post-visit.
|
||||||
if let StmtKind::ClassDef { name, .. } = &stmt.node {
|
if let StmtKind::ClassDef { name, .. } = &stmt.node {
|
||||||
|
self.pop_scope();
|
||||||
self.add_binding(
|
self.add_binding(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
Binding {
|
Binding {
|
||||||
|
|
@ -484,22 +480,30 @@ where
|
||||||
location: stmt.location,
|
location: stmt.location,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
self.parents.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_annotation(&mut self, expr: &'b Expr) {
|
fn visit_annotation(&mut self, expr: &'b Expr) {
|
||||||
let initial = self.in_annotation;
|
let initial = self.in_annotation;
|
||||||
self.in_annotation = true;
|
self.in_annotation = true;
|
||||||
self.visit_expr(expr, None);
|
self.visit_expr(expr);
|
||||||
self.in_annotation = initial;
|
self.in_annotation = initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'b Expr, parent: Option<&Stmt>) {
|
fn visit_expr(&mut self, expr: &'b Expr) {
|
||||||
let initial = self.in_f_string;
|
let initial = self.in_f_string;
|
||||||
|
|
||||||
|
// Pre-visit.
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Name { ctx, .. } => match ctx {
|
ExprKind::Name { ctx, .. } => match ctx {
|
||||||
ExprContext::Load => self.handle_node_load(expr),
|
ExprContext::Load => self.handle_node_load(expr),
|
||||||
ExprContext::Store => self.handle_node_store(expr, parent),
|
ExprContext::Store => {
|
||||||
|
let parent = self.parents.pop().expect("No parnet statement found.");
|
||||||
|
self.handle_node_store(expr, Some(parent));
|
||||||
|
self.parents.push(parent);
|
||||||
|
}
|
||||||
ExprContext::Del => self.handle_node_delete(expr),
|
ExprContext::Del => self.handle_node_delete(expr),
|
||||||
},
|
},
|
||||||
ExprKind::Call { func, .. } => {
|
ExprKind::Call { func, .. } => {
|
||||||
|
|
@ -579,9 +583,9 @@ where
|
||||||
| ExprKind::ListComp { .. }
|
| ExprKind::ListComp { .. }
|
||||||
| ExprKind::DictComp { .. }
|
| ExprKind::DictComp { .. }
|
||||||
| ExprKind::SetComp { .. } => self.push_scope(Scope::new(ScopeKind::Generator)),
|
| ExprKind::SetComp { .. } => self.push_scope(Scope::new(ScopeKind::Generator)),
|
||||||
ExprKind::Lambda { .. } => self.push_scope(Scope::new(ScopeKind::Function)),
|
|
||||||
ExprKind::Yield { .. } | ExprKind::YieldFrom { .. } => {
|
ExprKind::Yield { .. } | ExprKind::YieldFrom { .. } => {
|
||||||
let scope = self.scopes.last().expect("No current scope found.");
|
let scope =
|
||||||
|
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
if self
|
if self
|
||||||
.settings
|
.settings
|
||||||
.select
|
.select
|
||||||
|
|
@ -738,17 +742,21 @@ where
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
visitor::walk_expr(self, expr);
|
// Recurse.
|
||||||
|
match &expr.node {
|
||||||
|
ExprKind::Lambda { .. } => {
|
||||||
|
self.deferred_lambdas.push((expr, self.scope_stack.clone()));
|
||||||
|
}
|
||||||
|
_ => visitor::walk_expr(self, expr),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post-visit.
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::GeneratorExp { .. }
|
ExprKind::GeneratorExp { .. }
|
||||||
| ExprKind::ListComp { .. }
|
| ExprKind::ListComp { .. }
|
||||||
| ExprKind::DictComp { .. }
|
| ExprKind::DictComp { .. }
|
||||||
| ExprKind::SetComp { .. }
|
| ExprKind::SetComp { .. } => {
|
||||||
| ExprKind::Lambda { .. } => {
|
self.pop_scope();
|
||||||
if let Some(scope) = self.scopes.pop() {
|
|
||||||
self.dead_scopes.push(scope);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ExprKind::JoinedStr { .. } => {
|
ExprKind::JoinedStr { .. } => {
|
||||||
self.in_f_string = initial;
|
self.in_f_string = initial;
|
||||||
|
|
@ -761,8 +769,10 @@ where
|
||||||
match &excepthandler.node {
|
match &excepthandler.node {
|
||||||
ExcepthandlerKind::ExceptHandler { name, .. } => match name {
|
ExcepthandlerKind::ExceptHandler { name, .. } => match name {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
let scope = self.scopes.last().expect("No current scope found.");
|
let scope =
|
||||||
|
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
if scope.values.contains_key(name) {
|
if scope.values.contains_key(name) {
|
||||||
|
let parent = self.parents.pop().expect("No parnet statement found.");
|
||||||
self.handle_node_store(
|
self.handle_node_store(
|
||||||
&Expr::new(
|
&Expr::new(
|
||||||
excepthandler.location,
|
excepthandler.location,
|
||||||
|
|
@ -771,12 +781,15 @@ where
|
||||||
ctx: ExprContext::Store,
|
ctx: ExprContext::Store,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
None,
|
Some(parent),
|
||||||
);
|
);
|
||||||
|
self.parents.push(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
let scope = self.scopes.last().expect("No current scope found.");
|
let parent = self.parents.pop().expect("No parnet statement found.");
|
||||||
let prev_definition = scope.values.get(name).cloned();
|
let scope =
|
||||||
|
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
|
let definition = scope.values.get(name).cloned();
|
||||||
self.handle_node_store(
|
self.handle_node_store(
|
||||||
&Expr::new(
|
&Expr::new(
|
||||||
excepthandler.location,
|
excepthandler.location,
|
||||||
|
|
@ -785,13 +798,15 @@ where
|
||||||
ctx: ExprContext::Store,
|
ctx: ExprContext::Store,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
None,
|
Some(parent),
|
||||||
);
|
);
|
||||||
|
self.parents.push(parent);
|
||||||
|
|
||||||
walk_excepthandler(self, excepthandler);
|
walk_excepthandler(self, excepthandler);
|
||||||
|
|
||||||
let scope = self.scopes.last_mut().expect("No current scope found.");
|
let scope = &mut self.scopes
|
||||||
if let Some(binding) = scope.values.remove(name) {
|
[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
|
if let Some(binding) = &scope.values.remove(name) {
|
||||||
if self.settings.select.contains(&CheckCode::F841) && binding.used.is_none()
|
if self.settings.select.contains(&CheckCode::F841) && binding.used.is_none()
|
||||||
{
|
{
|
||||||
self.checks.push(Check::new(
|
self.checks.push(Check::new(
|
||||||
|
|
@ -801,7 +816,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(binding) = prev_definition {
|
if let Some(binding) = definition {
|
||||||
scope.values.insert(name.to_string(), binding);
|
scope.values.insert(name.to_string(), binding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -859,41 +874,47 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Checker<'_> {
|
impl<'a> Checker<'a> {
|
||||||
fn push_scope(&mut self, scope: Scope) {
|
fn push_scope(&mut self, scope: Scope) {
|
||||||
|
self.scope_stack.push(self.scopes.len());
|
||||||
self.scopes.push(scope);
|
self.scopes.push(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_scope(&mut self) {
|
fn pop_scope(&mut self) {
|
||||||
self.dead_scopes
|
self.dead_scopes.push(
|
||||||
.push(self.scopes.pop().expect("Attempted to pop without scope."));
|
self.scope_stack
|
||||||
|
.pop()
|
||||||
|
.expect("Attempted to pop without scope."),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_builtins(&mut self) {
|
fn bind_builtins(&mut self) {
|
||||||
|
let scope = &mut self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
|
|
||||||
for builtin in BUILTINS {
|
for builtin in BUILTINS {
|
||||||
self.add_binding(
|
scope.values.insert(
|
||||||
builtin.to_string(),
|
builtin.to_string(),
|
||||||
Binding {
|
Binding {
|
||||||
kind: BindingKind::Builtin,
|
kind: BindingKind::Builtin,
|
||||||
location: Default::default(),
|
location: Default::default(),
|
||||||
used: None,
|
used: None,
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
for builtin in MAGIC_GLOBALS {
|
for builtin in MAGIC_GLOBALS {
|
||||||
self.add_binding(
|
scope.values.insert(
|
||||||
builtin.to_string(),
|
builtin.to_string(),
|
||||||
Binding {
|
Binding {
|
||||||
kind: BindingKind::Builtin,
|
kind: BindingKind::Builtin,
|
||||||
location: Default::default(),
|
location: Default::default(),
|
||||||
used: None,
|
used: None,
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_binding(&mut self, name: String, binding: Binding) {
|
fn add_binding(&mut self, name: String, binding: Binding) {
|
||||||
let scope = self.scopes.last_mut().expect("No current scope found.");
|
let scope = &mut self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
|
|
||||||
// TODO(charlie): Don't treat annotations as assignments if there is an existing value.
|
// TODO(charlie): Don't treat annotations as assignments if there is an existing value.
|
||||||
let binding = match scope.values.get(&name) {
|
let binding = match scope.values.get(&name) {
|
||||||
|
|
@ -909,14 +930,17 @@ impl Checker<'_> {
|
||||||
|
|
||||||
fn handle_node_load(&mut self, expr: &Expr) {
|
fn handle_node_load(&mut self, expr: &Expr) {
|
||||||
if let ExprKind::Name { id, .. } = &expr.node {
|
if let ExprKind::Name { id, .. } = &expr.node {
|
||||||
let scope_id = self.scopes.last_mut().expect("No current scope found.").id;
|
let scope_id =
|
||||||
|
self.scopes[*(self.scope_stack.last().expect("No current scope found."))].id;
|
||||||
|
|
||||||
let mut first_iter = true;
|
let mut first_iter = true;
|
||||||
let mut in_generators = false;
|
let mut in_generator = false;
|
||||||
for scope in self.scopes.iter_mut().rev() {
|
for scope_index in self.scope_stack.iter().rev() {
|
||||||
|
let scope = &mut self.scopes[*scope_index];
|
||||||
if matches!(scope.kind, ScopeKind::Class) {
|
if matches!(scope.kind, ScopeKind::Class) {
|
||||||
if id == "__class__" {
|
if id == "__class__" {
|
||||||
return;
|
return;
|
||||||
} else if !first_iter && !in_generators {
|
} else if !first_iter && !in_generator {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -926,7 +950,7 @@ impl Checker<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
first_iter = false;
|
first_iter = false;
|
||||||
in_generators = matches!(scope.kind, ScopeKind::Generator);
|
in_generator = matches!(scope.kind, ScopeKind::Generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.settings.select.contains(&CheckCode::F821) {
|
if self.settings.select.contains(&CheckCode::F821) {
|
||||||
|
|
@ -940,7 +964,8 @@ impl Checker<'_> {
|
||||||
|
|
||||||
fn handle_node_store(&mut self, expr: &Expr, parent: Option<&Stmt>) {
|
fn handle_node_store(&mut self, expr: &Expr, parent: Option<&Stmt>) {
|
||||||
if let ExprKind::Name { id, .. } = &expr.node {
|
if let ExprKind::Name { id, .. } = &expr.node {
|
||||||
let current = self.scopes.last().expect("No current scope found.");
|
let current =
|
||||||
|
&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)
|
||||||
|
|
@ -970,14 +995,13 @@ impl Checker<'_> {
|
||||||
// TODO(charlie): Handle alternate binding types (like `Annotation`).
|
// TODO(charlie): Handle alternate binding types (like `Annotation`).
|
||||||
if id == "__all__"
|
if id == "__all__"
|
||||||
&& matches!(current.kind, ScopeKind::Module)
|
&& matches!(current.kind, ScopeKind::Module)
|
||||||
&& match parent {
|
&& parent
|
||||||
None => false,
|
.map(|stmt| {
|
||||||
Some(stmt) => {
|
|
||||||
matches!(stmt.node, StmtKind::Assign { .. })
|
matches!(stmt.node, StmtKind::Assign { .. })
|
||||||
|| matches!(stmt.node, StmtKind::AugAssign { .. })
|
|| matches!(stmt.node, StmtKind::AugAssign { .. })
|
||||||
|| matches!(stmt.node, StmtKind::AnnAssign { .. })
|
|| matches!(stmt.node, StmtKind::AnnAssign { .. })
|
||||||
}
|
})
|
||||||
}
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
// Really need parent here.
|
// Really need parent here.
|
||||||
self.add_binding(
|
self.add_binding(
|
||||||
|
|
@ -1003,9 +1027,9 @@ impl Checker<'_> {
|
||||||
|
|
||||||
fn handle_node_delete(&mut self, expr: &Expr) {
|
fn handle_node_delete(&mut self, expr: &Expr) {
|
||||||
if let ExprKind::Name { id, .. } = &expr.node {
|
if let ExprKind::Name { id, .. } = &expr.node {
|
||||||
let current = self.scopes.last_mut().expect("No current scope found.");
|
let scope =
|
||||||
if current.values.remove(id).is_none()
|
&mut self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
&& self.settings.select.contains(&CheckCode::F821)
|
if scope.values.remove(id).is_none() && self.settings.select.contains(&CheckCode::F821)
|
||||||
{
|
{
|
||||||
self.checks.push(Check::new(
|
self.checks.push(Check::new(
|
||||||
CheckKind::UndefinedName(id.clone()),
|
CheckKind::UndefinedName(id.clone()),
|
||||||
|
|
@ -1015,13 +1039,93 @@ impl Checker<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_deferred(&mut self, path: &str) {
|
fn check_deferred_annotations<'b>(&mut self, path: &str, allocator: &'b mut Vec<Expr>)
|
||||||
// while !self.deferred.is_empty() {
|
where
|
||||||
// let value = self.deferred.pop().unwrap();
|
'b: 'a,
|
||||||
// if let Ok(expr) = parser::parse_expression(&value, path) {
|
{
|
||||||
// self.visit_expr(&expr, None);
|
while !self.deferred_annotations.is_empty() {
|
||||||
// }
|
let value = self.deferred_annotations.pop().unwrap();
|
||||||
// }
|
if let Ok(expr) = parser::parse_expression(value, path) {
|
||||||
|
allocator.push(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for expr in allocator {
|
||||||
|
self.visit_expr(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_deferred_functions(&mut self) {
|
||||||
|
while !self.deferred_functions.is_empty() {
|
||||||
|
let (stmt, scopes) = self.deferred_functions.pop().unwrap();
|
||||||
|
|
||||||
|
self.scope_stack = scopes;
|
||||||
|
self.push_scope(Scope::new(ScopeKind::Function));
|
||||||
|
|
||||||
|
match &stmt.node {
|
||||||
|
StmtKind::FunctionDef { body, args, .. }
|
||||||
|
| StmtKind::AsyncFunctionDef { body, args, .. } => {
|
||||||
|
self.visit_arguments(args);
|
||||||
|
for stmt in body {
|
||||||
|
self.visit_stmt(stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let scope = &self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
|
for (name, binding) in scope.values.iter() {
|
||||||
|
// TODO(charlie): Ignore if using `locals`.
|
||||||
|
if self.settings.select.contains(&CheckCode::F841)
|
||||||
|
&& binding.used.is_none()
|
||||||
|
&& name != "_"
|
||||||
|
&& name != "__tracebackhide__"
|
||||||
|
&& name != "__traceback_info__"
|
||||||
|
&& name != "__traceback_supplement__"
|
||||||
|
&& matches!(binding.kind, BindingKind::Assignment)
|
||||||
|
{
|
||||||
|
self.checks.push(Check::new(
|
||||||
|
CheckKind::UnusedVariable(name.to_string()),
|
||||||
|
binding.location,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pop_scope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_deferred_lambdas(&mut self) {
|
||||||
|
while !self.deferred_lambdas.is_empty() {
|
||||||
|
let (expr, scopes) = self.deferred_lambdas.pop().unwrap();
|
||||||
|
|
||||||
|
self.scope_stack = scopes;
|
||||||
|
self.push_scope(Scope::new(ScopeKind::Function));
|
||||||
|
|
||||||
|
if let ExprKind::Lambda { args, body } = &expr.node {
|
||||||
|
self.visit_arguments(args);
|
||||||
|
self.visit_expr(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
let scope = &self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||||
|
for (name, binding) in scope.values.iter() {
|
||||||
|
// TODO(charlie): Ignore if using `locals`.
|
||||||
|
if self.settings.select.contains(&CheckCode::F841)
|
||||||
|
&& binding.used.is_none()
|
||||||
|
&& name != "_"
|
||||||
|
&& name != "__tracebackhide__"
|
||||||
|
&& name != "__traceback_info__"
|
||||||
|
&& name != "__traceback_supplement__"
|
||||||
|
&& matches!(binding.kind, BindingKind::Assignment)
|
||||||
|
{
|
||||||
|
self.checks.push(Check::new(
|
||||||
|
CheckKind::UnusedVariable(name.to_string()),
|
||||||
|
binding.location,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pop_scope();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_dead_scopes(&mut self) {
|
fn check_dead_scopes(&mut self) {
|
||||||
|
|
@ -1031,7 +1135,9 @@ impl Checker<'_> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for scope in &self.dead_scopes {
|
for index in self.dead_scopes.clone() {
|
||||||
|
let scope = &self.scopes[index];
|
||||||
|
|
||||||
let all_binding = scope.values.get("__all__");
|
let all_binding = scope.values.get("__all__");
|
||||||
let all_names = all_binding.and_then(|binding| match &binding.kind {
|
let all_names = all_binding.and_then(|binding| match &binding.kind {
|
||||||
BindingKind::Export(names) => Some(names),
|
BindingKind::Export(names) => Some(names),
|
||||||
|
|
@ -1086,48 +1192,26 @@ pub fn check_ast(
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
autofix: &autofix::Mode,
|
autofix: &autofix::Mode,
|
||||||
path: &str,
|
path: &str,
|
||||||
stmt_allocator: &mut Vec<Stmt>,
|
|
||||||
expr_allocator: &mut Vec<Expr>,
|
|
||||||
) -> Vec<Check> {
|
) -> Vec<Check> {
|
||||||
let mut checker = Checker::new(settings, autofix, path, content);
|
let mut checker = Checker::new(settings, autofix, path, content);
|
||||||
checker.push_scope(Scope::new(ScopeKind::Module));
|
checker.push_scope(Scope::new(ScopeKind::Module));
|
||||||
checker.bind_builtins();
|
checker.bind_builtins();
|
||||||
|
|
||||||
|
// Iterate over the AST.
|
||||||
for stmt in python_ast {
|
for stmt in python_ast {
|
||||||
checker.visit_stmt(stmt);
|
checker.visit_stmt(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check deferred annotations.
|
// Check any deferred statements.
|
||||||
while !checker.deferred_annotations.is_empty() {
|
let mut allocator = vec![];
|
||||||
let value = checker.deferred_annotations.pop().unwrap();
|
checker.check_deferred_annotations(path, &mut allocator);
|
||||||
if let Ok(expr) = parser::parse_expression(&value, path) {
|
checker.check_deferred_functions();
|
||||||
expr_allocator.push(expr);
|
checker.check_deferred_lambdas();
|
||||||
}
|
|
||||||
}
|
|
||||||
for expr in expr_allocator {
|
|
||||||
checker.visit_expr(expr, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check deferred annotations.
|
|
||||||
while !checker.deferred_functions.is_empty() {
|
|
||||||
let (stmt, scopes) = checker.deferred_functions.pop().unwrap();
|
|
||||||
|
|
||||||
checker.scopes = scopes.to_vec();
|
|
||||||
checker.scopes.push(Scope::new(ScopeKind::Function));
|
|
||||||
match &stmt.node {
|
|
||||||
StmtKind::FunctionDef { body, .. } | StmtKind::AsyncFunctionDef { body, .. } => {
|
|
||||||
for stmt in body {
|
|
||||||
checker.visit_stmt(stmt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
if let Some(scope) = checker.scopes.pop() {
|
|
||||||
checker.dead_scopes.push(scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Reset the scope to module-level, and check all consumed scopes.
|
||||||
|
checker.scope_stack = vec![GLOBAL_SCOPE_INDEX];
|
||||||
checker.pop_scope();
|
checker.pop_scope();
|
||||||
checker.check_dead_scopes();
|
checker.check_dead_scopes();
|
||||||
|
|
||||||
checker.checks
|
checker.checks
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ use std::path::Path;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use rustpython_parser::ast::{Expr, Stmt};
|
|
||||||
use rustpython_parser::parser;
|
use rustpython_parser::parser;
|
||||||
|
|
||||||
use crate::autofix::fix_file;
|
use crate::autofix::fix_file;
|
||||||
|
|
@ -28,17 +27,7 @@ fn check_path(path: &Path, settings: &Settings, autofix: &autofix::Mode) -> Resu
|
||||||
{
|
{
|
||||||
let path = path.to_string_lossy();
|
let path = path.to_string_lossy();
|
||||||
let python_ast = parser::parse_program(&contents, &path)?;
|
let python_ast = parser::parse_program(&contents, &path)?;
|
||||||
let mut stmt_allocator: Vec<Stmt> = vec![];
|
checks.extend(check_ast(&python_ast, &contents, settings, autofix, &path));
|
||||||
let mut expr_allocator: Vec<Expr> = vec![];
|
|
||||||
checks.extend(check_ast(
|
|
||||||
&python_ast,
|
|
||||||
&contents,
|
|
||||||
settings,
|
|
||||||
autofix,
|
|
||||||
&path,
|
|
||||||
&mut stmt_allocator,
|
|
||||||
&mut expr_allocator,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the lines-based checks.
|
// Run the lines-based checks.
|
||||||
|
|
@ -101,7 +90,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn e402() -> Result<()> {
|
fn e402() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/E402.py"),
|
Path::new("./resources/test/fixtures/E402.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -110,6 +99,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![Check {
|
let expected = vec![Check {
|
||||||
kind: CheckKind::ModuleImportNotAtTopOfFile,
|
kind: CheckKind::ModuleImportNotAtTopOfFile,
|
||||||
location: Location::new(20, 1),
|
location: Location::new(20, 1),
|
||||||
|
|
@ -125,7 +115,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn e501() -> Result<()> {
|
fn e501() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/E501.py"),
|
Path::new("./resources/test/fixtures/E501.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -134,6 +124,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![Check {
|
let expected = vec![Check {
|
||||||
kind: CheckKind::LineTooLong,
|
kind: CheckKind::LineTooLong,
|
||||||
location: Location::new(5, 89),
|
location: Location::new(5, 89),
|
||||||
|
|
@ -149,7 +140,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn e711() -> Result<()> {
|
fn e711() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/E711.py"),
|
Path::new("./resources/test/fixtures/E711.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -158,6 +149,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::NoneComparison(RejectedCmpop::Eq),
|
kind: CheckKind::NoneComparison(RejectedCmpop::Eq),
|
||||||
|
|
@ -180,7 +172,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn e712() -> Result<()> {
|
fn e712() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/E712.py"),
|
Path::new("./resources/test/fixtures/E712.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -189,6 +181,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::TrueFalseComparison(true, RejectedCmpop::Eq),
|
kind: CheckKind::TrueFalseComparison(true, RejectedCmpop::Eq),
|
||||||
|
|
@ -222,7 +215,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn e713() -> Result<()> {
|
fn e713() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/E713.py"),
|
Path::new("./resources/test/fixtures/E713.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -231,6 +224,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![Check {
|
let expected = vec![Check {
|
||||||
kind: CheckKind::NotInTest,
|
kind: CheckKind::NotInTest,
|
||||||
location: Location::new(2, 12),
|
location: Location::new(2, 12),
|
||||||
|
|
@ -246,7 +240,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn e714() -> Result<()> {
|
fn e714() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/E714.py"),
|
Path::new("./resources/test/fixtures/E714.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -255,6 +249,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![Check {
|
let expected = vec![Check {
|
||||||
kind: CheckKind::NotIsTest,
|
kind: CheckKind::NotIsTest,
|
||||||
location: Location::new(1, 13),
|
location: Location::new(1, 13),
|
||||||
|
|
@ -270,7 +265,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn e731() -> Result<()> {
|
fn e731() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/E731.py"),
|
Path::new("./resources/test/fixtures/E731.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -279,6 +274,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::DoNotAssignLambda,
|
kind: CheckKind::DoNotAssignLambda,
|
||||||
|
|
@ -302,7 +298,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f401() -> Result<()> {
|
fn f401() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F401.py"),
|
Path::new("./resources/test/fixtures/F401.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -311,12 +307,8 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
|
||||||
kind: CheckKind::UnusedImport("logging.handlers".to_string()),
|
|
||||||
location: Location::new(12, 1),
|
|
||||||
fix: None,
|
|
||||||
},
|
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::UnusedImport("functools".to_string()),
|
kind: CheckKind::UnusedImport("functools".to_string()),
|
||||||
location: Location::new(3, 1),
|
location: Location::new(3, 1),
|
||||||
|
|
@ -327,6 +319,11 @@ mod tests {
|
||||||
location: Location::new(4, 1),
|
location: Location::new(4, 1),
|
||||||
fix: None,
|
fix: None,
|
||||||
},
|
},
|
||||||
|
Check {
|
||||||
|
kind: CheckKind::UnusedImport("logging.handlers".to_string()),
|
||||||
|
location: Location::new(12, 1),
|
||||||
|
fix: None,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
assert_eq!(actual.len(), expected.len());
|
assert_eq!(actual.len(), expected.len());
|
||||||
for i in 0..actual.len() {
|
for i in 0..actual.len() {
|
||||||
|
|
@ -338,7 +335,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f403() -> Result<()> {
|
fn f403() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F403.py"),
|
Path::new("./resources/test/fixtures/F403.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -347,6 +344,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::ImportStarUsage,
|
kind: CheckKind::ImportStarUsage,
|
||||||
|
|
@ -368,7 +366,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn f541() -> Result<()> {
|
fn f541() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F541.py"),
|
Path::new("./resources/test/fixtures/F541.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -377,6 +375,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::FStringMissingPlaceholders,
|
kind: CheckKind::FStringMissingPlaceholders,
|
||||||
|
|
@ -464,7 +463,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f631() -> Result<()> {
|
fn f631() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F631.py"),
|
Path::new("./resources/test/fixtures/F631.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -473,6 +472,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::AssertTuple,
|
kind: CheckKind::AssertTuple,
|
||||||
|
|
@ -495,7 +495,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f634() -> Result<()> {
|
fn f634() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F634.py"),
|
Path::new("./resources/test/fixtures/F634.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -504,6 +504,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::IfTuple,
|
kind: CheckKind::IfTuple,
|
||||||
|
|
@ -526,7 +527,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f704() -> Result<()> {
|
fn f704() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F704.py"),
|
Path::new("./resources/test/fixtures/F704.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -535,6 +536,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::YieldOutsideFunction,
|
kind: CheckKind::YieldOutsideFunction,
|
||||||
|
|
@ -562,7 +564,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f706() -> Result<()> {
|
fn f706() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F706.py"),
|
Path::new("./resources/test/fixtures/F706.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -571,6 +573,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::ReturnOutsideFunction,
|
kind: CheckKind::ReturnOutsideFunction,
|
||||||
|
|
@ -593,7 +596,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f707() -> Result<()> {
|
fn f707() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F707.py"),
|
Path::new("./resources/test/fixtures/F707.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -602,6 +605,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::DefaultExceptNotLast,
|
kind: CheckKind::DefaultExceptNotLast,
|
||||||
|
|
@ -629,7 +633,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f821() -> Result<()> {
|
fn f821() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F821.py"),
|
Path::new("./resources/test/fixtures/F821.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -638,6 +642,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::UndefinedName("self".to_string()),
|
kind: CheckKind::UndefinedName("self".to_string()),
|
||||||
|
|
@ -670,7 +675,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f822() -> Result<()> {
|
fn f822() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F822.py"),
|
Path::new("./resources/test/fixtures/F822.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -679,6 +684,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![Check {
|
let expected = vec![Check {
|
||||||
kind: CheckKind::UndefinedExport("b".to_string()),
|
kind: CheckKind::UndefinedExport("b".to_string()),
|
||||||
location: Location::new(3, 1),
|
location: Location::new(3, 1),
|
||||||
|
|
@ -694,7 +700,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f823() -> Result<()> {
|
fn f823() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F823.py"),
|
Path::new("./resources/test/fixtures/F823.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -703,6 +709,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![Check {
|
let expected = vec![Check {
|
||||||
kind: CheckKind::UndefinedLocal("my_var".to_string()),
|
kind: CheckKind::UndefinedLocal("my_var".to_string()),
|
||||||
location: Location::new(6, 5),
|
location: Location::new(6, 5),
|
||||||
|
|
@ -718,7 +725,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f831() -> Result<()> {
|
fn f831() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F831.py"),
|
Path::new("./resources/test/fixtures/F831.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -727,6 +734,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::DuplicateArgumentName,
|
kind: CheckKind::DuplicateArgumentName,
|
||||||
|
|
@ -754,7 +762,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f841() -> Result<()> {
|
fn f841() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F841.py"),
|
Path::new("./resources/test/fixtures/F841.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -763,6 +771,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::UnusedVariable("e".to_string()),
|
kind: CheckKind::UnusedVariable("e".to_string()),
|
||||||
|
|
@ -785,7 +794,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn f901() -> Result<()> {
|
fn f901() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/F901.py"),
|
Path::new("./resources/test/fixtures/F901.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -794,6 +803,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::RaiseNotImplemented,
|
kind: CheckKind::RaiseNotImplemented,
|
||||||
|
|
@ -816,7 +826,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn r001() -> Result<()> {
|
fn r001() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/R001.py"),
|
Path::new("./resources/test/fixtures/R001.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -825,6 +835,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::UselessObjectInheritance("A".to_string()),
|
kind: CheckKind::UselessObjectInheritance("A".to_string()),
|
||||||
|
|
@ -1037,7 +1048,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn r002() -> Result<()> {
|
fn r002() -> Result<()> {
|
||||||
let actual = check_path(
|
let mut actual = check_path(
|
||||||
Path::new("./resources/test/fixtures/R002.py"),
|
Path::new("./resources/test/fixtures/R002.py"),
|
||||||
&settings::Settings {
|
&settings::Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
|
|
@ -1046,6 +1057,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
&autofix::Mode::Generate,
|
&autofix::Mode::Generate,
|
||||||
)?;
|
)?;
|
||||||
|
actual.sort_by_key(|check| check.location);
|
||||||
let expected = vec![
|
let expected = vec![
|
||||||
Check {
|
Check {
|
||||||
kind: CheckKind::NoAssertEquals,
|
kind: CheckKind::NoAssertEquals,
|
||||||
|
|
|
||||||
199
src/visitor.rs
199
src/visitor.rs
|
|
@ -11,7 +11,7 @@ pub trait Visitor<'a> {
|
||||||
fn visit_annotation(&mut self, expr: &'a Expr) {
|
fn visit_annotation(&mut self, expr: &'a Expr) {
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
fn visit_expr(&mut self, expr: &'a Expr, _parent: Option<&Stmt>) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
fn visit_constant(&mut self, constant: &'a Constant) {
|
fn visit_constant(&mut self, constant: &'a Constant) {
|
||||||
|
|
@ -63,43 +63,82 @@ pub trait Visitor<'a> {
|
||||||
|
|
||||||
pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::FunctionDef { args, body, .. } => {
|
StmtKind::FunctionDef {
|
||||||
|
args,
|
||||||
|
body,
|
||||||
|
decorator_list,
|
||||||
|
returns,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
visitor.visit_arguments(args);
|
visitor.visit_arguments(args);
|
||||||
// for stmt in body {
|
for expr in decorator_list {
|
||||||
// visitor.visit_stmt(stmt)
|
visitor.visit_expr(expr)
|
||||||
// }
|
}
|
||||||
|
for expr in returns {
|
||||||
|
visitor.visit_annotation(expr);
|
||||||
|
}
|
||||||
|
for stmt in body {
|
||||||
|
visitor.visit_stmt(stmt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
StmtKind::AsyncFunctionDef { args, body, .. } => {
|
StmtKind::AsyncFunctionDef {
|
||||||
|
args,
|
||||||
|
body,
|
||||||
|
decorator_list,
|
||||||
|
returns,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
visitor.visit_arguments(args);
|
visitor.visit_arguments(args);
|
||||||
// for stmt in body {
|
for expr in decorator_list {
|
||||||
// visitor.visit_stmt(stmt)
|
visitor.visit_expr(expr)
|
||||||
// }
|
}
|
||||||
|
for expr in returns {
|
||||||
|
visitor.visit_annotation(expr);
|
||||||
|
}
|
||||||
|
for stmt in body {
|
||||||
|
visitor.visit_stmt(stmt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
StmtKind::ClassDef { body, .. } => {
|
StmtKind::ClassDef {
|
||||||
|
bases,
|
||||||
|
keywords,
|
||||||
|
body,
|
||||||
|
decorator_list,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
for expr in bases {
|
||||||
|
visitor.visit_expr(expr)
|
||||||
|
}
|
||||||
|
for keyword in keywords {
|
||||||
|
visitor.visit_keyword(keyword)
|
||||||
|
}
|
||||||
|
for expr in decorator_list {
|
||||||
|
visitor.visit_expr(expr)
|
||||||
|
}
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
visitor.visit_stmt(stmt)
|
visitor.visit_stmt(stmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Return { value } => {
|
StmtKind::Return { value } => {
|
||||||
if let Some(expr) = value {
|
if let Some(expr) = value {
|
||||||
visitor.visit_expr(expr, Some(stmt))
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Delete { targets } => {
|
StmtKind::Delete { targets } => {
|
||||||
for expr in targets {
|
for expr in targets {
|
||||||
visitor.visit_expr(expr, Some(stmt))
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Assign { targets, value, .. } => {
|
StmtKind::Assign { targets, value, .. } => {
|
||||||
for expr in targets {
|
for expr in targets {
|
||||||
visitor.visit_expr(expr, Some(stmt))
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
visitor.visit_expr(value, Some(stmt))
|
visitor.visit_expr(value)
|
||||||
}
|
}
|
||||||
StmtKind::AugAssign { target, op, value } => {
|
StmtKind::AugAssign { target, op, value } => {
|
||||||
visitor.visit_expr(target, Some(stmt));
|
visitor.visit_expr(target);
|
||||||
visitor.visit_operator(op);
|
visitor.visit_operator(op);
|
||||||
visitor.visit_expr(value, Some(stmt));
|
visitor.visit_expr(value);
|
||||||
}
|
}
|
||||||
StmtKind::AnnAssign {
|
StmtKind::AnnAssign {
|
||||||
target,
|
target,
|
||||||
|
|
@ -107,10 +146,10 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
value,
|
value,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
visitor.visit_expr(target, Some(stmt));
|
visitor.visit_expr(target);
|
||||||
visitor.visit_annotation(annotation);
|
visitor.visit_annotation(annotation);
|
||||||
if let Some(expr) = value {
|
if let Some(expr) = value {
|
||||||
visitor.visit_expr(expr, Some(stmt))
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::For {
|
StmtKind::For {
|
||||||
|
|
@ -120,8 +159,8 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
orelse,
|
orelse,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
visitor.visit_expr(target, Some(stmt));
|
visitor.visit_expr(target);
|
||||||
visitor.visit_expr(iter, Some(stmt));
|
visitor.visit_expr(iter);
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
visitor.visit_stmt(stmt)
|
visitor.visit_stmt(stmt)
|
||||||
}
|
}
|
||||||
|
|
@ -136,8 +175,8 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
orelse,
|
orelse,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
visitor.visit_expr(target, Some(stmt));
|
visitor.visit_expr(target);
|
||||||
visitor.visit_expr(iter, Some(stmt));
|
visitor.visit_expr(iter);
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
visitor.visit_stmt(stmt)
|
visitor.visit_stmt(stmt)
|
||||||
}
|
}
|
||||||
|
|
@ -146,7 +185,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::While { test, body, orelse } => {
|
StmtKind::While { test, body, orelse } => {
|
||||||
visitor.visit_expr(test, Some(stmt));
|
visitor.visit_expr(test);
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
visitor.visit_stmt(stmt)
|
visitor.visit_stmt(stmt)
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +194,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::If { test, body, orelse } => {
|
StmtKind::If { test, body, orelse } => {
|
||||||
visitor.visit_expr(test, Some(stmt));
|
visitor.visit_expr(test);
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
visitor.visit_stmt(stmt)
|
visitor.visit_stmt(stmt)
|
||||||
}
|
}
|
||||||
|
|
@ -181,17 +220,17 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
}
|
}
|
||||||
StmtKind::Match { subject, cases } => {
|
StmtKind::Match { subject, cases } => {
|
||||||
// TODO(charlie): Handle `cases`.
|
// TODO(charlie): Handle `cases`.
|
||||||
visitor.visit_expr(subject, Some(stmt));
|
visitor.visit_expr(subject);
|
||||||
for match_case in cases {
|
for match_case in cases {
|
||||||
visitor.visit_match_case(match_case);
|
visitor.visit_match_case(match_case);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Raise { exc, cause } => {
|
StmtKind::Raise { exc, cause } => {
|
||||||
if let Some(expr) = exc {
|
if let Some(expr) = exc {
|
||||||
visitor.visit_expr(expr, Some(stmt))
|
visitor.visit_expr(expr)
|
||||||
};
|
};
|
||||||
if let Some(expr) = cause {
|
if let Some(expr) = cause {
|
||||||
visitor.visit_expr(expr, Some(stmt))
|
visitor.visit_expr(expr)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
StmtKind::Try {
|
StmtKind::Try {
|
||||||
|
|
@ -214,9 +253,9 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Assert { test, msg } => {
|
StmtKind::Assert { test, msg } => {
|
||||||
visitor.visit_expr(test, None);
|
visitor.visit_expr(test);
|
||||||
if let Some(expr) = msg {
|
if let Some(expr) = msg {
|
||||||
visitor.visit_expr(expr, Some(stmt))
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Import { names } => {
|
StmtKind::Import { names } => {
|
||||||
|
|
@ -231,7 +270,7 @@ pub fn walk_stmt<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, stmt: &'a Stmt) {
|
||||||
}
|
}
|
||||||
StmtKind::Global { .. } => {}
|
StmtKind::Global { .. } => {}
|
||||||
StmtKind::Nonlocal { .. } => {}
|
StmtKind::Nonlocal { .. } => {}
|
||||||
StmtKind::Expr { value } => visitor.visit_expr(value, Some(stmt)),
|
StmtKind::Expr { value } => visitor.visit_expr(value),
|
||||||
StmtKind::Pass => {}
|
StmtKind::Pass => {}
|
||||||
StmtKind::Break => {}
|
StmtKind::Break => {}
|
||||||
StmtKind::Continue => {}
|
StmtKind::Continue => {}
|
||||||
|
|
@ -243,55 +282,55 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
|
||||||
ExprKind::BoolOp { op, values } => {
|
ExprKind::BoolOp { op, values } => {
|
||||||
visitor.visit_boolop(op);
|
visitor.visit_boolop(op);
|
||||||
for expr in values {
|
for expr in values {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::NamedExpr { target, value } => {
|
ExprKind::NamedExpr { target, value } => {
|
||||||
visitor.visit_expr(target, None);
|
visitor.visit_expr(target);
|
||||||
visitor.visit_expr(value, None);
|
visitor.visit_expr(value);
|
||||||
}
|
}
|
||||||
ExprKind::BinOp { left, op, right } => {
|
ExprKind::BinOp { left, op, right } => {
|
||||||
visitor.visit_expr(left, None);
|
visitor.visit_expr(left);
|
||||||
visitor.visit_operator(op);
|
visitor.visit_operator(op);
|
||||||
visitor.visit_expr(right, None);
|
visitor.visit_expr(right);
|
||||||
}
|
}
|
||||||
ExprKind::UnaryOp { op, operand } => {
|
ExprKind::UnaryOp { op, operand } => {
|
||||||
visitor.visit_unaryop(op);
|
visitor.visit_unaryop(op);
|
||||||
visitor.visit_expr(operand, None);
|
visitor.visit_expr(operand);
|
||||||
}
|
}
|
||||||
ExprKind::Lambda { args, body } => {
|
ExprKind::Lambda { args, body } => {
|
||||||
visitor.visit_arguments(args);
|
visitor.visit_arguments(args);
|
||||||
visitor.visit_expr(body, None);
|
visitor.visit_expr(body);
|
||||||
}
|
}
|
||||||
ExprKind::IfExp { test, body, orelse } => {
|
ExprKind::IfExp { test, body, orelse } => {
|
||||||
visitor.visit_expr(test, None);
|
visitor.visit_expr(test);
|
||||||
visitor.visit_expr(body, None);
|
visitor.visit_expr(body);
|
||||||
visitor.visit_expr(orelse, None);
|
visitor.visit_expr(orelse);
|
||||||
}
|
}
|
||||||
ExprKind::Dict { keys, values } => {
|
ExprKind::Dict { keys, values } => {
|
||||||
for expr in keys {
|
for expr in keys {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
for expr in values {
|
for expr in values {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Set { elts } => {
|
ExprKind::Set { elts } => {
|
||||||
for expr in elts {
|
for expr in elts {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::ListComp { elt, generators } => {
|
ExprKind::ListComp { elt, generators } => {
|
||||||
for comprehension in generators {
|
for comprehension in generators {
|
||||||
visitor.visit_comprehension(comprehension)
|
visitor.visit_comprehension(comprehension)
|
||||||
}
|
}
|
||||||
visitor.visit_expr(elt, None);
|
visitor.visit_expr(elt);
|
||||||
}
|
}
|
||||||
ExprKind::SetComp { elt, generators } => {
|
ExprKind::SetComp { elt, generators } => {
|
||||||
for comprehension in generators {
|
for comprehension in generators {
|
||||||
visitor.visit_comprehension(comprehension)
|
visitor.visit_comprehension(comprehension)
|
||||||
}
|
}
|
||||||
visitor.visit_expr(elt, None);
|
visitor.visit_expr(elt);
|
||||||
}
|
}
|
||||||
ExprKind::DictComp {
|
ExprKind::DictComp {
|
||||||
key,
|
key,
|
||||||
|
|
@ -301,33 +340,33 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
|
||||||
for comprehension in generators {
|
for comprehension in generators {
|
||||||
visitor.visit_comprehension(comprehension)
|
visitor.visit_comprehension(comprehension)
|
||||||
}
|
}
|
||||||
visitor.visit_expr(key, None);
|
visitor.visit_expr(key);
|
||||||
visitor.visit_expr(value, None);
|
visitor.visit_expr(value);
|
||||||
}
|
}
|
||||||
ExprKind::GeneratorExp { elt, generators } => {
|
ExprKind::GeneratorExp { elt, generators } => {
|
||||||
for comprehension in generators {
|
for comprehension in generators {
|
||||||
visitor.visit_comprehension(comprehension)
|
visitor.visit_comprehension(comprehension)
|
||||||
}
|
}
|
||||||
visitor.visit_expr(elt, None);
|
visitor.visit_expr(elt);
|
||||||
}
|
}
|
||||||
ExprKind::Await { value } => visitor.visit_expr(value, None),
|
ExprKind::Await { value } => visitor.visit_expr(value),
|
||||||
ExprKind::Yield { value } => {
|
ExprKind::Yield { value } => {
|
||||||
if let Some(expr) = value {
|
if let Some(expr) = value {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::YieldFrom { value } => visitor.visit_expr(value, None),
|
ExprKind::YieldFrom { value } => visitor.visit_expr(value),
|
||||||
ExprKind::Compare {
|
ExprKind::Compare {
|
||||||
left,
|
left,
|
||||||
ops,
|
ops,
|
||||||
comparators,
|
comparators,
|
||||||
} => {
|
} => {
|
||||||
visitor.visit_expr(left, None);
|
visitor.visit_expr(left);
|
||||||
for cmpop in ops {
|
for cmpop in ops {
|
||||||
visitor.visit_cmpop(cmpop);
|
visitor.visit_cmpop(cmpop);
|
||||||
}
|
}
|
||||||
for expr in comparators {
|
for expr in comparators {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Call {
|
ExprKind::Call {
|
||||||
|
|
@ -335,9 +374,9 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
|
||||||
args,
|
args,
|
||||||
keywords,
|
keywords,
|
||||||
} => {
|
} => {
|
||||||
visitor.visit_expr(func, None);
|
visitor.visit_expr(func);
|
||||||
for expr in args {
|
for expr in args {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
for keyword in keywords {
|
for keyword in keywords {
|
||||||
visitor.visit_keyword(keyword);
|
visitor.visit_keyword(keyword);
|
||||||
|
|
@ -346,28 +385,28 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
|
||||||
ExprKind::FormattedValue {
|
ExprKind::FormattedValue {
|
||||||
value, format_spec, ..
|
value, format_spec, ..
|
||||||
} => {
|
} => {
|
||||||
visitor.visit_expr(value, None);
|
visitor.visit_expr(value);
|
||||||
if let Some(expr) = format_spec {
|
if let Some(expr) = format_spec {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::JoinedStr { values } => {
|
ExprKind::JoinedStr { values } => {
|
||||||
for expr in values {
|
for expr in values {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Constant { value, .. } => visitor.visit_constant(value),
|
ExprKind::Constant { value, .. } => visitor.visit_constant(value),
|
||||||
ExprKind::Attribute { value, ctx, .. } => {
|
ExprKind::Attribute { value, ctx, .. } => {
|
||||||
visitor.visit_expr(value, None);
|
visitor.visit_expr(value);
|
||||||
visitor.visit_expr_context(ctx);
|
visitor.visit_expr_context(ctx);
|
||||||
}
|
}
|
||||||
ExprKind::Subscript { value, slice, ctx } => {
|
ExprKind::Subscript { value, slice, ctx } => {
|
||||||
visitor.visit_expr(value, None);
|
visitor.visit_expr(value);
|
||||||
visitor.visit_expr(slice, None);
|
visitor.visit_expr(slice);
|
||||||
visitor.visit_expr_context(ctx);
|
visitor.visit_expr_context(ctx);
|
||||||
}
|
}
|
||||||
ExprKind::Starred { value, ctx } => {
|
ExprKind::Starred { value, ctx } => {
|
||||||
visitor.visit_expr(value, None);
|
visitor.visit_expr(value);
|
||||||
visitor.visit_expr_context(ctx);
|
visitor.visit_expr_context(ctx);
|
||||||
}
|
}
|
||||||
ExprKind::Name { ctx, .. } => {
|
ExprKind::Name { ctx, .. } => {
|
||||||
|
|
@ -375,25 +414,25 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
|
||||||
}
|
}
|
||||||
ExprKind::List { elts, ctx } => {
|
ExprKind::List { elts, ctx } => {
|
||||||
for expr in elts {
|
for expr in elts {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
visitor.visit_expr_context(ctx);
|
visitor.visit_expr_context(ctx);
|
||||||
}
|
}
|
||||||
ExprKind::Tuple { elts, ctx } => {
|
ExprKind::Tuple { elts, ctx } => {
|
||||||
for expr in elts {
|
for expr in elts {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
visitor.visit_expr_context(ctx);
|
visitor.visit_expr_context(ctx);
|
||||||
}
|
}
|
||||||
ExprKind::Slice { lower, upper, step } => {
|
ExprKind::Slice { lower, upper, step } => {
|
||||||
if let Some(expr) = lower {
|
if let Some(expr) = lower {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
if let Some(expr) = upper {
|
if let Some(expr) = upper {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
if let Some(expr) = step {
|
if let Some(expr) = step {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -411,10 +450,10 @@ pub fn walk_comprehension<'a, V: Visitor<'a> + ?Sized>(
|
||||||
visitor: &mut V,
|
visitor: &mut V,
|
||||||
comprehension: &'a Comprehension,
|
comprehension: &'a Comprehension,
|
||||||
) {
|
) {
|
||||||
visitor.visit_expr(&comprehension.target, None);
|
visitor.visit_expr(&comprehension.target);
|
||||||
visitor.visit_expr(&comprehension.iter, None);
|
visitor.visit_expr(&comprehension.iter);
|
||||||
for expr in &comprehension.ifs {
|
for expr in &comprehension.ifs {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,7 +464,7 @@ pub fn walk_excepthandler<'a, V: Visitor<'a> + ?Sized>(
|
||||||
match &excepthandler.node {
|
match &excepthandler.node {
|
||||||
ExcepthandlerKind::ExceptHandler { type_, body, .. } => {
|
ExcepthandlerKind::ExceptHandler { type_, body, .. } => {
|
||||||
if let Some(expr) = type_ {
|
if let Some(expr) = type_ {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
visitor.visit_stmt(stmt);
|
visitor.visit_stmt(stmt);
|
||||||
|
|
@ -448,13 +487,13 @@ pub fn walk_arguments<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arguments: &
|
||||||
visitor.visit_arg(arg);
|
visitor.visit_arg(arg);
|
||||||
}
|
}
|
||||||
for expr in &arguments.kw_defaults {
|
for expr in &arguments.kw_defaults {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
if let Some(arg) = &arguments.kwarg {
|
if let Some(arg) = &arguments.kwarg {
|
||||||
visitor.visit_arg(arg)
|
visitor.visit_arg(arg)
|
||||||
}
|
}
|
||||||
for expr in &arguments.defaults {
|
for expr in &arguments.defaults {
|
||||||
visitor.visit_expr(expr, None)
|
visitor.visit_expr(expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -465,20 +504,20 @@ pub fn walk_arg<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, arg: &'a Arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_keyword<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, keyword: &'a Keyword) {
|
pub fn walk_keyword<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, keyword: &'a Keyword) {
|
||||||
visitor.visit_expr(&keyword.node.value, None);
|
visitor.visit_expr(&keyword.node.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_withitem<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, withitem: &'a Withitem) {
|
pub fn walk_withitem<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, withitem: &'a Withitem) {
|
||||||
visitor.visit_expr(&withitem.context_expr, None);
|
visitor.visit_expr(&withitem.context_expr);
|
||||||
if let Some(expr) = &withitem.optional_vars {
|
if let Some(expr) = &withitem.optional_vars {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_match_case<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, match_case: &'a MatchCase) {
|
pub fn walk_match_case<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, match_case: &'a MatchCase) {
|
||||||
visitor.visit_pattern(&match_case.pattern);
|
visitor.visit_pattern(&match_case.pattern);
|
||||||
if let Some(expr) = &match_case.guard {
|
if let Some(expr) = &match_case.guard {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
for stmt in &match_case.body {
|
for stmt in &match_case.body {
|
||||||
visitor.visit_stmt(stmt);
|
visitor.visit_stmt(stmt);
|
||||||
|
|
@ -487,7 +526,7 @@ pub fn walk_match_case<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, match_case:
|
||||||
|
|
||||||
pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a Pattern) {
|
pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a Pattern) {
|
||||||
match &pattern.node {
|
match &pattern.node {
|
||||||
PatternKind::MatchValue { value } => visitor.visit_expr(value, None),
|
PatternKind::MatchValue { value } => visitor.visit_expr(value),
|
||||||
PatternKind::MatchSingleton { value } => visitor.visit_constant(value),
|
PatternKind::MatchSingleton { value } => visitor.visit_constant(value),
|
||||||
PatternKind::MatchSequence { patterns } => {
|
PatternKind::MatchSequence { patterns } => {
|
||||||
for pattern in patterns {
|
for pattern in patterns {
|
||||||
|
|
@ -496,7 +535,7 @@ pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a P
|
||||||
}
|
}
|
||||||
PatternKind::MatchMapping { keys, patterns, .. } => {
|
PatternKind::MatchMapping { keys, patterns, .. } => {
|
||||||
for expr in keys {
|
for expr in keys {
|
||||||
visitor.visit_expr(expr, None);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
for pattern in patterns {
|
for pattern in patterns {
|
||||||
visitor.visit_pattern(pattern);
|
visitor.visit_pattern(pattern);
|
||||||
|
|
@ -508,7 +547,7 @@ pub fn walk_pattern<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, pattern: &'a P
|
||||||
kwd_patterns,
|
kwd_patterns,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
visitor.visit_expr(cls, None);
|
visitor.visit_expr(cls);
|
||||||
for pattern in patterns {
|
for pattern in patterns {
|
||||||
visitor.visit_pattern(pattern);
|
visitor.visit_pattern(pattern);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue