Parse function annotations within the ClassDef scope (#144)

This commit is contained in:
Charlie Marsh 2022-09-10 15:20:39 -04:00 committed by GitHub
parent c247730bf5
commit dfd8a4158d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 4 deletions

View File

@ -65,3 +65,15 @@ from typing import List, TypedDict
class Item(TypedDict): class Item(TypedDict):
nodes: List[TypedDict("Node", {"name": str})] nodes: List[TypedDict("Node", {"name": str})]
from enum import Enum
class Ticket:
class Status(Enum):
OPEN = "OPEN"
CLOSED = "CLOSED"
def set_status(self, status: Status):
self.status = status

View File

@ -126,20 +126,53 @@ where
name, name,
decorator_list, decorator_list,
returns, returns,
args,
.. ..
} }
| StmtKind::AsyncFunctionDef { | StmtKind::AsyncFunctionDef {
name, name,
decorator_list, decorator_list,
returns, returns,
args,
.. ..
} => { } => {
for expr in decorator_list { for expr in decorator_list {
self.visit_expr(expr); self.visit_expr(expr);
} }
for arg in &args.posonlyargs {
if let Some(expr) = &arg.node.annotation {
self.visit_annotation(expr);
}
}
for arg in &args.args {
if let Some(expr) = &arg.node.annotation {
self.visit_annotation(expr);
}
}
if let Some(arg) = &args.vararg {
if let Some(expr) = &arg.node.annotation {
self.visit_annotation(expr);
}
}
for arg in &args.kwonlyargs {
if let Some(expr) = &arg.node.annotation {
self.visit_annotation(expr);
}
}
if let Some(arg) = &args.kwarg {
if let Some(expr) = &arg.node.annotation {
self.visit_annotation(expr);
}
}
for expr in returns { for expr in returns {
self.visit_annotation(expr); self.visit_annotation(expr);
} }
for expr in &args.kw_defaults {
self.visit_expr(expr);
}
for expr in &args.defaults {
self.visit_expr(expr);
}
self.add_binding( self.add_binding(
name.to_string(), name.to_string(),
Binding { Binding {
@ -758,10 +791,27 @@ where
self.checks self.checks
.extend(checks::check_duplicate_arguments(arguments)); .extend(checks::check_duplicate_arguments(arguments));
} }
visitor::walk_arguments(self, arguments);
// Bind, but intentionally avoid walking default expressions, as we handle them upstream.
for arg in &arguments.posonlyargs {
self.visit_arg(arg);
}
for arg in &arguments.args {
self.visit_arg(arg);
}
if let Some(arg) = &arguments.vararg {
self.visit_arg(arg);
}
for arg in &arguments.kwonlyargs {
self.visit_arg(arg);
}
if let Some(arg) = &arguments.kwarg {
self.visit_arg(arg);
}
} }
fn visit_arg(&mut self, arg: &'b Arg) { fn visit_arg(&mut self, arg: &'b Arg) {
// Bind, but intentionally avoid walking the annotation, as we handle it upstream.
self.add_binding( self.add_binding(
arg.node.arg.to_string(), arg.node.arg.to_string(),
Binding { Binding {
@ -770,7 +820,6 @@ where
location: arg.location, location: arg.location,
}, },
); );
visitor::walk_arg(self, arg);
} }
} }
@ -984,8 +1033,9 @@ impl<'a> Checker<'a> {
_ => {} _ => {}
} }
let scope = &self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
if self.settings.select.contains(&CheckCode::F841) { if self.settings.select.contains(&CheckCode::F841) {
let scope =
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
self.checks.extend(checks::check_unused_variables(scope)); self.checks.extend(checks::check_unused_variables(scope));
} }
@ -1006,8 +1056,9 @@ impl<'a> Checker<'a> {
self.visit_expr(body); self.visit_expr(body);
} }
let scope = &self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
if self.settings.select.contains(&CheckCode::F841) { if self.settings.select.contains(&CheckCode::F841) {
let scope =
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
self.checks.extend(checks::check_unused_variables(scope)); self.checks.extend(checks::check_unused_variables(scope));
} }