feat(parser)!: use BindingIdentifier for namespace declaration names (#6003)

Use `BindingIdentifier` instead of `IdentifierName` so that AST visitors can access the bound symbol id for the namespace's name. This makes namespace consistent with other named declarations, such as `Class`, `Function`, and `TSInterfaceDeclaration`.

We should consider modifying `TSModuleDeclarationName::StringLiteral(...)` to also store a `symbol_id`, since one gets bound in semantic for it as well.
This commit is contained in:
DonIsaac 2024-10-08 08:39:30 +00:00
parent 87f700fa24
commit 01b878ecdb
10 changed files with 78 additions and 42 deletions

View file

@ -1391,7 +1391,7 @@ pub enum TSModuleDeclarationKind {
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[serde(untagged)]
pub enum TSModuleDeclarationName<'a> {
Identifier(IdentifierName<'a>) = 0,
Identifier(BindingIdentifier<'a>) = 0,
StringLiteral(StringLiteral<'a>) = 1,
}

View file

@ -1091,19 +1091,19 @@ const _: () = {
assert!(size_of::<TSTypePredicateName>() == 16usize);
assert!(align_of::<TSTypePredicateName>() == 8usize);
assert!(size_of::<TSModuleDeclaration>() == 64usize);
assert!(size_of::<TSModuleDeclaration>() == 72usize);
assert!(align_of::<TSModuleDeclaration>() == 8usize);
assert!(offset_of!(TSModuleDeclaration, span) == 0usize);
assert!(offset_of!(TSModuleDeclaration, id) == 8usize);
assert!(offset_of!(TSModuleDeclaration, body) == 40usize);
assert!(offset_of!(TSModuleDeclaration, kind) == 56usize);
assert!(offset_of!(TSModuleDeclaration, declare) == 57usize);
assert!(offset_of!(TSModuleDeclaration, scope_id) == 60usize);
assert!(offset_of!(TSModuleDeclaration, body) == 48usize);
assert!(offset_of!(TSModuleDeclaration, kind) == 64usize);
assert!(offset_of!(TSModuleDeclaration, declare) == 65usize);
assert!(offset_of!(TSModuleDeclaration, scope_id) == 68usize);
assert!(size_of::<TSModuleDeclarationKind>() == 1usize);
assert!(align_of::<TSModuleDeclarationKind>() == 1usize);
assert!(size_of::<TSModuleDeclarationName>() == 32usize);
assert!(size_of::<TSModuleDeclarationName>() == 40usize);
assert!(align_of::<TSModuleDeclarationName>() == 8usize);
assert!(size_of::<TSModuleDeclarationBody>() == 16usize);
@ -2628,19 +2628,19 @@ const _: () = {
assert!(size_of::<TSTypePredicateName>() == 12usize);
assert!(align_of::<TSTypePredicateName>() == 4usize);
assert!(size_of::<TSModuleDeclaration>() == 44usize);
assert!(size_of::<TSModuleDeclaration>() == 48usize);
assert!(align_of::<TSModuleDeclaration>() == 4usize);
assert!(offset_of!(TSModuleDeclaration, span) == 0usize);
assert!(offset_of!(TSModuleDeclaration, id) == 8usize);
assert!(offset_of!(TSModuleDeclaration, body) == 28usize);
assert!(offset_of!(TSModuleDeclaration, kind) == 36usize);
assert!(offset_of!(TSModuleDeclaration, declare) == 37usize);
assert!(offset_of!(TSModuleDeclaration, scope_id) == 40usize);
assert!(offset_of!(TSModuleDeclaration, body) == 32usize);
assert!(offset_of!(TSModuleDeclaration, kind) == 40usize);
assert!(offset_of!(TSModuleDeclaration, declare) == 41usize);
assert!(offset_of!(TSModuleDeclaration, scope_id) == 44usize);
assert!(size_of::<TSModuleDeclarationKind>() == 1usize);
assert!(align_of::<TSModuleDeclarationKind>() == 1usize);
assert!(size_of::<TSModuleDeclarationName>() == 20usize);
assert!(size_of::<TSModuleDeclarationName>() == 24usize);
assert!(align_of::<TSModuleDeclarationName>() == 4usize);
assert!(size_of::<TSModuleDeclarationBody>() == 8usize);

View file

@ -11423,9 +11423,9 @@ impl<'a> AstBuilder<'a> {
///
/// ## Parameters
/// - span: The [`Span`] covering this node
/// - name
/// - name: The identifier name being bound.
#[inline]
pub fn ts_module_declaration_name_identifier_name<A>(
pub fn ts_module_declaration_name_binding_identifier<A>(
self,
span: Span,
name: A,
@ -11433,17 +11433,17 @@ impl<'a> AstBuilder<'a> {
where
A: IntoIn<'a, Atom<'a>>,
{
TSModuleDeclarationName::Identifier(self.identifier_name(span, name))
TSModuleDeclarationName::Identifier(self.binding_identifier(span, name))
}
/// Convert a [`IdentifierName`] into a [`TSModuleDeclarationName::Identifier`]
/// Convert a [`BindingIdentifier`] into a [`TSModuleDeclarationName::Identifier`]
#[inline]
pub fn ts_module_declaration_name_from_identifier_name<T>(
pub fn ts_module_declaration_name_from_binding_identifier<T>(
self,
inner: T,
) -> TSModuleDeclarationName<'a>
where
T: IntoIn<'a, IdentifierName<'a>>,
T: IntoIn<'a, BindingIdentifier<'a>>,
{
TSModuleDeclarationName::Identifier(inner.into_in(self.allocator))
}

View file

@ -3888,7 +3888,7 @@ pub mod walk {
it: &TSModuleDeclarationName<'a>,
) {
match it {
TSModuleDeclarationName::Identifier(it) => visitor.visit_identifier_name(it),
TSModuleDeclarationName::Identifier(it) => visitor.visit_binding_identifier(it),
TSModuleDeclarationName::StringLiteral(it) => visitor.visit_string_literal(it),
}
}

View file

@ -4109,7 +4109,7 @@ pub mod walk_mut {
it: &mut TSModuleDeclarationName<'a>,
) {
match it {
TSModuleDeclarationName::Identifier(it) => visitor.visit_identifier_name(it),
TSModuleDeclarationName::Identifier(it) => visitor.visit_binding_identifier(it),
TSModuleDeclarationName::StringLiteral(it) => visitor.visit_string_literal(it),
}
}

View file

@ -300,7 +300,7 @@ impl<'a> ParserImpl<'a> {
);
let id = match self.cur_kind() {
Kind::Str => self.parse_literal_string().map(TSModuleDeclarationName::StringLiteral),
_ => self.parse_identifier_name().map(TSModuleDeclarationName::Identifier),
_ => self.parse_binding_identifier().map(TSModuleDeclarationName::Identifier),
}?;
let body = if self.eat(Kind::Dot) {

View file

@ -416,13 +416,19 @@ impl<'a> Binder<'a> for TSModuleDeclaration<'a> {
// At declaration time a module has no value declaration it is only when a value declaration
// is made inside a the scope of a module that the symbol is modified
let ambient = if self.declare { SymbolFlags::Ambient } else { SymbolFlags::None };
// FIXME: insert symbol_id into TSModuleDeclarationName AST node
let _symbol_id = builder.declare_symbol(
let symbol_id = builder.declare_symbol(
self.id.span(),
self.id.name().as_str(),
SymbolFlags::NameSpaceModule | ambient,
SymbolFlags::None,
);
// do not bind `global` for `declare global { ... }`
if !self.kind.is_global() {
if let TSModuleDeclarationName::Identifier(id) = &self.id {
id.symbol_id.set(Some(symbol_id));
}
}
}
}

View file

@ -153,7 +153,8 @@ impl<'a, 'ctx> TypeScriptNamespace<'a, 'ctx> {
let mut names: FxHashSet<Atom<'a>> = FxHashSet::default();
let TSModuleDeclarationName::Identifier(IdentifierName { name: real_name, .. }) = decl.id
let TSModuleDeclarationName::Identifier(BindingIdentifier { name: real_name, .. }) =
decl.id
else {
return None;
};

View file

@ -4987,7 +4987,7 @@ pub(crate) unsafe fn walk_ts_module_declaration_name<'a, Tr: Traverse<'a>>(
traverser.enter_ts_module_declaration_name(&mut *node, ctx);
match &mut *node {
TSModuleDeclarationName::Identifier(node) => {
walk_identifier_name(traverser, node as *mut _, ctx)
walk_binding_identifier(traverser, node as *mut _, ctx)
}
TSModuleDeclarationName::StringLiteral(node) => {
walk_string_literal(traverser, node as *mut _, ctx)

View file

@ -3,7 +3,7 @@ commit: a709f989
parser_typescript Summary:
AST Parsed : 6470/6479 (99.86%)
Positive Passed: 6459/6479 (99.69%)
Negative Passed: 1234/5715 (21.59%)
Negative Passed: 1235/5715 (21.61%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration10.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration11.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration13.ts
@ -1906,7 +1906,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/statics.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/staticsNotInScopeInClodule.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/strictFunctionTypesErrors.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/strictModeInConstructor.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/strictModeReservedWordInModuleDeclaration.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/strictNullEmptyDestructuring.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/strictNullNotNullIndexTypeNoLib.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/strictOptionalProperties3.ts
@ -12021,6 +12020,37 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
· ──────
╰────
× The keyword 'public' is reserved
╭─[typescript/tests/cases/compiler/strictModeReservedWordInModuleDeclaration.ts:2:8]
1 │ "use strict"
2 │ module public { }
· ──────
3 │ module private { }
╰────
× The keyword 'private' is reserved
╭─[typescript/tests/cases/compiler/strictModeReservedWordInModuleDeclaration.ts:3:8]
2 │ module public { }
3 │ module private { }
· ───────
4 │ module public.whatever {
╰────
× The keyword 'public' is reserved
╭─[typescript/tests/cases/compiler/strictModeReservedWordInModuleDeclaration.ts:4:8]
3 │ module private { }
4 │ module public.whatever {
· ──────
5 │ }
╰────
× The keyword 'private' is reserved
╭─[typescript/tests/cases/compiler/strictModeReservedWordInModuleDeclaration.ts:6:8]
5 │ }
6 │ module private.public.foo { }
· ───────
╰────
× The keyword 'package' is reserved
╭─[typescript/tests/cases/compiler/strictModeWordInImportDeclaration.ts:2:13]
1 │ "use strict"
@ -13041,21 +13071,20 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
3 │
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[typescript/tests/cases/conformance/ambient/ambientModuleDeclarationWithReservedIdentifierInDottedPath.ts:11:8]
10
11 │ declare module debugger {} // still an error
· ▲
╰────
help: Try insert a semicolon here
× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[typescript/tests/cases/conformance/ambient/ambientModuleDeclarationWithReservedIdentifierInDottedPath2.ts:9:8]
8 │
9 │ declare namespace debugger {} // still an error
· ▲
× Unexpected token
╭─[typescript/tests/cases/conformance/ambient/ambientModuleDeclarationWithReservedIdentifierInDottedPath.ts:3:23]
2
3 │ declare module chrome.debugger {
· ────────
4 │ declare var tabId: number;
╰────
× Unexpected token
╭─[typescript/tests/cases/conformance/ambient/ambientModuleDeclarationWithReservedIdentifierInDottedPath2.ts:1:26]
1 │ declare namespace chrome.debugger {
· ────────
2 │ declare var tabId: number;
╰────
help: Try insert a semicolon here
× Cannot use `await` as an identifier in an async context
╭─[typescript/tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction5_es2017.ts:1:18]