-
-
Notifications
You must be signed in to change notification settings - Fork 255
Fix Flow return types on arrow functions #124
Conversation
Current coverage is 94.93% (diff: 88.88%)
|
@@ -613,6 +613,10 @@ pp.parseParenAndDistinguishExpression = function (startPos, startLoc, canBeArrow | |||
return val; | |||
}; | |||
|
|||
pp.shouldParseArrow = function () { | |||
return !this.canInsertSemicolon(); |
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.
This seems to be a tab here?
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.
Oops, sorry! (I'm one of those people lol). Lint didn't pick it up. I've pushed a change.
@@ -1162,6 +1162,7 @@ export default function (instance) { | |||
let state = this.state.clone(); | |||
try { | |||
let returnType = this.flowParseTypeAnnotation(); | |||
if (this.canInsertSemicolon()) this.unexpected(); |
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.
Can we make this maybe a nice error message here? Flow says "Illegal newline before arrow", which is already better than "unexpected token".
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 think so, because any syntax errors are immediately caught at the end of parseArrow
: https://github.com/danharper/babylon/blob/774bf486fe2f117393dcf5ee14aa2c050ae40dd7/src/plugins/flow.js#L1169-L1175
(which is also why the raise error happens at 1:1
and not at the actual position)
I'm not 100% sure on why it works like this, though.
(it's for regression tests in babel/babel@caecebf)
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.
Argh, true.
This try catch is there because when we encounter a colon at this spot we are not yet sure about a.) if it is an valid arrow at all b.) if the colon might be from a ternary operator (something like this i think a ? b: c => {}
). So if a SyntaxError is thrown while parsing the return type we reset the state to what it was before we started parsing the type and let the regular parsing function of babylon handle it.
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.
oh I see, thanks for the explanation 👍
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.
Thinking: we could just throw a different error, catch it, then throw with a nicer message instead:
if (this.match(tt.colon)) {
let state = this.state.clone();
try {
let returnType = this.flowParseTypeAnnotation();
- if (this.canInsertSemicolon()) this.unexpected();
+ if (this.canInsertSemicolon()) throw new Error("IS_SEMICOLON_ERR");
if (!this.match(tt.arrow)) this.unexpected();
// assign after it is clear it is an arrow
node.returnType = returnType;
} catch (err) {
if (err instanceof SyntaxError) {
this.state = state;
+ } else if (err.message === "IS_SEMICOLON_ERR") {
+ this.unexpected(null, "Illegal newline before arrow");
} else {
throw err;
}
}
}
It's not great, but it produces a much nicer error message, in the correct location too.
Thoughts?
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.
Not entirely sure if that has any side effects on this try/catch logic.
So maybe we jsut leave it for now, and later on have a look how we can improve the message.
Looks good. In general it would be nice if different fixes could go to different PRs as it is then easier to understand which change is for which fix, but in this small case it does not really matter. Thanks for all your contributions. |
Sure, I'll make sure to split them in the future! :) |
Two commits.
First fixes: babel/babel-eslint#348 which can be summed up as this should be valid, but isn't:
https://flowtype.org/try/#0MYewdgzgLgBAHjAvDAFAMxCAXDaAnASzAHMBKAKBzAFcBbAIwFM8kA+GAbxj0amrzAwATDAC+5IA
Second fixes a bug where Babel won't error when there's a line break before the
=>
when there's a type annotation (basically this existing test, but with a return type in the mix):https://flowtype.org/try/#0BQSgXABAzgLgTgSwHYHMBQBeAfBA3gXyA