Allow empty arrow bodies#9
Conversation
rattrayalex
left a comment
There was a problem hiding this comment.
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.
nit: same line or curly please (surprised this isn't in the eslint rules... hmm)
| // c/p parseBlock | ||
|
|
||
| pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?) { | ||
| pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?, isArrowBody?) { |
There was a problem hiding this comment.
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.
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.
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.
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.
@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.
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 |
| // c/p parseBlock | ||
|
|
||
| pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?) { | ||
| pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?, allowEmptyBody?) { |
There was a problem hiding this comment.
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.
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.
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.
Actually not as bad as I thought:
wcjohnson@997428e
Let me know if you want this plucked
There was a problem hiding this comment.
Added some comments there, I think... not sure if they went through
There was a problem hiding this comment.
@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.
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.
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