Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(es/parser): Add disallow_ambiguous_jsx_like option to parse mts and cts files like tsc and babel #6913

Merged
1 change: 1 addition & 0 deletions crates/swc/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,7 @@ impl Default for Rc {
jsc: JscConfig {
syntax: Some(Syntax::Typescript(TsConfig {
tsx: false,
disallow_ambiguous_jsx_like: true,
..Default::default()
})),
..Default::default()
Expand Down
1 change: 1 addition & 0 deletions crates/swc/tests/rust_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ fn shopify_2_same_opt() {
decorators: false,
dts: false,
no_early_errors: false,
disallow_ambiguous_jsx_like: false,
})),
transform: None.into(),
external_helpers: false.into(),
Expand Down
1 change: 1 addition & 0 deletions crates/swc/tests/tsc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ fn matrix(input: &Path) -> Vec<TestUnitData> {
decorators,
dts: false,
no_early_errors: false,
disallow_ambiguous_jsx_like: false,
})),
external_helpers: true.into(),
target: Some(target),
Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_dep_graph/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ mod tests {
tsx: file_name.contains("tsx"),
decorators: true,
no_early_errors: true,
disallow_ambiguous_jsx_like: false,
}),
EsVersion::Es2015,
(&*fm).into(),
Expand Down
11 changes: 11 additions & 0 deletions crates/swc_ecma_parser/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ pub enum SyntaxError {
span: Span,
note: &'static str,
},

ReservedTypeAssertion,
ReservedArrowTypeParam,
}

impl SyntaxError {
Expand Down Expand Up @@ -709,6 +712,14 @@ impl SyntaxError {
format!("Unexpected token. Did you mean {}?", did_you_mean).into()
}
SyntaxError::WithLabel { inner, .. } => inner.error.1.msg(),
SyntaxError::ReservedTypeAssertion => "This syntax is reserved in files with the .mts \
or .cts extension. Use an `as` expression \
instead."
.into(),
SyntaxError::ReservedArrowTypeParam => "This syntax is reserved in files with the \
.mts or .cts extension. Add a trailing comma, \
as in `<T,>() => ...`."
.into(),
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions crates/swc_ecma_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,13 @@ impl Syntax {
Syntax::Es(..) => true,
}
}

fn disallow_ambiguous_jsx_like(self) -> bool {
match self {
Syntax::Typescript(t) => t.disallow_ambiguous_jsx_like,
_ => false,
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
Expand All @@ -292,6 +299,14 @@ pub struct TsConfig {

#[serde(skip, default)]
pub no_early_errors: bool,

/// babel: `disallowAmbiguousJSXLike`
/// Even when JSX parsing is not enabled, this option disallows using syntax
/// that would be ambiguous with JSX (`<X> y` type assertions and
/// `<X>()=>{}` type arguments)
/// see: https://babeljs.io/docs/en/babel-plugin-transform-typescript#disallowambiguousjsxlike
#[serde(skip, default)]
pub disallow_ambiguous_jsx_like: bool,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
Expand Down
4 changes: 4 additions & 0 deletions crates/swc_ecma_parser/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ impl<I: Tokens> Parser<I> {
#[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
fn parse_assignment_expr_base(&mut self) -> PResult<Box<Expr>> {
trace_cur!(self, parse_assignment_expr_base);
let start = self.input.cur_span();

if self.input.syntax().typescript()
&& (is_one_of!(self, '<', JSXTagStart))
Expand Down Expand Up @@ -120,6 +121,9 @@ impl<I: Tokens> Parser<I> {
Ok(Some(arrow))
});
if let Some(res) = res {
if self.input.syntax().disallow_ambiguous_jsx_like() {
self.emit_err(start, SyntaxError::ReservedArrowTypeParam);
}
return Ok(res);
}
}
Expand Down
4 changes: 4 additions & 0 deletions crates/swc_ecma_parser/src/parser/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,10 @@ impl<I: Tokens> Parser<I> {
pub(super) fn parse_ts_type_assertion(&mut self, start: BytePos) -> PResult<TsTypeAssertion> {
debug_assert!(self.input.syntax().typescript());

if self.input.syntax().disallow_ambiguous_jsx_like() {
self.emit_err(span!(self, start), SyntaxError::ReservedTypeAssertion);
}

// Not actually necessary to set state.inType because we never reach here if JSX
// plugin is enabled, but need `tsInType` to satisfy the assertion in
// `tsParseType`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<T>x;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

x This syntax is reserved in files with the .mts or .cts extension. Use an `as` expression instead.
,-[$DIR/tests/typescript-errors/disallow-ambiguous-jsx-like/cts-case1/input.cts:1:1]
1 | <T>x;
: ^
`----
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<T>() => 1;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

x This syntax is reserved in files with the .mts or .cts extension. Add a trailing comma, as in `<T,>() => ...`.
,-[$DIR/tests/typescript-errors/disallow-ambiguous-jsx-like/cts-case2/input.cts:1:1]
1 | <T>() => 1;
: ^
`----
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<T>x;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

x This syntax is reserved in files with the .mts or .cts extension. Use an `as` expression instead.
,-[$DIR/tests/typescript-errors/disallow-ambiguous-jsx-like/mts-case1/input.mts:1:1]
1 | <T>x;
: ^
`----
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<T>(x) => 1;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

x This syntax is reserved in files with the .mts or .cts extension. Add a trailing comma, as in `<T,>() => ...`.
,-[$DIR/tests/typescript-errors/disallow-ambiguous-jsx-like/mts-case2/input.mts:1:1]
1 | <T>(x) => 1;
: ^
`----
3 changes: 3 additions & 0 deletions crates/swc_ecma_parser/tests/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ where
tsx: fname.contains("tsx"),
decorators: true,
no_early_errors,
disallow_ambiguous_jsx_like: fname.contains("cts") || fname.contains("mts"),
..Default::default()
}),
EsVersion::Es2015,
Expand All @@ -266,6 +267,8 @@ where
}

#[testing::fixture("tests/typescript-errors/**/*.ts")]
#[testing::fixture("tests/typescript-errors/**/*.mts")]
#[testing::fixture("tests/typescript-errors/**/*.cts")]
#[testing::fixture("tests/typescript-errors/**/*.tsx")]
fn errors(file: PathBuf) {
let file_name = file.display().to_string();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<T,>() => 1;
<T,>(x) => 1;
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
{
"type": "Script",
"span": {
"start": 1,
"end": 27,
"ctxt": 0
},
"body": [
{
"type": "ExpressionStatement",
"span": {
"start": 1,
"end": 13,
"ctxt": 0
},
"expression": {
"type": "ArrowFunctionExpression",
"span": {
"start": 1,
"end": 12,
"ctxt": 0
},
"params": [],
"body": {
"type": "NumericLiteral",
"span": {
"start": 11,
"end": 12,
"ctxt": 0
},
"value": 1.0,
"raw": "1"
},
"async": false,
"generator": false,
"typeParameters": {
"type": "TsTypeParameterDeclaration",
"span": {
"start": 1,
"end": 5,
"ctxt": 0
},
"parameters": [
{
"type": "TsTypeParameter",
"span": {
"start": 2,
"end": 3,
"ctxt": 0
},
"name": {
"type": "Identifier",
"span": {
"start": 2,
"end": 3,
"ctxt": 0
},
"value": "T",
"optional": false
},
"in": false,
"out": false,
"const": false,
"constraint": null,
"default": null
}
]
},
"returnType": null
}
},
{
"type": "ExpressionStatement",
"span": {
"start": 14,
"end": 27,
"ctxt": 0
},
"expression": {
"type": "ArrowFunctionExpression",
"span": {
"start": 14,
"end": 26,
"ctxt": 0
},
"params": [
{
"type": "Identifier",
"span": {
"start": 19,
"end": 20,
"ctxt": 0
},
"value": "x",
"optional": false,
"typeAnnotation": null
}
],
"body": {
"type": "NumericLiteral",
"span": {
"start": 25,
"end": 26,
"ctxt": 0
},
"value": 1.0,
"raw": "1"
},
"async": false,
"generator": false,
"typeParameters": {
"type": "TsTypeParameterDeclaration",
"span": {
"start": 14,
"end": 18,
"ctxt": 0
},
"parameters": [
{
"type": "TsTypeParameter",
"span": {
"start": 15,
"end": 16,
"ctxt": 0
},
"name": {
"type": "Identifier",
"span": {
"start": 15,
"end": 16,
"ctxt": 0
},
"value": "T",
"optional": false
},
"in": false,
"out": false,
"const": false,
"constraint": null,
"default": null
}
]
},
"returnType": null
}
}
],
"interpreter": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<T,>() => 1;
<T,>(x) => 1;
Loading