-
-
Notifications
You must be signed in to change notification settings - Fork 134
Fix: correct ASI for arrow function followed by parenthesized expressions #354
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
base: master
Are you sure you want to change the base?
Conversation
The test failures are due to the fact that you're generating the parser with ABI 15, which the bindings are not compatible with. Please use Also, please update the reference queries to the grammar change, if necessary. |
Ugh, CI forces generation... Can you add
(This should be a separate |
please use conventional commits, and squash and reorder your commits before this is ready to merge |
Oh jinx It looks like despite what the release notes say, this can't be overridden via
|
Yes, hence my asking you to disable the test (which you did, which is why CI passes now). But please check that the queries are still compatbile! |
fc20d18
to
361637e
Compare
Sure, I updated the commit format. As for queries being compatible, I think we're good because grammar tests pass and my ~600 AST conversion tests from https://github.com/jackschu/ESTree-sitter tests also pass. But if there are specific queries you think might be negatively impacted let me know. This does change the classification of arrow_function (was a primary_expression, is now an expression) and new_expression (was an expression, is now a primary_expression), so some queries will get different results, but I think this is correct. |
361637e
to
e47b6e4
Compare
As long as the old queries are still valid, that's ok. We've had PRs that change the grammar in a way that they break without thinking to adapt the reference queries here (because they use their own). |
Yeah I dont think this could make any queries invalid but for future PRs where are these reference queries? |
e47d0fe
to
454814e
Compare
…sions. arrow_functions are now expressions rather than primary_expressions and new_expressions are now primary_expressions.
454814e
to
462d182
Compare
Problem
Observed
The following parses incorrectly
Without this changeset, the grammar treats this as an arrow function that is being invoked.
We can gut check that this is wrong by running the following in node
Expected
Instead this should parse as an arrow function, an automatically injected semicolon, and a parenthesized number, eg
Solution
Background
Ill be using PascalCase to indicate spec nouns and snake_case to indicate tree-sitter-javascript nouns.
This grammar considers two levels of expressions.
expression
andprimary_expression
. These both exist in the ecmascript spec, but are obviously not perfect representations of their highly-granular spec counterparts (this in intentional as the tree-sitter docs point out).The spec considers a third kind of expression called MemberExpression. This is just one level above PrimaryExpression in the spec and includes things that our
primary_expression
already includes (property access, subscript expression,meta
,super
, etc.).Change: Reorganize Expressions
It turns out that there are several issues in the way of handling this correctly, all of which I tackle in this PR. Our high level goal is to make
()=>{}(1)
parse as an Error so ASI is forced to kick in if there were to be a newline in there.call_expression
s currently acceptexpression
as its body, the spec has CallExpression accept basically exclusively MemberExpression as its body. This diff movescall_expression
to accept exclusivelyprimary_expression
. On its own this doesn't clearly correct any issue directly, but it moves us towards a consistent view a top the spec and it'll be important for use in later steps.new_expression
is considered to be considered aprimary_expression
, but the spec considers it to be a MemberExpression. So productions likenew foo()()
won't parse but should. So I movenew_expression
to be considered aprimary_expression
(after all it seems like in spirit ourprimary_expression
is a MemberExpressoin).new
with no args is lower precedence than call expressions butnew
with args is higher precedence (src).template_call
as a prec level (added in Fix: Operator precedence rules for tagged template functions #336 )new_expression
no longer needs to produce itself, sinceprimary_expression
is sufficient, so we can dropprec.right
expression
.Change: Make
()=>{}(1)
illegalAt this point we've made
()=>{}(1)
parse as an arrow function with an invoked object as its result. This is progress over it being a call expression with an arrow function as a body, because we're now in a scenario where this is a clearly illegal production. This is clear because the spec requires that ConciseBody (aka the shorthand return result format) for ArrowFunctions don't start with{
.Here I stand-up an external scanner for
'=>' <not followed by {>
which im calling$._shorthand_arrow,
. And I use this inarrow_function
to make()=>{}(1)
take thestatement_body
path rather than theexpression
shorthand path. I tried pretty hard to do this via precedences but couldn't get it to work (if someone could explain to me why that's pretty impossible or intuitively hard I'd appreciate that).Change: Allow ASI before '(' sometimes
At this point
()=>{}(1)
does error, but ASI still doesnt trigger for the newline version.This is because we blanketly consider seeing
(
as the next symbol to void ASI. This is useful forf\n(1)
but seems misguided.ASI basically asks "is the next token valid" and only kicks in if its not (src). So I expose
(
to the external scanner and void ASI only if(
is a valid. I do the same thing to[
preemptively because I assume it has the same problem.At this point it all parses correctly :)