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

Suggest async when await is followed by arrow function. #314

Closed
wants to merge 6 commits into from
Closed

Suggest async when await is followed by arrow function. #314

wants to merge 6 commits into from

Conversation

keyehzy
Copy link
Contributor

@keyehzy keyehzy commented May 17, 2021

Attempts to fix issues #279 and #278.

In both cases we can check if await ( is followed by an arrow function, suggest changing it to async and then rollback.

For the expression beginning with await ( inside an async function the expression following it is parsed twice, this happens because we have no way to know beforehand if we want that expression to be parsed and await might be an identifier or something else.

Attempts to fix issue #279.

Excluded the cases where `await` is followed by an `async` then
followed by an arrow function. In this case `await` must be an unary
operator.

This commit does not solve issue #278 just yet, but should be a
start. Here the error is only caught for top-level await and async
function, i.e cases where async is *not* treated as an identifier.
Will squash it latter.
It's done by checking if there is a arrow function after `await` even
if its treated as an identifier.

There is some code duplication between this commit and the earlier
one so I will try to work out a way to combine these two.

Also, I don't know enough JS to know if the tests are strict
enough to catch all the cases.
I figured that you don't need to distinguish between the cases where
the `await` function is inside an `async` function or not. In either
case, if we see an arrow function we can emit the same error
suggesting the change to `async`.
@keyehzy
Copy link
Contributor Author

keyehzy commented May 18, 2021

Should be good for review.

Copy link
Collaborator

@strager strager left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments marked 'blocking'.

I think we should punt on fixing #278 in this PR; I think we should focus on #279. The two issues are related, but I don't think we can kill two birds with one stone.

@@ -869,6 +869,64 @@ TEST_F(test_parse_expression, await_unary_operator_inside_async_functions) {
EXPECT_EQ(summarize(ast), "await(var x)");
EXPECT_THAT(p.errors(), IsEmpty());
}

{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think these new tests belong in a different TEST_F than test_parse_expression.await_unary_operator_inside_async_functions. For example, the test on line 899 is for a normal (non-async) function, which is definitely not what the test's name implies.

Comment on lines +903 to +912
EXPECT_EQ(ast->kind(), expression_kind::binary_operator);
EXPECT_THAT(
p.errors(),
ElementsAre(
ERROR_TYPE_FIELD(error_await_creating_arrow_function,
await_operator,
offsets_matcher(p.code(), 0, u8"await")),
ERROR_TYPE_FIELD(
error_missing_operator_between_expression_and_arrow_function,
where, offsets_matcher(p.code(), 0, u8"await ("))));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: This parsing doesn't seem right at all. error_missing_operator_between_expression_and_arrow_function is wrong, assuming you want to fix #278. The whole point of #278 is to avoid E063.

Also, creating a binary_operator out of thin air is weird.

if (child->kind() == expression_kind::_invalid) {
this->error_reporter_->report(error_missing_operand_for_operator{
.where = operator_span,
});
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be a lot simpler to check if child->kind() is arrow_function_with_statements or arrow_function_with_expression here? That wouldn't fix #278, but based on your tests, #278 isn't really fixed by this commit anyway.

@@ -715,6 +715,30 @@ expression* parser::parse_await_expression(token await_token, precedence prec) {
}
}();

if (this->peek().type == token_type::left_paren) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code fails to catch arrow functions which don't have parentheses around the parameter list. For example:

await x => {}

See my comment on line 760 for a possible solution.

@strager
Copy link
Collaborator

strager commented Nov 6, 2021

@keyehzy reposted this as #488.

@strager strager closed this Nov 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants