File: src\Analyzers\CSharp\Tests\ConditionalExpressionInStringInterpolation\CSharpAddParenthesesAroundConditionalExpressionInInterpolatedStringCodeFixProviderTests.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.
 
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.ConditionalExpressionInStringInterpolation;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
using Xunit.Abstractions;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConditionalExpressionInStringInterpolation;
 
[Trait(Traits.Feature, Traits.Features.CodeActionsAddParenthesesAroundConditionalExpressionInInterpolatedString)]
public class CSharpAddParenthesesAroundConditionalExpressionInInterpolatedStringCodeFixProviderTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_NoEditor
{
    public CSharpAddParenthesesAroundConditionalExpressionInInterpolatedStringCodeFixProviderTests(ITestOutputHelper logger)
       : base(logger)
    {
    }
 
    internal override (DiagnosticAnalyzer?, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
        => (null, new CSharpAddParenthesesAroundConditionalExpressionInInterpolatedStringCodeFixProvider());
 
    private async Task TestInMethodAsync(string initialMethodBody, string expectedMethodBody)
    {
        var template = """
            class Application
            {{
                public void M()
                {{
                    {0}
                }}
            }}
            """;
        await TestInRegularAndScriptAsync(
            string.Format(template, initialMethodBody),
            string.Format(template, expectedMethodBody)).ConfigureAwait(false);
    }
 
    [Fact]
    public async Task TestAddParenthesesSimpleConditionalExpression()
    {
        await TestInMethodAsync(
            """var s = $"{ true ? 1 [|:|] 2}";""",
            """var s = $"{ (true ? 1 : 2)}";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesMultiLineConditionalExpression1()
    {
        await TestInMethodAsync("""
            var s = $@"{ true
                        [|? 1|]
                        : 2}";
            """, """
            var s = $@"{ (true
                        ? 1
                        : 2)}";
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesMultiLineConditionalExpression2()
    {
        await TestInMethodAsync("""
            var s = $@"{
                        true
                        ?
                        [|1|]
                        : 
                        2
                        }";
            """, """
            var s = $@"{
                        (true
                        ?
                        1
                        : 
                        2
            )            }";
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesWithTrivia()
    {
        await TestInMethodAsync(
            """var s = $"{ /* Leading1 */ true /* Leading2 */ ? /* TruePart1 */ 1 /* TruePart2 */[|:|] /* FalsePart1 */ 2 /* FalsePart2 */ }";""",
            """var s = $"{ /* Leading1 */ (true /* Leading2 */ ? /* TruePart1 */ 1 /* TruePart2 */: /* FalsePart1 */ 2) /* FalsePart2 */ }";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesClosingBracketInFalseCondition()
    {
        await TestInMethodAsync(
            """var s = $"{ true ? new int[0] [|:|] new int[] {} }";""",
            """var s = $"{ (true ? new int[0] : new int[] {}) }";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesStringLiteralInFalseCondition()
    {
        await TestInMethodAsync(
            """var s = $"{ true ? "1" [|:|] "2" }";""",
            """var s = $"{ (true ? "1" : "2") }";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesVerbatimStringLiteralInFalseCondition()
    {
        await TestInMethodAsync(
            """"var s = $"{ true ? "1" [|:|] @"""2""" }";"""",
            """"var s = $"{ (true ? "1" : @"""2""") }";"""");
    }
 
    [Fact]
    public async Task TestAddParenthesesStringLiteralInFalseConditionWithClosingParenthesisInLiteral()
    {
        await TestInMethodAsync(
            """var s = $"{ true ? "1" [|:|] "2)" }";""",
            """var s = $"{ (true ? "1" : "2)") }";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesStringLiteralInFalseConditionWithEscapedDoubleQuotes()
    {
        await TestInMethodAsync(
            """var s = $"{ true ? "1" [|:|] "2\"" }";""",
            """var s = $"{ (true ? "1" : "2\"") }";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesStringLiteralInFalseConditionWithCodeLikeContent()
    {
        await TestInMethodAsync(
            """var s = $"{ true ? "1" [|:|] "M(new int[] {}, \"Parameter\");" }";""",
            """var s = $"{ (true ? "1" : "M(new int[] {}, \"Parameter\");") }";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesNestedConditionalExpression1()
    {
        await TestInMethodAsync(
            """var s2 = $"{ true ? "1" [|:|] (false ? "2" : "3") };""",
            """var s2 = $"{ (true ? "1" : (false ? "2" : "3")) };""");
    }
 
    [Fact]
    public async Task TestAddParenthesesNestedConditionalExpression2()
    {
        await TestInMethodAsync(
            """var s2 = $"{ true ? "1" [|:|] false ? "2" : "3" };""",
            """var s2 = $"{ (true ? "1" : false ? "2" : "3") };""");
    }
 
    [Fact]
    public async Task TestAddParenthesesNestedConditionalWithNestedInterpolatedString()
    {
        await TestInMethodAsync(
            """
            var s2 = $"{ (true ? "1" : false ? $"{ true ? "2" [|:|] "3"}" : "4") }"
            """,
            """
            var s2 = $"{ (true ? "1" : false ? $"{ (true ? "2" : "3")}" : "4") }"
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesMultipleInterpolatedSections1()
    {
        await TestInMethodAsync(
            """var s3 = $"Text1 { true ? "Text2" [|:|] "Text3"} Text4 { (true ? "Text5" : "Text6")} Text7";""",
            """var s3 = $"Text1 { (true ? "Text2" : "Text3")} Text4 { (true ? "Text5" : "Text6")} Text7";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesMultipleInterpolatedSections2()
    {
        await TestInMethodAsync(
            """var s3 = $"Text1 { (true ? "Text2" : "Text3")} Text4 { true ? "Text5" [|:|] "Text6"} Text7";""",
            """var s3 = $"Text1 { (true ? "Text2" : "Text3")} Text4 { (true ? "Text5" : "Text6")} Text7";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesMultipleInterpolatedSections3()
    {
        await TestInMethodAsync(
            """var s3 = $"Text1 { true ? "Text2" [|:|] "Text3"} Text4 { true ? "Text5" : "Text6"} Text7";""",
            """var s3 = $"Text1 { (true ? "Text2" : "Text3")} Text4 { true ? "Text5" : "Text6"} Text7";""");
    }
 
    [Fact]
    public async Task TestAddParenthesesWhileTyping1()
    {
        await TestInMethodAsync(
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { true ? "Text2" [|:|]
            NextLineOfCode();
            """,
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { (true ? "Text2" :)
            NextLineOfCode();
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesWhileTyping2()
    {
        await TestInMethodAsync(
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { true ? "Text2" [|:|] "
            NextLineOfCode();
            """,
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { (true ? "Text2" : ")
            NextLineOfCode();
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesWhileTyping3()
    {
        await TestInMethodAsync(
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { true ? "Text2" [|:|] "Text3
            NextLineOfCode();
            """,
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { (true ? "Text2" : "Text3)
            NextLineOfCode();
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesWhileTyping4()
    {
        await TestInMethodAsync(
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { true ? "Text2" [|:|] "Text3"
            NextLineOfCode();
            """,
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { (true ? "Text2" : "Text3")
            NextLineOfCode();
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesWhileTyping5()
    {
        await TestInMethodAsync(
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { true ? "Text2" [|:|] "Text3" }
            NextLineOfCode();
            """,
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { (true ? "Text2" : "Text3") }
            NextLineOfCode();
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesWithCS1026PresentBeforeFixIsApplied1()
    {
        await TestInMethodAsync(
            """
            (
            var s3 = $"Text1 { true ? "Text2" [|:|] "Text3" }
            NextLineOfCode();
            """,
            """
            (
            var s3 = $"Text1 { (true ? "Text2" : "Text3") }
            NextLineOfCode();
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesWithCS1026PresentBeforeFixIsApplied2()
    {
        await TestInMethodAsync(
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { true ? "Text2" [|:|] "Text3" }
            NextLineOfCode(
            """,
            """
            PreviousLineOfCode();
            var s3 = $"Text1 { (true ? "Text2" : "Text3") }
            NextLineOfCode(
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesWithCS1026PresentBeforeFixIsApplied3()
    {
        await TestInMethodAsync(
            """
            PreviousLineOfCode();
            var s3 = ($"Text1 { true ? "Text2" [|:|] "Text3" }
            NextLineOfCode();
            """,
            """
            PreviousLineOfCode();
            var s3 = ($"Text1 { (true ? "Text2" : "Text3") }
            NextLineOfCode();
            """);
    }
 
    [Fact]
    public async Task TestAddParenthesesAddOpeningParenthesisOnly()
    {
        await TestInMethodAsync(
            """
            var s3 = $"{ true ? 1 [|:|] 2 )}"
            """,
            """
            var s3 = $"{ (true ? 1 : 2 )}"
            """);
    }
}