Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ impl<'a> Traverse<'a> for Transformer<'a> {
}

fn enter_expression(&mut self, expr: &mut Expression<'a>, _ctx: &TraverseCtx<'a>) {
self.x0_typescript.transform_expression(expr);
self.x1_react.transform_expression(expr);
self.x3_es2015.transform_expression(expr);
}

fn exit_expression(&mut self, expr: &mut Expression<'a>, _ctx: &TraverseCtx<'a>) {
self.x0_typescript.transform_expression_on_exit(expr);
self.x3_es2015.transform_expression_on_exit(expr);
}

Expand Down Expand Up @@ -245,4 +245,8 @@ impl<'a> Traverse<'a> for Transformer<'a> {
) {
self.x0_typescript.transform_module_declaration(decl);
}

fn enter_ts_type_assertion(&mut self, node: &mut TSTypeAssertion<'a>, _ctx: &TraverseCtx<'a>) {
self.x0_typescript.transform_ts_type_assertion(node);
}
}
32 changes: 30 additions & 2 deletions crates/oxc_transformer/src/typescript/annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use oxc_span::{Atom, SPAN};
use oxc_syntax::operator::AssignmentOperator;
use rustc_hash::FxHashSet;

use super::collector::TypeScriptReferenceCollector;
use super::{
collector::TypeScriptReferenceCollector,
diagnostics::{type_assertion_reserved, type_parameters_reserved},
};

pub struct TypeScriptAnnotations<'a> {
#[allow(dead_code)]
Expand Down Expand Up @@ -197,6 +200,20 @@ impl<'a> TypeScriptAnnotations<'a> {
}

pub fn transform_arrow_expression(&mut self, expr: &mut ArrowFunctionExpression<'a>) {
if self.is_mts_or_ctx_file() {
// <T>() => {} is invalid, but <T, >() => {} is valid
if let Some(type_parameters) = &expr.type_parameters {
if type_parameters.params.len() == 1
&& !type_parameters
.span
.source_text(self.ctx.source_text)
.trim_end()
.ends_with(',')
{
self.ctx.error(type_parameters_reserved(expr.span));
}
}
}
expr.type_parameters = None;
expr.return_type = None;
}
Expand Down Expand Up @@ -240,7 +257,7 @@ impl<'a> TypeScriptAnnotations<'a> {
});
}

pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
pub fn transform_expression_on_exit(&mut self, expr: &mut Expression<'a>) {
*expr = self.ctx.ast.copy(expr.get_inner_expression());
}

Expand Down Expand Up @@ -396,4 +413,15 @@ impl<'a> TypeScriptAnnotations<'a> {
pub fn transform_jsx_fragment(&mut self, _elem: &mut JSXFragment<'a>) {
self.has_jsx_fragment = true;
}

pub fn transform_ts_type_assertion(&mut self, node: &mut TSTypeAssertion<'a>) {
if self.is_mts_or_ctx_file() {
self.ctx.error(type_assertion_reserved(node.span));
}
}

pub fn is_mts_or_ctx_file(&self) -> bool {
let extension = self.ctx.source_path.extension();
extension.is_some_and(|ext| matches!(ext.to_str(), Some("mts" | "cts")))
}
}
8 changes: 8 additions & 0 deletions crates/oxc_transformer/src/typescript/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,11 @@ pub fn ambient_module_nested(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warning("Ambient modules cannot be nested in other modules or namespaces.")
.with_label(span0)
}

pub fn type_assertion_reserved(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warning("This syntax is reserved in files with the .mts or .cts extension. Use an `as` expression instead.").with_label(span)
}

pub fn type_parameters_reserved(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warning("This syntax is reserved in files with the .mts or .cts extension. Add a trailing comma, as in `<T,>() => ...`.").with_label(span)
}
8 changes: 6 additions & 2 deletions crates/oxc_transformer/src/typescript/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ impl<'a> TypeScript<'a> {
self.reference_collector.visit_transform_export_named_declaration(decl);
}

pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
self.annotations.transform_expression(expr);
pub fn transform_expression_on_exit(&mut self, expr: &mut Expression<'a>) {
self.annotations.transform_expression_on_exit(expr);
}

pub fn transform_formal_parameter(&mut self, param: &mut FormalParameter<'a>) {
Expand Down Expand Up @@ -211,4 +211,8 @@ impl<'a> TypeScript<'a> {
pub fn transform_jsx_fragment(&mut self, elem: &mut JSXFragment<'a>) {
self.annotations.transform_jsx_fragment(elem);
}

pub fn transform_ts_type_assertion(&mut self, node: &mut TSTypeAssertion<'a>) {
self.annotations.transform_ts_type_assertion(node);
}
}
8 changes: 2 additions & 6 deletions tasks/transform_conformance/babel.snap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
commit: 4bd1b2c2

Passed: 309/362
Passed: 313/362

# All Passed:
* babel-preset-react
Expand All @@ -16,12 +16,8 @@ Passed: 309/362
* spec/newableArrowFunction-default/input.js
* spec/newableArrowFunction-vs-spec-false/input.js

# babel-preset-typescript (7/16)
# babel-preset-typescript (11/16)
* node-extensions/import-in-cts/input.cts
* node-extensions/type-assertion-in-cts/input.cts
* node-extensions/type-assertion-in-mts/input.mts
* node-extensions/type-param-arrow-in-cts/input.mts
* node-extensions/type-param-arrow-in-mts/input.mts
* node-extensions/with-in-mts/input.mts
* opts/allowDeclareFields/input.ts
* opts/optimizeConstEnums/input.ts
Expand Down
2 changes: 2 additions & 0 deletions tasks/transform_conformance/src/test_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,8 @@ fn get_babel_error(error: &str) -> String {
"Duplicate __self prop found." => "Duplicate __self prop found. You are most likely using the deprecated transform-react-jsx-self Babel plugin. Both __source and __self are automatically set when using the automatic runtime. Please remove transform-react-jsx-source and transform-react-jsx-self from your Babel config.",
"Duplicate __source prop found." => "Duplicate __source prop found. You are most likely using the deprecated transform-react-jsx-source Babel plugin. Both __source and __self are automatically set when using the automatic runtime. Please remove transform-react-jsx-source and transform-react-jsx-self from your Babel config.",
"Expected `>` but found `/`" => "Unexpected token, expected \",\"",
"This syntax is reserved in files with the .mts or .cts extension. Use an `as` expression instead." => "This syntax is reserved in files with the .mts or .cts extension. Use an `as` expression instead. (1:0)",
"This syntax is reserved in files with the .mts or .cts extension. Add a trailing comma, as in `<T,>() => ...`." => "This syntax is reserved in files with the .mts or .cts extension. Add a trailing comma, as in `<T,>() => ...`. (1:0)",
_ => error
}.to_string()
}