/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Analyzers/CSharp/Tests/ConvertSwitchStatementToExpression/ConvertSwitchStatementToExpressionTests.cs
2 549 строк
71 KB
Cyrus Najmabadi
Fix tests
16 окт 2025, 23:49
16 окт 2025, 23:49
3e16ed9
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.CodeStyle; using Microsoft.CodeAnalysis.CSharp.ConvertSwitchStatementToExpression; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Testing; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertSwitchStatementToExpression; using VerifyCS = CSharpCodeFixVerifier< ConvertSwitchStatementToExpressionDiagnosticAnalyzer, ConvertSwitchStatementToExpressionCodeFixProvider>; [Trait(Traits.Feature, Traits.Features.CodeActionsConvertSwitchStatementToExpression)] public sealed class ConvertSwitchStatementToExpressionTests { private static readonly LanguageVersion CSharp9 = LanguageVersion.CSharp9; [Theory, CombinatorialData] public void TestStandardProperty(AnalyzerProperty property) => VerifyCS.VerifyStandardProperty(property); [Fact] public Task TestReturn() => VerifyCS.VerifyCodeFixAsync( """ class Program { int M(int i) { [|switch|] (i) { case 1: return 4; case 2: return 5; case 3: return 6; default: return 7; } } } """, """ class Program { int M(int i) { return i switch { 1 => 4, 2 => 5, 3 => 6, _ => 7, }; } } """); [Fact] public Task TestReturnAndThrow() => VerifyCS.VerifyCodeFixAsync( """ class Program { int M(int i) { [|switch|] (i) { case 1: return 4; default: throw null; case 2: return 5; case 3: return 6; } } } """, """ class Program { int M(int i) { return i switch { 1 => 4, 2 => 5, 3 => 6, _ => throw null, }; } } """); [Fact] public Task TestAssignment_Array() => VerifyCS.VerifyCodeFixAsync( """ class Program { int[] array = new int[1]; void M(int i) { [|switch|] (i) { case 1: array[0] = 4; break; case 2: array[0] = 5; break; case 3: array[0] = 6; break; default: array[0] = 7; break; } } } """, """ class Program { int[] array = new int[1]; void M(int i) { array[0] = i switch { 1 => 4, 2 => 5, 3 => 6, _ => 7, }; } } """); [Fact] public async Task TestMissingOnDifferentIndexerArgs() { var code = """ class Program { int[] array = new int[1]; void M(int i) { switch (i) { case 1: array[1] = 4; break; case 2: array[2] = 5; break; case 3: array[2] = 6; break; default: array[2] = 7; break; } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public async Task TestMissingOnQualifiedName() { var code = """ class Program { int[] array = new int[1]; void M(int i) { switch (i) { case 1: this.array[2] = 4; break; case 2: array[2] = 5; break; case 3: array[2] = 6; break; default: array[2] = 7; break; } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public async Task TestMissingOnDefaultBreak_01() { var code = """ class Program { void M(int i) { switch (i) { default: break; } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public async Task TestMissingOnDefaultBreak_02() { var code = """ class Program { void M(int i) { switch (i) { case { }: break; } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public async Task TestMissingOnDefaultBreak_03() { var code = """ class Program { void M(int i) { switch (i) { case var _: break; } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public async Task TestMissingOnDefaultBreak_04() { var code = """ class Program { void M(int i) { switch (i) { case var x: break; } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public async Task TestMissingOnAllBreak() { var code = """ class Program { void M(int i) { switch (i) { case 1: break; case 2: break; case 3: break; } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public Task TestAllThrow() => VerifyCS.VerifyCodeFixAsync( """ using System; class Program { void M(int i) { [|switch|] (i) { case 1: throw null; default: throw new Exception(); } } } """, """ using System; class Program { void M(int i) { throw i switch { 1 => null, _ => new Exception(), }; } } """); [Fact] public Task TestAssignment() => VerifyCS.VerifyCodeFixAsync( """ class Program { void M(int i) { int j; [|switch|] (i) { case 1: j = 4; break; case 2: j = 5; break; case 3: j = 6; break; } throw null; } } """, """ class Program { void M(int i) { var j = i switch { 1 => 4, 2 => 5, 3 => 6, _ => throw null, }; } } """); [Fact] public async Task TestMissingOnNextStatementMismatch() { var code = """ class Program { int M(int i) { int j = 0; switch (i) { case 1: j = 4; break; case 2: j = 5; break; case 3: j = 6; break; } return j; } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public async Task TestMissingOnAssignmentMismatch() { var code = """ class Program { int M(int i) { int j = 0; switch (i) { case 1: j = 4; break; case 2: j += 5; break; } return j; } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public Task TestAssignment_Compound() => VerifyCS.VerifyCodeFixAsync( """ class Program { void M(int i) { int j = 0; [|switch|] (i) { case 1: j += 4; break; case 2: j += 5; break; case 3: j += 6; break; } throw null; } } """, """ class Program { void M(int i) { int j = 0; j += i switch { 1 => 4, 2 => 5, 3 => 6, _ => throw null, }; } } """); [Fact] public Task TestAssignment_UseBeforeAssignment() => VerifyCS.VerifyCodeFixAsync( """ class Program { void M(int i) { int j = 123; M(i); [|switch|] (i) { case 1: j = 4; break; case 2: j = 5; break; case 3: j = 6; break; } throw null; } } """, """ class Program { void M(int i) { int j = 123; M(i); j = i switch { 1 => 4, 2 => 5, 3 => 6, _ => throw null, }; } } """); [Fact] public async Task TestMissingOnMultiAssignment() { var code = """ class Program { void M(int i) { int j, k; switch (i) { case 1: j = 4; k = 5; break; case 2: j = 6; k = 7; break; case 3: j = 8; k = 9; break; } throw null; } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public async Task TestMissingOnMultiCaseSection() { var code = """ class Program { void M(int i) { int j; switch (i) { case 1: case 2: j = 4; break; } throw null; } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public Task TestMissingOnMultiCaseSectionWithWhenClause_CSharp9() => new VerifyCS.Test { TestCode = """ class Program { void M(int i) { int j; switch (i) { case 1: case 2 when true: j = 4; break; } throw null; } } """, LanguageVersion = CSharp9, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/42368")] public Task TestOnMultiCaseSection_CSharp9() => new VerifyCS.Test { TestCode = """ class Program { void M(int i) { int j; [|switch|] (i) { case 1: case 2: j = 4; break; } throw null; } } """, FixedCode = """ class Program { void M(int i) { var j = i switch { 1 or 2 => 4, _ => throw null, }; } } """, LanguageVersion = CSharp9, }.RunAsync(); [Fact] public async Task TestMissingOnMultiCompoundAssignment() { var code = """ class Program { void M(int i) { int j = 0, k = 0; switch (i) { case 1: j += 4; k += 5; break; case 2: j += 6; k += 7; break; case 3: j += 8; k += 9; break; } throw null; } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public async Task TestMissingOnGoto() { var code = """ class Program { int M(int i) { switch (i) { case 1: return 0; case 2: goto default; default: return 2; } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact] public Task TestTrivia_01() => VerifyCS.VerifyCodeFixAsync( """ class Program { int M(int i) { // leading switch [|switch|] (i) // trailing switch { // leading label case 1: // trailing label // leading body return 4; // trailing body case 2: return 5; case 3: return 6; } // leading next statement throw null; // leading next statement } } """, """ class Program { int M(int i) { // leading switch return i switch // trailing switch { // leading label // trailing label 1 => 4,// leading body // trailing body 2 => 5, 3 => 6, // leading next statement _ => throw null,// leading next statement }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37873")] public Task TestTrivia_02() => VerifyCS.VerifyCodeFixAsync( """ class Program { static int GetValue(int input) { [|switch|] (input) { case 1: // this little piggy went to market return 42; case 2: // this little piggy stayed home return 50; case 3: // this little piggy had roast beef return 79; default: // this little piggy had none return 80; } } } """, """ class Program { static int GetValue(int input) { return input switch { 1 => 42,// this little piggy went to market 2 => 50,// this little piggy stayed home 3 => 79,// this little piggy had roast beef _ => 80,// this little piggy had none }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/52258")] public Task TestTrivia_03() => VerifyCS.VerifyCodeFixAsync( """ class Program { int M(int i) { [|switch|] (i) { // Tip-toe through the trailing trivia case 0: return 123; case 1: return 234; default: throw null; } } } """, """ class Program { int M(int i) { return i switch { // Tip-toe through the trailing trivia 0 => 123, 1 => 234, _ => throw null, }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36086")] public async Task TestSeverity() { var analyzer = new ConvertSwitchStatementToExpressionDiagnosticAnalyzer(); var descriptor = analyzer.SupportedDiagnostics.First(descriptor => descriptor.Id == IDEDiagnosticIds.ConvertSwitchStatementToExpressionDiagnosticId); await new VerifyCS.Test { TestCode = """ class Program { int M(int i) { switch (i) { case 1: return 4; case 2: return 5; case 3: return 6; default: return 7; } } } """, ExpectedDiagnostics = { // Test0.cs(5,9): warning IDE0066: Use 'switch' expression new DiagnosticResult(descriptor).WithSeverity(DiagnosticSeverity.Warning).WithSpan(5, 9, 5, 15).WithSpan(5, 9, 15, 10), }, Options = { { CSharpCodeStyleOptions.PreferSwitchExpression, true, NotificationOption2.Warning }, }, }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36995")] public Task TestAddParenthesesAroundBinaryExpression() => VerifyCS.VerifyCodeFixAsync( """ class Program { void M(int i) { int j = 123; [|switch|] (i % 10) { case 1: j = 4; break; case 2: j = 5; break; } throw null; } } """, """ class Program { void M(int i) { int j = 123; j = (i % 10) switch { 1 => 4, 2 => 5, _ => throw null, }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37947")] public Task TestMultiLabelWithDefault() => VerifyCS.VerifyCodeFixAsync( """ using System; class Program { public static string FromDay(DayOfWeek dayOfWeek) { [|switch|] (dayOfWeek) { case DayOfWeek.Monday: return "Monday"; case DayOfWeek.Friday: default: return "Other"; } } } """, """ using System; class Program { public static string FromDay(DayOfWeek dayOfWeek) { return dayOfWeek switch { DayOfWeek.Monday => "Monday", _ => "Other", }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37949")] public async Task TestMissingOnUseInNextStatement() { var code = """ using System; class Program { public static void Throw(int index) { string name = ""; switch (index) { case 0: name = "1"; break; case 1: name = "2"; break; } throw new Exception(name); } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36876")] public Task TestDeclarationInOuterScope() => VerifyCS.VerifyCodeFixAsync( """ using System; using System.IO; class Program { static SeekOrigin origin; static long offset; static long position; static long length; public static void Test() { long target; try { [|switch|] (origin) { case SeekOrigin.Begin: target = offset; break; case SeekOrigin.Current: target = checked(offset + position); break; case SeekOrigin.End: target = checked(offset + length); break; default: throw new ArgumentOutOfRangeException(nameof(origin)); } } catch (OverflowException) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (target < 0) { throw new ArgumentOutOfRangeException(nameof(offset)); } } } """, """ using System; using System.IO; class Program { static SeekOrigin origin; static long offset; static long position; static long length; public static void Test() { long target; try { target = origin switch { SeekOrigin.Begin => offset, SeekOrigin.Current => checked(offset + position), SeekOrigin.End => checked(offset + length), _ => throw new ArgumentOutOfRangeException(nameof(origin)), }; } catch (OverflowException) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (target < 0) { throw new ArgumentOutOfRangeException(nameof(offset)); } } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37872")] public async Task TestMissingFixOnDirectives() { var code = """ class Program { static void Main() { } static int GetValue(int input) { switch (input) { case 1: return 42; case 2: #if PLATFORM_UNIX return 50; #else return 51; #endif case 3: return 79; default: return 80; } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37872")] public async Task TestMissingFixAllOnDirectives() { var fixedCode = """ class Program { static void Main() { } static int GetValue(int input) { return input switch { 1 => 42, _ => 80, }; switch (input) { case 1: return 42; case 2: #if PLATFORM_UNIX return 50; #else return 51; #endif case 3: return 79; default: return 80; } } } """; await new VerifyCS.Test { TestCode = """ class Program { static void Main() { } static int GetValue(int input) { [|switch|] (input) { case 1: return 42; default: return 80; } switch (input) { case 1: return 42; case 2: #if PLATFORM_UNIX return 50; #else return 51; #endif case 3: return 79; default: return 80; } } } """, FixedState = { Sources = { fixedCode }, MarkupHandling = MarkupMode.Allow, }, }.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37950")] public Task TestShouldNotCastNullOnNullableValueType_ReturnStatement() => VerifyCS.VerifyCodeFixAsync( """ class Program { public static bool? GetBool(string name) { [|switch|] (name) { case "a": return true; case "b": return false; default: return null; } } } """, """ class Program { public static bool? GetBool(string name) { return name switch { "a" => true, "b" => false, _ => null, }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37950")] public Task TestShouldNotCastNullOnNullableValueType_Assignment() => VerifyCS.VerifyCodeFixAsync( """ class Program { public static void Test(string name) { bool? result; [|switch|] (name) { case "a": result = true; break; case "b": result = false; break; default: result = null; break; } } } """, """ class Program { public static void Test(string name) { bool? result = name switch { "a" => true, "b" => false, _ => null, }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38771")] public Task TestExplicitDeclaration_Interfaces() => new VerifyCS.Test { TestCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Apple : IFruit, IFruit2 { } class Banana : IFruit, IFruit2 { } public static void Test(string name) { IFruit2 fruit; [|switch|] (name) { case "apple": fruit = new Apple(); break; case "banana": fruit = new Banana(); break; default: throw new InvalidOperationException("Unknown fruit."); } } } """, FixedCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Apple : IFruit, IFruit2 { } class Banana : IFruit, IFruit2 { } public static void Test(string name) { IFruit2 fruit = name switch { "apple" => new Apple(), "banana" => new Banana(), _ => throw new InvalidOperationException("Unknown fruit."), }; } } """, Options = { { CSharpCodeStyleOptions.VarElsewhere, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38771")] public Task TestExplicitDeclaration_Interfaces2() => new VerifyCS.Test { TestCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Apple : IFruit, IFruit2 { } class Banana : IFruit, IFruit2 { } public static void Test(string name) { IFruit2 fruit; [|switch|] (name) { case "banana": fruit = new Banana(); break; case "banana2": fruit = new Banana(); break; default: throw new InvalidOperationException("Unknown fruit."); } } } """, FixedCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Apple : IFruit, IFruit2 { } class Banana : IFruit, IFruit2 { } public static void Test(string name) { IFruit2 fruit = name switch { "banana" => new Banana(), "banana2" => new Banana(), _ => throw new InvalidOperationException("Unknown fruit."), }; } } """, Options = { { CSharpCodeStyleOptions.VarElsewhere, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38771")] public Task TestExplicitDeclaration_Interfaces3() => new VerifyCS.Test { TestCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Apple : IFruit2 { } class Banana : IFruit, IFruit2 { } public static void Test(string name) { IFruit2 fruit; [|switch|] (name) { case "apple": fruit = new Apple(); break; case "banana": fruit = new Banana(); break; default: throw new InvalidOperationException("Unknown fruit."); } } } """, FixedCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Apple : IFruit2 { } class Banana : IFruit, IFruit2 { } public static void Test(string name) { IFruit2 fruit = name switch { "apple" => new Apple(), "banana" => new Banana(), _ => throw new InvalidOperationException("Unknown fruit."), }; } } """, Options = { { CSharpCodeStyleOptions.VarElsewhere, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38771")] public Task TestExplicitDeclaration_ClassInheritance() => new VerifyCS.Test { TestCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Apple : IFruit2 { } class Banana : IFruit, IFruit2 { } class OrganicApple : Apple { } class OrganicBanana : Banana { } public static void Test(string name) { IFruit2 fruit; [|switch|] (name) { case "apple": fruit = new OrganicApple(); break; case "banana": fruit = new OrganicBanana(); break; default: throw new InvalidOperationException("Unknown fruit."); } } } """, FixedCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Apple : IFruit2 { } class Banana : IFruit, IFruit2 { } class OrganicApple : Apple { } class OrganicBanana : Banana { } public static void Test(string name) { IFruit2 fruit = name switch { "apple" => new OrganicApple(), "banana" => new OrganicBanana(), _ => throw new InvalidOperationException("Unknown fruit."), }; } } """, Options = { { CSharpCodeStyleOptions.VarElsewhere, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38771")] public Task TestExplicitDeclaration_ClassInheritance2() => new VerifyCS.Test { TestCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Banana : IFruit, IFruit2 { } class OrganicBanana : Banana, IFruit { } public static void Test(string name) { IFruit2 fruit; [|switch|] (name) { case "banana": fruit = new Banana(); break; case "organic banana": fruit = new OrganicBanana(); break; default: throw new InvalidOperationException("Unknown fruit."); } } } """, FixedCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Banana : IFruit, IFruit2 { } class OrganicBanana : Banana, IFruit { } public static void Test(string name) { IFruit2 fruit = name switch { "banana" => new Banana(), "organic banana" => new OrganicBanana(), _ => throw new InvalidOperationException("Unknown fruit."), }; } } """, Options = { { CSharpCodeStyleOptions.VarElsewhere, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38771")] public Task TestImplicitDeclaration_ClassInheritance() => new VerifyCS.Test { TestCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Banana : IFruit, IFruit2 { } class OrganicBanana : Banana { } public static void Test(string name) { Banana fruit; [|switch|] (name) { case "banana": fruit = new Banana(); break; case "organic banana": fruit = new OrganicBanana(); break; default: throw new InvalidOperationException("Unknown fruit."); } } } """, FixedCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Banana : IFruit, IFruit2 { } class OrganicBanana : Banana { } public static void Test(string name) { var fruit = name switch { "banana" => new Banana(), "organic banana" => new OrganicBanana(), _ => throw new InvalidOperationException("Unknown fruit."), }; } } """, Options = { { CSharpCodeStyleOptions.VarElsewhere, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38771")] public Task TestImplicitDeclaration_ClassInheritance2() => new VerifyCS.Test { TestCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Banana : IFruit, IFruit2 { } class OrganicBanana : Banana, IFruit { } public static void Test(string name) { Banana fruit; [|switch|] (name) { case "banana": fruit = new Banana(); break; case "organic banana": fruit = new OrganicBanana(); break; default: throw new InvalidOperationException("Unknown fruit."); } } } """, FixedCode = """ using System; class Program { interface IFruit { } interface IFruit2 { } class Banana : IFruit, IFruit2 { } class OrganicBanana : Banana, IFruit { } public static void Test(string name) { var fruit = name switch { "banana" => new Banana(), "organic banana" => new OrganicBanana(), _ => throw new InvalidOperationException("Unknown fruit."), }; } } """, Options = { { CSharpCodeStyleOptions.VarElsewhere, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38771")] public Task TestExplicitDeclaration_AllCasesDefaultLiteral() => new VerifyCS.Test { TestCode = """ class Program { public static void Test() { var a = 0; object o; [|switch|] (a) { case 0: o = default; break; default: o = default; break; } } } """, FixedCode = """ class Program { public static void Test() { var a = 0; object o = a switch { 0 => default, _ => default, }; } } """, Options = { { CSharpCodeStyleOptions.VarForBuiltInTypes, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact] public Task TestExplicitDeclaration_MixedDefaultLiteralDefaultParameter() => new VerifyCS.Test { TestCode = """ class Program { public static void Test() { var a = 0; object o; [|switch|] (a) { case 0: o = default(string); break; default: o = default; break; } } } """, FixedCode = """ class Program { public static void Test() { var a = 0; object o = a switch { 0 => default(string), _ => default, }; } } """, Options = { { CSharpCodeStyleOptions.VarForBuiltInTypes, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact] public Task TestImplicitDeclaration_AllCasesDefaultParameter() => new VerifyCS.Test { TestCode = """ class Program { public static void Test() { var a = 0; object o; [|switch|] (a) { case 0: o = default(object); break; default: o = default(object); break; } } } """, FixedCode = """ class Program { public static void Test() { var a = 0; var o = a switch { 0 => default(object), _ => default(object), }; } } """, Options = { { CSharpCodeStyleOptions.VarForBuiltInTypes, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact] public Task TestExplicitDeclaration_AllCasesDefaultParameter() => new VerifyCS.Test { TestCode = """ class Program { public static void Test() { var a = 0; object o; [|switch|] (a) { case 0: o = default(object); break; default: o = default(object); break; } } } """, FixedCode = """ class Program { public static void Test() { var a = 0; object o = a switch { 0 => default(object), _ => default(object), }; } } """, Options = { { CSharpCodeStyleOptions.VarForBuiltInTypes, false, NotificationOption2.Silent }, }, }.RunAsync(); [Fact] public Task TestExplicitDeclaration_DeclarationTypeDifferentFromAllCaseTypes() => new VerifyCS.Test { TestCode = """ class Program { public static void Test() { var a = 0; object o; [|switch|] (a) { case 0: o = ""; break; default: o = ""; break; } } } """, FixedCode = """ class Program { public static void Test() { var a = 0; object o = a switch { 0 => "", _ => "", }; } } """, Options = { { CSharpCodeStyleOptions.VarForBuiltInTypes, true, NotificationOption2.Silent }, }, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40198")] public async Task TestNotWithRefReturns() { var code = """ using System; class Program { static ref int GetRef(int[] mem, int addr, int mode) { switch (mode) { case 0: return ref mem[mem[addr]]; case 1: return ref mem[addr]; default: throw new Exception(); } } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40198")] public async Task TestNotWithRefAssignment() { var code = """ using System; class Program { static ref int GetRef(int[] mem, int addr, int mode) { ref int i = ref addr; switch (mode) { case 0: i = ref mem[mem[addr]]; break; default: throw new Exception(); } return ref mem[addr]; } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40198")] public async Task TestNotWithRefConditionalAssignment() { var code = """ using System; class Program { static ref int GetRef(int[] mem, int addr, int mode) { ref int i = ref addr; switch (mode) { case 0: i = ref true ? ref mem[mem[addr]] : ref mem[mem[addr]]; break; default: throw new Exception(); } return ref mem[addr]; } } """; await VerifyCS.VerifyCodeFixAsync(code, code); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/40198")] public Task TestWithRefInsideConditionalAssignment() => VerifyCS.VerifyCodeFixAsync( """ using System; class Program { static void GetRef(int[] mem, int addr, int mode) { ref int i = ref addr; [|switch|] (mode) { case 0: i = true ? ref mem[mem[addr]] : ref mem[mem[addr]]; break; default: throw new Exception(); } } } """, """ using System; class Program { static void GetRef(int[] mem, int addr, int mode) { ref int i = ref addr; i = mode switch { 0 => true ? ref mem[mem[addr]] : ref mem[mem[addr]], _ => throw new Exception(), }; } } """); [Fact] public async Task TopLevelStatement() { var source = """ int i = 0; [|switch|] (i) { case 1: return 4; default: return 7; } """; var test = new VerifyCS.Test { TestState = { OutputKind = OutputKind.ConsoleApplication, Sources = { source }, }, FixedCode = """ int i = 0; return i switch { 1 => 4, _ => 7, }; """, LanguageVersion = LanguageVersion.CSharp9, }; await test.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/44449")] public async Task TopLevelStatement_FollowedWithThrow() { // We should be rewriting the declaration for 'j' to get 'var j = i switch ...' var source = """ int i = 0; int j; [|switch|] (i) { case 1: j = 4; break; case 2: j = 5; break; } throw null; """; var test = new VerifyCS.Test { TestState = { Sources = { source }, OutputKind = OutputKind.ConsoleApplication, }, FixedCode = """ int i = 0; int j; j = i switch { 1 => 4, 2 => 5, _ => throw null, }; """, LanguageVersion = LanguageVersion.CSharp9, }; await test.RunAsync(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/48006")] public Task TestOnMultiCaseSection_String_CSharp9() => new VerifyCS.Test { TestCode = """ class Program { bool M(string s) { [|switch|] (s) { case "Last": case "First": case "Count": return true; default: return false; } } } """, FixedCode = """ class Program { bool M(string s) { return s switch { "Last" or "First" or "Count" => true, _ => false, }; } } """, LanguageVersion = CSharp9, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/49788")] public Task TestParenthesizedExpression1() => VerifyCS.VerifyCodeFixAsync( """ class Program { int M(object i) { [|switch|] (i.GetType()) { default: return 0; } } } """, """ class Program { int M(object i) { return i.GetType() switch { _ => 0, }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/49788")] public Task TestParenthesizedExpression2() => VerifyCS.VerifyCodeFixAsync( """ class Program { int M() { [|switch|] (1 + 1) { default: return 0; } } } """, """ class Program { int M() { return (1 + 1) switch { _ => 0, }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58636")] public Task TestRuntimeTypeConversion_Assignment1() => VerifyCS.VerifyCodeFixAsync( """ class Program { void M(string s) { object result; [|switch|] (s) { case "a": result = 1234; break; case "b": result = 3.14; break; default: throw new System.Exception(); } } } """, """ class Program { void M(string s) { object result = s switch { "a" => 1234, "b" => (object)3.14, _ => throw new System.Exception(), }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58636")] public Task TestRuntimeTypeConversion_Assignment2() => VerifyCS.VerifyCodeFixAsync( """ class Program { void M(string s) { object result; [|switch|] (s) { case "a": result = 1234; break; case "b": result = 3.14; break; case "c": result = true; break; default: throw new System.Exception(); } } } """, """ class Program { void M(string s) { object result = s switch { "a" => 1234, "b" => 3.14, "c" => true, _ => throw new System.Exception(), }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/77084")] public async Task TestRuntimeTypeConversion_Assignment3() { await VerifyCS.VerifyCodeFixAsync( """ class Program { void M(string s) { object result; [|switch|] (s) { case "a": result = 1234; break; case "b": result = 3.14; break; default: result = true; break; } } } """, """ class Program { void M(string s) { object result = s switch { "a" => 1234, "b" => 3.14, _ => true, }; } } """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58636")] public Task TestRuntimeTypeConversion_Return1() => VerifyCS.VerifyCodeFixAsync( """ class Program { object M(string s) { [|switch|] (s) { case "a": return 1234; case "b": return 3.14; default: throw new System.Exception(); } } } """, """ class Program { object M(string s) { return s switch { "a" => 1234, "b" => (object)3.14, _ => throw new System.Exception(), }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58636")] public Task TestRuntimeTypeConversion_Return2() => VerifyCS.VerifyCodeFixAsync( """ class Program { object M(string s) { [|switch|] (s) { case "a": return 1234; case "b": return 3.14; case "c": return true; default: throw new System.Exception(); } } } """, """ class Program { object M(string s) { return s switch { "a" => 1234, "b" => 3.14, "c" => true, _ => throw new System.Exception(), }; } } """); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/77084")] public async Task TestRuntimeTypeConversion_Return3() { await VerifyCS.VerifyCodeFixAsync( """ class Program { object M(string s) { [|switch|] (s) { case "a": return true; default: return false; } } } """, """ class Program { object M(string s) { return s switch { "a" => true, _ => false, }; } } """); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/61278")] public Task TestLeadingTrivia1() => new VerifyCS.Test { TestCode = """ using System; class C { public static int RefactorReplacementDemoMethod(int argument) { Console.WriteLine(nameof(RefactorReplacementDemoMethod)); // This comment will get deleted, together with the blank lines around it. // Very similar issue already filed, but no resolution to this issue so far. int result; [|switch|] (argument) { case 1: result = 1001; break; case 2: result = 1002; break; default: result = -1; break; } return result; } } """, FixedCode = """ using System; class C { public static int RefactorReplacementDemoMethod(int argument) { Console.WriteLine(nameof(RefactorReplacementDemoMethod)); // This comment will get deleted, together with the blank lines around it. // Very similar issue already filed, but no resolution to this issue so far. var result = argument switch { 1 => 1001, 2 => 1002, _ => -1, }; return result; } } """, LanguageVersion = LanguageVersion.CSharp9, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/61278")] public Task TestLeadingTrivia2() => new VerifyCS.Test { TestCode = """ using System; class C { public static int RefactorReplacementDemoMethod(int argument) { Console.WriteLine(nameof(RefactorReplacementDemoMethod)); // This comment will get deleted, together with the blank lines around it. // Very similar issue already filed, but no resolution to this issue so far. int result, x = 0; [|switch|] (argument) { case 1: result = 1001; break; case 2: result = 1002; break; default: result = -1; break; } return result; } } """, FixedCode = """ using System; class C { public static int RefactorReplacementDemoMethod(int argument) { Console.WriteLine(nameof(RefactorReplacementDemoMethod)); // This comment will get deleted, together with the blank lines around it. // Very similar issue already filed, but no resolution to this issue so far. int x = 0; var result = argument switch { 1 => 1001, 2 => 1002, _ => -1, }; return result; } } """, LanguageVersion = LanguageVersion.CSharp9, }.RunAsync(); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/77081")] public Task TestTupleSwitch() => VerifyCS.VerifyCodeFixAsync( """ class Program { bool M(int i, string j) { [|switch|] (i, j) { case (0, _): return true; case (_, null): return true; default: return false; } } } """, """ class Program { bool M(int i, string j) { return (i, j) switch { (0, _) => true, (_, null) => true, _ => false, }; } } """); }