-
Notifications
You must be signed in to change notification settings - Fork 428
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
Preserve function body braces and distinguish open vs. X.() #1826
base: master
Are you sure you want to change the base?
Conversation
Summary:Created a new place to store some stylistic information in the AST. `[@refmt "foo"]` attributes used at parse time, never printed. Test Plan: Reviewers: CC:
let add = a => [@onRet] a; | ||
let add = a => | ||
[@onRet] | ||
{ |
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's happening 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.
The input file actually has braces. The old test output was stripping the braces and now this diff preserves them.
This is what the input has:
let add(a) { [@onRet] a };
It doesn't distinguish between [@a] { x }
and { [@a] x }
as you can see.
[@bs.get null] key2: [@onType2] Js.t(int), | ||
[@bs.get null] key3: [@onType2] Js.t(int), | ||
[@bs.get | ||
{ |
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's happening here then?
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 same thing. The attributes were specified with braces, and before this diff they were getting refmt
ed away.
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.
Does that mean these will always get formatted like this now or something?
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.
If you remove the braces I guess they will get formatted how they were previously.
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.
Exactly. Previously, the braces were getting formatted away. Now, we preserve whether or not you included additional braces. You can have it format whichever way you want - and it will preserve your intent.
While I really like the local open change, I’m less sold on retaining optional braces. I usually like the way simplifying a function can lead to the braces becoming unnecessary and collapse the code; often into a single line. Although I guess it’s easy to argue both sides. This does make me think that reducing how opinionated refmt is means we start needing some options to control behaviour 🤔 |
The open brace issue is pretty important because they get removed before you have the opportunity to add a let binding before the return value. Today people already do force the braces to be preserved by adding a dummy let binding to unit. That’s pretty extreme. What this diff does is just makes it more natural to tell the formatter you want them preserved. |
I run into the bracket issue all the time, particularly because I'm used to a format-on-save workflow.
Will format out the braces and I have to add them back constantly. Typically my workaround is to always add some empty unit statements to the function body like this:
Really looking forward to this change |
@kyldvs Literally my exact workflow! Looking forward to it as well. |
@jordwalke are you still planning to land this (or something similar)? I've been encountering both behaviors you outlined originally and it makes editing in vscode with |
This is the main reason I have refmt on save turned off. I might try to get to this to resolve the conflicts if I can in the next couple weeks |
@jaredly Just an observation: I felt that the refactor included in this diff was really necessary to make it easy to retain these "preserved styles". I found the current approach in the printer/parser not really sustainable and kind of fragile. With my refactor in this stack, there's a specific place carved out just for stylistic preservation and it is clearly out of the way because it's its own category that is cleanly filtered out. |
Thank you for your pull request. We require contributors to sign our Contributor License Agreement, and yours has expired. Before we can review or merge your code, we need you to email [email protected] with your details so we can update your status. |
This is an alternative to reasonml#1826 implementing just the brace preservation code, to make it easier to be reviewed. I think this is now in a better place to get into the codebase given that we have `Reason_attributes` outside of `Reason_pprint_ast` and that we now remove our own attributes before printing to OCaml. I think we can probably refactor this code further in future PRs, as well as add other stylistic preservation changes.
This is an alternative to reasonml#1826 implementing just the brace preservation code, to make it easier to be reviewed. I think this is now in a better place to get into the codebase given that we have `Reason_attributes` outside of `Reason_pprint_ast` and that we now remove our own attributes before printing to OCaml. I think we can probably refactor this code further in future PRs, as well as add other stylistic preservation changes.
* Preserve function body braces This is an alternative to #1826 implementing just the brace preservation code, to make it easier to be reviewed. I think this is now in a better place to get into the codebase given that we have `Reason_attributes` outside of `Reason_pprint_ast` and that we now remove our own attributes before printing to OCaml. I think we can probably refactor this code further in future PRs, as well as add other stylistic preservation changes. * Rebase and fix * address review comments * Adding so many optional laballed to `unparseExprRecurse` can't scale
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
4 similar comments
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Summary:Created a new place to store some stylistic information in the
AST.
[@refmt "foo"]
attributes used at parse time, never printed.Before the following would get reformatted:
To this:
That was annoying to many people because you can't easily add a "let" binding above the switch.
After this diff, the original form will be preserved:
With this diff you can still have the printer print this form if you prefer: You simply write it in this form and it will be retained.
I consider this a "pretty good" solution to making editing Reason syntax more enjoyable, but is certainly not the best possible solution. Ideally we would automatically insert the braces depending on whether or not the body of the function "breaks". We can also (or even instead) do that when our formatter is more expressive.
Before the following would get reformatted:
To this:
Which is sometimes neat, but sometimes it gets pretty unwieldy especially with nested opens. With this diff, we preserve the original way you wrote the
open
. You can write it withopen X
orX.()
and the formatter will retain the form you wrote. It's pretty hard to write an algorithm that looks great in all cases.