Skip to content

Conversation

wcjohnson
Copy link

Fixes wcjohnson#1

Copy link

@rattrayalex rattrayalex left a 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");

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)

// c/p parseBlock

pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?) {
pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?, isArrowBody?) {

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...

Copy link
Author

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.

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,

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?

Copy link
Author

@wcjohnson wcjohnson Apr 6, 2017

Choose a reason for hiding this comment

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

@rattrayalex Yes:

https://github.com/wcjohnson/babylon-lightscript/blob/a27269694673bbe26aed026fcdbc23ecc64ca94f/test/fixtures/lightscript/named-arrow-functions/skinny-white/expected.json

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.

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.

@rattrayalex
Copy link

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
@wcjohnson wcjohnson force-pushed the upstream-empty-arrows branch from ab2bddb to 287eddf Compare April 6, 2017 20:34
@wcjohnson
Copy link
Author

Squashed

// c/p parseBlock

pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?) {
pp.parseWhiteBlock = function (allowDirectives?, isIfExpression?, allowEmptyBody?) {

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",

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) =>)

Copy link
Author

@wcjohnson wcjohnson Apr 6, 2017

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.

Copy link
Author

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

@rattrayalex

Actually not as bad as I thought:
wcjohnson@997428e

Let me know if you want this plucked

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

Copy link
Author

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.

@wcjohnson
Copy link
Author

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
@wcjohnson
Copy link
Author

wcjohnson commented Apr 7, 2017

@rattrayalex

Changing the arrow token to startsExpr worked great, except it broke one Flow fixture in a way that's kind of strange. The fixture break was expected because the startsExpr in the token stream changed from false to true, but nonetheless the result is a little strange.

The parse tree being output looks correct to me, including the type annotation data, but the structure of the fixture got changed. See: e7ff094

  • The return type annotation node got moved before the function body node. Is this because lsc parses flow types in a different order than babylon?

  • All the token information got dropped from the regenerated fixture even though it was present in the original, no idea why that happened.

Thoughts?

@rattrayalex
Copy link

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...

@wcjohnson
Copy link
Author

If both those things are expected, then I see no problems with the new fixture.

@rattrayalex
Copy link

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?

@wcjohnson
Copy link
Author

wcjohnson commented Apr 7, 2017

It's expecting startExpr to be false when it's true...

  index › flow/type annotations/99
  Error: flow/type-annotations/99/actual.js: false !== true (startsExpr/type/7/tokens)
    runTest (test/utils/runFixtureTests.js:164:13)
    Test.fn (test/utils/runFixtureTests.js:25:22)

  index › flow/type annotations/99
  Error: /Users/wcj/dev/lightscript-devkit/packages/babylon-lightscript/test/fixtures/flow/type-annotations/99/actual.js: false !== true (startsExpr/type/7/tokens)
    runTest (test/utils/runFixtureTests.js:164:13)
    Test.fn (test/utils/runFixtureTests.js:107:20)

@rattrayalex
Copy link

Ah, gotcha. Let's just delete the tokens from that test then. I'd rather do it another way but this is fine.

@wcjohnson
Copy link
Author

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 }),

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.

Copy link
Author

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.

@rattrayalex
Copy link

Alright, merging – thanks for this!

@rattrayalex rattrayalex merged commit a7d60a7 into lightscript:lightscript Apr 9, 2017
@wcjohnson wcjohnson deleted the upstream-empty-arrows branch April 12, 2017 00:53
rattrayalex added a commit that referenced this pull request May 15, 2017
rattrayalex added a commit that referenced this pull request May 15, 2017
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