Bind excepthandler names (#62)

This commit is contained in:
Charlie Marsh 2022-08-31 18:16:37 -04:00 committed by GitHub
parent 0b9e3f8b47
commit 3f739214b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 65 deletions

View File

@ -40,9 +40,7 @@ class Class:
# TODO(charlie): This should be recognized as a defined variable. # TODO(charlie): This should be recognized as a defined variable.
Class # noqa: F821 Class # noqa: F821
try: try:
x = 1 / 0 x = 1 / 0
except Exception as e: except Exception as e:
# TODO(charlie): This should be recognized as a defined variable. print(e)
print(e) # noqa: F821

View File

@ -2,7 +2,8 @@ use std::collections::{BTreeMap, BTreeSet};
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use rustpython_parser::ast::{ use rustpython_parser::ast::{
Arg, Arguments, Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind, Suite, Arg, Arguments, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind,
Location, Stmt, StmtKind, Suite,
}; };
use rustpython_parser::parser; use rustpython_parser::parser;
@ -11,7 +12,7 @@ use crate::check_ast::ScopeKind::{Class, Function, Generator, Module};
use crate::checks::{Check, CheckCode, CheckKind}; use crate::checks::{Check, CheckCode, CheckKind};
use crate::settings::Settings; use crate::settings::Settings;
use crate::visitor; use crate::visitor;
use crate::visitor::Visitor; use crate::visitor::{walk_excepthandler, Visitor};
fn id() -> usize { fn id() -> usize {
static COUNTER: AtomicUsize = AtomicUsize::new(1); static COUNTER: AtomicUsize = AtomicUsize::new(1);
@ -301,7 +302,6 @@ impl Visitor for Checker<'_> {
); );
} }
} }
fn visit_annotation(&mut self, expr: &Expr) { fn visit_annotation(&mut self, expr: &Expr) {
let initial = self.in_annotation; let initial = self.in_annotation;
self.in_annotation = true; self.in_annotation = true;
@ -365,6 +365,39 @@ impl Visitor for Checker<'_> {
}; };
} }
fn visit_excepthandler(&mut self, excepthandler: &Excepthandler) {
match &excepthandler.node {
ExcepthandlerKind::ExceptHandler { name, .. } => match name {
Some(name) => {
let scope = self.scopes.last().expect("No current scope found.");
if scope.values.contains_key(name) {
self.handle_node_store(&Expr::new(
excepthandler.location,
ExprKind::Name {
id: name.to_string(),
ctx: ExprContext::Store,
},
));
}
self.handle_node_store(&Expr::new(
excepthandler.location,
ExprKind::Name {
id: name.to_string(),
ctx: ExprContext::Store,
},
));
walk_excepthandler(self, excepthandler);
let scope = self.scopes.last_mut().expect("No current scope found.");
scope.values.remove(name);
}
None => walk_excepthandler(self, excepthandler),
},
}
}
fn visit_arguments(&mut self, arguments: &Arguments) { fn visit_arguments(&mut self, arguments: &Arguments) {
if self if self
.settings .settings

View File

@ -14,9 +14,6 @@ pub trait Visitor {
fn visit_expr(&mut self, expr: &Expr) { fn visit_expr(&mut self, expr: &Expr) {
walk_expr(self, expr); walk_expr(self, expr);
} }
fn visit_ident(&mut self, ident: &str) {
walk_ident(self, ident);
}
fn visit_constant(&mut self, constant: &Constant) { fn visit_constant(&mut self, constant: &Constant) {
walk_constant(self, constant); walk_constant(self, constant);
} }
@ -67,53 +64,48 @@ pub trait Visitor {
pub fn walk_stmt<V: Visitor + ?Sized>(visitor: &mut V, stmt: &Stmt) { pub fn walk_stmt<V: Visitor + ?Sized>(visitor: &mut V, stmt: &Stmt) {
match &stmt.node { match &stmt.node {
StmtKind::FunctionDef { StmtKind::FunctionDef {
name,
args, args,
body, body,
decorator_list, decorator_list,
returns, returns,
.. ..
} => { } => {
visitor.visit_ident(name);
visitor.visit_arguments(args); visitor.visit_arguments(args);
for stmt in body {
visitor.visit_stmt(stmt)
}
for expr in decorator_list { for expr in decorator_list {
visitor.visit_expr(expr) visitor.visit_expr(expr)
} }
for expr in returns { for expr in returns {
visitor.visit_annotation(expr); visitor.visit_annotation(expr);
} }
for stmt in body {
visitor.visit_stmt(stmt)
}
} }
StmtKind::AsyncFunctionDef { StmtKind::AsyncFunctionDef {
name,
args, args,
body, body,
decorator_list, decorator_list,
returns, returns,
.. ..
} => { } => {
visitor.visit_ident(name);
visitor.visit_arguments(args); visitor.visit_arguments(args);
for stmt in body {
visitor.visit_stmt(stmt)
}
for expr in decorator_list { for expr in decorator_list {
visitor.visit_expr(expr) visitor.visit_expr(expr)
} }
for expr in returns { for expr in returns {
visitor.visit_annotation(expr); visitor.visit_annotation(expr);
} }
for stmt in body {
visitor.visit_stmt(stmt)
}
} }
StmtKind::ClassDef { StmtKind::ClassDef {
name,
bases, bases,
keywords, keywords,
body, body,
decorator_list, decorator_list,
..
} => { } => {
visitor.visit_ident(name);
for expr in bases { for expr in bases {
visitor.visit_expr(expr) visitor.visit_expr(expr)
} }
@ -271,24 +263,13 @@ pub fn walk_stmt<V: Visitor + ?Sized>(visitor: &mut V, stmt: &Stmt) {
visitor.visit_alias(alias); visitor.visit_alias(alias);
} }
} }
StmtKind::ImportFrom { module, names, .. } => { StmtKind::ImportFrom { names, .. } => {
if let Some(ident) = module {
visitor.visit_ident(ident);
}
for alias in names { for alias in names {
visitor.visit_alias(alias); visitor.visit_alias(alias);
} }
} }
StmtKind::Global { names } => { StmtKind::Global { .. } => {}
for ident in names { StmtKind::Nonlocal { .. } => {}
visitor.visit_ident(ident)
}
}
StmtKind::Nonlocal { names } => {
for ident in names {
visitor.visit_ident(ident)
}
}
StmtKind::Expr { value } => visitor.visit_expr(value), StmtKind::Expr { value } => visitor.visit_expr(value),
StmtKind::Pass => {} StmtKind::Pass => {}
StmtKind::Break => {} StmtKind::Break => {}
@ -428,8 +409,7 @@ pub fn walk_expr<V: Visitor + ?Sized>(visitor: &mut V, expr: &Expr) {
visitor.visit_expr(value); visitor.visit_expr(value);
visitor.visit_expr_context(ctx); visitor.visit_expr_context(ctx);
} }
ExprKind::Name { id, ctx } => { ExprKind::Name { ctx, .. } => {
visitor.visit_ident(id);
visitor.visit_expr_context(ctx); visitor.visit_expr_context(ctx);
} }
ExprKind::List { elts, ctx } => { ExprKind::List { elts, ctx } => {
@ -476,13 +456,10 @@ pub fn walk_comprehension<V: Visitor + ?Sized>(visitor: &mut V, comprehension: &
pub fn walk_excepthandler<V: Visitor + ?Sized>(visitor: &mut V, excepthandler: &Excepthandler) { pub fn walk_excepthandler<V: Visitor + ?Sized>(visitor: &mut V, excepthandler: &Excepthandler) {
match &excepthandler.node { match &excepthandler.node {
ExcepthandlerKind::ExceptHandler { type_, name, body } => { ExcepthandlerKind::ExceptHandler { type_, body, .. } => {
if let Some(expr) = type_ { if let Some(expr) = type_ {
visitor.visit_expr(expr); visitor.visit_expr(expr);
} }
if let Some(ident) = name {
visitor.visit_ident(ident);
}
for stmt in body { for stmt in body {
visitor.visit_stmt(stmt); visitor.visit_stmt(stmt);
} }
@ -550,50 +527,34 @@ pub fn walk_pattern<V: Visitor + ?Sized>(visitor: &mut V, pattern: &Pattern) {
visitor.visit_pattern(pattern) visitor.visit_pattern(pattern)
} }
} }
PatternKind::MatchMapping { PatternKind::MatchMapping { keys, patterns, .. } => {
keys,
patterns,
rest,
} => {
for expr in keys { for expr in keys {
visitor.visit_expr(expr); visitor.visit_expr(expr);
} }
for pattern in patterns { for pattern in patterns {
visitor.visit_pattern(pattern); visitor.visit_pattern(pattern);
} }
if let Some(ident) = rest {
visitor.visit_ident(ident);
}
} }
PatternKind::MatchClass { PatternKind::MatchClass {
cls, cls,
patterns, patterns,
kwd_attrs,
kwd_patterns, kwd_patterns,
..
} => { } => {
visitor.visit_expr(cls); visitor.visit_expr(cls);
for pattern in patterns { for pattern in patterns {
visitor.visit_pattern(pattern); visitor.visit_pattern(pattern);
} }
for ident in kwd_attrs {
visitor.visit_ident(ident);
}
for pattern in kwd_patterns { for pattern in kwd_patterns {
visitor.visit_pattern(pattern); visitor.visit_pattern(pattern);
} }
} }
PatternKind::MatchStar { name } => { PatternKind::MatchStar { .. } => {}
if let Some(ident) = name { PatternKind::MatchAs { pattern, .. } => {
visitor.visit_ident(ident)
}
}
PatternKind::MatchAs { pattern, name } => {
if let Some(pattern) = pattern { if let Some(pattern) = pattern {
visitor.visit_pattern(pattern) visitor.visit_pattern(pattern)
} }
if let Some(ident) = name {
visitor.visit_ident(ident)
}
} }
PatternKind::MatchOr { patterns } => { PatternKind::MatchOr { patterns } => {
for pattern in patterns { for pattern in patterns {
@ -604,22 +565,25 @@ pub fn walk_pattern<V: Visitor + ?Sized>(visitor: &mut V, pattern: &Pattern) {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
pub fn walk_ident<V: Visitor + ?Sized>(visitor: &mut V, ident: &str) {} #[inline(always)]
#[allow(unused_variables)]
pub fn walk_expr_context<V: Visitor + ?Sized>(visitor: &mut V, expr_context: &ExprContext) {} pub fn walk_expr_context<V: Visitor + ?Sized>(visitor: &mut V, expr_context: &ExprContext) {}
#[allow(unused_variables)] #[allow(unused_variables)]
#[inline(always)]
pub fn walk_boolop<V: Visitor + ?Sized>(visitor: &mut V, boolop: &Boolop) {} pub fn walk_boolop<V: Visitor + ?Sized>(visitor: &mut V, boolop: &Boolop) {}
#[allow(unused_variables)] #[allow(unused_variables)]
#[inline(always)]
pub fn walk_operator<V: Visitor + ?Sized>(visitor: &mut V, operator: &Operator) {} pub fn walk_operator<V: Visitor + ?Sized>(visitor: &mut V, operator: &Operator) {}
#[allow(unused_variables)] #[allow(unused_variables)]
#[inline(always)]
pub fn walk_unaryop<V: Visitor + ?Sized>(visitor: &mut V, unaryop: &Unaryop) {} pub fn walk_unaryop<V: Visitor + ?Sized>(visitor: &mut V, unaryop: &Unaryop) {}
#[allow(unused_variables)] #[allow(unused_variables)]
#[inline(always)]
pub fn walk_cmpop<V: Visitor + ?Sized>(visitor: &mut V, cmpop: &Cmpop) {} pub fn walk_cmpop<V: Visitor + ?Sized>(visitor: &mut V, cmpop: &Cmpop) {}
#[allow(unused_variables)] #[allow(unused_variables)]
#[inline(always)]
pub fn walk_alias<V: Visitor + ?Sized>(visitor: &mut V, alias: &Alias) {} pub fn walk_alias<V: Visitor + ?Sized>(visitor: &mut V, alias: &Alias) {}