mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
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:
parent
fa7a6babce
commit
0e6d3ceee5
7 changed files with 63 additions and 22 deletions
|
|
@ -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())
|
||||
}
|
||||
|
|
|
|||
23
crates/oxc_transformer_dts/src/diagnostics.rs
Normal file
23
crates/oxc_transformer_dts/src/diagnostics.rs
Normal 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)
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
mod class;
|
||||
mod context;
|
||||
mod declaration;
|
||||
mod diagnostics;
|
||||
mod function;
|
||||
mod inferrer;
|
||||
mod module;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in a new issue