-
Notifications
You must be signed in to change notification settings - Fork 5
Allow empty arrow bodies #9
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
Allow empty arrow bodies #9
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good... how do you feel about it?
this.addExtra(node, "curly", false); | ||
if (!node.body.length) this.unexpected(node.start, "Expected an Indent or Statement"); | ||
if (!isArrowBody && !node.body.length) | ||
this.unexpected(node.start, "Expected an Indent or Statement"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: same line or curly please (surprised this isn't in the eslint rules... hmm)
src/plugins/lightscript.js
Outdated
// c/p parseBlock | ||
|
||
pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?) { | ||
pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?, isArrowBody?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love adding an extra param here, but I can't think of a cleaner way...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's necessary due to the way this is used throughout the code. I first tried removing the empty block check entirely, but then the parser allows a lot of malformed if: constructs that it shouldn't. So we need to know if we're in an arrow body or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. Maybe allowEmptyBody
as the param name instead? not really impt
"body": { | ||
"type": "BlockStatement", | ||
"start": 5, | ||
"end": 7, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, odd that the blockstatement has this positioning... looks like it's capturing the arrow... is that happening for other arrow function blocks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rattrayalex Yes:
parseWhiteBlock
is calling startNode
before eat(tt.Arrow)
, so the arrow's position is mapped into the resulting whiteblock node.
Not sure if that is the intended behavior or not, ultimately, but changing it should probably be out of scope for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, thanks for checking. Fine to leave for now.
Cool, I think this looks good... if you're down to change the param name, I'll merge once you've done that + squashed! |
3 squashed commits: - Allow empty arrow bodies - Delint - Change param name
ab2bddb
to
287eddf
Compare
Squashed |
src/plugins/lightscript.js
Outdated
// c/p parseBlock | ||
|
||
pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?) { | ||
pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?, allowEmptyBody?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry I didn't catch this before, but instead of doing the param, we can detect by whether there's an arrow in the code itself:
let allowEmptyBody;
// must start with colon or arrow
if (isIfExpression) {
this.expect(tt.colon);
if (!this.isLineBreak()) return this.parseMaybeAssign();
} else if (this.eat(tt.colon)) {
if (!this.isLineBreak()) return this.parseStatement(false);
} else if (this.eat(tt.arrow)) {
allowEmptyBody = true;
if (!this.isLineBreak()) {
Thoughts?
"sourceType": "script", | ||
"body": [ | ||
{ | ||
"type": "NamedArrowDeclaration", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I didn't think of this before, but we should probably have a test for non-named arrows, eg:
=>
perhaps plus the slightly more sane
f((x) =>)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These don't work right, basically because parseWhiteBlock
calls parseMaybeAssign
here, which expects a non empty expression. I intend to fix this, but odds are you won't like it much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually not as bad as I thought:
wcjohnson@997428e
Let me know if you want this plucked
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some comments there, I think... not sure if they went through
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rattrayalex Saw your comments. Plucked the changeset to this branch, will test and fix here.
Incidentally, I have compiler fixtures for all this stuff (all passing) at wcjohnson/babel-plugin-lightscript@1d464e9 |
- Update `parseWhiteBlock` to only call `parseMaybeAssign` if it seems like the start of an expression. - Added fixtures
Changing the arrow token to The parse tree being output looks correct to me, including the type annotation data, but the structure of the fixture got changed. See: e7ff094
Thoughts? |
The ordering of the nodes doesn't matter, and tokens aren't added to new fixtures these days, so that doesn't matter either. Neither does the identifierName thing. What was the incompatible part of the diff? I'm surprised it overwrote it... |
If both those things are expected, then I see no problems with the new fixture. |
I try pretty hard not to modify existing stuff unless it's needed, especially tests. What error is thrown if it's left as it was on master? |
It's expecting
|
Ah, gotcha. Let's just delete the tokens from that test then. I'd rather do it another way but this is fine. |
Restored the old fixture and just removed the token stream; everything passing. |
dot: new TokenType("."), | ||
question: new TokenType("?", { beforeExpr }), | ||
arrow: new TokenType("=>", { beforeExpr }), | ||
arrow: new TokenType("=>", { beforeExpr, startsExpr }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally this would only happen when this.hasPlugin("lightscript")
, but I don't think there's an easy way to do that yet. So this is fine for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, unfortunately this is all declarative code, running outside the context of a particular this
or parser configuration. Would require major changes to the way babylon initializes itself.
Alright, merging – thanks for this! |
This reverts commit a7d60a7.
This reverts commit a7d60a7.
Fixes wcjohnson#1