fix(es/parser): Parse types in CallExpression inside templates (#6611)

**Related issue:**

 - Closes https://github.com/swc-project/swc/issues/6601.
This commit is contained in:
Alexander Akait 2022-12-10 03:05:25 +03:00 committed by GitHub
parent 66b52824e5
commit c44f1d0a7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 4308 additions and 17 deletions

View File

@ -369,9 +369,6 @@ pub struct Context {
in_forced_jsx_context: bool,
/// If true, `:` should not be treated as a type annotation.
dont_parse_colon_as_type_ann: bool,
// If true, allow super.x and super[x]
allow_direct_super: bool,

View File

@ -218,7 +218,6 @@ impl<I: Tokens> Parser<I> {
let ctx = Context {
in_cond_expr: true,
will_expect_colon_for_cond: false,
dont_parse_colon_as_type_ann: false,
..self.ctx()
};
let alt = self.with_ctx(ctx).parse_assignment_expr()?;
@ -306,7 +305,6 @@ impl<I: Tokens> Parser<I> {
tok!('[') => {
let ctx = Context {
will_expect_colon_for_cond: false,
dont_parse_colon_as_type_ann: false,
..self.ctx()
};
return self.with_ctx(ctx).parse_array_lit();
@ -378,8 +376,13 @@ impl<I: Tokens> Parser<I> {
}
tok!('`') => {
let ctx = Context {
will_expect_colon_for_cond: false,
..self.ctx()
};
// parse template literal
return Ok(Box::new(Expr::Tpl(self.parse_tpl(false)?)));
return Ok(Box::new(Expr::Tpl(self.with_ctx(ctx).parse_tpl(false)?)));
}
tok!('(') => {
@ -841,7 +844,6 @@ impl<I: Tokens> Parser<I> {
let return_type = if !self.ctx().will_expect_colon_for_cond
&& self.input.syntax().typescript()
&& is!(self, ':')
&& !self.ctx().dont_parse_colon_as_type_ann
{
self.try_parse_ts(|p| {
let return_type = p.parse_ts_type_or_type_predicate_ann(&tok!(':'))?;
@ -1470,7 +1472,12 @@ impl<I: Tokens> Parser<I> {
// MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged]
if is!(self, '`') {
let tpl = self.parse_tagged_tpl(expr, None)?;
let ctx = Context {
will_expect_colon_for_cond: false,
..self.ctx()
};
let tpl = self.with_ctx(ctx).parse_tagged_tpl(expr, None)?;
return Ok((Box::new(Expr::TaggedTpl(tpl)), true));
}

View File

@ -14,7 +14,6 @@ impl<I: Tokens> Parser<I> {
{
let ctx = Context {
will_expect_colon_for_cond: false,
dont_parse_colon_as_type_ann: false,
..self.ctx()
};
self.with_ctx(ctx).parse_with(|p| {

View File

@ -610,15 +610,8 @@ impl<'a, I: Tokens> Parser<I> {
let is_case = is!(p, "case");
let case_start = cur_pos!(p);
bump!(p);
let ctx = Context {
dont_parse_colon_as_type_ann: true,
..p.ctx()
};
let test = if is_case {
p.with_ctx(ctx)
.include_in_expr(true)
.parse_expr()
.map(Some)?
p.include_in_expr(true).parse_expr().map(Some)?
} else {
if let Some(previous) = span_of_previous_default {
syntax_error!(p, SyntaxError::MultipleDefault { previous });

View File

@ -0,0 +1,104 @@
function exampleFunction1() {
return Math.random() > 0.5
? `<button
@click="${(): void => console.log('this line causes a syntax error')}"
></button>`
: `<button
@click="${(): void => console.log('this line does NOT causes a syntax error')}"
></button>`;
}
function exampleFunction2() {
return Math.random() > 0.5
? `<bar></bar>` + `<button
@click="${(): void => console.log('this line causes a syntax error')}"
></button>`
: `<bar></bar>` + `<button
@click="${(): void => console.log('this line does NOT causes a syntax error')}"
></button>`;
}
function exampleFunction3() {
return Math.random() > 0.5
? (): void => console.log('this line causes a syntax error')
: (): void => console.log('this line does NOT causes a syntax error');
}
function exampleFunction4() {
return Math.random() > 0.5
? function (): void { console.log('this line causes a syntax error') }
: function (): void { console.log('this line does NOT causes a syntax error') };
}
function exampleFunction5() {
return Math.random() > 0.5
? (function (): void { console.log('this line causes a syntax error') })
: (function (): void { console.log('this line does NOT causes a syntax error') });
}
function exampleFunction6() {
return Math.random() > 0.5
? "test" == "test"
? `<button @click="${(): void => console.log('this line causes a syntax error')}"></button>`
: "bar"
: `<button
@click="${(): void => console.log('this line does NOT causes a syntax error')}"
></button>`;
}
function exampleFunction6() {
return Math.random() > 0.5
? `<button @click="${(): void => console.log('this line causes a syntax error')}"></button>`
: "test" == "test"
? `<button @click="${(): void => console.log('this line causes a syntax error')}"></button>`
: "bar";
}
function exampleFunction7() {
return Math.random() > 0.5
? foo`<button @click="${(): void => console.log('this line causes a syntax error')}"></button>`
: bar`<button @click="${(): void => console.log('this line does NOT causes a syntax error')}"></button>`;
}
function exampleFunction8() {
return Math.random() > 0.5
? ((): void => console.log('this line causes a syntax error'))
: ((): void => console.log('this line does NOT causes a syntax error'));
}
function exampleFunction9() {
return Math.random() > 0.5
? async (): Promise<void> => console.log('this line causes a syntax error')
: async (): Promise<void> => console.log('this line causes a syntax error');
}
function exampleFunction10() {
const foo = "Oranges";
switch (foo) {
case 'Oranges': {
return `<button @click="${(): void => console.log('this line causes a syntax error')}" ></button>`;
}
default:
console.log(`Sorry, we are out of test.`);
}
}
function exampleFunction11() {
switch (true) {
case ((): boolean => true)(): {
console.log('This shape is a square.');
break;
}
}
}
function exampleFunction12() {
switch (((): boolean => true)()) {
case ((): boolean => true)(): {
console.log('This shape is a square.');
break;
}
}
}

File diff suppressed because it is too large Load Diff