Skip to content

Commit e13e57e

Browse files
authored
Localize cleanup for FunctionDef and ClassDef (#10837)
## Summary Came across this code while digging into the semantic model with @AlexWaygood, and found it confusing because of how it splits `push_scope` from the paired `pop_scope` (took me a few minutes to even figure out if/where we were popping the pushed scope). Since this "cleanup" is already totally split by node type, there doesn't seem to be any gain in having it as a separate "step" rather than just incorporating it into the traversal clauses for those node types. I left the equivalent cleanup step alone for the expression case, because in that case it is actually generic across several different node types, and due to the use of the common `visit_generators` utility there isn't a clear way to keep the pushes and corresponding pops localized. Feel free to just reject this if I've missed a good reason for it to stay this way! ## Test Plan Tests and clippy.
1 parent c3e28f9 commit e13e57e

File tree

1 file changed

+25
-29
lines changed
  • crates/ruff_linter/src/checkers/ast

1 file changed

+25
-29
lines changed

crates/ruff_linter/src/checkers/ast/mod.rs

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ impl<'a> Visitor<'a> for Checker<'a> {
571571
match stmt {
572572
Stmt::FunctionDef(
573573
function_def @ ast::StmtFunctionDef {
574+
name,
574575
body,
575576
parameters,
576577
decorator_list,
@@ -690,9 +691,21 @@ impl<'a> Visitor<'a> for Checker<'a> {
690691
if let Some(globals) = Globals::from_body(body) {
691692
self.semantic.set_globals(globals);
692693
}
694+
let scope_id = self.semantic.scope_id;
695+
self.analyze.scopes.push(scope_id);
696+
self.semantic.pop_scope(); // Function scope
697+
self.semantic.pop_definition();
698+
self.semantic.pop_scope(); // Type parameter scope
699+
self.add_binding(
700+
name,
701+
stmt.identifier(),
702+
BindingKind::FunctionDefinition(scope_id),
703+
BindingFlags::empty(),
704+
);
693705
}
694706
Stmt::ClassDef(
695707
class_def @ ast::StmtClassDef {
708+
name,
696709
body,
697710
arguments,
698711
decorator_list,
@@ -733,6 +746,18 @@ impl<'a> Visitor<'a> for Checker<'a> {
733746
// Set the docstring state before visiting the class body.
734747
self.docstring_state = DocstringState::Expected;
735748
self.visit_body(body);
749+
750+
let scope_id = self.semantic.scope_id;
751+
self.analyze.scopes.push(scope_id);
752+
self.semantic.pop_scope(); // Class scope
753+
self.semantic.pop_definition();
754+
self.semantic.pop_scope(); // Type parameter scope
755+
self.add_binding(
756+
name,
757+
stmt.identifier(),
758+
BindingKind::ClassDefinition(scope_id),
759+
BindingFlags::empty(),
760+
);
736761
}
737762
Stmt::TypeAlias(ast::StmtTypeAlias {
738763
range: _,
@@ -889,35 +914,6 @@ impl<'a> Visitor<'a> for Checker<'a> {
889914
};
890915

891916
// Step 3: Clean-up
892-
match stmt {
893-
Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) => {
894-
let scope_id = self.semantic.scope_id;
895-
self.analyze.scopes.push(scope_id);
896-
self.semantic.pop_scope(); // Function scope
897-
self.semantic.pop_definition();
898-
self.semantic.pop_scope(); // Type parameter scope
899-
self.add_binding(
900-
name,
901-
stmt.identifier(),
902-
BindingKind::FunctionDefinition(scope_id),
903-
BindingFlags::empty(),
904-
);
905-
}
906-
Stmt::ClassDef(ast::StmtClassDef { name, .. }) => {
907-
let scope_id = self.semantic.scope_id;
908-
self.analyze.scopes.push(scope_id);
909-
self.semantic.pop_scope(); // Class scope
910-
self.semantic.pop_definition();
911-
self.semantic.pop_scope(); // Type parameter scope
912-
self.add_binding(
913-
name,
914-
stmt.identifier(),
915-
BindingKind::ClassDefinition(scope_id),
916-
BindingFlags::empty(),
917-
);
918-
}
919-
_ => {}
920-
}
921917

922918
// Step 4: Analysis
923919
analyze::statement(stmt, self);

0 commit comments

Comments
 (0)