refactor(ast): move scope from TSModuleBlock to TSModuleDeclaration (#3488)

Closes #3471.

Remove scope from `TSModuleBlock` and add scope to `TSModuleDeclaration` instead.
This commit is contained in:
overlookmotel 2024-05-31 17:33:05 +00:00
parent 9c3d1631a4
commit 55bbde2888
8 changed files with 82 additions and 54 deletions

View file

@ -868,8 +868,8 @@ pub enum TSTypePredicateName<'a> {
This(TSThisType),
}
#[visited_node]
#[derive(Debug, Hash)]
#[visited_node(scope(ScopeFlags::TsModuleBlock), enter_scope_before(body))]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSModuleDeclaration<'a> {
@ -889,6 +889,28 @@ pub struct TSModuleDeclaration<'a> {
pub kind: TSModuleDeclarationKind,
/// Valid Modifiers: `declare`, `export`
pub modifiers: Modifiers<'a>,
pub scope_id: Cell<Option<ScopeId>>,
}
impl<'a> TSModuleDeclaration<'a> {
pub fn new(
span: Span,
id: TSModuleDeclarationName<'a>,
body: Option<TSModuleDeclarationBody<'a>>,
kind: TSModuleDeclarationKind,
modifiers: Modifiers<'a>,
) -> Self {
Self { span, id, body, kind, modifiers, scope_id: Cell::default() }
}
}
impl<'a> Hash for TSModuleDeclaration<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.id.hash(state);
self.body.hash(state);
self.kind.hash(state);
self.modifiers.hash(state);
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -931,27 +953,14 @@ pub enum TSModuleDeclarationBody<'a> {
TSModuleBlock(Box<'a, TSModuleBlock<'a>>),
}
#[visited_node(scope(ScopeFlags::TsModuleBlock))]
#[derive(Debug)]
#[visited_node]
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSModuleBlock<'a> {
#[cfg_attr(feature = "serialize", serde(flatten))]
pub span: Span,
pub body: Vec<'a, Statement<'a>>,
pub scope_id: Cell<Option<ScopeId>>,
}
impl<'a> TSModuleBlock<'a> {
pub fn new(span: Span, body: Vec<'a, Statement<'a>>) -> Self {
Self { span, body, scope_id: Cell::default() }
}
}
impl<'a> Hash for TSModuleBlock<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.body.hash(state);
}
}
#[visited_node]

View file

@ -1495,7 +1495,7 @@ impl<'a> AstBuilder<'a> {
kind: TSModuleDeclarationKind,
modifiers: Modifiers<'a>,
) -> Box<'a, TSModuleDeclaration<'a>> {
self.alloc(TSModuleDeclaration { span, id, body, kind, modifiers })
self.alloc(TSModuleDeclaration::new(span, id, body, kind, modifiers))
}
#[inline]
@ -1734,7 +1734,7 @@ impl<'a> AstBuilder<'a> {
span: Span,
body: Vec<'a, Statement<'a>>,
) -> Box<'a, TSModuleBlock<'a>> {
self.alloc(TSModuleBlock::new(span, body))
self.alloc(TSModuleBlock { span, body })
}
#[inline]

View file

@ -2579,6 +2579,7 @@ pub mod walk {
TSModuleDeclarationName::Identifier(ident) => visitor.visit_identifier_name(ident),
TSModuleDeclarationName::StringLiteral(lit) => visitor.visit_string_literal(lit),
}
visitor.enter_scope(ScopeFlags::TsModuleBlock);
match &decl.body {
Some(TSModuleDeclarationBody::TSModuleDeclaration(decl)) => {
visitor.visit_ts_module_declaration(decl);
@ -2588,16 +2589,15 @@ pub mod walk {
}
None => {}
}
visitor.leave_scope();
visitor.leave_node(kind);
}
pub fn walk_ts_module_block<'a, V: Visit<'a>>(visitor: &mut V, block: &TSModuleBlock<'a>) {
let kind = AstKind::TSModuleBlock(visitor.alloc(block));
visitor.enter_scope(ScopeFlags::TsModuleBlock);
visitor.enter_node(kind);
visitor.visit_statements(&block.body);
visitor.leave_node(kind);
visitor.leave_scope();
}
pub fn walk_ts_type_alias_declaration<'a, V: Visit<'a>>(

View file

@ -2728,6 +2728,7 @@ pub mod walk_mut {
TSModuleDeclarationName::Identifier(ident) => visitor.visit_identifier_name(ident),
TSModuleDeclarationName::StringLiteral(lit) => visitor.visit_string_literal(lit),
}
visitor.enter_scope(ScopeFlags::TsModuleBlock);
match &mut decl.body {
Some(TSModuleDeclarationBody::TSModuleDeclaration(decl)) => {
visitor.visit_ts_module_declaration(decl);
@ -2737,6 +2738,7 @@ pub mod walk_mut {
}
None => {}
}
visitor.leave_scope();
visitor.leave_node(kind);
}
@ -2745,11 +2747,9 @@ pub mod walk_mut {
block: &mut TSModuleBlock<'a>,
) {
let kind = AstType::TSModuleBlock;
visitor.enter_scope(ScopeFlags::TsModuleBlock);
visitor.enter_node(kind);
visitor.visit_statements(&mut block.body);
visitor.leave_node(kind);
visitor.leave_scope();
}
pub fn walk_ts_type_alias_declaration_mut<'a, V: VisitMut<'a>>(

View file

@ -1772,14 +1772,26 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
self.leave_node(kind);
}
fn visit_ts_module_block(&mut self, block: &TSModuleBlock<'a>) {
let kind = AstKind::TSModuleBlock(self.alloc(block));
self.enter_scope(ScopeFlags::TsModuleBlock);
block.scope_id.set(Some(self.current_scope_id));
fn visit_ts_module_declaration(&mut self, decl: &TSModuleDeclaration<'a>) {
let kind = AstKind::TSModuleDeclaration(self.alloc(decl));
self.enter_node(kind);
self.visit_statements(&block.body);
self.leave_node(kind);
match &decl.id {
TSModuleDeclarationName::Identifier(ident) => self.visit_identifier_name(ident),
TSModuleDeclarationName::StringLiteral(lit) => self.visit_string_literal(lit),
}
self.enter_scope(ScopeFlags::TsModuleBlock);
decl.scope_id.set(Some(self.current_scope_id));
match &decl.body {
Some(TSModuleDeclarationBody::TSModuleDeclaration(decl)) => {
self.visit_ts_module_declaration(decl);
}
Some(TSModuleDeclarationBody::TSModuleBlock(block)) => {
self.visit_ts_module_block(block);
}
None => {}
}
self.leave_scope();
self.leave_node(kind);
}
fn visit_ts_type_parameter(&mut self, ty: &TSTypeParameter<'a>) {

View file

@ -144,14 +144,11 @@ impl<'a> TypeScript<'a> {
);
// Reuse TSModuleBlock's scope id in transformed function.
let mut scope_id = None;
let scope_id = decl.scope_id.get();
let namespace_top_level = if let Some(body) = decl.body {
match body {
TSModuleDeclarationBody::TSModuleBlock(block) => {
scope_id = block.scope_id.get();
block.unbox().body
}
TSModuleDeclarationBody::TSModuleBlock(block) => block.unbox().body,
// We handle `namespace X.Y {}` as if it was
// namespace X {
// export namespace Y {}

View file

@ -10662,6 +10662,8 @@ pub(crate) const OFFSET_TS_MODULE_DECLARATION_BODY: usize = offset_of!(TSModuleD
pub(crate) const OFFSET_TS_MODULE_DECLARATION_KIND: usize = offset_of!(TSModuleDeclaration, kind);
pub(crate) const OFFSET_TS_MODULE_DECLARATION_MODIFIERS: usize =
offset_of!(TSModuleDeclaration, modifiers);
pub(crate) const OFFSET_TS_MODULE_DECLARATION_SCOPE_ID: usize =
offset_of!(TSModuleDeclaration, scope_id);
#[repr(transparent)]
#[derive(Debug)]
@ -10696,6 +10698,14 @@ impl<'a> TSModuleDeclarationWithoutId<'a> {
as *const Modifiers<'a>)
}
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_TS_MODULE_DECLARATION_SCOPE_ID)
as *const Cell<Option<ScopeId>>)
}
}
}
#[repr(transparent)]
@ -10731,11 +10741,18 @@ impl<'a> TSModuleDeclarationWithoutBody<'a> {
as *const Modifiers<'a>)
}
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_TS_MODULE_DECLARATION_SCOPE_ID)
as *const Cell<Option<ScopeId>>)
}
}
}
pub(crate) const OFFSET_TS_MODULE_BLOCK_SPAN: usize = offset_of!(TSModuleBlock, span);
pub(crate) const OFFSET_TS_MODULE_BLOCK_BODY: usize = offset_of!(TSModuleBlock, body);
pub(crate) const OFFSET_TS_MODULE_BLOCK_SCOPE_ID: usize = offset_of!(TSModuleBlock, scope_id);
#[repr(transparent)]
#[derive(Debug)]
@ -10746,14 +10763,6 @@ impl<'a> TSModuleBlockWithoutBody<'a> {
pub fn span(&self) -> &Span {
unsafe { &*((self.0 as *const u8).add(OFFSET_TS_MODULE_BLOCK_SPAN) as *const Span) }
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_TS_MODULE_BLOCK_SCOPE_ID)
as *const Cell<Option<ScopeId>>)
}
}
}
pub(crate) const OFFSET_TS_TYPE_LITERAL_SPAN: usize = offset_of!(TSTypeLiteral, span);

View file

@ -4826,6 +4826,15 @@ pub(crate) unsafe fn walk_ts_module_declaration<'a, Tr: Traverse<'a>>(
as *mut TSModuleDeclarationName,
ctx,
);
let mut previous_scope_id = None;
if let Some(scope_id) = (*((node as *mut u8)
.add(ancestor::OFFSET_TS_MODULE_DECLARATION_SCOPE_ID)
as *mut Cell<Option<ScopeId>>))
.get()
{
previous_scope_id = Some(ctx.current_scope_id());
ctx.set_current_scope_id(scope_id);
}
if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_TS_MODULE_DECLARATION_BODY)
as *mut Option<TSModuleDeclarationBody>)
{
@ -4834,6 +4843,9 @@ pub(crate) unsafe fn walk_ts_module_declaration<'a, Tr: Traverse<'a>>(
}
ctx.pop_stack();
traverser.exit_ts_module_declaration(&mut *node, ctx);
if let Some(previous_scope_id) = previous_scope_id {
ctx.set_current_scope_id(previous_scope_id);
}
}
pub(crate) unsafe fn walk_ts_module_declaration_name<'a, Tr: Traverse<'a>>(
@ -4875,14 +4887,6 @@ pub(crate) unsafe fn walk_ts_module_block<'a, Tr: Traverse<'a>>(
node: *mut TSModuleBlock<'a>,
ctx: &mut TraverseCtx<'a>,
) {
let mut previous_scope_id = None;
if let Some(scope_id) = (*((node as *mut u8).add(ancestor::OFFSET_TS_MODULE_BLOCK_SCOPE_ID)
as *mut Cell<Option<ScopeId>>))
.get()
{
previous_scope_id = Some(ctx.current_scope_id());
ctx.set_current_scope_id(scope_id);
}
traverser.enter_ts_module_block(&mut *node, ctx);
ctx.push_stack(Ancestor::TSModuleBlockBody(ancestor::TSModuleBlockWithoutBody(node)));
walk_statements(
@ -4892,9 +4896,6 @@ pub(crate) unsafe fn walk_ts_module_block<'a, Tr: Traverse<'a>>(
);
ctx.pop_stack();
traverser.exit_ts_module_block(&mut *node, ctx);
if let Some(previous_scope_id) = previous_scope_id {
ctx.set_current_scope_id(previous_scope_id);
}
}
pub(crate) unsafe fn walk_ts_type_literal<'a, Tr: Traverse<'a>>(