diff --git a/crates/oxc_ast/src/ast_kind.rs b/crates/oxc_ast/src/ast_kind.rs index 2403735cc..f7a2d52d8 100644 --- a/crates/oxc_ast/src/ast_kind.rs +++ b/crates/oxc_ast/src/ast_kind.rs @@ -109,6 +109,10 @@ pub enum AstKind<'a> { Decorator(&'a Decorator<'a>), ModuleDeclaration(&'a ModuleDeclaration<'a>), + ImportDeclaration(&'a ImportDeclaration<'a>), + ImportSpecifier(&'a ImportSpecifier), + ImportDefaultSpecifier(&'a ImportDefaultSpecifier), + ImportNamespaceSpecifier(&'a ImportNamespaceSpecifier), // JSX // Please make sure to add these to `is_jsx` below. @@ -422,6 +426,10 @@ impl<'a> GetSpan for AstKind<'a> { Self::Decorator(x) => x.span, Self::ModuleDeclaration(x) => x.span(), + Self::ImportDeclaration(x) => x.span, + Self::ImportSpecifier(x) => x.span, + Self::ImportDefaultSpecifier(x) => x.span, + Self::ImportNamespaceSpecifier(x) => x.span, Self::JSXOpeningElement(x) => x.span, Self::JSXClosingElement(x) => x.span, @@ -603,6 +611,10 @@ impl<'a> AstKind<'a> { Self::Decorator(_) => "Decorator".into(), Self::ModuleDeclaration(_) => "ModuleDeclaration".into(), + Self::ImportDeclaration(_) => "ImportDeclaration".into(), + Self::ImportSpecifier(_) => "ImportSpecifier".into(), + Self::ImportDefaultSpecifier(_) => "ImportDefaultSpecifier".into(), + Self::ImportNamespaceSpecifier(_) => "ImportNamespaceSpecifier".into(), Self::JSXOpeningElement(_) => "JSXOpeningElement".into(), Self::JSXClosingElement(_) => "JSXClosingElement".into(), Self::JSXElementName(_) => "JSXElementName".into(), diff --git a/crates/oxc_ast/src/visit.rs b/crates/oxc_ast/src/visit.rs index cb8fed207..183212729 100644 --- a/crates/oxc_ast/src/visit.rs +++ b/crates/oxc_ast/src/visit.rs @@ -1334,6 +1334,8 @@ pub trait Visit<'a>: Sized { } fn visit_import_declaration(&mut self, decl: &ImportDeclaration<'a>) { + let kind = AstKind::ImportDeclaration(self.alloc(decl)); + self.enter_node(kind); if let Some(specifiers) = &decl.specifiers { for specifier in specifiers { self.visit_import_declaration_specifier(specifier); @@ -1341,6 +1343,7 @@ pub trait Visit<'a>: Sized { } self.visit_string_literal(&decl.source); // TODO: assertions + self.leave_node(kind); } fn visit_import_declaration_specifier(&mut self, specifier: &ImportDeclarationSpecifier) { @@ -1358,16 +1361,25 @@ pub trait Visit<'a>: Sized { } fn visit_import_specifier(&mut self, specifier: &ImportSpecifier) { + let kind = AstKind::ImportSpecifier(self.alloc(specifier)); + self.enter_node(kind); // TODO: imported self.visit_binding_identifier(&specifier.local); + self.leave_node(kind); } fn visit_import_default_specifier(&mut self, specifier: &ImportDefaultSpecifier) { + let kind = AstKind::ImportDefaultSpecifier(self.alloc(specifier)); + self.enter_node(kind); self.visit_binding_identifier(&specifier.local); + self.leave_node(kind); } fn visit_import_name_specifier(&mut self, specifier: &ImportNamespaceSpecifier) { + let kind = AstKind::ImportNamespaceSpecifier(self.alloc(specifier)); + self.enter_node(kind); self.visit_binding_identifier(&specifier.local); + self.leave_node(kind); } fn visit_export_all_declaration(&mut self, _decl: &ExportAllDeclaration<'a>) {} diff --git a/crates/oxc_ast/src/visit_mut.rs b/crates/oxc_ast/src/visit_mut.rs index 333901214..5437002bd 100644 --- a/crates/oxc_ast/src/visit_mut.rs +++ b/crates/oxc_ast/src/visit_mut.rs @@ -1333,13 +1333,16 @@ pub trait VisitMut<'a>: Sized { } fn visit_import_declaration(&mut self, decl: &mut ImportDeclaration<'a>) { + let kind = AstKind::ImportDeclaration(self.alloc(decl)); + self.enter_node(kind); if let Some(specifiers) = &mut decl.specifiers { for specifier in specifiers.iter_mut() { self.visit_import_declaration_specifier(specifier); } } - // TODO: source + self.visit_string_literal(&mut decl.source); // TODO: assertions + self.leave_node(kind); } fn visit_import_declaration_specifier(&mut self, specifier: &mut ImportDeclarationSpecifier) { @@ -1357,16 +1360,25 @@ pub trait VisitMut<'a>: Sized { } fn visit_import_specifier(&mut self, specifier: &mut ImportSpecifier) { + let kind = AstKind::ImportSpecifier(self.alloc(specifier)); + self.enter_node(kind); // TODO: imported self.visit_binding_identifier(&mut specifier.local); + self.leave_node(kind); } fn visit_import_default_specifier(&mut self, specifier: &mut ImportDefaultSpecifier) { + let kind = AstKind::ImportDefaultSpecifier(self.alloc(specifier)); + self.enter_node(kind); self.visit_binding_identifier(&mut specifier.local); + self.leave_node(kind); } fn visit_import_name_specifier(&mut self, specifier: &mut ImportNamespaceSpecifier) { + let kind = AstKind::ImportNamespaceSpecifier(self.alloc(specifier)); + self.enter_node(kind); self.visit_binding_identifier(&mut specifier.local); + self.leave_node(kind); } fn visit_export_all_declaration(&mut self, _decl: &mut ExportAllDeclaration<'a>) {} diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index eeb1b07e3..8d64f4a95 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -288,6 +288,34 @@ impl<'a> Binder for ModuleDeclaration<'a> { } } +fn declare_symbol_for_import_specifier(ident: &BindingIdentifier, builder: &mut SemanticBuilder) { + let symbol_id = builder.declare_symbol( + ident.span, + &ident.name, + SymbolFlags::ImportBinding, + SymbolFlags::ImportBindingExcludes, + ); + ident.symbol_id.set(Some(symbol_id)); +} + +impl Binder for ImportSpecifier { + fn bind(&self, builder: &mut SemanticBuilder) { + declare_symbol_for_import_specifier(&self.local, builder); + } +} + +impl Binder for ImportDefaultSpecifier { + fn bind(&self, builder: &mut SemanticBuilder) { + declare_symbol_for_import_specifier(&self.local, builder); + } +} + +impl Binder for ImportNamespaceSpecifier { + fn bind(&self, builder: &mut SemanticBuilder) { + declare_symbol_for_import_specifier(&self.local, builder); + } +} + impl<'a> Binder for TSTypeAliasDeclaration<'a> { fn bind(&self, builder: &mut SemanticBuilder) { let symbol_id = builder.declare_symbol(