fix(ast)!: align TSImportType with ESTree (#2578)

Implements
https://github.com/typescript-eslint/typescript-eslint/issues/2998

The copy of props feels wrong, but could not get it working otherwise
with the box and borrow things 😅

Also I found that TSImportType was missing some entries for visitors and
codegen.

In the case of codegen I'm not really understand the need as all the
types seems to be dismissed?
This commit is contained in:
Arnaud Barré 2024-03-04 05:28:18 +01:00 committed by GitHub
parent fe29fa4797
commit f66059e91b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 55 additions and 27 deletions

View file

@ -761,17 +761,24 @@ pub struct TSInferType<'a> {
pub struct TSTypeQuery<'a> {
#[cfg_attr(feature = "serde", serde(flatten))]
pub span: Span,
pub expr_name: TSTypeName<'a>,
pub expr_name: TSTypeQueryExprName<'a>,
pub type_parameters: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
}
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))]
#[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))]
pub enum TSTypeQueryExprName<'a> {
TSTypeName(TSTypeName<'a>),
TSImportType(TSImportType<'a>),
}
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "camelCase"))]
#[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))]
pub struct TSImportType<'a> {
#[cfg_attr(feature = "serde", serde(flatten))]
pub span: Span,
pub is_type_of: bool,
pub argument: TSType<'a>,
pub qualifier: Option<TSTypeName<'a>>,
pub attributes: Option<TSImportAttributes<'a>>,

View file

@ -1642,7 +1642,7 @@ impl<'a> AstBuilder<'a> {
pub fn ts_type_query_type(
&self,
span: Span,
expr_name: TSTypeName<'a>,
expr_name: TSTypeQueryExprName<'a>,
type_parameters: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
) -> TSType<'a> {
TSType::TSTypeQuery(self.alloc(TSTypeQuery { span, expr_name, type_parameters }))
@ -1687,7 +1687,6 @@ impl<'a> AstBuilder<'a> {
pub fn ts_import_type(
&self,
span: Span,
is_type_of: bool,
argument: TSType<'a>,
qualifier: Option<TSTypeName<'a>>,
attributes: Option<TSImportAttributes<'a>>,
@ -1695,7 +1694,6 @@ impl<'a> AstBuilder<'a> {
) -> TSType<'a> {
TSType::TSImportType(self.alloc(TSImportType {
span,
is_type_of,
argument,
qualifier,
attributes,

View file

@ -1870,7 +1870,10 @@ pub trait Visit<'a>: Sized {
fn visit_ts_type_query(&mut self, ty: &TSTypeQuery<'a>) {
let kind = AstKind::TSTypeQuery(self.alloc(ty));
self.enter_node(kind);
self.visit_ts_type_name(&ty.expr_name);
match &ty.expr_name {
TSTypeQueryExprName::TSTypeName(name) => self.visit_ts_type_name(name),
TSTypeQueryExprName::TSImportType(_import) => {} // TODO
}
if let Some(type_parameters) = &ty.type_parameters {
self.visit_ts_type_parameter_instantiation(type_parameters);
}

View file

@ -1872,7 +1872,10 @@ pub trait VisitMut<'a>: Sized {
fn visit_ts_type_query(&mut self, ty: &mut TSTypeQuery<'a>) {
let kind = AstKind::TSTypeQuery(self.alloc(ty));
self.enter_node(kind);
self.visit_ts_type_name(&mut ty.expr_name);
match &mut ty.expr_name {
TSTypeQueryExprName::TSTypeName(name) => self.visit_ts_type_name(name),
TSTypeQueryExprName::TSImportType(_import) => {} // TODO
}
if let Some(type_parameters) = &mut ty.type_parameters {
self.visit_ts_type_parameter_instantiation(type_parameters);
}

View file

@ -143,12 +143,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSType<'a> {
decl.literal.gen(p, ctx);
}
Self::TSImportType(decl) => {
if decl.is_type_of {
p.print_str(b"typeof ");
}
p.print_str(b"import(");
decl.argument.gen(p, ctx);
p.print_str(b")");
decl.gen(p, ctx);
}
Self::TSQualifiedName(decl) => {
decl.left.gen(p, ctx);
@ -450,6 +445,23 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeQuery<'a> {
}
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeQueryExprName<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
match self {
Self::TSTypeName(decl) => decl.gen(p, ctx),
Self::TSImportType(decl) => decl.gen(p, ctx),
}
}
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSImportType<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.print_str(b"import(");
self.argument.gen(p, ctx);
p.print_str(b")");
}
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeParameterInstantiation<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
p.print_str(b"<");

View file

@ -392,14 +392,17 @@ impl<'a> ParserImpl<'a> {
Kind::NoSubstitutionTemplate | Kind::TemplateHead => {
self.parse_ts_template_literal_type(false)
}
Kind::Typeof => {
if self.peek_at(Kind::Import) {
self.parse_ts_import_type()
} else {
self.parse_ts_typeof_type()
}
Kind::Typeof => self.parse_ts_typeof_type(),
Kind::Import => {
let node = self.parse_ts_import_type()?;
Ok(self.ast.ts_import_type(
node.span,
node.argument,
node.qualifier,
node.attributes,
node.type_parameters,
))
}
Kind::Import => self.parse_ts_import_type(),
Kind::Minus if self.peek_kind().is_number() => self.parse_ts_literal_type(),
Kind::Question => self.parse_js_doc_unknown_or_nullable_type(),
// null should not be parsed as a literal type
@ -759,14 +762,17 @@ impl<'a> ParserImpl<'a> {
fn parse_ts_typeof_type(&mut self) -> Result<TSType<'a>> {
let span = self.start_span();
self.expect(Kind::Typeof)?;
let expr_name = self.parse_ts_type_name()?;
let expr_name: TSTypeQueryExprName = if self.at(Kind::Import) {
TSTypeQueryExprName::TSImportType(self.parse_ts_import_type()?)
} else {
TSTypeQueryExprName::TSTypeName(self.parse_ts_type_name()?)
};
let type_parameters = self.parse_ts_type_arguments()?;
Ok(self.ast.ts_type_query_type(self.end_span(span), expr_name, type_parameters))
}
fn parse_ts_import_type(&mut self) -> Result<TSType<'a>> {
fn parse_ts_import_type(&mut self) -> Result<TSImportType<'a>> {
let span = self.start_span();
let is_type_of = self.eat(Kind::Typeof);
self.expect(Kind::Import)?;
self.expect(Kind::LParen)?;
let argument = self.parse_ts_type()?;
@ -778,14 +784,13 @@ impl<'a> ParserImpl<'a> {
let type_parameters = self.parse_ts_type_arguments()?;
Ok(self.ast.ts_import_type(
self.end_span(span),
is_type_of,
Ok(TSImportType {
span: self.end_span(span),
argument,
qualifier,
attributes,
type_parameters,
))
})
}
fn parse_ts_import_attributes(&mut self) -> Result<TSImportAttributes<'a>> {