-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Improve NormalizeWhitespace
for object initializers
#65249
Improve NormalizeWhitespace
for object initializers
#65249
Conversation
note: i added support for multiline expressions in string interpolations to the language. |
src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs
Outdated
Show resolved
Hide resolved
Yes, but of 2 available variants I think the single-line looks better. Let me show: How it was before this PR: $"{new SomeClass
{A = 1, B = 2}}" How it could be if I didn't explicitly chenged it: $"{new SomeClass
{
A = 1,
B = 2
}}" How it is currently done: $"{new SomeClass { A = 1, B = 2 }}" Considering that it is very unlikely that an interpolated string would contain large object initializer, I think, the single-line approach looks better. Even if it can be not very obvious from the case I've shown above, just add some content and it will become a mess: $"This is the first part of an interpolation string {new SomeClass
{
A = 1,
B = 2
}}. This is the second part if an interpolation string. And as this constant part grows the start of object declaration is more and more separated from its initializer: {new SomeOtherClass
{
C = "whos this initializer is?)"
D = 3.14m
}}" The |
Co-authored-by: CyrusNajmabadi <cyrus.najmabadi@gmail.com>
Please doc the code to include this explanation. Thanks! |
…m/DoctorKrolic/roslyn into normalize-whitespace-initializers
Looked through, but i didn't see a test with nested initializers. e.g. |
In the latest commit there is a test with many nested initializers. Isn't it what you want to see? |
could you point me to it? |
There are a bunch of nested different initializers and anonymous object declarations |
I don't see the code construct I was calling out in my request though. I don't see simple nested initializers. |
Can I have a review 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.
LGTM Thanks (iteration 15)
@dotnet/roslyn-compiler for second review. Thanks |
Still want a second review) And someone also restart failed CI pls |
@dotnet/roslyn-ide for sign-off on workspaces tests change |
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.
LGTM just had some minor comments to address first.
=> node is AccessorListSyntax accessorList && | ||
node.Parent is PropertyDeclarationSyntax property && | ||
property.Initializer != null; | ||
=> node is AccessorListSyntax { Parent: PropertyDeclarationSyntax { Initializer: not null } }; |
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.
In general, please try to keep style-only changes like these to a minimum in the compiler layer. No need to undo any such changes already in the PR.
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.
Originally I only removed accessorList
as it was never used, but Cyrus then suggested to use pattern matching and I accepted it. Ok, will try to avoid such changes later.
Also I have an idea to convert all multiline strings is SyntaxNormalizerTests
to raw form in order to make them actually readable in a separate PR after this one is merged. Would such change be considered as style-only and rejected?
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.
Also I have an idea to convert all multiline strings is
SyntaxNormalizerTests
to raw form in order to make them actually readable in a separate PR after this one is merged
I personally would be fine with this. @jcouv as long as you're also fine with this, I'd say @DoctorKrolic can go ahead and open a subsequent PR to convert the @""
strings in that file to """ """
.
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 would be fine with this. they're tests, so there's no risk. and test-strings were a primary use case for raw-strings :)
src/Workspaces/CSharpTest/CodeGeneration/SyntaxGeneratorTests.cs
Outdated
Show resolved
Hide resolved
public void TestNormalizeObjectInitializer() | ||
{ | ||
TestNormalizeExpression( | ||
"new{}", """ |
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.
Just curious, where did all these baselines come from? Were they taken from somewhere or was there some method used which lead to producing all of them?
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 produced them manually myself. There is some logic behind almost every one. Here the pattern is the following:
- Empty
{}
- Add simple properties
- Add
,
after the last simple property (I actually caught several bugs when decided to add these tests) - Repeat this patter for
new{...}
->new SomeClass{...}
->new SomeClass(){...}
- Add nested complex property with its own initializer/anonymous object declaration
- Repeat the whole pattern 1-4 for this nested property
- Add another double-nested property and repeat 1-4 for it
Similar with with
initializers tests
Collection/array initializers are not that much structured. But there are some interesting cases there as well, e.g. new[] { 2 + 2 * 2 }
. Here the first parent of first 2
is not an initializer, but a binary expression, while in a simpler case like new [] { 2 }
the parent is an initializer, so I had to adopt code for that.
Probably the only test that is not actually structured is the last one in TestNormalizeNestedInitializers
, where I just produced some weird pretty unrealistic scenario with a bunch on different nested initializers/anonymous object creations and I managed to find some bugs using it as well)
src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Rikki Gibson <rikkigibson@gmail.com>
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.
Still LGTM Thanks (iteration 20)
@RikkiGibson I resolved merge conflicts, just need an approval from you |
Thanks @DoctorKrolic for the contribution! |
Fixes: #61204
Normilize whitespace for object/collection initializers by putting every new statement in a separate line:
When initializer is inside string interpolation (doesn't matter verbatim or not), the behaviour changes to nicely format initializer in a single line, e.g.: