File: SplitOrMergeIfStatements\SplitIntoConsecutiveIfStatementsTests.cs
Web Access
Project: src\src\Features\CSharpTest\Microsoft.CodeAnalysis.CSharp.Features.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Features.UnitTests)
// 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.
 
#nullable disable
 
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.SplitOrMergeIfStatements;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.SplitOrMergeIfStatements;
 
[Trait(Traits.Feature, Traits.Features.CodeActionsSplitIntoConsecutiveIfStatements)]
public sealed class SplitIntoConsecutiveIfStatementsTests : AbstractCSharpCodeActionTest_NoEditor
{
    protected override CodeRefactoringProvider CreateCodeRefactoringProvider(TestWorkspace workspace, TestParameters parameters)
        => new CSharpSplitIntoConsecutiveIfStatementsCodeRefactoringProvider();
 
    [Theory]
    [InlineData("a [||]|| b")]
    [InlineData("a |[||]| b")]
    [InlineData("a ||[||] b")]
    [InlineData("a [||||] b")]
    public Task SplitOnOrOperatorSpans(string condition)
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (
            """ + condition + """
            )
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                    {
                    }
                    else if (b)
                    {
                    }
                }
            }
            """);
 
    [Theory]
    [InlineData("a [|||]| b")]
    [InlineData("a[| |||] b")]
    [InlineData("a[||] || b")]
    public Task NotSplitOnOrOperatorSpans(string condition)
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (
            """ + condition + """
            )
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task NotSplitOnIfKeyword()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    [||]if (a || b)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task NotSplitOnAndOperator()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]&& b)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task NotSplitOnBitwiseOrOperator()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]| b)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task NotSplitOnOrOperatorOutsideIfStatement()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    var v = a [||]|| b;
                }
            }
            """);
 
    [Fact]
    public Task NotSplitOnOrOperatorInIfStatementBody()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a || b)
                        a [||]|| b;
                }
            }
            """);
 
    [Fact]
    public Task SplitWithChainedOrExpression1()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a [||]|| b || c || d)
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a)
                    {
                    }
                    else if (b || c || d)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithChainedOrExpression2()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a || b [||]|| c || d)
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a || b)
                    {
                    }
                    else if (c || d)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithChainedOrExpression3()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a || b || c [||]|| d)
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a || b || c)
                    {
                    }
                    else if (d)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task NotSplitInsideParentheses1()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if ((a [||]|| b) || c || d)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task NotSplitInsideParentheses2()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a || b || (c [||]|| d))
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task NotSplitInsideParentheses3()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if ((a || b [||]|| c || d))
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithOtherExpressionInsideParentheses1()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a [||]|| (b || c) || d)
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a)
                    {
                    }
                    else if ((b || c) || d)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithOtherExpressionInsideParentheses2()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a || (b || c) [||]|| d)
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b, bool c, bool d)
                {
                    if (a || (b || c))
                    {
                    }
                    else if (d)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithMixedAndExpression1()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if (a [||]|| b && c)
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if (a)
                    {
                    }
                    else if (b && c)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithMixedAndExpression2()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if (a && b [||]|| c)
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if (a && b)
                    {
                    }
                    else if (c)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task NotSplitWithMixedConditionalExpression1()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if (a [||]|| b ? c : c)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task NotSplitWithMixedConditionalExpression2()
        => TestMissingInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if (a ? b : b [||]|| c)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithMixedConditionalExpressionInsideParentheses1()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if (a [||]|| (b ? c : c))
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if (a)
                    {
                    }
                    else if ((b ? c : c))
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithMixedConditionalExpressionInsideParentheses2()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if ((a ? b : b) [||]|| c)
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b, bool c)
                {
                    if ((a ? b : b))
                    {
                    }
                    else if (c)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithStatementInsideBlock()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                    {
                        System.Console.WriteLine(a || b);
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                    {
                        System.Console.WriteLine(a || b);
                    }
                    else if (b)
                    {
                        System.Console.WriteLine(a || b);
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithStatementWithoutBlock()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        System.Console.WriteLine(a || b);
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        System.Console.WriteLine(a || b);
                    else if (b)
                        System.Console.WriteLine(a || b);
                }
            }
            """);
 
    [Fact]
    public Task SplitWithNestedIfStatement()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        if (true) { }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                    {
                        if (true) { }
                    }
                    else if (b)
                        if (true) { }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithNestedIfStatementInWhileLoop()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        while (a)
                            if (true)
                                using (null) { }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                    {
                        while (a)
                            if (true)
                                using (null) { }
                    }
                    else if (b)
                        while (a)
                            if (true)
                                using (null) { }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithNestedIfStatementInsideBlockInWhileLoop()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        while (a)
                        {
                            if (true)
                                using (null) { }
                        }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        while (a)
                        {
                            if (true)
                                using (null) { }
                        }
                    else if (b)
                        while (a)
                        {
                            if (true)
                                using (null) { }
                        }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithNestedIfStatementInsideBlock()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                    {
                        if (true) { }
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                    {
                        if (true) { }
                    }
                    else if (b)
                    {
                        if (true) { }
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithMissingStatement()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
            else if (b)
                }
            }
            """);
 
    [Fact]
    public Task SplitWithElseStatementInsideBlock()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        System.Console.WriteLine();
                    else
                    {
                        System.Console.WriteLine(a || b);
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        System.Console.WriteLine();
                    else if (b)
                        System.Console.WriteLine();
                    else
                    {
                        System.Console.WriteLine(a || b);
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithElseStatementWithoutBlock()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        System.Console.WriteLine();
                    else
                        System.Console.WriteLine(a || b);
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        System.Console.WriteLine();
                    else if (b)
                        System.Console.WriteLine();
                    else
                        System.Console.WriteLine(a || b);
                }
            }
            """);
 
    [Fact]
    public Task SplitWithElseNestedIfStatement()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        System.Console.WriteLine();
                    else if (true) { }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        System.Console.WriteLine();
                    else if (b)
                        System.Console.WriteLine();
                    else if (true) { }
                }
            }
            """);
 
    [Fact]
    public Task SplitWithElseIfElse()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        System.Console.WriteLine();
                    else if (a)
                        System.Console.WriteLine(a);
                    else
                        System.Console.WriteLine(b);
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        System.Console.WriteLine();
                    else if (b)
                        System.Console.WriteLine();
                    else if (a)
                        System.Console.WriteLine(a);
                    else
                        System.Console.WriteLine(b);
                }
            }
            """);
 
    [Fact]
    public Task SplitAsPartOfElseIfElse()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (true)
                        System.Console.WriteLine();
                    else if (a [||]|| b)
                        System.Console.WriteLine(a);
                    else
                        System.Console.WriteLine(b);
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (true)
                        System.Console.WriteLine();
                    else if (a)
                        System.Console.WriteLine(a);
                    else if (b)
                        System.Console.WriteLine(a);
                    else
                        System.Console.WriteLine(b);
                }
            }
            """);
 
    [Fact]
    public Task SplitWithMissingElseStatement()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        System.Console.WriteLine();
                    else
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        System.Console.WriteLine();
                    else if (b)
                        System.Console.WriteLine();
                    else
                }
            }
            """);
 
    [Fact]
    public Task SplitWithPreservedSingleLineFormatting()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b) System.Console.WriteLine();
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a) System.Console.WriteLine();
                    else if (b) System.Console.WriteLine();
                }
            }
            """);
 
    [Fact]
    public Task SplitIntoSeparateStatementsIfControlFlowQuits1()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        return;
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        return;
                    if (b)
                        return;
                }
            }
            """);
 
    [Fact]
    public Task SplitIntoSeparateStatementsIfControlFlowQuits2()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        throw new System.Exception();
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        throw new System.Exception();
                    if (b)
                        throw new System.Exception();
                }
            }
            """);
 
    [Fact]
    public Task SplitIntoSeparateStatementsIfControlFlowQuits3()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (true)
                    {
                        if (a [||]|| b)
                            continue;
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (true)
                    {
                        if (a)
                            continue;
                        if (b)
                            continue;
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitIntoSeparateStatementsIfControlFlowQuits4()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (true)
                    {
                        if (a [||]|| b)
                        {
                            if (a)
                                continue;
                            else
                                break;
                        }
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (true)
                    {
                        if (a)
                        {
                            if (a)
                                continue;
                            else
                                break;
                        }
 
                        if (b)
                        {
                            if (a)
                                continue;
                            else
                                break;
                        }
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitIntoSeparateStatementsIfControlFlowQuits5()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (true)
                    {
                        if (a [||]|| b)
                            switch (a)
                            {
                                default:
                                    continue;
                            }
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (true)
                    {
                        if (a)
                            switch (a)
                            {
                                default:
                                    continue;
                            }
 
                        if (b)
                            switch (a)
                            {
                                default:
                                    continue;
                            }
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitIntoSeparateStatementsIfControlFlowQuitsInSwitchSection()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    switch (a)
                    {
                        case true:
                            if (a [||]|| b)
                                break;
                            break;
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    switch (a)
                    {
                        case true:
                            if (a)
                                break;
                            if (b)
                                break;
                            break;
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitIntoSeparateStatementsIfControlFlowQuitsWithNestedIfStatement()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        if (true)
                            return;
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        if (true)
                            return;
                    if (b)
                        if (true)
                            return;
                }
            }
            """);
 
    [Fact]
    public Task SplitIntoSeparateStatementsIfControlFlowQuitsWithPreservedSingleLineFormatting()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b) return;
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a) return;
                    if (b) return;
                }
            }
            """);
 
    [Fact]
    public Task SplitNotIntoSeparateStatementsIfControlFlowContinues1()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                    {
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                    {
                    }
                    else if (b)
                    {
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitNotIntoSeparateStatementsIfControlFlowContinues2()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                    {
                        if (a)
                            return;
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                    {
                        if (a)
                            return;
                    }
                    else if (b)
                    {
                        if (a)
                            return;
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitNotIntoSeparateStatementsIfControlFlowContinues3()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        while (a)
                        {
                            break;
                        }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        while (a)
                        {
                            break;
                        }
                    else if (b)
                        while (a)
                        {
                            break;
                        }
                }
            }
            """);
 
    [Fact]
    public Task SplitNotIntoSeparateStatementsIfControlFlowContinues4()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (true)
                    {
                        if (a [||]|| b)
                            switch (a)
                            {
                                default:
                                    break;
                            }
                    }
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (true)
                    {
                        if (a)
                            switch (a)
                            {
                                default:
                                    break;
                            }
                        else if (b)
                            switch (a)
                            {
                                default:
                                    break;
                            }
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitNotIntoSeparateStatementsWithElseIfControlFlowQuits()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a [||]|| b)
                        return;
                    else
                        return;
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        return;
                    else if (b)
                        return;
                    else
                        return;
                }
            }
            """);
 
    [Fact]
    public Task SplitIntoSeparateStatementsAsEmbeddedStatementIfControlFlowQuits()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (a)
                        if (a [||]|| b)
                            return;
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    while (a)
                    {
                        if (a)
                            return;
                        if (b)
                            return;
                    }
                }
            }
            """);
 
    [Fact]
    public Task SplitNotIntoSeparateStatementsAsElseIfIfControlFlowQuits()
        => TestInRegularAndScriptAsync(
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        return;
                    else if (a [||]|| b)
                        return;
                }
            }
            """,
            """
            class C
            {
                void M(bool a, bool b)
                {
                    if (a)
                        return;
                    else if (a)
                        return;
                    else if (b)
                        return;
                }
            }
            """);
}