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
Added support for record and tuple syntax. #10865
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.
At a glance, looks like you added the "hash": true
option to use #{ }
syntax, and otherwise, the {| |}
syntax is used. I'd suggest that you instead make a mandatory parameter which is string-valued, like "syntax": "bar"
vs "syntax": "hash"
. This could be more future-proof.
@littledan the changes to the tokenzier check for the existence of the I'm also not opposed to switching to |
@@ -1046,11 +1060,27 @@ export default class ExpressionParser extends LValParser { | |||
this.state.inFSharpPipelineDirectBody = oldInFSharpPipelineDirectBody; | |||
return this.finishNode(node, "ArrayExpression"); | |||
} | |||
case tt.braceBarL: | |||
case tt.braceHashL: { |
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.
should assert recordAndTuple
presents otherwise it is a syntax error.
this.expectPlugin("recordAndTuple");
Can you add a test case when recordAndTuple
is not enabled?
aliases: ["Expression"], | ||
fields: { | ||
syntaxType: { | ||
validate: assertValueType("string"), |
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.
Let's be more explicit
assertOneOf("bar", "hash")
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'm not sure that this information should be there. This seems like syntax-specific information, not related to the AST.
It's similar to how the presence or absence of a semicolon is not represented in the AST.
I would prefer it as an option in @babel/generator
, which should throw when printing a RecordExpression
node if that option is not specified.
@babel/plugin-syntax-record-and-tuple
would set both the parser option and the generator option.
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.
@nicolo-ribaudo do you mean an additional property on the node specifically for the generator to use to pick syntax to output? If so, why wouldn't you just use the existing syntaxType
property?
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.
The generator options are independent on AST. By doing so we can have the AST agnostic about the syntax types, which is semantically equivalent.
You can add a new format option here
const format = { |
and reference this option in the generator via this.format.recordTupleSyntaxType
.
In the syntax-*
you can mutate the generator options via options.generatorOpts.recordTupleSyntaxType
.
parserOpts.plugins.push([ | ||
"recordAndTuple", | ||
{ | ||
hash: options.hash, |
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 prefer to expose syntaxType
to the user land, because
- When either syntax variants is accepted, we can make that as default. We have similar design on pipeline-operator.
- We don't have to process option precedence issues like
hash: false, bar: false
andhash: true, bar: true
. - More open to competing proposals, if any
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.
Could you also add a parser test with Flow like this?
var a: {| x: number |} = {| x: 2 |}
@@ -93,9 +93,13 @@ export const types: { [name: string]: TokenType } = { | |||
|
|||
// Punctuation token types. | |||
bracketL: new TokenType("[", { beforeExpr, startsExpr }), | |||
bracketHashL: new TokenType("#[", { beforeExpr, startsExpr }), | |||
bracketBarL: 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.
bracketBarL: new TokenType("{|", { beforeExpr, startsExpr }), | |
bracketBarL: new TokenType("[|", { beforeExpr, startsExpr }), |
I've pushed a set of commits that I think addresses all of your concerns so far:
Let me know if I missed anything! Thank you for the super detailed + quick reviews! edit: looks like i need to account for some lint errors as well, I will follow up on those soon. |
d342e4b
to
e58cf0c
Compare
Just pushed a rebase, looks like the standalone tests pass, but e2e and coverage are failing, but they look like unrelated failures. Any ideas? @nicolo-ribaudo @JLHwung |
The CI failure is unrelated. Did you fetch the upstream? If you rebase on the latest upstream the CI error should be gone. |
@JLHwung yep, fetched upstream and rebased. parent commit of this PR is current HEAD of babel/babel#master |
@rickbutton Can you rebase again? The CI error has been fixed in recent commits. |
e58cf0c
to
f792ffe
Compare
@JLHwung rebased again, everything is green! (minus test262). Thank you! |
endToken = "}"; | ||
} else { | ||
throw new Error( | ||
`${this.format.recordAndTupleSyntaxType} is not a valid recordAndTuple syntax type`, |
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 error message should mention the option name, and also be easy to understand when the option is not provided. WDYT about this?
`The "recordAndTupleSyntaxType" generator option must be either "bar" or "hash" (${JSON.stringify(this.format.recordAndTupleSyntaxType)} received).`,
Also, please add a test for an invalid value of the option and for when the option is not set.
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.
@nicolo-ribaudo pushed a change to include this new message, and added the tests you mentioned.
The babel-generator
test runner doesn't support the standard throws
option in options.json
(looks like it isn't using the same infra as everything else). I took the liberty of adding support for throws
to the package's test suite, let me know if this should exist somewhere else.
const start = this.state.pos; | ||
this.state.pos += 1; | ||
|
||
let ch = this.input.charCodeAt(this.state.pos); | ||
if (ch !== charCodes.exclamationMark) return false; |
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.
What is this change for?
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 moved this because it will incorrectly eat a #
character if the next character isn't a !
, I think that the this.state.pos
should only be advanced if it is actually going to be an interpreter directive. (This happens if the first line of the file is #{}
1437239
to
2ddfcd0
Compare
@@ -0,0 +1,4 @@ | |||
{ | |||
"plugins": [["recordAndTuple", { "syntaxType": "invalid" }]], | |||
"throws": "Unexpected token (1:1)" |
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.
Here we should throw an error similar to @babel/generator
's for the invalid option.
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.
Good call, how about this? (used the pipelineOperator option checks for a reference here).
'recordAndTuple` requires `syntaxType` option whose value should be one of: 'hash', 'bar'
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 👍
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.
done :)
7686bf4
to
34c9fea
Compare
TC39 Proposal Info:
Champion: @rricard @rickbutton
Spec Repo: https://github.com/tc39/proposal-record-tuple
Slides (Stage 1 at Oct 2019 TC39 Meeting): https://button.dev/talks/records-and-tuples-tc39-october-2019.pdf
This PR adds support for both the hash style
#{ a: 1 }
and the bar style{| a: 1 |}
record and tuple syntax tobabel-parser
under the optionrecordAndTuple.{hash/bar}
. I've also added a new pluginbabel-plugin-syntax-record-and-tuple
for enabling the parser option.This does not include a plugin for transforming the syntax, we intend to iterate on a transform and polyfill separately for now, similar to the approach taken for BigInt.
This is my first
babel
PR, so please let me know if I'm missing something!