diff --git a/src/Analyzers/CSharp/Tests/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionFixAllTests.cs b/src/Analyzers/CSharp/Tests/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionFixAllTests.cs index be82952deb667..2adc585610f97 100644 --- a/src/Analyzers/CSharp/Tests/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionFixAllTests.cs +++ b/src/Analyzers/CSharp/Tests/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionFixAllTests.cs @@ -194,12 +194,12 @@ System.Func M(int i, int j) // 1 // 2 _ => () => - { - return j switch - { - _ => 3, - }; - } + { + return j switch + { + _ => 3, + }; + } , }; diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ConvertLinq/ConvertForEachToLinqQueryTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/ConvertLinq/ConvertForEachToLinqQueryTests.cs index a86fa1a4029e1..ab5c7aee6e1ea 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/ConvertLinq/ConvertForEachToLinqQueryTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/ConvertLinq/ConvertForEachToLinqQueryTests.cs @@ -4324,7 +4324,7 @@ void M(IEnumerable nums) /* 8*/// 9 /* 10 */ where/* 11 *//* 12 */n1 /* 13 */ > /* 14 */ 0/* 15 */// 16 - select n1/* 4 *//* 21 */// 22 + select n1/* 4 *//* 21 */// 22 /*23*//*24*/ ) { diff --git a/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs index 1d26f92ade343..eccc90cec61fc 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/InlineTemporary/InlineTemporaryTests.cs @@ -1368,9 +1368,9 @@ await TestFixOneAsync(@" { int #if true - y, + y, #endif - z; + z; int a = 1; }"); @@ -1395,7 +1395,7 @@ await TestFixOneAsync(@" #if true #endif - z; + z; int a = 1; }"); @@ -1418,9 +1418,9 @@ await TestFixOneAsync(@" { int y, #if true - z + z #endif - ; + ; int a = 1; }"); diff --git a/src/EditorFeatures/CSharpTest/CodeActions/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.cs b/src/EditorFeatures/CSharpTest/CodeActions/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.cs index 91eb93138bfea..c716feadef23c 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/ReplaceMethodWithProperty/ReplaceMethodWithPropertyTests.cs @@ -1937,7 +1937,7 @@ int Goo get { throw e + - e; + e; } } }", options: new OptionsCollection(GetLanguage()) diff --git a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs index 4d20802ff3c66..f021e8c203279 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs @@ -8,11 +8,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.BraceCompletion; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; -using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editor.Implementation.Formatting; using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities; @@ -27,6 +25,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Formatting { + [Trait(Traits.Feature, Traits.Features.Formatting)] public class FormattingEngineTests : CSharpFormattingEngineTestBase { public FormattingEngineTests(ITestOutputHelper output) : base(output) { } @@ -43,7 +42,6 @@ private static Dictionary SmartIndentButDoNotFormatWhileTypi [WpfFact] [WorkItem(539682, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539682")] - [Trait(Traits.Feature, Traits.Features.Formatting)] public void FormatDocumentCommandHandler() { var code = @"class Program @@ -71,7 +69,6 @@ static void Main(string[] args) [WpfFact] [WorkItem(539682, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539682")] - [Trait(Traits.Feature, Traits.Features.Formatting)] public void FormatDocumentPasteCommandHandler() { var code = @"class Program @@ -99,7 +96,6 @@ static void Main(string[] args) [WpfFact] [WorkItem(547261, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547261")] - [Trait(Traits.Feature, Traits.Features.Formatting)] public void FormatDocumentReadOnlyWorkspacePasteCommandHandler() { var code = @"class Program @@ -127,7 +123,6 @@ static void Main(string[] args) [WpfFact] [WorkItem(912965, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/912965")] - [Trait(Traits.Feature, Traits.Features.Formatting)] public void DoNotFormatUsingStatementOnReturn() { var code = @"class Program @@ -155,7 +150,6 @@ static void Main(string[] args) [WpfFact] [WorkItem(912965, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/912965")] - [Trait(Traits.Feature, Traits.Features.Formatting)] public void FormatUsingStatementWhenTypingCloseParen() { var code = @"class Program @@ -183,7 +177,6 @@ static void Main(string[] args) [WpfFact] [WorkItem(912965, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/912965")] - [Trait(Traits.Feature, Traits.Features.Formatting)] public void FormatNotUsingStatementOnReturn() { var code = @"class Program @@ -210,7 +203,7 @@ static void Main(string[] args) } [WorkItem(977133, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/977133")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatRangeOrFormatTokenOnOpenBraceOnSameLine() { var code = @"class C @@ -231,7 +224,7 @@ public void M() } [WorkItem(14491, "https://github.com/dotnet/roslyn/pull/14491")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatRangeButFormatTokenOnOpenBraceOnNextLine() { var code = @"class C @@ -254,7 +247,7 @@ public void M() } [WorkItem(1007071, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1007071")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatPragmaWarningInbetweenDelegateDeclarationStatement() { var code = @"using System; @@ -287,7 +280,7 @@ static void Main(string[] args) } [WorkItem(771761, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/771761")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatHashRegion() { var code = @"using System; @@ -312,7 +305,7 @@ static void Main(string[] args) } [WorkItem(771761, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/771761")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatHashEndRegion() { var code = @"using System; @@ -339,7 +332,7 @@ static void Main(string[] args) } [WorkItem(987373, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/987373")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public async Task FormatSpansIndividuallyWithoutCollapsing() { var code = @"class C @@ -432,7 +425,7 @@ public void M() } [WorkItem(1044118, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1044118")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void SemicolonInCommentOnLastLineDoesNotFormat() { var code = @"using System; @@ -459,7 +452,7 @@ static void Main(string[] args) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideSingleLineRegularComment_1() { var code = @"class Program @@ -484,7 +477,7 @@ static void Main(int a, int b) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideSingleLineRegularComment_2() { var code = @"class Program @@ -509,7 +502,7 @@ static void Main(int a, int b) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideMultiLineRegularComment_1() { var code = @"class Program @@ -532,7 +525,7 @@ static void Main(int a/* { */, int b) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideMultiLineRegularComment_2() { var code = @"class Program @@ -557,7 +550,7 @@ static void Main(int a/* { [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideMultiLineRegularComment_3() { var code = @"class Program @@ -582,7 +575,7 @@ static void Main(int a/* { [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideSingleLineDocComment_1() { var code = @"class Program @@ -607,7 +600,7 @@ static void Main(int a, int b) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideSingleLineDocComment_2() { var code = @"class Program @@ -632,7 +625,7 @@ static void Main(int a, int b) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideMultiLineDocComment_1() { var code = @"class Program @@ -657,7 +650,7 @@ static void Main(int a, int b) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideMultiLineDocComment_2() { var code = @"class Program @@ -684,7 +677,7 @@ static void Main(int a, int b) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideMultiLineDocComment_3() { var code = @"class Program @@ -711,7 +704,7 @@ static void Main(int a, int b) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideInactiveCode() { var code = @"class Program @@ -742,7 +735,7 @@ static void Main(string[] args) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideStringLiteral() { var code = @"class Program @@ -765,7 +758,7 @@ static void Main(string[] args) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideCharLiteral() { var code = @"class Program @@ -788,7 +781,7 @@ static void Main(string[] args) [WorkItem(449, "https://github.com/dotnet/roslyn/issues/449")] [WorkItem(1077103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077103")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void NoFormattingInsideCommentsOfPreprocessorDirectives() { var code = @"class Program @@ -815,7 +808,7 @@ static void Main(string[] args) [WorkItem(464, "https://github.com/dotnet/roslyn/issues/464")] [WorkItem(908729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void ColonInSwitchCase() { var code = @"class Program @@ -846,7 +839,7 @@ static void Main(string[] args) [WorkItem(464, "https://github.com/dotnet/roslyn/issues/464")] [WorkItem(908729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void ColonInDefaultSwitchCase() { var code = @"class Program @@ -878,7 +871,7 @@ static void Main(string[] args) } [WorkItem(9097, "https://github.com/dotnet/roslyn/issues/9097")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void ColonInPatternSwitchCase01() { var code = @"class Program @@ -907,7 +900,7 @@ static void Main() [WorkItem(464, "https://github.com/dotnet/roslyn/issues/464")] [WorkItem(908729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void ColonInLabeledStatement() { var code = @"class Program @@ -930,7 +923,7 @@ static void Main(string[] args) [WorkItem(464, "https://github.com/dotnet/roslyn/issues/464")] [WorkItem(908729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatColonInTargetAttribute() { var code = @"using System; @@ -949,7 +942,7 @@ class C : Attribute [WorkItem(464, "https://github.com/dotnet/roslyn/issues/464")] [WorkItem(908729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatColonInBaseList() { var code = @"class C :$$ Attribute @@ -964,7 +957,7 @@ public void DoNotFormatColonInBaseList() [WorkItem(464, "https://github.com/dotnet/roslyn/issues/464")] [WorkItem(908729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatColonInThisConstructor() { var code = @"class Goo @@ -993,7 +986,7 @@ public void DoNotFormatColonInThisConstructor() [WorkItem(464, "https://github.com/dotnet/roslyn/issues/464")] [WorkItem(908729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatColonInConditionalOperator() { var code = @"class Program @@ -1016,7 +1009,7 @@ static void Main(string[] args) [WorkItem(464, "https://github.com/dotnet/roslyn/issues/464")] [WorkItem(908729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatColonInArgument() { var code = @"class Program @@ -1039,7 +1032,7 @@ static void Main(string[] args) [WorkItem(464, "https://github.com/dotnet/roslyn/issues/464")] [WorkItem(908729, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/908729")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatColonInTypeParameter() { var code = @"class Program @@ -1063,7 +1056,7 @@ class C1 } [WorkItem(2224, "https://github.com/dotnet/roslyn/issues/2224")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DontSmartFormatBracesOnSmartIndentNone() { var code = @"class Program @@ -1318,7 +1311,7 @@ public int P AssertFormatAfterTypeChar(code, expected); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatIncompleteBlockOnSingleLineIfNotTypingCloseCurly1() { var code = @"namespace ConsoleApplication1 @@ -1342,7 +1335,7 @@ static bool Property AssertFormatAfterTypeChar(code, expected); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatIncompleteBlockOnSingleLineIfNotTypingCloseCurly2() { var code = @"namespace ConsoleApplication1 @@ -1362,7 +1355,7 @@ class Program AssertFormatAfterTypeChar(code, expected); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatIncompleteBlockOnSingleLineIfNotTypingCloseCurly3() { var code = @"namespace ConsoleApplication1 @@ -1382,7 +1375,7 @@ class Program AssertFormatAfterTypeChar(code, expected); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatCompleteBlockOnSingleLineIfTypingCloseCurly1() { var code = @"namespace ConsoleApplication1 @@ -1404,7 +1397,7 @@ static bool Property AssertFormatAfterTypeChar(code, expected); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatCompleteBlockOnSingleLineIfTypingCloseCurly2() { var code = @"namespace ConsoleApplication1 @@ -1422,7 +1415,7 @@ class Program AssertFormatAfterTypeChar(code, expected); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatIncompleteBlockOnMultipleLinesIfTypingCloseCurly1() { var code = @"namespace ConsoleApplication1 @@ -1448,7 +1441,7 @@ static bool Property AssertFormatAfterTypeChar(code, expected); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatIncompleteBlockOnMultipleLinesIfTypingCloseCurly2() { var code = @"namespace ConsoleApplication1 @@ -1474,7 +1467,7 @@ static bool Property AssertFormatAfterTypeChar(code, expected); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoNotFormatCompleteBlockOnSingleLineIfTypingSemicolon() { var code = @@ -1500,7 +1493,7 @@ void M() AssertFormatAfterTypeChar(code, expected); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatCompleteBlockOnSingleLineIfTypingCloseCurlyOnLaterLine() { var code = @@ -1531,7 +1524,7 @@ void M() } [WorkItem(7900, "https://github.com/dotnet/roslyn/issues/7900")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatLockStatementWithEmbeddedStatementOnSemicolonDifferentLine() { var code = @"class C @@ -1556,7 +1549,7 @@ public void M() } [WorkItem(7900, "https://github.com/dotnet/roslyn/issues/7900")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatLockStatementWithEmbeddedStatementOnSemicolonSameLine() { var code = @"class C @@ -1579,7 +1572,7 @@ public void M() } [WorkItem(11642, "https://github.com/dotnet/roslyn/issues/11642")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatArbitraryNodeParenthesizedLambdaExpression() { // code equivalent to an expression synthesized like so: @@ -1590,8 +1583,58 @@ public void FormatArbitraryNodeParenthesizedLambdaExpression() AssertFormatOnArbitraryNode(node, expected); } + [WpfFact] + [WorkItem(57465, "https://github.com/dotnet/roslyn/issues/57465")] + public async Task FormatLambdaWithDirective() + { + var code = @"namespace N +{ + public class C + { + protected void Render() + { + if (outer) + { + M(() => + { +#nullable enable + if (inner) + { + } + } + ); + } + } + } +} +"; + var expected = @"namespace N +{ + public class C + { + protected void Render() + { + if (outer) + { + M(() => + { +#nullable enable + if (inner) + { + } + } + ); + } + } + } +} +"; + + await AssertFormatAsync(expected, code, spans: null); + } + [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentOpenBraceEvenWithFormatWhileTypingOff1() { var code = @@ -1618,7 +1661,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentOpenBraceEvenWithFormatWhileTypingOff2() { var code = @@ -1645,7 +1688,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentOpenBraceEvenWithFormatWhileTypingOff3() { // We only smart indent the { if it's on it's own line. @@ -1671,7 +1714,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentOpenBraceEvenWithFormatWhileTypingOff4() { // We only smart indent the { if it's on it's own line. @@ -1697,7 +1740,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentOpenBraceEvenWithFormatWhileTypingOff5() { // Typing the { should not affect the formating of the preceding tokens. @@ -1725,7 +1768,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentOpenBraceEvenWithFormatWhileTypingOff6() { // Typing the { should not affect the formating of the preceding tokens. @@ -1751,7 +1794,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentOpenBraceEvenWithFormatWhileTypingOff7() { var code = @@ -1772,7 +1815,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentCloseBraceEvenWithFormatWhileTypingOff1() { var code = @@ -1801,7 +1844,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentCloseBraceEvenWithFormatWhileTypingOff2() { // Note that the { is not updated since we are not formatting. @@ -1829,7 +1872,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentCloseBraceEvenWithFormatWhileTypingOff3() { var code = @@ -1852,7 +1895,7 @@ void M() } [WorkItem(30787, "https://github.com/dotnet/roslyn/issues/30787")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void DoSmartIndentCloseBraceEvenWithFormatWhileTypingOff4() { // Should not affect formatting of open brace @@ -1874,7 +1917,6 @@ void M() { } [WpfFact] - [Trait(Traits.Feature, Traits.Features.Formatting)] [WorkItem(31907, "https://github.com/dotnet/roslyn/issues/31907")] public async Task NullableReferenceTypes() { @@ -1901,7 +1943,7 @@ void MyMethod() } [WorkItem(30518, "https://github.com/dotnet/roslyn/issues/30518")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void FormatGeneratedNodeInInitializer() { var code = @"new bool[] { @@ -1923,7 +1965,6 @@ public void FormatGeneratedNodeInInitializer() } [WpfFact] - [Trait(Traits.Feature, Traits.Features.Formatting)] [WorkItem(27268, "https://github.com/dotnet/roslyn/issues/27268")] public async Task PositionalPattern() { @@ -1958,7 +1999,6 @@ void MyMethod() } [WpfFact] - [Trait(Traits.Feature, Traits.Features.Formatting)] public async Task WithExpression() { var code = @"[| @@ -1984,7 +2024,6 @@ void M() } [WpfFact] - [Trait(Traits.Feature, Traits.Features.Formatting)] public async Task WithExpression_MultiLine() { var code = @"[| @@ -2018,7 +2057,6 @@ void M() } [WpfFact] - [Trait(Traits.Feature, Traits.Features.Formatting)] public async Task WithExpression_MultiLine_UserPositionedBraces() { var code = @"[| @@ -2052,7 +2090,7 @@ void M() } [WorkItem(25003, "https://github.com/dotnet/roslyn/issues/25003")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void SeparateGroups_KeepMultipleLinesBetweenGroups() { var code = @"$$ @@ -2077,7 +2115,7 @@ public void SeparateGroups_KeepMultipleLinesBetweenGroups() } [WorkItem(25003, "https://github.com/dotnet/roslyn/issues/25003")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void SeparateGroups_KeepMultipleLinesBetweenGroups_FileScopedNamespace() { var code = @"$$ @@ -2106,7 +2144,7 @@ namespace N; } [WorkItem(25003, "https://github.com/dotnet/roslyn/issues/25003")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void SeparateGroups_DoNotGroupIfNotSorted() { var code = @"$$ @@ -2127,7 +2165,7 @@ public void SeparateGroups_DoNotGroupIfNotSorted() } [WorkItem(25003, "https://github.com/dotnet/roslyn/issues/25003")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void SeparateGroups_GroupIfSorted() { var code = @"$$ @@ -2149,7 +2187,7 @@ public void SeparateGroups_GroupIfSorted() } [WorkItem(25003, "https://github.com/dotnet/roslyn/issues/25003")] - [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] + [WpfFact] public void SeparateGroups_GroupIfSorted_RecognizeSystemNotFirst() { var code = @"$$ @@ -2256,7 +2294,7 @@ private static void AssertFormatAfterTypeChar(string code, string expected, Dict var newSnapshot = subjectDocument.GetTextBuffer().CurrentSnapshot; - Assert.Equal(expected, newSnapshot.GetText()); + AssertEx.EqualOrDiff(expected, newSnapshot.GetText()); } } } diff --git a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs index b905addc182d9..7a7eb4a5d95fb 100644 --- a/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs +++ b/src/EditorFeatures/TestUtilities/Formatting/CoreFormatterTestsBase.cs @@ -5,6 +5,7 @@ #nullable disable using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -18,6 +19,7 @@ using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text.Shared.Extensions; using Microsoft.VisualStudio.Text; @@ -176,7 +178,7 @@ protected async Task AssertFormatAsync(string expected, string code, IEnumerable { var factory = (TestFormattingRuleFactoryServiceFactory.Factory)formattingRuleProvider; factory.BaseIndentation = baseIndentation.Value; - factory.TextSpan = spans.First(); + factory.TextSpan = spans?.First() ?? syntaxTree.GetRoot(CancellationToken.None).FullSpan; } var optionSet = workspace.Options; @@ -220,7 +222,7 @@ internal void AssertFormat(Workspace workspace, string expected, SyntaxFormattin if (actual != expected) { _output.WriteLine(actual); - Assert.Equal(expected, actual); + AssertEx.EqualOrDiff(expected, actual); } } @@ -264,12 +266,12 @@ protected async Task AssertFormatWithBaseIndentAsync( string expected, string markupCode, int baseIndentation, Dictionary options = null) { - MarkupTestFile.GetSpan(markupCode, out var code, out var span); + TestFileMarkupParser.GetSpans(markupCode, out var code, out ImmutableArray spans); await AssertFormatAsync( expected, code, - new List { span }, + spans, changedOptionSet: options, baseIndentation: baseIndentation); } diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb b/src/EditorFeatures/VisualBasicTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb index 985f3fb7a7908..117e73e1a6016 100644 --- a/src/EditorFeatures/VisualBasicTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb +++ b/src/EditorFeatures/VisualBasicTest/CodeActions/ReplacePropertyWithMethods/ReplacePropertyWithMethodsTests.vb @@ -45,7 +45,7 @@ end class", "class C Public Function GetProp() As Integer return _ -0 + 0 End Function end class") End Function @@ -64,7 +64,7 @@ end class", "class C Public Function GetProp() As Integer return _ ' Test -0 + 0 End Function end class") End Function diff --git a/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs b/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs index 55e783f57cd84..39245c983caeb 100644 --- a/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs +++ b/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs @@ -2986,8 +2986,8 @@ await AssertFormatAsync(@"class C int Method() { var q = from c in Get(1 + - 2 + - 3) + 2 + + 3) from b in Get(1 + 2 + 3) diff --git a/src/Workspaces/CoreTestUtilities/Formatting/FormattingTestBase.cs b/src/Workspaces/CoreTestUtilities/Formatting/FormattingTestBase.cs index 8d7d718b351a7..c19aca7599943 100644 --- a/src/Workspaces/CoreTestUtilities/Formatting/FormattingTestBase.cs +++ b/src/Workspaces/CoreTestUtilities/Formatting/FormattingTestBase.cs @@ -3,12 +3,12 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; @@ -67,7 +67,7 @@ private protected async Task AssertFormatAsync( var root = await syntaxTree.GetRootAsync(); var options = SyntaxFormattingOptions.Create(optionSet, workspace.Services, root.Language); - AssertFormat(workspace.Services, expected, root, spans, options, await document.GetTextAsync()); + await AssertFormatAsync(workspace.Services, expected, root, spans.AsImmutable(), options, await document.GetTextAsync()); // format with node and transform AssertFormatWithTransformation(workspace.Services, expected, root, spans, options, treeCompare, parseOptions); @@ -93,10 +93,48 @@ internal void AssertFormatWithTransformation( } } - internal static void AssertFormat(HostWorkspaceServices services, string expected, SyntaxNode root, IEnumerable spans, SyntaxFormattingOptions options, SourceText sourceText) + private static async Task AssertFormatAsync(HostWorkspaceServices services, string expected, SyntaxNode root, ImmutableArray spans, SyntaxFormattingOptions options, SourceText sourceText) { + // Verify formatting the input code produces the expected result var result = Formatter.GetFormattedTextChanges(root, spans, services, options); AssertResult(expected, sourceText, result); + + // Verify formatting the output code produces itself (formatting is idempotent) + var resultText = sourceText.WithChanges(result); + if (TryAdjustSpans(sourceText, result, resultText, spans, out var adjustedSpans)) + { + var resultRoot = await root.SyntaxTree.WithChangedText(resultText).GetRootAsync(); + var idempotentResult = Formatter.GetFormattedTextChanges(resultRoot, adjustedSpans, services, options); + AssertResult(expected, resultText, idempotentResult); + } + } + + private static bool TryAdjustSpans(SourceText inputText, IList changes, SourceText outputText, ImmutableArray inputSpans, out ImmutableArray outputSpans) + { + if (changes.Count == 0) + { + outputSpans = inputSpans; + return true; + } + + var outputBuilder = ImmutableArray.CreateBuilder(inputSpans.Length); + for (var i = 0; i < inputSpans.Length; i++) + { + var span = inputSpans[i]; + if (span.Start == 0 && span.End == inputText.Length) + { + // The input span is the full document + outputBuilder.Add(TextSpan.FromBounds(0, outputText.Length)); + continue; + } + + // The input span cannot be automatically adjusted + outputSpans = default; + return false; + } + + outputSpans = outputBuilder.MoveToImmutable(); + return true; } protected static void AssertResult(string expected, SourceText sourceText, IList result) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Engine/Trivia/CSharpTriviaFormatter.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Engine/Trivia/CSharpTriviaFormatter.cs index 50507e48f85ac..6b858eb9a44b5 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Engine/Trivia/CSharpTriviaFormatter.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Engine/Trivia/CSharpTriviaFormatter.cs @@ -69,19 +69,13 @@ protected override LineColumnRule GetLineColumnRuleBetween(SyntaxTrivia trivia1, // [trivia] [whitespace] [token] case if (trivia2.IsKind(SyntaxKind.None)) { - var insertNewLine = this.FormattingRules.GetAdjustNewLinesOperation(this.Token1, this.Token2) != null; - if (IsMultilineComment(trivia1)) { + var insertNewLine = this.FormattingRules.GetAdjustNewLinesOperation(this.Token1, this.Token2) != null; return LineColumnRule.PreserveLinesWithGivenIndentation(lines: insertNewLine ? 1 : 0); } - if (insertNewLine) - { - return LineColumnRule.PreserveLinesWithDefaultIndentation(lines: 0); - } - - if (existingWhitespaceBetween.Lines > 0 && existingWhitespaceBetween.Spaces != this.Spaces) + if (existingWhitespaceBetween.Spaces != this.Spaces) { return LineColumnRule.PreserveWithGivenSpaces(spaces: this.Spaces); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.AnchorData.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.AnchorData.cs index a89fb23292cfd..01de97733daff 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.AnchorData.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.AnchorData.cs @@ -17,20 +17,21 @@ private class AnchorData { private readonly AnchorIndentationOperation _operation; - public AnchorData(AnchorIndentationOperation operation, int originalColumn) + public AnchorData(AnchorIndentationOperation operation, SyntaxToken anchorToken, int originalColumn) { _operation = operation; + this.AnchorToken = anchorToken; this.OriginalColumn = originalColumn; } public TextSpan TextSpan => _operation.TextSpan; - public SyntaxToken AnchorToken => _operation.AnchorToken; - public SyntaxToken StartToken => _operation.StartToken; public SyntaxToken EndToken => _operation.EndToken; + public SyntaxToken AnchorToken { get; } + public int OriginalColumn { get; } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.cs index b3546b76d42e2..ea4d4eaba2d9d 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Context/FormattingContext.cs @@ -403,8 +403,21 @@ public void AddAnchorIndentationOperation(AnchorIndentationOperation operation) return; } - var originalSpace = _tokenStream.GetOriginalColumn(operation.StartToken); - var data = new AnchorData(operation, originalSpace); + // If the indentation changes on a line which other code is anchored to, adjust those other lines to reflect + // the same change in indentation. Note that we anchor to the first token on a line to account for common + // cases like the following code, where the `{` token is anchored to the `(` token of `()`: + // + // ↓ this space can be removed, which moves `(` one character to the left + // var x = Method( () => + // { + // ↑ this `{` anchors to `var` instead of `(`, which prevents it from moving when `(` is moved + // }); + // + // The calculation of true anchor token (which is always the first token on a line) is delayed to account + // for cases where the original anchor token is moved to a new line during a formatting operation. + var anchorToken = _tokenStream.FirstTokenOfBaseTokenLine(operation.AnchorToken); + var originalSpace = _tokenStream.GetOriginalColumn(anchorToken); + var data = new AnchorData(operation, anchorToken, originalSpace); _anchorTree.AddIntervalInPlace(data); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Rules/Operations/AnchorIndentationOperation.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Rules/Operations/AnchorIndentationOperation.cs index adcfb981e18f6..8175b0dad2b0e 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Rules/Operations/AnchorIndentationOperation.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Rules/Operations/AnchorIndentationOperation.cs @@ -13,25 +13,23 @@ namespace Microsoft.CodeAnalysis.Formatting.Rules /// internal sealed class AnchorIndentationOperation { - internal AnchorIndentationOperation(SyntaxToken anchorToken, SyntaxToken startToken, SyntaxToken endToken, TextSpan textSpan) + internal AnchorIndentationOperation(SyntaxToken anchorToken, SyntaxToken endToken, TextSpan textSpan) { Contract.ThrowIfTrue(anchorToken.RawKind == 0); Contract.ThrowIfTrue(textSpan.Start < 0 || textSpan.Length < 0); - Contract.ThrowIfTrue(startToken.RawKind == 0); Contract.ThrowIfTrue(endToken.RawKind == 0); this.AnchorToken = anchorToken; this.TextSpan = textSpan; - this.StartToken = startToken; this.EndToken = endToken; } public SyntaxToken AnchorToken { get; } public TextSpan TextSpan { get; } - public SyntaxToken StartToken { get; } + public SyntaxToken StartToken => AnchorToken; public SyntaxToken EndToken { get; } } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Rules/Operations/FormattingOperations.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Rules/Operations/FormattingOperations.cs index c3976ca379f8b..bc025f6b723b8 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Rules/Operations/FormattingOperations.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Formatting/Rules/Operations/FormattingOperations.cs @@ -25,16 +25,16 @@ internal static class FormattingOperations /// /// create anchor indentation region around start and end token - /// start token will act as anchor token and right after anchor token to end of end token will become anchor region + /// right after anchor token to end of end token will become anchor region /// - public static AnchorIndentationOperation CreateAnchorIndentationOperation(SyntaxToken startToken, SyntaxToken endToken) - => CreateAnchorIndentationOperation(startToken, startToken, endToken, TextSpan.FromBounds(startToken.Span.End, endToken.Span.End)); + public static AnchorIndentationOperation CreateAnchorIndentationOperation(SyntaxToken anchorToken, SyntaxToken endToken) + => CreateAnchorIndentationOperation(anchorToken, endToken, TextSpan.FromBounds(anchorToken.Span.End, endToken.Span.End)); /// /// create anchor indentation region more explicitly by providing all necessary information. /// - public static AnchorIndentationOperation CreateAnchorIndentationOperation(SyntaxToken anchorToken, SyntaxToken startToken, SyntaxToken endToken, TextSpan textSpan) - => new(anchorToken, startToken, endToken, textSpan); + public static AnchorIndentationOperation CreateAnchorIndentationOperation(SyntaxToken anchorToken, SyntaxToken endToken, TextSpan textSpan) + => new(anchorToken, endToken, textSpan); /// /// create suppress region around start and end token diff --git a/src/Workspaces/VisualBasicTest/Formatting/FormattingTests.vb b/src/Workspaces/VisualBasicTest/Formatting/FormattingTests.vb index b6125179e2998..a92283e2be319 100644 --- a/src/Workspaces/VisualBasicTest/Formatting/FormattingTests.vb +++ b/src/Workspaces/VisualBasicTest/Formatting/FormattingTests.vb @@ -478,7 +478,7 @@ Imports System. End Function - Public Async Function AnchorQueryStatement() As Task + Public Async Function AnchorQueryStatement1() As Task Dim code = Class C Sub Method() Dim a = From q In @@ -491,12 +491,60 @@ End Class Dim expected = Class C Sub Method() Dim a = From q In + {1, 3, 5} + Where q > 10 + Select q + End Sub +End Class + + Await AssertFormatLf2CrLfAsync(code.Value, expected.Value) + End Function + + + Public Async Function AnchorQueryStatement2() As Task + Dim code = Class C + Sub Method() + Dim a = From q In {1, 3, 5} Where q > 10 Select q End Sub End Class + Dim expected = Class C + Sub Method() + Dim a = From q In + {1, 3, 5} + Where q > 10 + Select q + End Sub +End Class + + Await AssertFormatLf2CrLfAsync(code.Value, expected.Value) + End Function + + + Public Async Function AnchorQueryStatement3() As Task + Dim code = Class C + Sub Method() + Dim a = + From q In + {1, 3, 5} + Where q > 10 + Select q + End Sub +End Class + + Dim expected = Class C + Sub Method() + Dim a = + From q In + {1, 3, 5} + Where q > 10 + Select q + End Sub +End Class + Await AssertFormatLf2CrLfAsync(code.Value, expected.Value) End Function