Skip to content
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

Formatting of object initializers depend on max line length #1437

Open
albert-tk25 opened this issue Jan 14, 2025 · 3 comments
Open

Formatting of object initializers depend on max line length #1437

albert-tk25 opened this issue Jan 14, 2025 · 3 comments

Comments

@albert-tk25
Copy link

Currently properties for object initializers are put on different lines of the expression length is greater than max line length and on same line otherwise, which looks strange.

Input:

var sort = new CustomSort() 
{ 
    Order = OrderBy.Ascending, 
    Field = CustomSortBy.Title 
};

var sort = new CustomSort() 
{ 
    Order = OrderBy.Ascending, 
    Field = CustomSortBy.Title,
    AnotherField =  CustomSortBy.Name
};

Output:

var sort = new CustomSort() { Order = OrderBy.Ascending, Field = CustomSortBy.Title };

var sort = new CustomSort() 
{ 
    Order = OrderBy.Ascending, 
    Field = CustomSortBy.Title,
    AnotherField =  CustomSortBy.Name
};

Expected behavior:

var sort = new CustomSort() 
{ 
    Order = OrderBy.Ascending, 
    Field = CustomSortBy.Title 
};

var sort = new CustomSort() 
{ 
    Order = OrderBy.Ascending, 
    Field = CustomSortBy.Title,
    AnotherField =  CustomSortBy.Name
};

@belav
Copy link
Owner

belav commented Jan 17, 2025

The current rules are (I may be forgetting some extra edge cases that break)

  • If an initializer has three or more properties break
  • If the initializer is longer than the max width break

If all initializers break, then code like the following is going to take up a lot of vertical space

var point1 = new Point { X = 1, Y = 1 };
var point2 = new Point { X = 2, Y = 2 };
var point3 = new Point { X = 3, Y = 3 };

// vs

var point1 = new Point
{
    X = 1,
    Y = 1,
};
var point2 = new Point
{
    X = 2,
    Y = 2,
};
var point3 = new Point
{
    X = 3,
    Y = 3,
};

The current rules do break things like this, which is also not the greatest

var point1 = new Point { X = 1, Y = 1, Z = 1 };

// is output as

var point1 = new Point
{
    X = 1,
    Y = 1,
    Z = 1,
};

I was expermimenting with prettier, and it looks like they take the existence of a break after the brace into account, meaning

// input
var point1 = new Point { X = 1, Y = 1, Z = 1 };
var point2 = new Point { X = 2, Y = 2 };
var point3 = new Point {
X = 3, Y = 3, Z = 3 };
var point2 = new Point {
X = 2, Y = 2 };

// output is
var point1 = new Point { X = 1, Y = 1, Z = 1 };
var point2 = new Point { X = 2, Y = 2 };
var point3 = new Point
{
    X = 3,
    Y = 3,
    Z = 3,
};
var point2 = new Point
{
    X = 2,
    Y = 2,
};

I'm not opposed to it, but it does feel a bit wrong to be required to "give a hint" to csharpier about how you want something to be formatted. It would be useful for me to track down any discussions from when prettier implemented that logic.

The only other thing I can think of is trying to define what a "simple" initializer looks like vs a "complex" one. Where the 3 property Point in my example would be considered simple and only break if over the max width, and the 2 property initializer in your example is complex and will break even below the max width.

@LoremFooBar
Copy link

It is a problem that's hard to solve apparently, see https://prettier.io/docs/en/rationale#multi-line-objects.
I like their workaround for this problem, and I'd like to see it implemented in CSharpier.

@albert-tk25
Copy link
Author

There doesn't seem to be a good solution to this. I would not be a fun of the Prettier approach.

For me a potential improvement would be to break also in case when the value assigned to one of the properties is not a literal (like in my case)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants