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
Keep multi-line formatting for destructuring assignment #2550
Comments
The output seems perfectly readable to me. The special-casing of objects is more of a failing in prettier than a feature, I don't think it makes sense to spread that to more cases. |
I agree that the above example is quite readable, I was only going for a minimal example case. For larger and deeper destructuring assignments I find it harder to read. Larger example const {
name: {
first,
last,
},
organisation: {
address: {
street: orgStreetAddress,
postcode: orgPostcode,
},
},
} = user; Prettier output: const {
name: { first, last },
organisation: { address: { street: orgStreetAddress, postcode: orgPostcode } }
} = user; If there's no interest in this change then I'm fine to drop it. |
Agreed, the input looks better. Maybe a better rule would be "always break nested object patterns onto multiple lines", rather than looking at the source. Though that rule might have to only apply to variable declarations, else this will be an issue: function f({ data: { name } }) {}
//Out:
function f({
data: {
name
}
}) {} Which would likely be seen as a regression. |
For React pure render functions I do find myself writing them similarly to your example output above. export default UserComponent ({
name: {
first,
last,
},
organisation: {
address: {
street: orgStreetAddress,
postcode: orgPostcode,
},
},
}) {
return (
<div>
...
</div>
)
}; I'd be fine with destructuring always using multiple lines but I imagine many others won't share that opinion. Are you against referencing the source formatting because it's difficult or because it's a special case and against the general spirit of Prettier? |
The latter. But moreso because it makes prettier less predictable. Having to learn "tricks" to get prettier to print optimal code sucks. An example I run into all the time: Object.assign({
foo: bar
}, baz); Will be printed as Object.assign(
{
foo: bar
},
baz
); When I usually want Object.assign(
{ foo: bar },
baz
); Which you can convince prettier to do by removing the line breaks, but not everyone knows that. |
@Brian-Gaffney makes an excelent point, I use that destructuring a lot on react pure components and I'm a little tired of using when you add or remove a key the diff will look like import {
Foo,
Bar,
- Baz,
} but with prettier the hole line has changes - import { Foo, Bar, Baz } from './Qux'
+ import { Foo, Bar } from './Qux' PS - Going for the minimal example here but keep in consideration real use cases like
|
I just opened up #2685 as a dupe of this. I'll reiterate my stance from that here.
Same with ES6 named imports, FWIW. |
Maybe we can limit multi-line formatting to only destructuring statements with 2 or more props (possibly also make it configurable)? Similar to the ESLint I'd love to have similar (configurable) behavior for objects, arrays and function args too. |
@alexrqs yep, diff-friendly code style is a good thing. |
Not to sound overeager, but these sound like good reasons to me. Next I'd like to add a trailing comma. What do we need to do to keep the discussion moving forward. Perhaps it can be weaved into #74 ? Is it right to suggest that this format would be consistent with the way we (want to) treat object literals and lists? |
If you also have less/css files in mind, consider scenarios like these:
Nobody want every of those selectors on a separate line. Which currently happens. (and using A linefeed right before |
@nocke Your example is not very good for suggesting different formatting. You only do that reset once, right? So it doesn't matter that much if that one rule gets a 20-line selector (in my opinion). |
Is the point of prettier to allow teams to agree on and enforce a style mechanically? Or is it to export the authors' particular preferences to the world at large? If the former, then I think it would benefit one of:
This is a big sticking point with some members of my team - I'm personally willing to pay the price of a few ugly destructures in order to get mechanical formatting, but I don't write the cheques. |
Definitely not that one. Sometimes issues need a lot of discussions before the best solution to go forward is found. Like the JSX ternary change. And sometime everyone ends up working on bugs or other features instead. |
I'm in favor of this- that said, I never use nested destructuring, partially because I prefer to keep prop shapes pretty shallow, and partially because I find it difficult to grok. |
2 real-world javascript examples: A) There are times, where you just want things as a big blob (my first example) –not wasting vertical space to scroll over– that's hardly ever to change:
B) ...in the very same project there are places, where you want everything on it's own line for sake of maintainability, even if it amounts to dozens of lines:
Meaning: |
As a side note, ESLint has options to allow breaking these nested objects into multiple lines vs. keeping them consolidated. At the minimum, it seems that prettier should be configurable to accept consolidated or broken-apart nested objects since the best style seem tricky to define except on a case-by-case basis. |
I would see (an option for) auto-detection as a good case-by-case basis. (see above) Do not rely on length or any other assumption, rely an what's there (and then consolidate, if the apparently chosen style is only „mostly“ there...). By the way, js-beautify has something like that, appending a
tested, and it works pretty nicely... |
Regarding:
and:
I'm not in any way affiliated with the project, but based on my understanding of it that would be impossible. Specifically I'm referring to the "detects ... are there mostly linebreaks between ..." part and the "rely on what's there" part. As I understand it prettier reduces your code to an AST first; that's part of the "magic" of how it can format files consistently. And doing that amounts to discarding all formatting that was there previously. In other words, Prettier can't do anything based on the way you had formatted something, because it is designed to throw out everything you had before and just generate a consistent result. I think the real fix here would be to give users more control over how Prettier output things every time. That is a request I'd definitely 👍 |
That’s not entirely true — Prettier does have ways of accessing the original source, and that’s used to keep multline objects multiline and preserve (single) blank lines. There is a feature request somewhere for an option to disable this and only use the AST, though. |
Here it is, for reference: #2068 |
As a new user testing Prettier in a fresh project, the newline behaviour around all destructuring (including import statements) and arrays, along with the closely related issues regarding jsx #3101 and json #2716, are the only deal-breakers preventing adoption. Our own reasons for using multi-line formatting in imports, destructures, objects, arrays, etc. relate mainly to supporting simple / automatic re-ordering and easy addition and removal of props, all of which help maintain clean git history (i.e. when used with As mentioned in #3101 (comment) code reviews benefit from multi-line props - this extends to merge operations - and the same applies when destructuring. Without this configuration option, it's possible we would see more, not less, formatting related changes in our git history which is at odds with our own motivations for implementing Prettier. FWIW the only time I wouldn't prefer a multi-line destructure is in an inline arrow function such as: [
{
key: 'value',
},
].map(({ key }) => key); ...but given the choice I would rather have the option to always enforce newlines when destructuring than support edge cases like this. The running suggestion in #3101 (comment) of defining the max number of props per line seems like it could carry across for all destructuring and import statements as well. i.e. a value of As an aside, the current destructure formatting seems inconsistent with the formatting applied when constructing an object- which appears to respect the author's intent. i.e. the following passes through formatting as-is: const a = 0;
const b = 1;
const c = { a, b };
const d = {
a,
b,
}; (although this is not the case with arrays...) |
Could we just always break onto multiple lines if there's nested destructuring, and keep it as it is for flat destructuring? |
If it warrants a configuration option I'd love to see a setting that supports always breaking. @azz to illustrate my preference, compare the following diffs: # Breaking nested destructure only
-const { a, b, c } = someObject;
+const {
+ a,
+ b,
+ c,
+ d: {
+ e,
+ },
+} = someObject; # Always breaking (clear addition, minimal delta)
const {
a,
b,
c,
+ d: {
+ e,
+ },
} = someObject; Meanwhile changes in another branch now need to be merged with the nested destructure formatting - each case results in a conflict - compare the two diffs: # Breaking nested destructure only (conflict must be resolved manually)
-const {
- a,
- b,
- c,
- d: {
- e,
- },
-} = someObject;
+const { a, b, c, f, g } = someObject; # Always breaking (easily resolved with merge tool / editor by accepting both changes)
const {
a,
b,
c,
- d: {
- e,
- },
+ f,
+ g,
} = someObject; |
We can't always optimize for diffs. Imagine if we printed every function like this: function foo(
a,
b
) {} We don't want to do that, and your example is similar. e.g.: const {
a,
} = b;
// or
const f = ({
a,
}) => a; |
Zero movement on this? I have tons of code like this now and I'd really like to clean it up without having to fork this entire project: function myFunction({
//
xxx,
yyy,
zzz,
}) {
...
} |
JSON.stringify(object, undefuned, 2) do as i want. Just do like this, please. One-line - hell. |
It's hard to argue spreading a multi-liner onto a single line doesn't hurt one's ability to diff code. However, it also leaves code smell in some situations helping identify opportunities for refactoring like: { container, header, body } = classes Where you've got N identifiers in two places—not ideal even with multi-line as it'll impede refactoring. Switching to the following is therefore easier to maintain and Prettier will reward under the current setup: <Html className={classes.container}>
<Head/>
<Body className={classes.body}>
<Heading className={classes.header}> So there's that. |
Hello people! Is there any work happening on this feature? Is prettier going to make my code pretty? 🙂 |
I hate to do this but I'd really like to see an update on this one. |
Do you really think this is prettier
than this..
?? |
that's why prettier is a bad tool. because some people prefer the first, and some the second. |
I do, I also respect @pvinis's opinion since the concept of "pretty" differs from person to person. |
@jimfilippou I understand what you are saying, but howcome there are other configurations for the user to change settings based on what they think is "pretty", whereas with this there is not. Some people prefer single quotes, others double, that's easily switched. Prettier gives you this option as it does not assert which one it thinks is prettier. |
Keeping this alive. Yet another person who would like to see an option for this. I much prefer deconstruction/object fields to be on new lines for readability |
I to want an option for this, being able to say |
That's actually perfect. I also still want to see an option for this. |
at the risk of throwing a spanner in the works, I just had completely random thought: could Prettier perhaps format these sections conditionally based on the existence of explicit trailing commas? drawing a little inspiration from the Dart formatter here: if code is written with a final trailing comma, then the formatter puts each entry on it's own line. whereas without this final trailing comma, it puts each entry on the same line (where applicable). naturally, to not change current default behaviour (i.e.: usage with no explicit configuration), a change like this would need to be hidden behind an appropriate configuration flag though.. but I imagine a boolean-style "respect-trailing-comma" toggle could work quite nicely, where setting this to FWIW, the following Dart snippet was all formatted in a single file: var listExampleA = [
'word',
'more words',
'final word',
];
var listExampleB = ['word', 'more words', 'final word'];
void funcExampleA(var arg1, var arg2) {}
void funcExampleB(
var arg1,
var arg2,
) {} |
For anyone looking for an alternative formatter, check out https://github.com/dprint/dprint-plugin-typescript it’s blazing fast and is reasonably configurable so that the choice of multi-line vs single line can be left to the developer |
Here's another alternative that implements this feature: This can be used in VS Code via the Deno extension. Just set your default formatter to it and you can leave the Of course, if you are doing formatting in your CI/CD pipeline you just have to install deno there too. {
"[typescript]": {
"editor.defaultFormatter": "denoland.vscode-deno"
},
} |
I discovered a Prettier plugin earlier today through this comment, which covers my needs with regards to JS arrays, but not for objects, as required for this issue.. since I've never tried my hand at creating Prettier plugins before, I might be missing something.. but perhaps |
I saw some people had issues in the past with multi-line arrays being put on a singleline by Prettier, and their workaround was to add a comment after the array's first element. I've tested with destructuring and it works too, even though it's not a great solution. Writing your destructuring like this will keep it untouched by Prettier
|
I do a similar thing for imports:
but it's annoying to need to. It's not that this is necessarily 'prettier' than
The failing is that it doesn't insist on readable diffs, and allows you to single-line it all if you remove the newline. |
Is it just me, or is it simply ridiculous that after 6 years this issue is still open and still there isn't multiline option for object deconstruction in prettier formatting with specificity for how many values are deconstructed before it breaks into multi line? |
@Frankcarvajal prettier is dead use dprint: #2550 (comment) |
honestly :)). i was reading this entire issue and hoped to find the answer i need but well, surprise |
HI all, come on I think we can do this 🙏🏼 thanks again for this great tool :) |
I think multi-line destructuring should not be collapsed by Prettier.
Same concept as the multi-line objects special case.
When doing destructuring (particularly nested) new lines can greatly enhance readability.
Example of current behaviour
Input:
Prettier output:
The text was updated successfully, but these errors were encountered: