|
// 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.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.ReplaceConditionalWithStatements;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ReplaceConditionalWithStatements;
using VerifyCS = CSharpCodeRefactoringVerifier<CSharpReplaceConditionalWithStatementsCodeRefactoringProvider>;
[UseExportProvider]
public class ReplaceConditionalWithStatementsTests
{
[Fact]
public async Task TestAssignment_ObjectType()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
void M(bool b)
{
object a;
a = $$b ? 0 : 1L;
}
}
""",
"""
class C
{
void M(bool b)
{
object a;
if (b)
{
a = (long)0;
}
else
{
a = 1L;
}
}
}
""");
}
[Fact]
public async Task TestAssignment_ObjectType_OnAssigment()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
void M(bool b)
{
object a;
$$a = b ? 0 : 1L;
}
}
""",
"""
class C
{
void M(bool b)
{
object a;
if (b)
{
a = (long)0;
}
else
{
a = 1L;
}
}
}
""");
}
[Fact]
public async Task TestAssignment_SameType()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
void M(bool b)
{
long a;
a = $$b ? 0 : 1L;
}
}
""",
"""
class C
{
void M(bool b)
{
long a;
if (b)
{
a = 0;
}
else
{
a = 1L;
}
}
}
""");
}
[Fact]
public async Task TestAssignment_RefConditional()
{
await VerifyCS.VerifyRefactoringAsync(
"""
#nullable enable
public class C
{
private C? y, z;
void M(bool b, ref C? x)
{
x = ref ($$b ? ref y : ref z);
}
}
""",
"""
#nullable enable
public class C
{
private C? y, z;
void M(bool b, ref C? x)
{
if (b)
{
x = ref (y);
}
else
{
x = ref (z);
}
}
}
""");
}
[Fact]
public async Task TestAssignment_Discard()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
void M(bool b)
{
_ = $$b ? 0 : 1L;
}
}
""",
"""
class C
{
void M(bool b)
{
if (b)
{
_ = (long)0;
}
else
{
_ = 1L;
}
}
}
""");
}
[Fact]
public async Task TestAssignment_GlobalStatement()
{
await new VerifyCS.Test
{
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp9,
TestState = { OutputKind = OutputKind.ConsoleApplication },
TestCode =
"""
bool b = true;
long a;
a = $$b ? 0 : 1L;
""",
FixedCode =
"""
bool b = true;
long a;
if (b)
{
a = 0;
}
else
{
a = 1L;
}
"""
}.RunAsync();
}
[Fact]
public async Task TestAssignment_GlobalStatement_OnAssignment()
{
await new VerifyCS.Test
{
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp9,
TestState = { OutputKind = OutputKind.ConsoleApplication },
TestCode =
"""
bool b = true;
long a;
$$a = b ? 0 : 1L;
""",
FixedCode =
"""
bool b = true;
long a;
if (b)
{
a = 0;
}
else
{
a = 1L;
}
"""
}.RunAsync();
}
[Fact]
public async Task TestRefLocalDeclaration1()
{
var source =
"""
class C
{
void M(bool b)
{
var y = new C();
var z = new C();
ref var x = ref ($$b ? ref y : ref z);
}
}
""";
await VerifyCS.VerifyRefactoringAsync(source, source);
}
[Fact]
public async Task TestUsingLocalDeclaration1()
{
var source =
"""
using System;
class C
{
void M(bool b, IDisposable d1, IDisposable d2)
{
using var x = $$b ? d1 : d2;
}
}
""";
await VerifyCS.VerifyRefactoringAsync(source, source);
}
[Fact]
public async Task TestCompoundAssignment()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
void M(bool b)
{
int a = 0;
a += $$b ? 1 : 2;
}
}
""",
"""
class C
{
void M(bool b)
{
int a = 0;
if (b)
{
a += 1;
}
else
{
a += 2;
}
}
}
""");
}
[Fact]
public async Task TestWithExpression()
{
await new VerifyCS.Test
{
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10,
TestCode =
"""
record X(int A);
class C
{
void M(bool b, X x)
{
x = x with { A = $$b ? 1 : 2 };
}
}
namespace System.Runtime.CompilerServices
{
public sealed class IsExternalInit
{
}
}
""",
FixedCode =
"""
record X(int A);
class C
{
void M(bool b, X x)
{
if (b)
{
x = x with { A = 1 };
}
else
{
x = x with { A = 2 };
}
}
}
namespace System.Runtime.CompilerServices
{
public sealed class IsExternalInit
{
}
}
"""
}.RunAsync();
}
[Fact]
public async Task TestLocalDeclarationStatement1()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
void M(bool b)
{
object a = $$b ? 0 : 1L;
}
}
""",
"""
class C
{
void M(bool b)
{
object a;
if (b)
{
a = (long)0;
}
else
{
a = 1L;
}
}
}
""");
}
[Fact]
public async Task TestLocalDeclarationStatement1_OnDeclaration()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
void M(bool b)
{
$$object a = b ? 0 : 1L;
}
}
""",
"""
class C
{
void M(bool b)
{
object a;
if (b)
{
a = (long)0;
}
else
{
a = 1L;
}
}
}
""");
}
[Fact]
public async Task TestLocalDeclarationStatement_WithVar()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
void M(bool b)
{
var a = $$b ? 0 : 1L;
}
}
""",
"""
class C
{
void M(bool b)
{
long a;
if (b)
{
a = 0;
}
else
{
a = 1L;
}
}
}
""");
}
[Fact]
public async Task TestLocalDeclarationStatement_ThrowExpression()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b)
{
int v = N(N($$b ? 42 : throw new Exception()));
}
int N(int v) => v;
}
""",
"""
using System;
class C
{
void M(bool b)
{
int v;
if (b)
{
v = N(N(42));
}
else
{
throw new Exception();
}
}
int N(int v) => v;
}
""");
}
[Fact]
public async Task TestLocalDeclarationStatement_TopLevel1()
{
await new VerifyCS.Test
{
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10,
TestState = { OutputKind = OutputKind.ConsoleApplication },
TestCode =
"""
bool b = true;
object a = $$b ? 0 : 1L;
""",
FixedCode =
"""
bool b = true;
object a;
if (b)
{
a = (long)0;
}
else
{
a = 1L;
}
"""
}.RunAsync();
}
[Fact]
public async Task TestLocalDeclarationStatement_TopLevel_OnDeclaration1()
{
await new VerifyCS.Test
{
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10,
TestState = { OutputKind = OutputKind.ConsoleApplication },
TestCode =
"""
bool b = true;
$$object a = b ? 0 : 1L;
""",
FixedCode =
"""
bool b = true;
object a;
if (b)
{
a = (long)0;
}
else
{
a = 1L;
}
"""
}.RunAsync();
}
[Fact]
public async Task TestLocalDeclarationStatement_TopLevel_WithVar1()
{
await new VerifyCS.Test
{
LanguageVersion = CodeAnalysis.CSharp.LanguageVersion.CSharp10,
TestState = { OutputKind = OutputKind.ConsoleApplication },
TestCode =
"""
bool b = true;
var a = $$b ? 0 : 1L;
""",
FixedCode =
"""
bool b = true;
long a;
if (b)
{
a = 0;
}
else
{
a = 1L;
}
"""
}.RunAsync();
}
[Fact]
public async Task TestReturnStatement_ObjectReturn()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
object M(bool b)
{
return $$b ? 0 : 1L;
}
}
""",
"""
class C
{
object M(bool b)
{
if (b)
{
return (long)0;
}
else
{
return 1L;
}
}
}
""");
}
[Fact]
public async Task TestReturnStatement_ObjectReturn_OnReturn()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
object M(bool b)
{
$$return b ? 0 : 1L;
}
}
""",
"""
class C
{
object M(bool b)
{
if (b)
{
return (long)0;
}
else
{
return 1L;
}
}
}
""");
}
[Fact]
public async Task TestReturnStatement_AcualTypeReturn()
{
await VerifyCS.VerifyRefactoringAsync(
"""
class C
{
long M(bool b)
{
return $$b ? 0 : 1L;
}
}
""",
"""
class C
{
long M(bool b)
{
if (b)
{
return 0;
}
else
{
return 1L;
}
}
}
""");
}
[Fact]
public async Task TestExpressionStatement_SimpleInvocationArgument()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b)
{
Console.WriteLine($$b ? 0 : 1L);
}
}
""",
"""
using System;
class C
{
void M(bool b)
{
if (b)
{
Console.WriteLine((long)0);
}
else
{
Console.WriteLine(1L);
}
}
}
""");
}
[Fact]
public async Task TestExpressionStatement_NestedInvocationArgument_Outer()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b, bool c)
{
Console.WriteLine($$b ? c ? 0 : 1 : c ? 2 : 3);
}
}
""",
"""
using System;
class C
{
void M(bool b, bool c)
{
if (b)
{
Console.WriteLine(c ? 0 : 1);
}
else
{
Console.WriteLine(c ? 2 : 3);
}
}
}
""");
}
[Fact]
public async Task TestExpressionStatement_NestedInvocationArgument_Inner1()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b, bool c)
{
Console.WriteLine(b ? $$c ? 0 : 1 : c ? 2 : 3);
}
}
""",
"""
using System;
class C
{
void M(bool b, bool c)
{
if (c)
{
Console.WriteLine(b ? 0 : c ? 2 : 3);
}
else
{
Console.WriteLine(b ? 1 : c ? 2 : 3);
}
}
}
""");
}
[Fact]
public async Task TestExpressionStatement_NestedInvocationArgument_Inner22()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b, bool c)
{
Console.WriteLine(b ? c ? 0 : 1 : $$c ? 2 : 3);
}
}
""",
"""
using System;
class C
{
void M(bool b, bool c)
{
if (c)
{
Console.WriteLine(b ? c ? 0 : 1 : 2);
}
else
{
Console.WriteLine(b ? c ? 0 : 1 : 3);
}
}
}
""");
}
[Fact]
public async Task TestExpressionStatement_InvocationWithInference1()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b)
{
F($$b ? (int)42 : (int?)null);
}
void F<T>(T value) => Console.WriteLine(typeof(T));
}
""",
"""
using System;
class C
{
void M(bool b)
{
if (b)
{
F((int?)(int)42);
}
else
{
F((int?)null);
}
}
void F<T>(T value) => Console.WriteLine(typeof(T));
}
""");
}
[Fact(Skip = "Causes assert in compiler layer")]
public async Task TestExpressionStatement_InvocationWithSimpleObjectCreation()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b)
{
F($$b ? new X() : new());
}
void F(object value) => Console.WriteLine(value.GetType());
}
class X { }
""",
"""
using System;
class C
{
void M(bool b)
{
if (b)
{
F(new X());
}
else
{
F((X)new());
}
}
void F(object value) => Console.WriteLine(value.GetType());
}
""");
}
[Fact]
public async Task TestExpressionStatement_SimpleInvocationArgument_OnStatement()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b)
{
$$Console.WriteLine(b ? 0 : 1L);
}
}
""",
"""
using System;
class C
{
void M(bool b)
{
if (b)
{
Console.WriteLine((long)0);
}
else
{
Console.WriteLine(1L);
}
}
}
""");
}
[Fact]
public async Task TestExpressionStatement_SecondInvocationArgument()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b)
{
Console.WriteLine(b ? "" : "", $$b ? 0 : 1L);
}
}
""",
"""
using System;
class C
{
void M(bool b)
{
if (b)
{
Console.WriteLine(b ? "" : "", (long)0);
}
else
{
Console.WriteLine(b ? "" : "", 1L);
}
}
}
""");
}
[Fact]
public async Task TestExpressionStatement_NestedInvocationArgument()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
bool M(bool b)
{
M(M(M($$b ? true : false)));
return default;
}
}
""",
"""
using System;
class C
{
bool M(bool b)
{
if (b)
{
M(M(M(true)));
}
else
{
M(M(M(false)));
}
return default;
}
}
""");
}
[Fact]
public async Task TestAwaitExpression1()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
using System.Threading.Tasks;
class C
{
async void M(bool b, Task x, Task y)
{
await ($$b ? x : y);
}
}
""",
"""
using System;
using System.Threading.Tasks;
class C
{
async void M(bool b, Task x, Task y)
{
if (b)
{
await (x);
}
else
{
await (y);
}
}
}
""");
}
[Fact]
public async Task TestAwaitExpression_OnAwait()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
using System.Threading.Tasks;
class C
{
async void M(bool b, Task x, Task y)
{
$$await (b ? x : y);
}
}
""",
"""
using System;
using System.Threading.Tasks;
class C
{
async void M(bool b, Task x, Task y)
{
if (b)
{
await (x);
}
else
{
await (y);
}
}
}
""");
}
[Fact]
public async Task TestThrowStatement1()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b)
{
throw $$b ? new Exception("x") : new Exception("y");
}
}
""",
"""
using System;
class C
{
void M(bool b)
{
if (b)
{
throw new Exception("x");
}
else
{
throw new Exception("y");
}
}
}
""");
}
[Fact]
public async Task TestThrowStatement_OnThrow1()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b)
{
$$throw b ? new Exception("x") : new Exception("y");
}
}
""",
"""
using System;
class C
{
void M(bool b)
{
if (b)
{
throw new Exception("x");
}
else
{
throw new Exception("y");
}
}
}
""");
}
[Fact]
public async Task TestDeepThrowOnOneSide()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
int M(bool b)
{
return N(N($$b ? 42 : throw new Exception()));
}
int N(int v) => v;
}
""",
"""
using System;
class C
{
int M(bool b)
{
if (b)
{
return N(N(42));
}
else
{
throw new Exception();
}
}
int N(int v) => v;
}
""");
}
[Fact]
public async Task TestDeepThrowOnOneSide_LocalDeclaration()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
class C
{
void M(bool b)
{
int v = N(N($$b ? 42 : throw new Exception()));
}
int N(int v) => v;
}
""",
"""
using System;
class C
{
void M(bool b)
{
int v;
if (b)
{
v = N(N(42));
}
else
{
throw new Exception();
}
}
int N(int v) => v;
}
""");
}
[Fact]
public async Task TestYieldReturn1()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
using System.Collections.Generic;
class C
{
IEnumerable<object> M(bool b)
{
yield return $$b ? 0 : 1L;
}
}
""",
"""
using System;
using System.Collections.Generic;
class C
{
IEnumerable<object> M(bool b)
{
if (b)
{
yield return (long)0;
}
else
{
yield return 1L;
}
}
}
""");
}
[Fact]
public async Task TestYieldReturn_OnYield1()
{
await VerifyCS.VerifyRefactoringAsync(
"""
using System;
using System.Collections.Generic;
class C
{
IEnumerable<object> M(bool b)
{
$$yield return b ? 0 : 1L;
}
}
""",
"""
using System;
using System.Collections.Generic;
class C
{
IEnumerable<object> M(bool b)
{
if (b)
{
yield return (long)0;
}
else
{
yield return 1L;
}
}
}
""");
}
}
|