From 16698bc1913cbf44ac9df19a4bdbee62a1569cc7 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Mon, 15 Jul 2024 18:36:20 +0000 Subject: [PATCH] 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. --- crates/oxc_semantic/src/builder.rs | 60 +++++++++++++++++++----------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 83d643ef3..c16f5bb9b 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -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); }