From 4c2e2bdf6136c7051629070b2fcc7c8a4f62a153 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Mon, 26 Feb 2024 15:48:05 +0800 Subject: [PATCH] fix(semantic): add export symbol flag to identifiers in export declarations (#2508) Related PR: #2335 --- crates/oxc_semantic/src/builder.rs | 24 +++++++++++++++++++++++- crates/oxc_semantic/tests/symbols.rs | 17 +++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index e444f1fbe..15d1fba9d 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -6,7 +6,10 @@ use std::{cell::RefCell, path::PathBuf, rc::Rc, sync::Arc}; use oxc_ast::{ast::*, AstKind, Trivias, TriviasMap, Visit}; use oxc_diagnostics::Error; use oxc_span::{Atom, SourceType, Span}; -use oxc_syntax::{module_record::ModuleRecord, operator::AssignmentOperator}; +use oxc_syntax::{ + module_record::{ExportLocalName, ModuleRecord}, + operator::AssignmentOperator, +}; use crate::{ binder::Binder, @@ -338,6 +341,22 @@ impl<'a> SemanticBuilder<'a> { pub fn add_redeclared_variables(&mut self, variable: VariableInfo) { self.redeclare_variables.variables.push(variable); } + + fn add_export_flag_for_export_identifier(&mut self) { + self.module_record.local_export_entries.iter().for_each(|entry| match &entry.local_name { + ExportLocalName::Name(name_span) => { + if let Some(symbol_id) = self.scope.get_root_binding(name_span.name()) { + self.symbols.union_flag(symbol_id, SymbolFlags::Export); + } + } + ExportLocalName::Default(span) => { + if let Some(symbol_id) = self.symbols.get_symbol_id_from_span(span) { + self.symbols.union_flag(symbol_id, SymbolFlags::Export); + } + } + ExportLocalName::Null => {} + }); + } } impl<'a> Visit<'a> for SemanticBuilder<'a> { @@ -1766,6 +1785,9 @@ impl<'a> SemanticBuilder<'a> { #[allow(clippy::single_match)] fn leave_kind(&mut self, kind: AstKind<'a>) { match kind { + AstKind::Program(_) => { + self.add_export_flag_for_export_identifier(); + } AstKind::Class(_) => { self.current_node_flags -= NodeFlags::Class; self.class_table_builder.pop_class(); diff --git a/crates/oxc_semantic/tests/symbols.rs b/crates/oxc_semantic/tests/symbols.rs index b6728e26c..15d50465d 100644 --- a/crates/oxc_semantic/tests/symbols.rs +++ b/crates/oxc_semantic/tests/symbols.rs @@ -86,3 +86,20 @@ fn test_types_simple() { .has_number_of_references(1) .test(); } + +#[test] +fn test_export_flag() { + let tester = SemanticTester::js( + " + const a = 1; + export { a, b, c as d }; + class b {} + export default c; + function c() {} + ", + ); + + tester.has_root_symbol("a").contains_flags(SymbolFlags::Export).test(); + tester.has_root_symbol("b").contains_flags(SymbolFlags::Export).test(); + tester.has_root_symbol("c").contains_flags(SymbolFlags::Export).test(); +}