Skip to content

Commit

Permalink
fix(typescript): fix <42>x; and other cases being parsed as JSX
Browse files Browse the repository at this point in the history
  • Loading branch information
strager committed Dec 27, 2023
1 parent 388155d commit 2b1300b
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/quick-lint-js/fe/parse-expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3606,7 +3606,29 @@ Expression* Parser::parse_jsx_or_typescript_generic_expression(
}
break;

// <readonly /> // JSX.
// <readonly T[]>expr // Type assertion.
case Token_Type::kw_keyof:
case Token_Type::kw_this:
case Token_Type::kw_readonly:
case Token_Type::kw_typeof:
case Token_Type::kw_unique:
case Token_Type::number:
default:
// For these uncommon cases, don't try hard to guess what the user
// meant.
this->lexer_.roll_back_transaction(std::move(transaction));
if (this->options_.jsx) {
return this->parse_jsx_expression(v);
} else {
return this->parse_typescript_angle_type_assertion_expression(
v, prec,
/*is_invalid_due_to_jsx_ambiguity=*/false);
}
break;

// <>hello<> // JSX.
case Token_Type::greater:
break;
}
this->lexer_.roll_back_transaction(std::move(transaction));
Expand Down
44 changes: 44 additions & 0 deletions test/test-parse-typescript-angle-type-assertion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ TEST_F(Test_Parse_TypeScript_Angle_Type_Assertion, angle_type_assertion) {
u8"< & Type>(expr);"_sv,
u8"<[Type]>(expr);"_sv,
u8"<Type[]>(expr);"_sv,
u8"<readonly Type[]>(expr);"_sv,
u8"<keyof Type>(expr);"_sv,
u8"<{k: Type}>(expr);"_sv,
}) {
SCOPED_TRACE(out_string8(code));
Expand Down Expand Up @@ -158,6 +160,48 @@ TEST_F(Test_Parse_TypeScript_Angle_Type_Assertion, angle_type_assertion) {
}));
}

{
Spy_Visitor p = test_parse_and_visit_statement(
u8"<typeof v>expr;"_sv, no_diags, typescript_options);
EXPECT_THAT(p.visits, ElementsAreArray({
"visit_enter_type_scope", // <
"visit_variable_use", // v
"visit_exit_type_scope", // >
"visit_variable_use", // expr
}));
EXPECT_THAT(p.variable_uses, ElementsAreArray({u8"v"_sv, u8"expr"_sv}));
}

{
Spy_Visitor p = test_parse_and_visit_statement(
u8"<unique symbol>expr;"_sv, no_diags, typescript_options);
EXPECT_THAT(p.visits, ElementsAreArray({
"visit_enter_type_scope", // <
"visit_exit_type_scope", // >
"visit_variable_use", // expr
}));
}

{
Spy_Visitor p = test_parse_and_visit_statement(u8"<this>expr;"_sv, no_diags,
typescript_options);
EXPECT_THAT(p.visits, ElementsAreArray({
"visit_enter_type_scope", // <
"visit_exit_type_scope", // >
"visit_variable_use", // expr
}));
}

{
Spy_Visitor p = test_parse_and_visit_statement(u8"<42>expr;"_sv, no_diags,
typescript_options);
EXPECT_THAT(p.visits, ElementsAreArray({
"visit_enter_type_scope", // <
"visit_exit_type_scope", // >
"visit_variable_use", // expr
}));
}

for (const String8& type :
typescript_builtin_type_keywords | typescript_special_type_keywords) {
Test_Parser p(concat(u8"<"_sv, type, u8">expr;"_sv), typescript_options);
Expand Down

0 comments on commit 2b1300b

Please sign in to comment.