File: Formatting\CodeCleanupTests.TestFixers.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.
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Formatting;
 
public partial class CodeCleanupTests
{
    private abstract class TestThirdPartyCodeFix : CodeFixProvider
    {
        public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create("HasDefaultCase");
 
        public override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            foreach (var diagnostic in context.Diagnostics)
            {
                context.RegisterCodeFix(
                    CodeAction.Create(
                        "Remove default case",
                        async cancellationToken =>
                        {
                            var root = await context.Document.GetSyntaxRootAsync(cancellationToken);
                            Assumes.NotNull(root);
                            var sourceTree = diagnostic.Location.SourceTree;
                            Assumes.NotNull(sourceTree);
                            var node = (await sourceTree.GetRootAsync(cancellationToken)).FindNode(diagnostic.Location.SourceSpan);
                            Assumes.NotNull(node?.Parent);
                            var newRoot = root.RemoveNode(node.Parent, SyntaxRemoveOptions.KeepNoTrivia);
                            Assumes.NotNull(newRoot);
                            return context.Document.WithSyntaxRoot(newRoot);
                        },
                        nameof(TestThirdPartyCodeFix)),
                    diagnostic);
            }
 
            return Task.CompletedTask;
        }
    }
 
    [PartNotDiscoverable, Shared, ExportCodeFixProvider(LanguageNames.CSharp)]
    private class TestThirdPartyCodeFixWithFixAll : TestThirdPartyCodeFix
    {
        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public TestThirdPartyCodeFixWithFixAll()
        {
        }
 
        public override FixAllProvider GetFixAllProvider() => BatchFixAllProvider.Instance;
    }
 
    [PartNotDiscoverable, Shared, ExportCodeFixProvider(LanguageNames.CSharp)]
    private class TestThirdPartyCodeFixWithOutFixAll : TestThirdPartyCodeFix
    {
        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public TestThirdPartyCodeFixWithOutFixAll()
        {
        }
    }
 
    [PartNotDiscoverable, Shared, ExportCodeFixProvider(LanguageNames.CSharp)]
    private class TestThirdPartyCodeFixModifiesSolution : TestThirdPartyCodeFix
    {
        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public TestThirdPartyCodeFixModifiesSolution()
        {
        }
 
        public override FixAllProvider GetFixAllProvider() => new ModifySolutionFixAll();
 
        private class ModifySolutionFixAll : FixAllProvider
        {
            public override Task<CodeAction?> GetFixAsync(FixAllContext fixAllContext)
            {
                var solution = fixAllContext.Solution;
                return Task.FromResult<CodeAction?>(CodeAction.Create(
                        "Remove default case",
                        async cancellationToken =>
                        {
                            var toFix = await fixAllContext.GetDocumentDiagnosticsToFixAsync();
                            Project? project = null;
                            foreach (var kvp in toFix)
                            {
                                var document = kvp.Key;
                                project ??= document.Project;
                                var diagnostics = kvp.Value;
                                var root = await document.GetSyntaxRootAsync(cancellationToken);
                                Assumes.NotNull(root);
                                foreach (var diagnostic in diagnostics)
                                {
                                    var sourceTree = diagnostic.Location.SourceTree;
                                    Assumes.NotNull(sourceTree);
                                    var node = (await sourceTree.GetRootAsync(cancellationToken)).FindNode(diagnostic.Location.SourceSpan);
                                    Assumes.NotNull(node?.Parent);
                                    var newRoot = root.RemoveNode(node.Parent, SyntaxRemoveOptions.KeepNoTrivia);
                                    Assumes.NotNull(newRoot);
                                    document = document.WithSyntaxRoot(newRoot);
                                }
 
                                solution = solution.WithDocumentText(document.Id, await document.GetTextAsync());
                            }
 
                            Assumes.NotNull(project);
                            return solution.AddDocument(DocumentId.CreateNewId(project.Id), "new.cs", SourceText.From(""));
                        },
                        nameof(TestThirdPartyCodeFix)));
            }
        }
    }
 
    [PartNotDiscoverable, Shared, ExportCodeFixProvider(LanguageNames.CSharp)]
    private class TestThirdPartyCodeFixDoesNotSupportDocumentScope : TestThirdPartyCodeFix
    {
        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public TestThirdPartyCodeFixDoesNotSupportDocumentScope()
        {
        }
 
        public override FixAllProvider GetFixAllProvider() => new ModifySolutionFixAll();
 
        private class ModifySolutionFixAll : FixAllProvider
        {
            public override IEnumerable<FixAllScope> GetSupportedFixAllScopes()
            {
                return new[] { FixAllScope.Project, FixAllScope.Solution, FixAllScope.Custom };
            }
 
            public override Task<CodeAction?> GetFixAsync(FixAllContext fixAllContext)
            {
                var solution = fixAllContext.Solution;
                return Task.FromResult<CodeAction?>(CodeAction.Create(
                        "Remove default case",
                        async cancellationToken =>
                        {
                            var toFix = await fixAllContext.GetDocumentDiagnosticsToFixAsync();
                            Project? project = null;
                            foreach (var kvp in toFix)
                            {
                                var document = kvp.Key;
                                project ??= document.Project;
                                var diagnostics = kvp.Value;
                                var root = await document.GetSyntaxRootAsync(cancellationToken);
                                Assumes.NotNull(root);
                                foreach (var diagnostic in diagnostics)
                                {
                                    var sourceTree = diagnostic.Location.SourceTree;
                                    Assumes.NotNull(sourceTree);
                                    var node = (await sourceTree.GetRootAsync(cancellationToken)).FindNode(diagnostic.Location.SourceSpan);
                                    Assumes.NotNull(node?.Parent);
                                    var newRoot = root.RemoveNode(node.Parent, SyntaxRemoveOptions.KeepNoTrivia);
                                    Assumes.NotNull(newRoot);
                                    document = document.WithSyntaxRoot(newRoot);
                                }
 
                                solution = solution.WithDocumentText(document.Id, await document.GetTextAsync());
                            }
 
                            Assumes.NotNull(project);
                            return solution.AddDocument(DocumentId.CreateNewId(project.Id), "new.cs", SourceText.From(""));
                        },
                        nameof(TestThirdPartyCodeFix)));
            }
        }
    }
}