File: CodeFixesAndRefactorings\FixAllProviderInfo.cs
Web Access
Project: src\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// 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 Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CodeFixesAndRefactorings;
 
/// <summary>
/// Contains computed information for a given <see cref="FixAllProvider"/>, such as supported diagnostic Ids and supported <see cref="FixAllScope"/>.
/// </summary>
internal abstract class FixAllProviderInfo
{
    public readonly IFixAllProvider FixAllProvider;
    public readonly ImmutableArray<FixAllScope> SupportedScopes;
 
    private FixAllProviderInfo(
        IFixAllProvider fixAllProvider,
        ImmutableArray<FixAllScope> supportedScopes)
    {
        FixAllProvider = fixAllProvider;
        SupportedScopes = supportedScopes;
    }
 
    /// <summary>
    /// Gets an optional <see cref="FixAllProviderInfo"/> for the given code fix provider or suppression fix provider.
    /// </summary>
    public static FixAllProviderInfo? Create(object provider)
    {
        if (provider is CodeFixProvider codeFixProvider)
        {
            return CreateWithCodeFixer(codeFixProvider);
        }
        else if (provider is CodeRefactoringProvider codeRefactoringProvider)
        {
            return CreateWithCodeRefactoring(codeRefactoringProvider);
        }
 
        return CreateWithSuppressionFixer((IConfigurationFixProvider)provider);
    }
 
    /// <summary>
    /// Gets an optional <see cref="FixAllProviderInfo"/> for the given code fix provider.
    /// </summary>
    private static FixAllProviderInfo? CreateWithCodeFixer(CodeFixProvider provider)
    {
        var fixAllProvider = provider.GetFixAllProvider();
        if (fixAllProvider == null)
        {
            return null;
        }
 
        var diagnosticIds = fixAllProvider.GetSupportedFixAllDiagnosticIds(provider);
        if (diagnosticIds == null || diagnosticIds.IsEmpty())
        {
            return null;
        }
 
        var scopes = fixAllProvider.GetSupportedFixAllScopes().ToImmutableArrayOrEmpty();
        if (scopes.IsEmpty)
        {
            return null;
        }
 
        return new CodeFixerFixAllProviderInfo(fixAllProvider, diagnosticIds, scopes);
    }
 
    /// <summary>
    /// Gets an optional <see cref="FixAllProviderInfo"/> for the given code refactoring provider.
    /// </summary>
    private static FixAllProviderInfo? CreateWithCodeRefactoring(CodeRefactoringProvider provider)
    {
        var fixAllProvider = provider.GetFixAllProvider();
        if (fixAllProvider == null)
        {
            return null;
        }
 
        var scopes = fixAllProvider.GetSupportedFixAllScopes().ToImmutableArrayOrEmpty();
        if (scopes.IsEmpty)
        {
            return null;
        }
 
        return new CodeRefactoringFixAllProviderInfo(fixAllProvider, scopes);
    }
 
    /// <summary>
    /// Gets an optional <see cref="FixAllProviderInfo"/> for the given suppression fix provider.
    /// </summary>
    private static FixAllProviderInfo? CreateWithSuppressionFixer(IConfigurationFixProvider provider)
    {
        var fixAllProvider = provider.GetFixAllProvider();
        if (fixAllProvider == null)
        {
            return null;
        }
 
        var scopes = fixAllProvider.GetSupportedFixAllScopes().ToImmutableArrayOrEmpty();
        if (scopes.IsEmpty)
        {
            return null;
        }
 
        return new SuppressionFixerFixAllProviderInfo(fixAllProvider, provider, scopes);
    }
 
    public abstract bool CanBeFixed(Diagnostic diagnostic);
 
    private sealed class CodeFixerFixAllProviderInfo(
        IFixAllProvider fixAllProvider,
        IEnumerable<string> supportedDiagnosticIds,
        ImmutableArray<FixAllScope> supportedScopes) : FixAllProviderInfo(fixAllProvider, supportedScopes)
    {
        public override bool CanBeFixed(Diagnostic diagnostic)
            => supportedDiagnosticIds.Contains(diagnostic.Id);
    }
 
    private sealed class SuppressionFixerFixAllProviderInfo(
        IFixAllProvider fixAllProvider,
        IConfigurationFixProvider suppressionFixer,
        ImmutableArray<FixAllScope> supportedScopes) : FixAllProviderInfo(fixAllProvider, supportedScopes)
    {
        private readonly Func<Diagnostic, bool> _canBeSuppressedOrUnsuppressed = suppressionFixer.IsFixableDiagnostic;
 
        public override bool CanBeFixed(Diagnostic diagnostic)
            => _canBeSuppressedOrUnsuppressed(diagnostic);
    }
 
    private sealed class CodeRefactoringFixAllProviderInfo(
        IFixAllProvider fixAllProvider,
        ImmutableArray<FixAllScope> supportedScopes) : FixAllProviderInfo(fixAllProvider, supportedScopes)
    {
        public override bool CanBeFixed(Diagnostic diagnostic)
            => throw ExceptionUtilities.Unreachable();
    }
}