mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(ast)!: add IdentifierReference to ExportSpecifier (#3820)
closes #3795 closes #3796
This commit is contained in:
parent
99a40ce6ac
commit
445603444f
21 changed files with 163 additions and 118 deletions
|
|
@ -1895,7 +1895,7 @@ pub struct ExportDefaultDeclaration<'a> {
|
|||
#[cfg_attr(feature = "serialize", serde(flatten))]
|
||||
pub span: Span,
|
||||
pub declaration: ExportDefaultDeclarationKind<'a>,
|
||||
pub exported: ModuleExportName<'a>, // `default`
|
||||
pub exported: ModuleExportName<'a>, // the `default` Keyword
|
||||
}
|
||||
|
||||
#[visited_node]
|
||||
|
|
@ -1955,6 +1955,8 @@ pub enum ExportDefaultDeclarationKind<'a> {
|
|||
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
|
||||
#[cfg_attr(feature = "serialize", serde(untagged))]
|
||||
pub enum ModuleExportName<'a> {
|
||||
Identifier(IdentifierName<'a>),
|
||||
IdentifierName(IdentifierName<'a>),
|
||||
/// For `local` in `ExportSpecifier`: `foo` in `export { foo }`
|
||||
IdentifierReference(IdentifierReference<'a>),
|
||||
StringLiteral(StringLiteral<'a>),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1447,7 +1447,8 @@ impl<'a> ExportDefaultDeclarationKind<'a> {
|
|||
impl<'a> fmt::Display for ModuleExportName<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let s = match self {
|
||||
Self::Identifier(identifier) => identifier.name.to_string(),
|
||||
Self::IdentifierName(identifier) => identifier.name.to_string(),
|
||||
Self::IdentifierReference(identifier) => identifier.name.to_string(),
|
||||
Self::StringLiteral(literal) => format!(r#""{}""#, literal.value),
|
||||
};
|
||||
write!(f, "{s}")
|
||||
|
|
@ -1457,8 +1458,17 @@ impl<'a> fmt::Display for ModuleExportName<'a> {
|
|||
impl<'a> ModuleExportName<'a> {
|
||||
pub fn name(&self) -> Atom<'a> {
|
||||
match self {
|
||||
Self::Identifier(identifier) => identifier.name.clone(),
|
||||
Self::IdentifierName(identifier) => identifier.name.clone(),
|
||||
Self::IdentifierReference(identifier) => identifier.name.clone(),
|
||||
Self::StringLiteral(literal) => literal.value.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn identifier_name(&self) -> Option<Atom<'a>> {
|
||||
match self {
|
||||
Self::IdentifierName(identifier) => Some(identifier.name.clone()),
|
||||
Self::IdentifierReference(identifier) => Some(identifier.name.clone()),
|
||||
Self::StringLiteral(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ ast_kinds! {
|
|||
ModuleDeclaration(&'a ModuleDeclaration<'a>),
|
||||
ImportDeclaration(&'a ImportDeclaration<'a>),
|
||||
ImportSpecifier(&'a ImportSpecifier<'a>),
|
||||
ExportSpecifier(&'a ExportSpecifier<'a>),
|
||||
ImportDefaultSpecifier(&'a ImportDefaultSpecifier<'a>),
|
||||
ImportNamespaceSpecifier(&'a ImportNamespaceSpecifier<'a>),
|
||||
ExportDefaultDeclaration(&'a ExportDefaultDeclaration<'a>),
|
||||
|
|
@ -469,6 +470,7 @@ impl<'a> GetSpan for AstKind<'a> {
|
|||
Self::ModuleDeclaration(x) => x.span(),
|
||||
Self::ImportDeclaration(x) => x.span,
|
||||
Self::ImportSpecifier(x) => x.span,
|
||||
Self::ExportSpecifier(x) => x.span,
|
||||
Self::ImportDefaultSpecifier(x) => x.span,
|
||||
Self::ImportNamespaceSpecifier(x) => x.span,
|
||||
Self::ExportDefaultDeclaration(x) => x.span,
|
||||
|
|
@ -675,6 +677,7 @@ impl<'a> AstKind<'a> {
|
|||
Self::ModuleDeclaration(_) => "ModuleDeclaration".into(),
|
||||
Self::ImportDeclaration(_) => "ImportDeclaration".into(),
|
||||
Self::ImportSpecifier(_) => "ImportSpecifier".into(),
|
||||
Self::ExportSpecifier(_) => "ExportSpecifier".into(),
|
||||
Self::ImportDefaultSpecifier(_) => "ImportDefaultSpecifier".into(),
|
||||
Self::ImportNamespaceSpecifier(_) => "ImportNamespaceSpecifier".into(),
|
||||
Self::ExportDefaultDeclaration(_) => "ExportDefaultDeclaration".into(),
|
||||
|
|
|
|||
|
|
@ -208,7 +208,8 @@ impl<'a> GetSpan for ImportAttributeKey<'a> {
|
|||
impl<'a> GetSpan for ModuleExportName<'a> {
|
||||
fn span(&self) -> Span {
|
||||
match self {
|
||||
Self::Identifier(identifier) => identifier.span,
|
||||
Self::IdentifierName(identifier) => identifier.span,
|
||||
Self::IdentifierReference(identifier) => identifier.span,
|
||||
Self::StringLiteral(literal) => literal.span,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -617,6 +617,14 @@ pub trait Visit<'a>: Sized {
|
|||
walk_export_named_declaration(self, decl);
|
||||
}
|
||||
|
||||
fn visit_export_specifier(&mut self, specifier: &ExportSpecifier<'a>) {
|
||||
walk_export_specifier(self, specifier);
|
||||
}
|
||||
|
||||
fn visit_module_export_name(&mut self, name: &ModuleExportName<'a>) {
|
||||
walk_module_export_name(self, name);
|
||||
}
|
||||
|
||||
fn visit_enum_member(&mut self, member: &TSEnumMember<'a>) {
|
||||
walk_enum_member(self, member);
|
||||
}
|
||||
|
|
@ -2433,7 +2441,7 @@ pub mod walk {
|
|||
) {
|
||||
let kind = AstKind::ImportSpecifier(visitor.alloc(specifier));
|
||||
visitor.enter_node(kind);
|
||||
// TODO: imported
|
||||
visitor.visit_module_export_name(&specifier.imported);
|
||||
visitor.visit_binding_identifier(&specifier.local);
|
||||
visitor.leave_node(kind);
|
||||
}
|
||||
|
|
@ -2496,12 +2504,36 @@ pub mod walk {
|
|||
if let Some(decl) = &decl.declaration {
|
||||
visitor.visit_declaration(decl);
|
||||
}
|
||||
for export_specifier in &decl.specifiers {
|
||||
visitor.visit_export_specifier(export_specifier);
|
||||
}
|
||||
if let Some(ref source) = decl.source {
|
||||
visitor.visit_string_literal(source);
|
||||
}
|
||||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
pub fn walk_export_specifier<'a, V: Visit<'a>>(
|
||||
visitor: &mut V,
|
||||
specifier: &ExportSpecifier<'a>,
|
||||
) {
|
||||
let kind = AstKind::ExportSpecifier(visitor.alloc(specifier));
|
||||
visitor.enter_node(kind);
|
||||
visitor.visit_module_export_name(&specifier.local);
|
||||
visitor.visit_module_export_name(&specifier.exported);
|
||||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
pub fn walk_module_export_name<'a, V: Visit<'a>>(visitor: &mut V, name: &ModuleExportName<'a>) {
|
||||
match name {
|
||||
ModuleExportName::IdentifierName(ident) => visitor.visit_identifier_name(ident),
|
||||
ModuleExportName::IdentifierReference(ident) => {
|
||||
visitor.visit_identifier_reference(ident);
|
||||
}
|
||||
ModuleExportName::StringLiteral(ident) => visitor.visit_string_literal(ident),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_enum_member<'a, V: Visit<'a>>(visitor: &mut V, member: &TSEnumMember<'a>) {
|
||||
let kind = AstKind::TSEnumMember(visitor.alloc(member));
|
||||
visitor.enter_node(kind);
|
||||
|
|
|
|||
|
|
@ -784,7 +784,11 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ImportDeclaration<'a> {
|
|||
}
|
||||
|
||||
let imported_name = match &spec.imported {
|
||||
ModuleExportName::Identifier(identifier) => {
|
||||
ModuleExportName::IdentifierName(identifier) => {
|
||||
identifier.gen(p, ctx);
|
||||
identifier.name.as_bytes()
|
||||
}
|
||||
ModuleExportName::IdentifierReference(identifier) => {
|
||||
identifier.gen(p, ctx);
|
||||
identifier.name.as_bytes()
|
||||
}
|
||||
|
|
@ -961,9 +965,8 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportSpecifier<'a> {
|
|||
impl<'a, const MINIFY: bool> Gen<MINIFY> for ModuleExportName<'a> {
|
||||
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
|
||||
match self {
|
||||
Self::Identifier(identifier) => {
|
||||
p.print_str(identifier.name.as_bytes());
|
||||
}
|
||||
Self::IdentifierName(identifier) => p.print_str(identifier.name.as_bytes()),
|
||||
Self::IdentifierReference(identifier) => p.print_str(identifier.name.as_bytes()),
|
||||
Self::StringLiteral(literal) => literal.gen(p, ctx),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
};
|
||||
|
||||
declaration.map(|(var_decl, declaration)| {
|
||||
let exported = ModuleExportName::Identifier(IdentifierName::new(
|
||||
let exported = ModuleExportName::IdentifierName(IdentifierName::new(
|
||||
SPAN,
|
||||
self.ast.new_atom("default"),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -123,9 +123,9 @@ impl<'a> Visit<'a> for ScopeTree<'a> {
|
|||
|
||||
fn visit_export_named_declaration(&mut self, decl: &ExportNamedDeclaration<'a>) {
|
||||
for specifier in &decl.specifiers {
|
||||
if let ModuleExportName::Identifier(ident) = &specifier.local {
|
||||
self.add_type_reference(ident.name.clone());
|
||||
self.add_value_reference(ident.name.clone());
|
||||
if let Some(name) = specifier.local.identifier_name() {
|
||||
self.add_type_reference(name.clone());
|
||||
self.add_value_reference(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use oxc_ast::{
|
|||
FormalParameter, Function, IdentifierReference, JSXAttribute, JSXAttributeItem,
|
||||
JSXAttributeValue, JSXChild, JSXElement, JSXElementName, JSXExpression,
|
||||
JSXExpressionContainer, JSXFragment, JSXIdentifier, JSXOpeningElement, LogicalExpression,
|
||||
MemberExpression, ModuleExportName, NewExpression, ObjectExpression, ObjectPropertyKind,
|
||||
MemberExpression, NewExpression, ObjectExpression, ObjectPropertyKind,
|
||||
ParenthesizedExpression, PrivateFieldExpression, Program, PropertyKey, SequenceExpression,
|
||||
SimpleAssignmentTarget, Statement, StaticMemberExpression, SwitchCase, ThisExpression,
|
||||
UnaryExpression, VariableDeclarator,
|
||||
|
|
@ -198,10 +198,8 @@ impl<'a> ListenerMap for ExportSpecifier<'a> {
|
|||
let ctx = options.ctx;
|
||||
let symbol_table = ctx.symbols();
|
||||
if has_comment_about_side_effect_check(self.exported.span(), ctx) {
|
||||
let ModuleExportName::Identifier(ident_name) = &self.exported else {
|
||||
return;
|
||||
};
|
||||
let Some(symbol_id) = options.ctx.symbols().get_symbol_id_from_name(&ident_name.name)
|
||||
let Some(name) = self.exported.identifier_name() else { return };
|
||||
let Some(symbol_id) = options.ctx.symbols().get_symbol_id_from_name(name.as_str())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ use oxc_ast::{
|
|||
ast::{
|
||||
match_expression, Argument, ArrayExpressionElement, AssignmentExpression, AssignmentTarget,
|
||||
BindingPatternKind, CallExpression, Declaration, Expression, ModuleDeclaration,
|
||||
ModuleExportName, ObjectPropertyKind, PropertyKey, VariableDeclarator,
|
||||
ObjectPropertyKind, PropertyKey, VariableDeclarator,
|
||||
},
|
||||
AstKind,
|
||||
};
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
use oxc_span::{GetSpan, Span};
|
||||
|
||||
use crate::{context::LintContext, rule::Rule, AstNode};
|
||||
|
||||
|
|
@ -107,17 +107,8 @@ impl Rule for NoThenable {
|
|||
}
|
||||
// check specifier
|
||||
for spec in &decl.specifiers {
|
||||
match spec.exported {
|
||||
ModuleExportName::Identifier(ref ident) => {
|
||||
if ident.name == "then" {
|
||||
ctx.diagnostic(export(ident.span));
|
||||
}
|
||||
}
|
||||
ModuleExportName::StringLiteral(ref lit) => {
|
||||
if lit.value == "then" {
|
||||
ctx.diagnostic(export(lit.span));
|
||||
}
|
||||
}
|
||||
if spec.exported.name() == "then" {
|
||||
ctx.diagnostic(export(spec.exported.span()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,7 +220,8 @@ impl<'a> Visit<'a> for ModuleLexer<'a> {
|
|||
// export { named }
|
||||
self.exports.extend(decl.specifiers.iter().map(|s| {
|
||||
let (exported_start, exported_end) = match &s.exported {
|
||||
ModuleExportName::Identifier(ident) => (ident.span.start, ident.span.end),
|
||||
ModuleExportName::IdentifierName(ident) => (ident.span.start, ident.span.end),
|
||||
ModuleExportName::IdentifierReference(ident) => (ident.span.start, ident.span.end),
|
||||
// +1 -1 to remove the string quotes
|
||||
ModuleExportName::StringLiteral(s) => (s.span.start + 1, s.span.end - 1),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ impl<'a> ParserImpl<'a> {
|
|||
span: Span,
|
||||
) -> Result<Box<'a, ExportNamedDeclaration<'a>>> {
|
||||
let export_kind = self.parse_import_or_export_kind();
|
||||
let specifiers =
|
||||
let mut specifiers =
|
||||
self.context(Context::empty(), self.ctx, ExportNamedSpecifiers::parse)?.elements;
|
||||
let (source, with_clause) = if self.eat(Kind::From) && self.cur_kind().is_literal() {
|
||||
let source = self.parse_literal_string()?;
|
||||
|
|
@ -229,7 +229,7 @@ impl<'a> ParserImpl<'a> {
|
|||
|
||||
// ExportDeclaration : export NamedExports ;
|
||||
if source.is_none() {
|
||||
for specifier in &specifiers {
|
||||
for specifier in specifiers.iter_mut() {
|
||||
match &specifier.local {
|
||||
// It is a Syntax Error if ReferencedBindings of NamedExports contains any StringLiterals.
|
||||
ModuleExportName::StringLiteral(literal) => {
|
||||
|
|
@ -242,18 +242,25 @@ impl<'a> ParserImpl<'a> {
|
|||
// For each IdentifierName n in ReferencedBindings of NamedExports:
|
||||
// It is a Syntax Error if StringValue of n is a ReservedWord or the StringValue of n
|
||||
// is one of "implements", "interface", "let", "package", "private", "protected", "public", or "static".
|
||||
ModuleExportName::Identifier(id) => {
|
||||
let match_result = Kind::match_keyword(&id.name);
|
||||
ModuleExportName::IdentifierName(ident) => {
|
||||
let match_result = Kind::match_keyword(&ident.name);
|
||||
if match_result.is_reserved_keyword()
|
||||
|| match_result.is_future_reserved_keyword()
|
||||
{
|
||||
self.error(diagnostics::export_reserved_word(
|
||||
&specifier.local.to_string(),
|
||||
&specifier.exported.to_string(),
|
||||
id.span,
|
||||
ident.span,
|
||||
));
|
||||
}
|
||||
|
||||
// `local` becomes a reference for `export { local }`.
|
||||
specifier.local = ModuleExportName::IdentifierReference(
|
||||
self.ast.identifier_reference(ident.span, ident.name.as_str()),
|
||||
);
|
||||
}
|
||||
// No prior code path should lead to parsing `ModuleExportName` as `IdentifierReference`.
|
||||
ModuleExportName::IdentifierReference(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -343,7 +350,7 @@ impl<'a> ParserImpl<'a> {
|
|||
decl
|
||||
}
|
||||
};
|
||||
let exported = ModuleExportName::Identifier(exported);
|
||||
let exported = ModuleExportName::IdentifierName(exported);
|
||||
let span = self.end_span(span);
|
||||
Ok(self.ast.export_default_declaration(span, declaration, exported))
|
||||
}
|
||||
|
|
@ -400,7 +407,7 @@ impl<'a> ParserImpl<'a> {
|
|||
} else {
|
||||
let local = self.parse_binding_identifier()?;
|
||||
let imported = IdentifierName { span: local.span, name: local.name.clone() };
|
||||
(ModuleExportName::Identifier(imported), local)
|
||||
(ModuleExportName::IdentifierName(imported), local)
|
||||
};
|
||||
Ok(self.ast.alloc(ImportSpecifier {
|
||||
span: self.end_span(specifier_span),
|
||||
|
|
@ -424,7 +431,7 @@ impl<'a> ParserImpl<'a> {
|
|||
};
|
||||
Ok(ModuleExportName::StringLiteral(literal))
|
||||
}
|
||||
_ => Ok(ModuleExportName::Identifier(self.parse_identifier_name()?)),
|
||||
_ => Ok(ModuleExportName::IdentifierName(self.parse_identifier_name()?)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1209,7 +1209,8 @@ impl<'a> Format<'a> for ExportSpecifier<'a> {
|
|||
impl<'a> Format<'a> for ModuleExportName<'a> {
|
||||
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
|
||||
match self {
|
||||
Self::Identifier(ident) => ident.format(p),
|
||||
Self::IdentifierName(ident) => ident.format(p),
|
||||
Self::IdentifierReference(ident) => ident.format(p),
|
||||
Self::StringLiteral(literal) => literal.format(p),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ use oxc_cfg::{
|
|||
};
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_span::{CompactStr, SourceType, Span};
|
||||
use oxc_syntax::{
|
||||
module_record::{ExportImportName, ModuleRecord},
|
||||
operator::AssignmentOperator,
|
||||
};
|
||||
use oxc_syntax::{module_record::ModuleRecord, operator::AssignmentOperator};
|
||||
|
||||
use crate::{
|
||||
binder::Binder,
|
||||
|
|
@ -388,22 +385,29 @@ impl<'a> SemanticBuilder<'a> {
|
|||
self.symbols.add_redeclare_variable(symbol_id, span);
|
||||
}
|
||||
|
||||
fn add_export_flag_for_export_identifier(&mut self) {
|
||||
self.module_record.indirect_export_entries.iter().for_each(|entry| {
|
||||
if let ExportImportName::Name(name) = &entry.import_name {
|
||||
if let Some(symbol_id) = self.symbols.get_symbol_id_from_name(name.name()) {
|
||||
self.symbols.union_flag(symbol_id, SymbolFlags::Export);
|
||||
fn add_export_flag_to_export_identifiers(&mut self, program: &Program<'a>) {
|
||||
for stmt in &program.body {
|
||||
if let Statement::ExportDefaultDeclaration(decl) = stmt {
|
||||
if let ExportDefaultDeclarationKind::Identifier(ident) = &decl.declaration {
|
||||
self.add_export_flag_to_identifier(ident.name.as_str());
|
||||
}
|
||||
}
|
||||
});
|
||||
if let Statement::ExportNamedDeclaration(decl) = stmt {
|
||||
for specifier in &decl.specifiers {
|
||||
if specifier.export_kind.is_value() {
|
||||
if let Some(name) = specifier.local.identifier_name() {
|
||||
self.add_export_flag_to_identifier(name.as_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.module_record.local_export_entries.iter().for_each(|entry| {
|
||||
if let Some(name) = entry.local_name.name() {
|
||||
if let Some(symbol_id) = self.scope.get_root_binding(name.as_str()) {
|
||||
self.symbols.union_flag(symbol_id, SymbolFlags::Export);
|
||||
}
|
||||
}
|
||||
});
|
||||
fn add_export_flag_to_identifier(&mut self, name: &str) {
|
||||
if let Some(symbol_id) = self.scope.get_binding(self.current_scope_id, name) {
|
||||
self.symbols.union_flag(symbol_id, SymbolFlags::Export);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1680,9 +1684,21 @@ impl<'a> SemanticBuilder<'a> {
|
|||
/* cfg */
|
||||
|
||||
match kind {
|
||||
AstKind::ExportDefaultDeclaration(_) | AstKind::ExportNamedDeclaration(_) => {
|
||||
AstKind::ExportDefaultDeclaration(_) => {
|
||||
self.current_symbol_flags |= SymbolFlags::Export;
|
||||
}
|
||||
AstKind::ExportNamedDeclaration(decl) => {
|
||||
self.current_symbol_flags |= SymbolFlags::Export;
|
||||
if decl.export_kind.is_type() {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
}
|
||||
}
|
||||
AstKind::ExportAllDeclaration(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
}
|
||||
AstKind::ExportSpecifier(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
}
|
||||
AstKind::ImportSpecifier(specifier) => {
|
||||
specifier.bind(self);
|
||||
}
|
||||
|
|
@ -1768,6 +1784,9 @@ impl<'a> SemanticBuilder<'a> {
|
|||
AstKind::TSTypeParameter(type_parameter) => {
|
||||
type_parameter.bind(self);
|
||||
}
|
||||
AstKind::ExportSpecifier(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
}
|
||||
AstKind::TSTypeName(_) => {
|
||||
self.current_reference_flag = ReferenceFlag::Type;
|
||||
}
|
||||
|
|
@ -1815,16 +1834,28 @@ 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::Program(program) => {
|
||||
self.add_export_flag_to_export_identifiers(program);
|
||||
}
|
||||
AstKind::Class(_) => {
|
||||
self.current_node_flags -= NodeFlags::Class;
|
||||
self.class_table_builder.pop_class();
|
||||
}
|
||||
AstKind::ExportDefaultDeclaration(_) | AstKind::ExportNamedDeclaration(_) => {
|
||||
AstKind::ExportDefaultDeclaration(_) => {
|
||||
self.current_symbol_flags -= SymbolFlags::Export;
|
||||
}
|
||||
AstKind::ExportNamedDeclaration(decl) => {
|
||||
self.current_symbol_flags -= SymbolFlags::Export;
|
||||
if decl.export_kind.is_type() {
|
||||
self.current_reference_flag -= ReferenceFlag::Type;
|
||||
}
|
||||
}
|
||||
AstKind::ExportAllDeclaration(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag -= ReferenceFlag::Type;
|
||||
}
|
||||
AstKind::ExportSpecifier(s) if s.export_kind.is_type() => {
|
||||
self.current_reference_flag -= ReferenceFlag::Type;
|
||||
}
|
||||
AstKind::LabeledStatement(_) => self.label_builder.leave(),
|
||||
AstKind::StaticBlock(_) => {
|
||||
self.label_builder.leave_function_or_static_block();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use oxc_semantic::SymbolFlags;
|
||||
use oxc_syntax::module_record::ExportExportName;
|
||||
|
||||
use crate::util::SemanticTester;
|
||||
|
||||
|
|
@ -26,9 +25,7 @@ fn test_exports() {
|
|||
);
|
||||
|
||||
test.has_some_symbol("foo").is_exported().test();
|
||||
|
||||
// FIXME: failing
|
||||
// test.has_some_symbol("defaultExport").is_exported().test();
|
||||
test.has_some_symbol("defaultExport").is_exported().test();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -118,21 +115,6 @@ fn test_exported_default_class() {
|
|||
test.has_class("Foo");
|
||||
test.has_some_symbol("a").is_not_exported().test();
|
||||
test.has_some_symbol("T").is_not_exported().test();
|
||||
|
||||
{
|
||||
let foo_test = test.has_some_symbol("Foo");
|
||||
let (semantic, _) = foo_test.inner();
|
||||
let m = semantic.module_record();
|
||||
let local_default_entry = m
|
||||
.local_export_entries
|
||||
.iter()
|
||||
.find(|export| matches!(export.export_name, ExportExportName::Default(_)))
|
||||
.unwrap();
|
||||
assert!(local_default_entry.local_name.name().is_some_and(|name| name == &"Foo"));
|
||||
assert!(!m.exported_bindings.contains_key("Foo"));
|
||||
assert!(m.export_default.is_some());
|
||||
foo_test.contains_flags(SymbolFlags::Export).test();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
mod class_tester;
|
||||
mod expect;
|
||||
mod symbol_tester;
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use class_tester::ClassTester;
|
||||
pub use expect::Expect;
|
||||
|
|
@ -88,7 +88,6 @@ impl<'a> SemanticTester<'a> {
|
|||
let semantic_ret = SemanticBuilder::new(self.source_text, self.source_type)
|
||||
.with_check_syntax_error(true)
|
||||
.with_trivias(parse.trivias)
|
||||
.build_module_record(PathBuf::new(), program)
|
||||
.with_cfg(self.cfg)
|
||||
.build(program);
|
||||
|
||||
|
|
|
|||
|
|
@ -159,21 +159,12 @@ impl<'a> SymbolTester<'a> {
|
|||
self.test_result = match self.test_result {
|
||||
Ok(symbol_id) => {
|
||||
let binding = self.target_symbol_name.clone();
|
||||
let is_in_module_record =
|
||||
self.semantic.module_record().exported_bindings.contains_key(binding.as_str())
|
||||
&& self.semantic.scopes().get_root_binding(&binding) == Some(symbol_id);
|
||||
let has_export_flag = self.semantic.symbols().get_flag(symbol_id).is_export();
|
||||
match (is_in_module_record, has_export_flag) {
|
||||
(false, false) => Err(OxcDiagnostic::error(format!(
|
||||
"Expected {binding} to be exported. Symbol is not in module record and does not have SymbolFlags::Export"
|
||||
))),
|
||||
(false, true) => Err(OxcDiagnostic::error(format!(
|
||||
"Expected {binding} to be exported. Symbol is not in module record, but has SymbolFlags::Export"
|
||||
))),
|
||||
(true, false) => Err(OxcDiagnostic::error(format!(
|
||||
"Expected {binding} to be exported. Symbol is in module record, but does not have SymbolFlags::Export"
|
||||
))),
|
||||
(true, true) => Ok(symbol_id),
|
||||
if self.semantic.symbols().get_flag(symbol_id).is_export() {
|
||||
Ok(symbol_id)
|
||||
} else {
|
||||
Err(OxcDiagnostic::error(format!(
|
||||
"Expected {binding} to be exported with SymbolFlags::Export"
|
||||
)))
|
||||
}
|
||||
}
|
||||
e => e,
|
||||
|
|
@ -191,15 +182,6 @@ impl<'a> SymbolTester<'a> {
|
|||
Err(OxcDiagnostic::error(format!(
|
||||
"Expected {binding} to not be exported. Symbol has export flag."
|
||||
)))
|
||||
} else if self
|
||||
.semantic
|
||||
.module_record()
|
||||
.exported_bindings
|
||||
.contains_key(binding.as_str())
|
||||
{
|
||||
Err(OxcDiagnostic::error(format!(
|
||||
"Expected {binding} to not be exported. Binding is in the module record"
|
||||
)))
|
||||
} else {
|
||||
Ok(symbol_id)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,10 @@ impl<'a> ModuleImports<'a> {
|
|||
let local = name.local.unwrap_or_else(|| name.imported.clone());
|
||||
ImportDeclarationSpecifier::ImportSpecifier(self.ast.alloc(ImportSpecifier {
|
||||
span: SPAN,
|
||||
imported: ModuleExportName::Identifier(IdentifierName::new(SPAN, name.imported)),
|
||||
imported: ModuleExportName::IdentifierName(IdentifierName::new(
|
||||
SPAN,
|
||||
name.imported,
|
||||
)),
|
||||
local: BindingIdentifier {
|
||||
span: SPAN,
|
||||
name: local,
|
||||
|
|
|
|||
|
|
@ -516,11 +516,6 @@ impl<'a> TypeScriptAnnotations<'a> {
|
|||
|
||||
pub fn has_value_reference(&self, name: &str, ctx: &TraverseCtx<'a>) -> bool {
|
||||
if let Some(symbol_id) = ctx.scopes().get_root_binding(name) {
|
||||
if ctx.symbols().get_flag(symbol_id).is_export()
|
||||
&& !self.type_identifier_names.contains(name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ctx
|
||||
.symbols()
|
||||
.get_resolved_references(symbol_id)
|
||||
|
|
|
|||
|
|
@ -3109,7 +3109,12 @@ pub(crate) unsafe fn walk_module_export_name<'a, Tr: Traverse<'a>>(
|
|||
) {
|
||||
traverser.enter_module_export_name(&mut *node, ctx);
|
||||
match &mut *node {
|
||||
ModuleExportName::Identifier(node) => walk_identifier_name(traverser, node as *mut _, ctx),
|
||||
ModuleExportName::IdentifierName(node) => {
|
||||
walk_identifier_name(traverser, node as *mut _, ctx)
|
||||
}
|
||||
ModuleExportName::IdentifierReference(node) => {
|
||||
walk_identifier_reference(traverser, node as *mut _, ctx)
|
||||
}
|
||||
ModuleExportName::StringLiteral(node) => {
|
||||
walk_string_literal(traverser, node as *mut _, ctx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
commit: 12619ffe
|
||||
|
||||
Passed: 472/927
|
||||
Passed: 473/927
|
||||
|
||||
# All Passed:
|
||||
* babel-preset-react
|
||||
|
|
@ -445,11 +445,10 @@ Passed: 472/927
|
|||
* opts/optimizeConstEnums/input.ts
|
||||
* opts/rewriteImportExtensions/input.ts
|
||||
|
||||
# babel-plugin-transform-typescript (128/151)
|
||||
# babel-plugin-transform-typescript (129/151)
|
||||
* enum/mix-references/input.ts
|
||||
* enum/ts5.0-const-foldable/input.ts
|
||||
* exports/declared-types/input.ts
|
||||
* exports/imported-types/input.ts
|
||||
* exports/interface/input.ts
|
||||
* imports/elide-no-import-specifiers/input.ts
|
||||
* imports/elision-locations/input.ts
|
||||
|
|
|
|||
Loading…
Reference in a new issue