refactor(semantic): move function/class-specific code into specific visitors (#4278)

Instead of calling `bind_function_or_class_expression` for every scope, and then branching on the AST node kind, insert the relevant code into the visitors for functions and classes. This reduces work on all other kinds of scopes e.g. block statements.
This commit is contained in:
overlookmotel 2024-07-15 18:36:20 +00:00
parent ee16668168
commit 16698bc191

View file

@ -430,24 +430,6 @@ impl<'a> SemanticBuilder<'a> {
self.symbols.union_flag(symbol_id, SymbolFlags::Export);
}
}
fn bind_function_or_class_expression(&mut self) {
match self.nodes.kind(self.current_node_id) {
AstKind::Class(class) => {
if class.is_expression() {
// We need to bind class expression in the class scope,
class.bind(self);
}
}
AstKind::Function(func) => {
if func.is_expression() {
// We need to bind function expression in the function scope,
func.bind(self);
}
}
_ => {}
}
}
}
impl<'a> Visit<'a> for SemanticBuilder<'a> {
@ -484,10 +466,6 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
if self.unresolved_references.len() <= self.current_scope_depth {
self.unresolved_references.push(UnresolvedReferences::default());
}
if !flags.is_top() {
self.bind_function_or_class_expression();
}
}
fn leave_scope(&mut self) {
@ -570,6 +548,39 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
self.leave_node(kind);
}
fn visit_class(&mut self, class: &Class<'a>) {
let kind = AstKind::Class(self.alloc(class));
self.enter_node(kind);
self.visit_decorators(&class.decorators);
if let Some(id) = &class.id {
self.visit_binding_identifier(id);
}
self.enter_scope(ScopeFlags::StrictMode, &class.scope_id);
if class.is_expression() {
// We need to bind class expression in the class scope
class.bind(self);
}
if let Some(type_parameters) = &class.type_parameters {
self.visit_ts_type_parameter_declaration(type_parameters);
}
if let Some(super_class) = &class.super_class {
self.visit_class_heritage(super_class);
}
if let Some(super_type_parameters) = &class.super_type_parameters {
self.visit_ts_type_parameter_instantiation(super_type_parameters);
}
if let Some(implements) = &class.implements {
self.visit_ts_class_implementses(implements);
}
self.visit_class_body(&class.body);
self.leave_scope();
self.leave_node(kind);
}
fn visit_continue_statement(&mut self, stmt: &ContinueStatement<'a>) {
let kind = AstKind::ContinueStatement(self.alloc(stmt));
self.enter_node(kind);
@ -1458,6 +1469,11 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
&func.scope_id,
);
if func.is_expression() {
// We need to bind function expression in the function scope
func.bind(self);
}
if let Some(id) = &func.id {
self.visit_binding_identifier(id);
}