Inconsistent multiline printing of record types and values
Comparing ReScript's behavior to Prettier's, Prettier is consistent for types and values, but ReScript is not.
My proposal is to standardize on Prettier's behavior, also because it seems to follow user intention better. If the user put the first record field on a separate line, we may assume that they intend to keep the formatting multiline and/or add more fields later.
Prettier
Types
type X = { a: number };
type Y = { a: number
};
type Z = {
a: number
};
reformats to
type X = { a: number };
type Y = { a: number };
type Z = {
a: number;
};
Values
let x = { a: 2 };
let x = { a: 2,
};
let x = {
a: 2,
};
reformats to
let x = { a: 2 };
let x = { a: 2 };
let x = {
a: 2,
};
ReScript
Types
type x = {a: int}
type y = {a: int
}
type z = {
a: int,
}
reformats to
type x = {a: int}
type y = {a: int}
type z = {a: int}
Values
let x = {a: 2}
let x = {a: 2
}
let x = {
a: 2
}
reformats to
let x = {a: 2}
let x = {
a: 2,
}
let x = {
a: 2,
}
this is one of my pet peeves with the formatter, i usually just do
type t = {
//
field: bool
}
when i have a single field because of it
One argument against this is that, depending on who wrote the code in a team, type x = { a:int } may be multiline or not. The author decides, and that leads to inconsistencies in the codebase because it is a stylistic choice not everyone would make. So a format check on CI doesn't really tell you whether team agreements are being followed.
Another technical note: this behavior occurs in multiple unrelated AST nodes, so capturing all these cases will probably be more challenging than handling just these two examples.
switch foo {
| Blah => {
true
}
}
becomes
switch foo {
| Blah => true
}
Would you keep this here as well then?
Overall, I have no strong opinion. Maybe this will make a lot of people happy and we should strive for it, but it would be a trade-off at some level.
One argument against this is that, depending on who wrote the code in a team,
type x = { a:int }may be multiline or not. The author decides, and that leads to inconsistencies in the codebase because it is a stylistic choice not everyone would make. So a format check on CI doesn't really tell you whether team agreements are being followed.
I think the main goal of a formatter is to make the code more readable — both for the author and anyone else reading it later. From my experience with other formatters (mostly Haskell and Elixir), they usually try to respect the user’s formatting choices whenever possible. Things like multiline formatting are often just stylistic preferences that should be preserved if they don’t hurt consistency. The same goes for lists and arrays, not just records. Some people feel that single-line arrays are more readable, while others prefer having each item on its own line. Personally, I don’t have a strong opinion on the exact style — as long as the code is formatted consistently everywhere, I’m happy with it.
On the technical side, formatting can happen across different AST nodes, even when the code looks similar on the surface. As long as the technical side allows for it, I think we should preserve the user’s original style. That said, if formatting depends on unrelated context, that’s probably a good boundary where we shouldn’t do it (see #7941).
What's most important for me is consistency in formatting behavior
- between type definitions and values
- between records and objects
neither of which we have today.
Of course, consistent in what way is a valid question:
- Like ReScript currently does it for record types?
- Like ReScript currently does it for record values?
- Like Prettier does it?
Personally I think the way that Prettier does it is a good solution as it, like @shulhi put it, tries to respect the user’s formatting choice, and is also what people will be used to from JS. But maybe we need more feedback from the community here.
Things like multiline formatting are often just stylistic preferences and should be preserved when they don't break consistency. The same applies to lists and arrays, not just records.
To be clear, I'm not against this in principle. It is a Pandora's box. Allowing it without any constraints will lead to a string of formatter issues where folks will say "I had X and the formatter made it Y, but I need it to be X again."
Personally I think the way Prettier does it is a good solution.
As a general remark, how Prettier does things is only a partial argument. We don't need to follow everything Prettier does. We should have the freedom to disagree with certain Prettier practices and not be bullied into parity just because we accepted one of its choices in a single pull request.
My key concern is that we agree on a stance that has wide support from the core team and gives clear guidance about which practices and constraints we enforce.
Things like multiline formatting are often just stylistic preferences and should be preserved when they don't break consistency. The same applies to lists and arrays, not just records.
To be clear, I'm not against this in principle. It is a Pandora's box. Allowing it without any constraints will lead to a string of formatter issues where folks will say "I had X and the formatter made it Y, but I need it to be X again."
Personally I think the way Prettier does it is a good solution.
As a general remark, how Prettier does things is only a partial argument. We don't need to follow everything Prettier does. We should have the freedom to disagree with certain Prettier practices and not be bullied into parity just because we accepted one of its choices in a single pull request.
My key concern is that we agree on a stance that has wide support from the core team and gives clear guidance about which practices and constraints we enforce.
i think prettier should be the baseline here. disagreeing with it should require a good argument imo. prettier is battle-tested to no end with regard to what is configurable and how its default are configured.
I'm not saying that's a bad idea, but I wouldn't follow it religiously. Biome and Oxlint have made minor changes and aren't fully compatible either.