File: Formatting\CodeCleanupTests.cs
Web Access
Project: src\src\EditorFeatures\CSharpTest\Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.EditorFeatures.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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeCleanup;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.CSharp;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.UnitTests.Diagnostics;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Formatting;
 
[UseExportProvider]
[Trait(Traits.Feature, Traits.Features.CodeCleanup)]
public partial class CodeCleanupTests
{
    [Fact]
    public Task RemoveUsings()
    {
        var code = """
            using System;
            using System.Collections.Generic;
            class Program
            {
                static void Main(string[] args)
                {
                    Console.WriteLine();
                }
            }
            """;
 
        var expected = """
            using System;
            internal class Program
            {
                private static void Main(string[] args)
                {
                    Console.WriteLine();
                }
            }
            """;
        return AssertCodeCleanupResult(expected, code);
    }
 
    [Fact]
    public Task SortUsings()
    {
        var code = """
            using System.Collections.Generic;
            using System;
            class Program
            {
                static void Main(string[] args)
                {
                    var list = new List<int>();
                    Console.WriteLine(list.Count);
                }
            }
            """;
 
        var expected = """
            using System;
            using System.Collections.Generic;
            internal class Program
            {
                private static void Main(string[] args)
                {
                    List<int> list = new();
                    Console.WriteLine(list.Count);
                }
            }
            """;
        return AssertCodeCleanupResult(expected, code);
    }
 
    [Fact]
    public Task SortGlobalUsings()
    {
        var code = """
            using System.Threading.Tasks;
            using System.Threading;
            global using System.Collections.Generic;
            global using System;
            class Program
            {
                static Task Main(string[] args)
                {
                    Barrier b = new Barrier(0);
                    var list = new List<int>();
                    Console.WriteLine(list.Count);
                    b.Dispose();
                }
            }
            """;
 
        var expected = """
            global using System;
            global using System.Collections.Generic;
            using System.Threading;
            using System.Threading.Tasks;
            internal class Program
            {
                private static Task Main(string[] args)
                {
                    Barrier b = new(0);
                    List<int> list = new();
                    Console.WriteLine(list.Count);
                    b.Dispose();
                }
            }
            """;
        return AssertCodeCleanupResult(expected, code);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36984")]
    public Task GroupUsings()
    {
        var code = """
            using M;
            using System;
 
            internal class Program
            {
                private static void Main(string[] args)
                {
                    Console.WriteLine("Hello World!");
 
                    new Goo();
                }
            }
 
            namespace M
            {
                public class Goo { }
            }
            """;
 
        var expected = """
            using M;
 
            using System;
 
            internal class Program
            {
                private static void Main(string[] args)
                {
                    Console.WriteLine("Hello World!");
 
                    _ = new Goo();
                }
            }
 
            namespace M
            {
                public class Goo { }
            }
            """;
        return AssertCodeCleanupResult(expected, code, systemUsingsFirst: false, separateUsingGroups: true);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/36984")]
    public Task SortAndGroupUsings()
    {
        var code = """
            using M;
            using System;
 
            internal class Program
            {
                private static void Main(string[] args)
                {
                    Console.WriteLine("Hello World!");
 
                    new Goo();
                }
            }
 
            namespace M
            {
                public class Goo { }
            }
            """;
 
        var expected = """
            using System;
 
            using M;
 
            internal class Program
            {
                private static void Main(string[] args)
                {
                    Console.WriteLine("Hello World!");
 
                    _ = new Goo();
                }
            }
 
            namespace M
            {
                public class Goo { }
            }
            """;
        return AssertCodeCleanupResult(expected, code, systemUsingsFirst: true, separateUsingGroups: true);
    }
 
    [Fact]
    public Task FixAddRemoveBraces()
    {
        var code = """
            class Program
            {
                int Method()
                {
                    int a = 0;
                    if (a > 0)
                        a ++;
 
                    return a;
                }
            }
            """;
        var expected = """
            internal class Program
            {
                private int Method()
                {
                    int a = 0;
                    if (a > 0)
                    {
                        a++;
                    }
 
                    return a;
                }
            }
            """;
        return AssertCodeCleanupResult(expected, code);
    }
 
    [Fact]
    public Task RemoveUnusedVariable()
    {
        var code = """
            class Program
            {
                void Method()
                {
                    int a;
                }
            }
            """;
        var expected = """
            internal class Program
            {
                private void Method()
                {
                }
            }
            """;
        return AssertCodeCleanupResult(expected, code);
    }
 
    [Fact]
    public Task FixAccessibilityModifiers()
    {
        var code = """
            class Program
            {
                void Method()
                {
                    int a;
                }
            }
            """;
        var expected = """
            internal class Program
            {
                private void Method()
                {
                }
            }
            """;
        return AssertCodeCleanupResult(expected, code);
    }
 
    [Fact]
    public Task FixUsingPlacementPreferOutside()
    {
        var code = """
            namespace A
            {
                using System;
 
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                    }
                }
            }
            """;
 
        var expected = """
            using System;
 
            namespace A
            {
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                    }
                }
            }
            """;
 
        return AssertCodeCleanupResult(expected, code);
    }
 
    [Fact]
    public Task FixUsingPlacementPreferInside()
    {
        var code = """
            using System;
 
            namespace A
            {
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                    }
                }
            }
            """;
 
        var expected = """
            namespace A
            {
                using System;
 
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                    }
                }
            }
            """;
 
        return AssertCodeCleanupResult(expected, code, InsideNamespaceOption);
    }
 
    [Fact]
    public Task FixUsingPlacementPreferInsidePreserve()
    {
        var code = """
            using System;
 
            namespace A
            {
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                    }
                }
            }
            """;
 
        var expected = code;
 
        return AssertCodeCleanupResult(expected, code, InsidePreferPreservationOption);
    }
 
    [Fact]
    public Task FixUsingPlacementPreferOutsidePreserve()
    {
        var code = """
            namespace A
            {
                using System;
 
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                    }
                }
            }
            """;
 
        var expected = code;
 
        return AssertCodeCleanupResult(expected, code, OutsidePreferPreservationOption);
    }
 
    [Fact]
    public Task FixUsingPlacementMixedPreferOutside()
    {
        var code = """
            using System;
 
            namespace A
            {
                using System.Collections.Generic;
 
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                        List<int> list = new List<int>();
                        Console.WriteLine(list.Length);
                    }
                }
            }
            """;
 
        var expected = """
            using System;
            using System.Collections.Generic;
 
            namespace A
            {
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                        List<int> list = [];
                        Console.WriteLine(list.Length);
                    }
                }
            }
            """;
 
        return AssertCodeCleanupResult(expected, code, OutsideNamespaceOption);
    }
 
    [Fact]
    public Task FixUsingPlacementMixedPreferInside()
    {
        var code = """
            using System;
 
            namespace A
            {
                using System.Collections.Generic;
 
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                        List<int> list = new();
                        Console.WriteLine(list.Length);
                    }
                }
            }
            """;
 
        var expected = """
            namespace A
            {
                using System;
                using System.Collections.Generic;
 
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                        List<int> list = [];
                        Console.WriteLine(list.Length);
                    }
                }
            }
            """;
 
        return AssertCodeCleanupResult(expected, code, InsideNamespaceOption);
    }
 
    [Fact]
    public Task FixUsingPlacementMixedPreferInsidePreserve()
    {
        var code = """
            using System;
 
            namespace A
            {
                using System.Collections.Generic;
 
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                        List<int> list = [];
                        Console.WriteLine(list.Length);
                    }
                }
            }
            """;
 
        var expected = code;
 
        return AssertCodeCleanupResult(expected, code, InsidePreferPreservationOption);
    }
 
    [Fact]
    public Task FixUsingPlacementMixedPreferOutsidePreserve()
    {
        var code = """
            using System;
 
            namespace A
            {
                using System.Collections.Generic;
 
                internal class Program
                {
                    private void Method()
                    {
                        Console.WriteLine();
                        List<int> list = [];
                        Console.WriteLine(list.Length);
                    }
                }
            }
            """;
 
        var expected = code;
 
        return AssertCodeCleanupResult(expected, code, OutsidePreferPreservationOption);
    }
 
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/70187")]
    [CombinatorialData]
    public Task FixAllWarningsAndErrorsWithCustomFixIdsExplicitlyEnabled(
        bool applyAllAnalyzerFixersId,
        bool explicitlyIncludeCompilerId,
        [CombinatorialValues(DiagnosticSeverity.Warning, DiagnosticSeverity.Info)] DiagnosticSeverity severity)
    {
        var code = """
            namespace A
            {
                internal class Program
                {
                    private void Method()
                    {
                        int a = 42; // CS0219: The variable 'a' is assigned but its value is never used.
                    }
                }
            }
            """;
 
        var expectedCleanup = false;
        if (explicitlyIncludeCompilerId)
        {
            expectedCleanup = true;
        }
        else if (applyAllAnalyzerFixersId)
        {
            expectedCleanup = severity >= DiagnosticSeverity.Warning;
        }
 
        var expected = code;
        if (expectedCleanup)
        {
            expected = """
            namespace A
            {
                internal class Program
                {
                    private void Method()
                    {
                    }
                }
            }
            """;
        }
 
        Func<string, bool> enabledFixIdsFilter = id =>
            id switch
            {
                "CS0219" => explicitlyIncludeCompilerId,
                "ApplyAllAnalyzerFixersId" => applyAllAnalyzerFixersId,
                _ => false
            };
 
        var diagnosticIdsWithSeverity = new[] { ("CS0219", severity) };
 
        return AssertCodeCleanupResult(expected, code, enabledFixIdsFilter: enabledFixIdsFilter, diagnosticIdsWithSeverity: diagnosticIdsWithSeverity);
    }
 
    [Theory]
    [InlineData(LanguageNames.CSharp)]
    [InlineData(LanguageNames.VisualBasic)]
    public void VerifyAllCodeStyleFixersAreSupportedByCodeCleanup(string language)
    {
        var supportedDiagnostics = GetSupportedDiagnosticIdsForCodeCleanupService(language);
 
        // No Duplicates
        Assert.Equal(supportedDiagnostics, supportedDiagnostics.Distinct());
    }
 
    private const string _code = """
        class C
        {
            public void M1(int x, int y)
            {
                switch (x)
                {
                    case 1:
                    case 10:
                        break;
                    default:
                        break;
                }
 
                switch (y)
                {
                    case 1:
                        break;
                    case 1000:
                    default:
                        break;
                }
 
                switch (x)
                {
                    case 1:
                        break;
                    case 1000:
                        break;
                }
 
                switch (y)
                {
                    default:
                        break;
                }
 
                switch (y) { }
 
                switch (x)
                {
                    case :
                    case 1000:
                        break;
                }
            }
        }
        """;
 
    private const string _fixed = """
        class C
        {
            public void M1(int x, int y)
            {
                switch (x)
                {
                    case 1:
                    case 10:
                        break;
                }
 
                switch (y)
                {
                    case 1:
                        break;
                }
 
                switch (x)
                {
                    case 1:
                        break;
                    case 1000:
                        break;
                }
 
                switch (y)
                {
                }
 
                switch (y) { }
 
                switch (x)
                {
                    case :
                    case 1000:
                        break;
                }
            }
        }
        """;
 
    [Fact]
    public async Task RunThirdPartyFixer()
    {
        await TestThirdPartyCodeFixerApplied<TestThirdPartyCodeFixWithFixAll, CaseTestAnalyzer>(_code, _fixed);
    }
 
    [Fact]
    public async Task DoNotRunThirdPartyFixerWithNoFixAll()
    {
        await TestThirdPartyCodeFixerNoChanges<TestThirdPartyCodeFixWithOutFixAll, CaseTestAnalyzer>(_code);
    }
 
    [Theory]
    [InlineData(DiagnosticSeverity.Warning)]
    [InlineData(DiagnosticSeverity.Error)]
    public async Task RunThirdPartyFixerWithSeverityOfWarningOrHigher(DiagnosticSeverity severity)
    {
        await TestThirdPartyCodeFixerApplied<TestThirdPartyCodeFixWithFixAll, CaseTestAnalyzer>(_code, _fixed, severity);
    }
 
    [Theory]
    [InlineData(DiagnosticSeverity.Hidden)]
    [InlineData(DiagnosticSeverity.Info)]
    public async Task DoNotRunThirdPartyFixerWithSeverityLessThanWarning(DiagnosticSeverity severity)
    {
        await TestThirdPartyCodeFixerNoChanges<TestThirdPartyCodeFixWithOutFixAll, CaseTestAnalyzer>(_code, severity);
    }
 
    [Fact]
    public async Task DoNotRunThirdPartyFixerIfItDoesNotSupportDocumentScope()
    {
        await TestThirdPartyCodeFixerNoChanges<TestThirdPartyCodeFixDoesNotSupportDocumentScope, CaseTestAnalyzer>(_code);
    }
 
    [Fact]
    public async Task DoNotApplyFixerIfChangesAreMadeOutsideDocument()
    {
        await TestThirdPartyCodeFixerNoChanges<TestThirdPartyCodeFixModifiesSolution, CaseTestAnalyzer>(_code);
    }
 
    private static Task TestThirdPartyCodeFixerNoChanges<TCodefix, TAnalyzer>(string code, DiagnosticSeverity severity = DiagnosticSeverity.Warning)
        where TAnalyzer : DiagnosticAnalyzer, new()
        where TCodefix : CodeFixProvider, new()
    {
        return TestThirdPartyCodeFixer<TCodefix, TAnalyzer>(code, code, severity);
    }
 
    private static Task TestThirdPartyCodeFixerApplied<TCodefix, TAnalyzer>(string code, string expected, DiagnosticSeverity severity = DiagnosticSeverity.Warning)
        where TAnalyzer : DiagnosticAnalyzer, new()
        where TCodefix : CodeFixProvider, new()
    {
        return TestThirdPartyCodeFixer<TCodefix, TAnalyzer>(code, expected, severity);
    }
 
    private static async Task TestThirdPartyCodeFixer<TCodefix, TAnalyzer>(string code = null, string expected = null, DiagnosticSeverity severity = DiagnosticSeverity.Warning)
        where TAnalyzer : DiagnosticAnalyzer, new()
        where TCodefix : CodeFixProvider, new()
    {
 
        using var workspace = EditorTestWorkspace.CreateCSharp(code, composition: EditorTestCompositions.EditorFeaturesWpf.AddParts(typeof(TCodefix)));
 
        var project = workspace.CurrentSolution.Projects.Single();
        var analyzer = (DiagnosticAnalyzer)new TAnalyzer();
        var diagnosticIds = analyzer.SupportedDiagnostics.SelectAsArray(d => d.Id);
 
        var editorconfigText = "is_global = true";
        foreach (var diagnosticId in diagnosticIds)
        {
            editorconfigText += $"\ndotnet_diagnostic.{diagnosticId}.severity = {severity.ToEditorConfigString()}";
        }
 
        var map = new Dictionary<string, ImmutableArray<DiagnosticAnalyzer>>{
            { LanguageNames.CSharp, ImmutableArray.Create(analyzer) }
        };
 
        project = project.AddAnalyzerReference(new TestAnalyzerReferenceByLanguage(map));
        project = project.Solution.WithProjectFilePath(project.Id, @$"z:\\{project.FilePath}").GetProject(project.Id);
        project = project.AddAnalyzerConfigDocument(".editorconfig", SourceText.From(editorconfigText), filePath: @"z:\\.editorconfig").Project;
        workspace.TryApplyChanges(project.Solution);
 
        var hostdoc = workspace.Documents.Single();
        var document = workspace.CurrentSolution.GetDocument(hostdoc.Id);
 
        var codeCleanupService = document.GetLanguageService<ICodeCleanupService>();
 
        var enabledDiagnostics = codeCleanupService.GetAllDiagnostics();
 
        var newDoc = await codeCleanupService.CleanupAsync(
            document, enabledDiagnostics, CodeAnalysisProgress.None, CancellationToken.None);
 
        var actual = await newDoc.GetTextAsync();
        Assert.Equal(expected, actual.ToString());
    }
 
    private static string[] GetSupportedDiagnosticIdsForCodeCleanupService(string language)
    {
        using var workspace = GetTestWorkspaceForLanguage(language);
        var hostdoc = workspace.Documents.Single();
        var document = workspace.CurrentSolution.GetDocument(hostdoc.Id);
 
        var codeCleanupService = document.GetLanguageService<ICodeCleanupService>();
 
        var enabledDiagnostics = codeCleanupService.GetAllDiagnostics();
        var supportedDiagnostics = enabledDiagnostics.Diagnostics.SelectMany(x => x.DiagnosticIds).ToArray();
        return supportedDiagnostics;
 
        static EditorTestWorkspace GetTestWorkspaceForLanguage(string language)
        {
            if (language == LanguageNames.CSharp)
            {
                return EditorTestWorkspace.CreateCSharp(string.Empty, composition: EditorTestCompositions.EditorFeaturesWpf);
            }
 
            if (language == LanguageNames.VisualBasic)
            {
                return EditorTestWorkspace.CreateVisualBasic(string.Empty, composition: EditorTestCompositions.EditorFeaturesWpf);
            }
 
            return null;
        }
    }
 
    /// <summary>
    /// Assert the expected code value equals the actual processed input <paramref name="code"/>.
    /// </summary>
    /// <param name="expected">The actual processed code to verify against.</param>
    /// <param name="code">The input code to be processed and tested.</param>
    /// <param name="systemUsingsFirst">Indicates whether <c><see cref="System"/>.*</c> '<c>using</c>' directives should preceed others. Default is <c>true</c>.</param>
    /// <param name="separateUsingGroups">Indicates whether '<c>using</c>' directives should be organized into separated groups. Default is <c>true</c>.</param>
    /// <param name="enabledFixIdsFilter">Optional filter to determine if a specific fix ID is explicitly enabled for cleanup.</param>
    /// <param name="diagnosticIdsWithSeverity">Optional list of diagnostic IDs with effective severities to be configured in editorconfig.</param>
    /// <returns>The <see cref="Task"/> to test code cleanup.</returns>
    private protected static Task AssertCodeCleanupResult(string expected, string code, bool systemUsingsFirst = true, bool separateUsingGroups = false, Func<string, bool> enabledFixIdsFilter = null, (string, DiagnosticSeverity)[] diagnosticIdsWithSeverity = null)
        => AssertCodeCleanupResult(expected, code, new(AddImportPlacement.OutsideNamespace, NotificationOption2.Silent), systemUsingsFirst, separateUsingGroups, enabledFixIdsFilter, diagnosticIdsWithSeverity);
 
    /// <summary>
    /// Assert the expected code value equals the actual processed input <paramref name="code"/>.
    /// </summary>
    /// <param name="expected">The actual processed code to verify against.</param>
    /// <param name="code">The input code to be processed and tested.</param>
    /// <param name="preferredImportPlacement">Indicates the code style option for the preferred 'using' directives placement.</param>
    /// <param name="systemUsingsFirst">Indicates whether <c><see cref="System"/>.*</c> '<c>using</c>' directives should preceed others. Default is <c>true</c>.</param>
    /// <param name="separateUsingGroups">Indicates whether '<c>using</c>' directives should be organized into separated groups. Default is <c>true</c>.</param>
    /// <param name="enabledFixIdsFilter">Optional filter to determine if a specific fix ID is explicitly enabled for cleanup.</param>
    /// <param name="diagnosticIdsWithSeverity">Optional list of diagnostic IDs with effective severities to be configured in editorconfig.</param>
    /// <returns>The <see cref="Task"/> to test code cleanup.</returns>
    private protected static async Task AssertCodeCleanupResult(string expected, string code, CodeStyleOption2<AddImportPlacement> preferredImportPlacement, bool systemUsingsFirst = true, bool separateUsingGroups = false, Func<string, bool> enabledFixIdsFilter = null, (string, DiagnosticSeverity)[] diagnosticIdsWithSeverity = null)
    {
        using var workspace = EditorTestWorkspace.CreateCSharp(code, composition: EditorTestCompositions.EditorFeaturesWpf);
 
        // must set global options since incremental analyzer infra reads from global options
        workspace.SetAnalyzerFallbackAndGlobalOptions(new OptionsCollection(LanguageNames.CSharp)
        {
            { GenerationOptions.SeparateImportDirectiveGroups, separateUsingGroups },
            { GenerationOptions.PlaceSystemNamespaceFirst, systemUsingsFirst },
            { CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, preferredImportPlacement },
        });
 
        var solution = workspace.CurrentSolution.WithAnalyzerReferences(
        [
            new AnalyzerFileReference(typeof(CSharpCompilerDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile),
            new AnalyzerFileReference(typeof(UseExpressionBodyDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile)
        ]);
 
        if (diagnosticIdsWithSeverity != null)
        {
            var editorconfigText = "is_global = true";
            foreach (var (diagnosticId, severity) in diagnosticIdsWithSeverity)
            {
                editorconfigText += $"\ndotnet_diagnostic.{diagnosticId}.severity = {severity.ToEditorConfigString()}";
            }
 
            var project = solution.Projects.Single();
            project = project.AddAnalyzerConfigDocument(".editorconfig", SourceText.From(editorconfigText), filePath: @"z:\\.editorconfig").Project;
            solution = project.Solution;
        }
 
        workspace.TryApplyChanges(solution);
 
        var hostdoc = workspace.Documents.Single();
        var document = workspace.CurrentSolution.GetDocument(hostdoc.Id);
 
        var codeCleanupService = document.GetLanguageService<ICodeCleanupService>();
 
        var enabledDiagnostics = codeCleanupService.GetAllDiagnostics();
 
        if (enabledFixIdsFilter != null)
            enabledDiagnostics = VisualStudio.LanguageServices.Implementation.CodeCleanup.AbstractCodeCleanUpFixer.AdjustDiagnosticOptions(enabledDiagnostics, enabledFixIdsFilter);
 
        var newDoc = await codeCleanupService.CleanupAsync(
            document, enabledDiagnostics, CodeAnalysisProgress.None, CancellationToken.None);
 
        var actual = await newDoc.GetTextAsync();
 
        Assert.Equal(expected, actual.ToString());
    }
 
    private static readonly CodeStyleOption2<AddImportPlacement> InsideNamespaceOption =
        new CodeStyleOption2<AddImportPlacement>(AddImportPlacement.InsideNamespace, NotificationOption2.Error);
 
    private static readonly CodeStyleOption2<AddImportPlacement> OutsideNamespaceOption =
        new CodeStyleOption2<AddImportPlacement>(AddImportPlacement.OutsideNamespace, NotificationOption2.Error);
 
    private static readonly CodeStyleOption2<AddImportPlacement> InsidePreferPreservationOption =
        new CodeStyleOption2<AddImportPlacement>(AddImportPlacement.InsideNamespace, NotificationOption2.None);
 
    private static readonly CodeStyleOption2<AddImportPlacement> OutsidePreferPreservationOption =
        new CodeStyleOption2<AddImportPlacement>(AddImportPlacement.OutsideNamespace, NotificationOption2.None);
}