feat(transformer-dts): report error for async function and generator (#3688)

feat(transformer-dts): report error for async function and generator

fix(transformer-dts): correct span for type containing private name error

fix(transformer-dts): should add reference for export specifiers
This commit is contained in:
Dunqing 2024-06-15 13:34:25 +00:00
parent fa7a6babce
commit 0e6d3ceee5
7 changed files with 63 additions and 22 deletions

View file

@ -237,6 +237,20 @@ macro_rules! match_ts_type {
pub use match_ts_type;
impl<'a> TSType<'a> {
pub fn get_identifier_reference(&self) -> Option<IdentifierReference<'a>> {
match self {
TSType::TSTypeReference(reference) => {
Some(TSTypeName::get_first_name(&reference.type_name))
}
TSType::TSQualifiedName(qualified) => Some(TSTypeName::get_first_name(&qualified.left)),
TSType::TSTypeQuery(query) => match &query.expr_name {
TSTypeQueryExprName::IdentifierReference(ident) => Some((*ident).clone()),
_ => None,
},
_ => None,
}
}
pub fn is_const_type_reference(&self) -> bool {
matches!(self, TSType::TSTypeReference(reference) if reference.type_name.is_const())
}

View file

@ -0,0 +1,23 @@
use oxc_ast::ast::Function;
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{Atom, Span};
pub fn function_must_have_explicit_return_type(func: &Function<'_>) -> OxcDiagnostic {
OxcDiagnostic::error(
"Function must have an explicit return type annotation with --isolatedDeclarations.",
)
.with_label(func.id.as_ref().map_or_else(
|| {
let start = func.params.span.start;
Span::new(start, start)
},
|id| id.span,
))
}
pub fn type_containing_private_name(name: &Atom<'_>, span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(format!(
"Type containing private name '{name}' can't be used with --isolatedDeclarations."
))
.with_label(span)
}

View file

@ -6,7 +6,10 @@ use oxc_ast::ast::{
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{GetSpan, SPAN};
use crate::{return_type::FunctionReturnType, TransformerDts};
use crate::{
diagnostics::function_must_have_explicit_return_type, return_type::FunctionReturnType,
TransformerDts,
};
impl<'a> TransformerDts<'a> {
pub fn infer_type_from_expression(&self, expr: &Expression<'a>) -> Option<TSType<'a>> {
@ -100,19 +103,21 @@ impl<'a> TransformerDts<'a> {
return self.ctx.ast.copy(&function.return_type);
}
if function.r#async || function.generator {
self.ctx.error(function_must_have_explicit_return_type(function));
}
let return_type = FunctionReturnType::infer(
self,
function
.body
.as_ref()
.unwrap_or_else(|| unreachable!("declare function can not have body")),
.unwrap_or_else(|| unreachable!("Only declare function can have no body")),
)
.map(|type_annotation| self.ctx.ast.ts_type_annotation(SPAN, type_annotation));
if return_type.is_none() {
self.ctx.error(OxcDiagnostic::error(
"Function must have an explicit return type annotation with --isolatedDeclarations.",
).with_label(function.span));
self.ctx.error(function_must_have_explicit_return_type(function));
Some(self.ctx.ast.ts_type_annotation(SPAN, self.ctx.ast.ts_unknown_keyword(SPAN)))
} else {

View file

@ -8,6 +8,7 @@
mod class;
mod context;
mod declaration;
mod diagnostics;
mod function;
mod inferrer;
mod module;

View file

@ -7,11 +7,10 @@ use oxc_ast::{
},
Visit,
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{Atom, GetSpan};
use oxc_syntax::scope::ScopeFlags;
use crate::{context::Ctx, TransformerDts};
use crate::{context::Ctx, diagnostics::type_containing_private_name, TransformerDts};
/// Infer return type from return statement. Does not support multiple return statements.
pub struct FunctionReturnType<'a> {
@ -67,11 +66,12 @@ impl<'a> FunctionReturnType<'a> {
};
if is_defined_in_current_scope {
transformer.ctx.error(
OxcDiagnostic::error(format!("Type containing private name '{reference_name}' can't be used with --isolatedDeclarations.")).with_label(
expr.span()
)
);
transformer.ctx.error(type_containing_private_name(
&reference_name,
expr_type
.get_identifier_reference()
.map_or_else(|| expr_type.span(), |ident| ident.span),
));
}
}

View file

@ -51,11 +51,11 @@ impl<'a> ScopeTree<'a> {
self.type_bindings.last_mut().unwrap().insert(ident.clone());
}
fn add_unresolved_value_reference(&mut self, ident: &Atom<'a>) {
fn add_value_reference(&mut self, ident: &Atom<'a>) {
self.value_references.last_mut().unwrap().insert(ident.clone());
}
fn add_unresolved_type_reference(&mut self, ident: &Atom<'a>) {
fn add_type_reference(&mut self, ident: &Atom<'a>) {
self.type_references.last_mut().unwrap().insert(ident.clone());
}
@ -65,7 +65,6 @@ impl<'a> ScopeTree<'a> {
fn resolve_references(&mut self) {
let current_value_bindings = self.value_bindings.pop().unwrap_or_default();
let current_value_references = self.value_references.pop().unwrap_or_default();
self.type_references
.last_mut()
.unwrap()
@ -95,7 +94,7 @@ impl<'a> Visit<'a> for ScopeTree<'a> {
}
fn visit_identifier_reference(&mut self, ident: &IdentifierReference<'a>) {
self.add_unresolved_value_reference(&ident.name);
self.add_value_reference(&ident.name);
}
fn visit_binding_pattern(&mut self, pattern: &BindingPattern<'a>) {
@ -107,7 +106,7 @@ impl<'a> Visit<'a> for ScopeTree<'a> {
fn visit_ts_type_name(&mut self, name: &TSTypeName<'a>) {
if let TSTypeName::IdentifierReference(ident) = name {
self.add_unresolved_type_reference(&ident.name);
self.add_type_reference(&ident.name);
} else {
walk_ts_type_name(self, name);
}
@ -116,7 +115,7 @@ impl<'a> Visit<'a> for ScopeTree<'a> {
fn visit_ts_type_query(&mut self, ty: &TSTypeQuery<'a>) {
if let Some(type_name) = ty.expr_name.as_ts_type_name() {
let ident = TSTypeName::get_first_name(type_name);
self.add_unresolved_value_reference(&ident.name);
self.add_value_reference(&ident.name);
} else {
walk_ts_type_query(self, ty);
}
@ -125,8 +124,8 @@ 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_binding(&ident.name);
self.add_value_binding(&ident.name);
self.add_type_reference(&ident.name);
self.add_value_reference(&ident.name);
}
}
}

View file

@ -2,14 +2,13 @@ commit: d8086f14
transpile Summary:
AST Parsed : 20/20 (100.00%)
Positive Passed: 7/20 (35.00%)
Positive Passed: 8/20 (40.00%)
Mismatch: "declarationAsyncAndGeneratorFunctions.ts"
Mismatch: "declarationBasicSyntax.ts"
Mismatch: "declarationComputedPropertyNames.ts"
Mismatch: "declarationCrossFileInferences.ts"
Mismatch: "declarationEmitPartialNodeReuse.ts"
Mismatch: "declarationFunctionDeclarations.ts"
Mismatch: "declarationLinkedAliases.ts"
Mismatch: "declarationNotInScopeTypes.ts"
Mismatch: "declarationPartialNodeReuseTypeOf.ts"
Mismatch: "declarationRestParameters.ts"