-
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
Fixed List pattern is not correctly formatted in the first arm of a switch expression #72269
base: main
Are you sure you want to change the base?
Fixed List pattern is not correctly formatted in the first arm of a switch expression #72269
Conversation
…witch expression fixes dotnet#72196
var lastToken = node.GetLastToken(includeZeroWidth: true); | ||
var baseToken = firstToken.GetPreviousToken(includeZeroWidth: true); | ||
|
||
SetAlignmentBlockOperation(list, baseToken, firstToken, lastToken, option); |
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.
An attempt (reverting the code + changes state below) that fixes the failing CollectionExpressionWrappingTests
if (node.Parent is not SwitchExpressionArmSyntax)
{
SetAlignmentBlockOperation(list, baseToken, firstToken, lastToken, option);
} else {
AddAlignmentBlockOperationRelativeToFirstTokenOnBaseTokenLine(list, bracketPair);
}
But I have a feeling this is not the right way :)
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.
this seems generally odd to me. i would expect taht indent block operations would be set for the switch expression, and its arms. Nothing to do with list expressions.
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.
Switch has indent block operations but not his arms. I think they don't need to have.
I think the problem is having wrong base & first tokens for list pattern
var result1 = new int[] { 1, 2 } switch // List pattern
{
[1] => "one",
_ => "unknown"
};
var result2 = new int[] { 1, 2 } switch // property pattern clause
{
{ Length: 0 } => "empty",
[1] => "one",
_ => "unknown"
};
First Switch expression arm | Base Token | Start Token | End Token |
---|---|---|---|
Property pattern clause | { (opening prop pattern) |
Length |
} (closing prop pattern) |
List pattern expected | [ (opening list pattern) |
1 |
] (closing list pattern) |
List pattern actual | { (opening switch expression) |
[ |
] (closing list pattern) |
cefea73
to
b385a69
Compare
@@ -257,7 +257,14 @@ private static void AddBracketIndentationOperation(List<IndentBlockOperation> li | |||
if (!bracketPair.IsValidBracketOrBracePair()) | |||
return; | |||
|
|||
if (node.Parent != null && node.Kind() is SyntaxKind.ListPattern or SyntaxKind.CollectionExpression) | |||
if (node.Parent != null && node.Kind() is SyntaxKind.ListPattern) |
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.
@CyrusNajmabadi I think the safest way is to separate ListPattern
from CollectionExpression
and use the logic before this change.
As I know list pattern doesn't support wrapping and we don't need to handle the double indentation issue.
PS: please take a look also at the previous comment
@CyrusNajmabadi any feedback here? 🌝 |
Can look later. On vacation. :+) |
@CyrusNajmabadi kind reminder :) |
@@ -257,7 +257,14 @@ private static void AddBracketIndentationOperation(List<IndentBlockOperation> li | |||
if (!bracketPair.IsValidBracketOrBracePair()) | |||
return; | |||
|
|||
if (node.Parent != null && node.Kind() is SyntaxKind.ListPattern or SyntaxKind.CollectionExpression) | |||
if (node.Parent != null && node.Kind() is SyntaxKind.ListPattern) |
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 IsKind
method is more efficient than Kind
if (node.Parent != null && node.Kind() is SyntaxKind.ListPattern) | |
if (node.Parent != null && node.IsKind(SyntaxKind.ListPattern)) |
return; | ||
} | ||
|
||
if (node.Parent != null && node.Kind() is SyntaxKind.CollectionExpression) | ||
{ | ||
// Brackets in list patterns are formatted like blocks, so align close bracket with open bracket |
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.
💡 This comment seems incorrect now
if (node.Parent != null && node.Kind() is SyntaxKind.ListPattern or SyntaxKind.CollectionExpression) | ||
if (node.Parent != null && node.Kind() is SyntaxKind.ListPattern) | ||
{ | ||
AddAlignmentBlockOperationRelativeToFirstTokenOnBaseTokenLine(list, bracketPair); |
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 happens if we omit this line?
What happens if we remove the SetAlignmentBlockOperation
call for CollectionExpression
?
What happens if we change the call for CollectionExpression
to use the same form we have for ListPattern
?
} | ||
|
||
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72196")] | ||
public async Task TestSwitchExpression_WithDiscardOperator_ShouldFormatListPattern() |
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.
📝 There is no list pattern here
code: @" | ||
var result3 = new int[] { 1, 2 } switch | ||
{ | ||
{ Length: 0 } => ""empty"", | ||
[1] => ""one"", | ||
_ => ""unknown"" | ||
}; | ||
", | ||
expected: @" | ||
var result3 = new int[] { 1, 2 } switch | ||
{ | ||
{ Length: 0 } => ""empty"", | ||
[1] => ""one"", | ||
_ => ""unknown"" | ||
}; | ||
"); |
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 these are the same, can you extract a local variable for it?
code: @" | ||
var result3 = new int[] { 1, 2 } switch | ||
{ | ||
{ Length: 0 } => ""empty"", | ||
[1] => ""one"", | ||
_ => ""unknown"" | ||
}; | ||
", | ||
expected: @" | ||
var result3 = new int[] { 1, 2 } switch | ||
{ | ||
{ Length: 0 } => ""empty"", | ||
[1] => ""one"", | ||
_ => ""unknown"" | ||
}; |
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 these are the same, can you extract a local variable for it?
@@ -10940,5 +10940,128 @@ public async Task TestNormalizeUsingAlias(string text, string expected) | |||
{ | |||
await AssertFormatAsync(expected, text); | |||
} | |||
|
|||
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72196")] | |||
public async Task TestSwitchExpression_WithFormattedListPattern_ShouldNotFormatListPattern() |
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 theory, this test should not be necessary. Ideally each call to AssertFormatAsync
should verify both of the following:
- Formatting
code
producesexpected
- If
code
andexpected
are not the same, formattingexpected
also producesexpected
Unfortunately, the AssertFormatAsync
method is a bit convoluted to applying this change should be done in a separate pull request.
Fixes #72196
UPD#1: converted to draft PR as other tests fail (CollectionExpressionWrappingTests), not sure the code change is the right one
UPD#2: It seems this bug was introduced by this change
I analyzed in comparison with the case if using property pattern. The code tries to get the indentation from the smallest containing interval, but since the alignment block operation does not calculate the spans correctly, it takes the indentation value from wrong (but indeed smallest) interval.
After code changes the same smallest interval is picked as we have in case the first switch arm is a property pattern:
ListPattern.mp4