Skip to content

Commit d32117c

Browse files
authored
Suggest fix for mispelled await inside async function
Fix for issue #279.
1 parent cc4c937 commit d32117c

File tree

4 files changed

+48
-0
lines changed

4 files changed

+48
-0
lines changed

src/parse.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,10 +837,16 @@ expression* parser::parse_await_expression(token await_token, precedence prec) {
837837
}
838838

839839
expression* child = this->parse_expression(prec);
840+
840841
if (child->kind() == expression_kind::_invalid) {
841842
this->error_reporter_->report(error_missing_operand_for_operator{
842843
.where = operator_span,
843844
});
845+
} else if (this->in_async_function_ && this->is_arrow_kind(child) &&
846+
child->attributes() != function_attributes::async) {
847+
this->error_reporter_->report(error_await_followed_by_arrow_function{
848+
.await_operator = operator_span,
849+
});
844850
}
845851
return this->make_expression<expression::await>(child, operator_span);
846852
}
@@ -2258,6 +2264,11 @@ void parser::consume_semicolon() {
22582264
}
22592265
}
22602266

2267+
bool parser::is_arrow_kind(expression* ast) noexcept {
2268+
return ast->kind() == expression_kind::arrow_function_with_statements ||
2269+
ast->kind() == expression_kind::arrow_function_with_expression;
2270+
}
2271+
22612272
void parser::crash_on_unimplemented_token(const char* qljs_file_name,
22622273
int qljs_line,
22632274
const char* qljs_function_name) {

src/quick-lint-js/error.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@
8888
ERROR(QLJS_TRANSLATABLE("'await' is only allowed in async functions"), \
8989
await_operator)) \
9090
\
91+
QLJS_ERROR_TYPE( \
92+
error_await_followed_by_arrow_function, "E178", \
93+
{ source_code_span await_operator; }, \
94+
ERROR(QLJS_TRANSLATABLE("'await' cannot be followed by an arrow " \
95+
"function; use 'async' instead"), \
96+
await_operator)) \
97+
\
9198
QLJS_ERROR_TYPE( \
9299
error_async_static_method, "E269", { source_code_span async_static; }, \
93100
ERROR( \

src/quick-lint-js/parse.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3686,6 +3686,8 @@ class parser {
36863686
expression *maybe_wrap_erroneous_arrow_function(expression *arrow_function,
36873687
expression *lhs);
36883688

3689+
bool is_arrow_kind(expression *ast) noexcept;
3690+
36893691
void consume_semicolon();
36903692

36913693
const token &peek() const noexcept { return this->lexer_.peek(); }

test/test-parse-expression.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,34 @@ TEST_F(test_parse_expression, await_unary_operator_inside_async_functions) {
925925
}
926926
}
927927

928+
TEST_F(test_parse_expression, await_followed_by_arrow_function) {
929+
{
930+
test_parser p(u8"await x => {}"_sv);
931+
auto guard = p.parser().enter_function(function_attributes::async);
932+
expression* ast = p.parse_expression();
933+
EXPECT_EQ(ast->kind(), expression_kind::await);
934+
EXPECT_EQ(ast->child_0()->kind(),
935+
expression_kind::arrow_function_with_statements);
936+
EXPECT_THAT(p.errors(),
937+
ElementsAre(ERROR_TYPE_FIELD(
938+
error_await_followed_by_arrow_function, await_operator,
939+
offsets_matcher(p.code(), 0, u8"await"))));
940+
}
941+
942+
{
943+
test_parser p(u8"await () => {}"_sv);
944+
auto guard = p.parser().enter_function(function_attributes::async);
945+
expression* ast = p.parse_expression();
946+
EXPECT_EQ(ast->kind(), expression_kind::await);
947+
EXPECT_EQ(ast->child_0()->kind(),
948+
expression_kind::arrow_function_with_statements);
949+
EXPECT_THAT(p.errors(),
950+
ElementsAre(ERROR_TYPE_FIELD(
951+
error_await_followed_by_arrow_function, await_operator,
952+
offsets_matcher(p.code(), 0, u8"await"))));
953+
}
954+
}
955+
928956
TEST_F(test_parse_expression,
929957
await_in_normal_function_vs_async_function_vs_top_level) {
930958
struct test_case {

0 commit comments

Comments
 (0)