From 64ee83d67ec10561803c75b5fe76589f040c7098 Mon Sep 17 00:00:00 2001 From: "Matthew \"strager\" Glazar" Date: Fri, 3 Nov 2023 22:28:06 -0400 Subject: [PATCH] fix(typescript): don't treat 'case await a: b;' as arrow function quick-lint-js's error detection for 'async a: b => c' is too optimistic. Disable it when the keyword prior is 'await' instead of 'async', fixing false positives for valid code such as the following: async function f() { switch (x) { case await y: z; break; } } --- docs/CHANGELOG.md | 2 + src/quick-lint-js/fe/parse-expression.cpp | 3 +- test/CMakeLists.txt | 1 + test/test-parse-typescript-statement.cpp | 64 +++++++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 test/test-parse-typescript-statement.cpp diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index e6f2c0f69e..81879ea155 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -12,6 +12,8 @@ Semantic Versioning. * TypeScript support (still experimental): * `export as namespace` statements are now parsed. + * `case await x:` no longer treats `:` as if it was a type annotation colon in + an arrow function parameter list. ## 2.18.0 (2023-11-03) diff --git a/src/quick-lint-js/fe/parse-expression.cpp b/src/quick-lint-js/fe/parse-expression.cpp index a8ff40c322..22799f1280 100644 --- a/src/quick-lint-js/fe/parse-expression.cpp +++ b/src/quick-lint-js/fe/parse-expression.cpp @@ -1105,7 +1105,8 @@ Expression* Parser::parse_async_expression_only( } std::optional type_colon_span; - if (this->peek().type == Token_Type::colon && this->options_.typescript) { + if (is_async && this->peek().type == Token_Type::colon && + this->options_.typescript) { // async param: Type => {} // Invalid. type_colon_span = this->peek().span(); Buffering_Visitor type_visits(&this->type_expression_memory_); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 88b3bfff22..947457ffe3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -167,6 +167,7 @@ quick_lint_js_add_executable( test-parse-typescript-module.cpp test-parse-typescript-namespace.cpp test-parse-typescript-object.cpp + test-parse-typescript-statement.cpp test-parse-typescript-this-parameters.cpp test-parse-typescript-type-alias.cpp test-parse-typescript-type.cpp diff --git a/test/test-parse-typescript-statement.cpp b/test/test-parse-typescript-statement.cpp new file mode 100644 index 0000000000..55c30723d1 --- /dev/null +++ b/test/test-parse-typescript-statement.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2020 Matthew "strager" Glazar +// See end of file for extended copyright information. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ::testing::ElementsAreArray; + +namespace quick_lint_js { +namespace { +class Test_Parse_TypeScript_Statement : public ::testing::Test {}; + +TEST_F(Test_Parse_TypeScript_Statement, + await_in_case_is_not_arrow_function_with_missing_parens) { + // This code used to confuse + // Diag_Arrow_Parameter_With_Type_Annotation_Requires_Parentheses detection. + { + Spy_Visitor p = test_parse_and_visit_statement( + u8"switch (x) { case await a: b => c; }"_sv, no_diags, + typescript_options); + EXPECT_THAT(p.variable_uses, + ElementsAreArray({u8"x"_sv, u8"a"_sv, u8"c"_sv})); + EXPECT_THAT(p.variable_declarations, + ElementsAreArray({arrow_param_decl(u8"b"_sv)})); + } +} +} +} + +// quick-lint-js finds bugs in JavaScript programs. +// Copyright (C) 2020 Matthew "strager" Glazar +// +// This file is part of quick-lint-js. +// +// quick-lint-js is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// quick-lint-js is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with quick-lint-js. If not, see .