File: CodeRefactorings\EnableNullable\EnableNullableCodeRefactoringProvider.FixAllProvider.cs
Web Access
Project: src\src\Features\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Features.csproj (Microsoft.CodeAnalysis.CSharp.Features)
// 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.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Shared.Extensions;
using FixAllScope = Microsoft.CodeAnalysis.CodeFixes.FixAllScope;
 
namespace Microsoft.CodeAnalysis.CSharp.CodeRefactorings.EnableNullable;
 
internal sealed partial class EnableNullableCodeRefactoringProvider : CodeRefactoringProvider
{
    internal sealed override CodeAnalysis.CodeRefactorings.FixAllProvider? GetFixAllProvider()
        => FixAllProvider.Instance;
 
    private sealed class FixAllProvider : CodeAnalysis.CodeRefactorings.FixAllProvider
    {
        public static readonly FixAllProvider Instance = new();
 
        private FixAllProvider()
        {
        }
 
        public override IEnumerable<FixAllScope> GetSupportedFixAllScopes()
            => ImmutableArray.Create(FixAllScope.Solution);
 
        public override Task<CodeAction?> GetFixAsync(FixAllContext fixAllContext)
        {
            Debug.Assert(fixAllContext.Scope == FixAllScope.Solution);
            return Task.FromResult<CodeAction?>(new FixAllCodeAction(EnableNullableReferenceTypesInSolutionAsync));
 
            async Task<Solution> EnableNullableReferenceTypesInSolutionAsync(
                CodeActionPurpose purpose, IProgress<CodeAnalysisProgress> progress, CancellationToken cancellationToken)
            {
                var solution = fixAllContext.Solution;
                foreach (var projectId in solution.ProjectIds)
                {
                    var project = solution.GetRequiredProject(projectId);
                    if (!ShouldOfferRefactoring(project))
                        continue;
 
                    solution = await EnableNullableReferenceTypesAsync(project, purpose, fixAllContext.CancellationToken).ConfigureAwait(false);
                }
 
                return solution;
            }
        }
 
        private sealed class FixAllCodeAction(Func<CodeActionPurpose, IProgress<CodeAnalysisProgress>, CancellationToken, Task<Solution>> createChangedSolution)
            : CodeAction.SolutionChangeAction(
                CSharpFeaturesResources.Enable_nullable_reference_types_in_solution,
                (progress, cancellationToken) => createChangedSolution(CodeActionPurpose.Apply, progress, cancellationToken),
                nameof(CSharpFeaturesResources.Enable_nullable_reference_types_in_solution))
        {
            private readonly Func<CodeActionPurpose, IProgress<CodeAnalysisProgress>, CancellationToken, Task<Solution>> _createChangedSolution = createChangedSolution;
 
            protected override async Task<IEnumerable<CodeActionOperation>> ComputePreviewOperationsAsync(CancellationToken cancellationToken)
            {
                var changedSolution = await _createChangedSolution(
                    CodeActionPurpose.Preview, CodeAnalysisProgress.None, cancellationToken).ConfigureAwait(false);
                if (changedSolution is null)
                    return [];
 
                return new CodeActionOperation[] { new ApplyChangesOperation(changedSolution) };
            }
        }
    }
}