Avoid putting decorators in the function scope (#86)

This commit is contained in:
Charlie Marsh 2022-09-02 09:13:06 -04:00 committed by GitHub
parent bf4722a62f
commit c0131e65e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 54 deletions

View File

@ -15,3 +15,13 @@ def baz():
global my_var global my_var
global my_dict global my_dict
my_dict[my_var] += 1 my_dict[my_var] += 1
def dec(x):
return x
@dec
def f():
dec = 1
return dec

View File

@ -88,6 +88,7 @@ impl Checker<'_> {
impl Visitor for Checker<'_> { impl Visitor for Checker<'_> {
fn visit_stmt(&mut self, stmt: &Stmt) { fn visit_stmt(&mut self, stmt: &Stmt) {
println!("stmt: {:?}", stmt);
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.
@ -109,18 +110,24 @@ impl Visitor for Checker<'_> {
} }
} }
} }
StmtKind::FunctionDef { name, .. } => { StmtKind::FunctionDef {
self.add_binding( name,
name.to_string(), decorator_list,
Binding { returns,
kind: BindingKind::Definition, ..
used: None,
location: stmt.location,
},
);
self.push_scope(Scope::new(Function));
} }
StmtKind::AsyncFunctionDef { name, .. } => { | StmtKind::AsyncFunctionDef {
name,
decorator_list,
returns,
..
} => {
for expr in decorator_list {
self.visit_expr(expr);
}
for expr in returns {
self.visit_annotation(expr);
}
self.add_binding( self.add_binding(
name.to_string(), name.to_string(),
Binding { Binding {
@ -150,7 +157,23 @@ impl Visitor for Checker<'_> {
} }
} }
} }
StmtKind::ClassDef { .. } => self.push_scope(Scope::new(Class)), StmtKind::ClassDef {
bases,
keywords,
decorator_list,
..
} => {
for expr in bases {
self.visit_expr(expr)
}
for keyword in keywords {
self.visit_keyword(keyword)
}
for expr in decorator_list {
self.visit_expr(expr)
}
self.push_scope(Scope::new(Class))
}
StmtKind::Import { names } => { StmtKind::Import { names } => {
for alias in names { for alias in names {
if alias.node.name.contains('.') && alias.node.asname.is_none() { if alias.node.name.contains('.') && alias.node.asname.is_none() {

View File

@ -63,61 +63,22 @@ 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 { args, body, .. } => {
args,
body,
decorator_list,
returns,
..
} => {
visitor.visit_arguments(args); visitor.visit_arguments(args);
for expr in decorator_list {
visitor.visit_expr(expr)
}
for expr in returns {
visitor.visit_annotation(expr);
}
for stmt in body { for stmt in body {
visitor.visit_stmt(stmt) visitor.visit_stmt(stmt)
} }
} }
StmtKind::AsyncFunctionDef { StmtKind::AsyncFunctionDef { args, body, .. } => {
args,
body,
decorator_list,
returns,
..
} => {
visitor.visit_arguments(args); visitor.visit_arguments(args);
for expr in decorator_list {
visitor.visit_expr(expr)
}
for expr in returns {
visitor.visit_annotation(expr);
}
for stmt in body { for stmt in body {
visitor.visit_stmt(stmt) visitor.visit_stmt(stmt)
} }
} }
StmtKind::ClassDef { StmtKind::ClassDef { body, .. } => {
bases,
keywords,
body,
decorator_list,
..
} => {
for expr in bases {
visitor.visit_expr(expr)
}
for keyword in keywords {
visitor.visit_keyword(keyword)
}
for stmt in body { for stmt in body {
visitor.visit_stmt(stmt) visitor.visit_stmt(stmt)
} }
for expr in decorator_list {
visitor.visit_expr(expr)
}
} }
StmtKind::Return { value } => { StmtKind::Return { value } => {
if let Some(expr) = value { if let Some(expr) = value {