feat(ast): visit TSModuleReference (#1998)

### Failed cases:

* 7c29fbc4db/packages/babel-plugin-transform-typescript/test/fixtures/imports/elision-qualifiedname/input.ts
* 7c29fbc4db/packages/babel-plugin-transform-typescript/test/fixtures/imports/elide-react/input.ts

We need to distinguish whether a reference is a type or a js variable
This commit is contained in:
Dunqing 2024-01-11 23:29:29 +08:00 committed by GitHub
parent afb2c501f5
commit 0a086860da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 132 additions and 17 deletions

View file

@ -4,7 +4,7 @@
//! [Archived TypeScript spec](https://github.com/microsoft/TypeScript/blob/3c99d50da5a579d9fa92d02664b1b66d4ff55944/doc/spec-ARCHIVED.md)
use oxc_allocator::{Box, Vec};
use oxc_span::{Atom, Span};
use oxc_span::{Atom, GetSpan, Span};
#[cfg(feature = "serde")]
use serde::Serialize;
@ -416,6 +416,15 @@ impl<'a> TSTypeName<'a> {
}
}
impl GetSpan for TSTypeName<'_> {
fn span(&self) -> Span {
match self {
TSTypeName::IdentifierReference(ident) => ident.span,
TSTypeName::QualifiedName(name) => name.span,
}
}
}
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "camelCase"))]
pub struct TSQualifiedName<'a> {

View file

@ -152,6 +152,10 @@ pub enum AstKind<'a> {
TSEnumBody(&'a TSEnumBody<'a>),
TSImportEqualsDeclaration(&'a TSImportEqualsDeclaration<'a>),
TSTypeName(&'a TSTypeName<'a>),
TSExternalModuleReference(&'a TSExternalModuleReference),
TSQualifiedName(&'a TSQualifiedName<'a>),
TSInterfaceDeclaration(&'a TSInterfaceDeclaration<'a>),
TSModuleDeclaration(&'a TSModuleDeclaration<'a>),
TSTypeAliasDeclaration(&'a TSTypeAliasDeclaration<'a>),
@ -456,6 +460,9 @@ impl<'a> GetSpan for AstKind<'a> {
Self::TSEnumBody(x) => x.span,
Self::TSImportEqualsDeclaration(x) => x.span,
Self::TSTypeName(x) => x.span(),
Self::TSExternalModuleReference(x) => x.span,
Self::TSQualifiedName(x) => x.span,
Self::TSInterfaceDeclaration(x) => x.span,
Self::TSModuleDeclaration(x) => x.span,
Self::TSTypeAliasDeclaration(x) => x.span,
@ -633,6 +640,9 @@ impl<'a> AstKind<'a> {
Self::TSEnumMember(_) => "TSEnumMember".into(),
Self::TSImportEqualsDeclaration(_) => "TSImportEqualsDeclaration".into(),
Self::TSTypeName(_) => "TSTypeName".into(),
Self::TSExternalModuleReference(_) => "TSExternalModuleReference".into(),
Self::TSQualifiedName(_) => "TSQualifiedName".into(),
Self::TSInterfaceDeclaration(_) => "TSInterfaceDeclaration".into(),
Self::TSModuleDeclaration(_) => "TSModuleDeclaration".into(),
Self::TSTypeAliasDeclaration(_) => "TSTypeAliasDeclaration".into(),

View file

@ -1451,6 +1451,41 @@ pub trait Visit<'a>: Sized {
let kind = AstKind::TSImportEqualsDeclaration(self.alloc(decl));
self.enter_node(kind);
self.visit_binding_identifier(&decl.id);
self.visit_ts_module_reference(&decl.module_reference);
self.leave_node(kind);
}
fn visit_ts_module_reference(&mut self, reference: &TSModuleReference<'a>) {
match reference {
TSModuleReference::TypeName(name) => self.visit_ts_type_name(name),
TSModuleReference::ExternalModuleReference(reference) => {
self.visit_ts_external_module_reference(reference);
}
}
}
fn visit_ts_type_name(&mut self, name: &TSTypeName<'a>) {
let kind = AstKind::TSTypeName(self.alloc(name));
self.enter_node(kind);
match &name {
TSTypeName::IdentifierReference(ident) => self.visit_identifier_reference(ident),
TSTypeName::QualifiedName(name) => self.visit_ts_qualified_name(name),
}
self.leave_node(kind);
}
fn visit_ts_external_module_reference(&mut self, reference: &TSExternalModuleReference) {
let kind = AstKind::TSExternalModuleReference(self.alloc(reference));
self.enter_node(kind);
self.visit_string_literal(&reference.expression);
self.leave_node(kind);
}
fn visit_ts_qualified_name(&mut self, name: &TSQualifiedName<'a>) {
let kind = AstKind::TSQualifiedName(self.alloc(name));
self.enter_node(kind);
self.visit_ts_type_name(&name.left);
self.visit_identifier_name(&name.right);
self.leave_node(kind);
}
@ -1681,13 +1716,6 @@ pub trait Visit<'a>: Sized {
self.visit_ts_type(&ty.element_type);
}
fn visit_ts_type_name(&mut self, name: &TSTypeName<'a>) {
match &name {
TSTypeName::IdentifierReference(ident) => self.visit_identifier_reference(ident),
TSTypeName::QualifiedName(_) => {}
}
}
fn visit_ts_null_keyword(&mut self, ty: &TSNullKeyword) {
let kind = AstKind::TSNullKeyword(self.alloc(ty));
self.enter_node(kind);

View file

@ -1443,6 +1443,41 @@ pub trait VisitMut<'a>: Sized {
let kind = AstKind::TSImportEqualsDeclaration(self.alloc(decl));
self.enter_node(kind);
self.visit_binding_identifier(&mut decl.id);
self.visit_ts_module_reference(&mut decl.module_reference);
self.leave_node(kind);
}
fn visit_ts_module_reference(&mut self, reference: &mut TSModuleReference<'a>) {
match reference {
TSModuleReference::TypeName(name) => self.visit_ts_type_name(name),
TSModuleReference::ExternalModuleReference(reference) => {
self.visit_ts_external_module_reference(reference);
}
}
}
fn visit_ts_type_name(&mut self, name: &mut TSTypeName<'a>) {
let kind = AstKind::TSTypeName(self.alloc(name));
self.enter_node(kind);
match name {
TSTypeName::IdentifierReference(ident) => self.visit_identifier_reference(ident),
TSTypeName::QualifiedName(name) => self.visit_ts_qualified_name(name),
}
self.leave_node(kind);
}
fn visit_ts_external_module_reference(&mut self, reference: &mut TSExternalModuleReference) {
let kind = AstKind::TSExternalModuleReference(self.alloc(reference));
self.enter_node(kind);
self.visit_string_literal(&mut reference.expression);
self.leave_node(kind);
}
fn visit_ts_qualified_name(&mut self, name: &mut TSQualifiedName<'a>) {
let kind = AstKind::TSQualifiedName(self.alloc(name));
self.enter_node(kind);
self.visit_ts_type_name(&mut name.left);
self.visit_identifier_name(&mut name.right);
self.leave_node(kind);
}
@ -1673,13 +1708,6 @@ pub trait VisitMut<'a>: Sized {
self.visit_ts_type(&mut ty.element_type);
}
fn visit_ts_type_name(&mut self, name: &mut TSTypeName<'a>) {
match name {
TSTypeName::IdentifierReference(ident) => self.visit_identifier_reference(ident),
TSTypeName::QualifiedName(_) => {}
}
}
fn visit_ts_null_keyword(&mut self, ty: &mut TSNullKeyword) {
let kind = AstKind::TSNullKeyword(self.alloc(ty));
self.enter_node(kind);

View file

@ -8624,6 +8624,38 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
16 │
╰────
× The keyword 'public' is reserved
╭─[compiler/strictModeReservedWord.ts:16:1]
16 │
17 │ var b: public.bar;
· ──────
18 │
╰────
× The keyword 'private' is reserved
╭─[compiler/strictModeReservedWord.ts:18:1]
18 │
19 │ function foo(x: private.x) { }
· ───────
20 │ function foo1(x: private.package.x) { }
╰────
× The keyword 'private' is reserved
╭─[compiler/strictModeReservedWord.ts:19:1]
19 │ function foo(x: private.x) { }
20 │ function foo1(x: private.package.x) { }
· ───────
21 │ function foo2(x: private.package.protected) { }
╰────
× The keyword 'private' is reserved
╭─[compiler/strictModeReservedWord.ts:20:1]
20 │ function foo1(x: private.package.x) { }
21 │ function foo2(x: private.package.protected) { }
· ───────
22 │ let b: interface.package.implements.B;
╰────
× Identifier `b` has already been declared
╭─[compiler/strictModeReservedWord.ts:16:1]
16 │
@ -8640,6 +8672,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
23 │ ublic();
╰────
× The keyword 'interface' is reserved
╭─[compiler/strictModeReservedWord.ts:21:1]
21 │ function foo2(x: private.package.protected) { }
22 │ let b: interface.package.implements.B;
· ─────────
23 │ ublic();
╰────
× The keyword 'static' is reserved
╭─[compiler/strictModeReservedWord.ts:23:1]
23 │ ublic();

View file

@ -863,9 +863,10 @@ Passed: 298/1179
* imports/elide-injected/input.ts
* imports/elide-no-import-specifiers/input.ts
* imports/elide-preact/input.ts
* imports/elide-type-referenced-in-imports-equal-no/input.ts
* imports/elide-react/input.ts
* imports/elision/input.ts
* imports/elision-locations/input.ts
* imports/elision-qualifiedname/input.ts
* imports/elision-rename/input.ts
* imports/enum-id/input.ts
* imports/enum-value/input.ts
@ -881,7 +882,6 @@ Passed: 298/1179
* imports/type-only-export-specifier-2/input.ts
* imports/type-only-import-specifier-3/input.ts
* imports/type-only-import-specifier-4/input.ts
* namespace/alias/input.ts
* namespace/ambient-module-nested/input.ts
* namespace/ambient-module-nested-exported/input.ts
* namespace/canonical/input.ts