File: src\Analyzers\Core\CodeFixes\GenerateParameterizedMember\AbstractGenerateParameterizedMemberService.cs
Web Access
Project: src\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.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.
 
#nullable disable
 
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.PooledObjects;
 
namespace Microsoft.CodeAnalysis.GenerateMember.GenerateParameterizedMember;
 
internal abstract partial class AbstractGenerateParameterizedMemberService<TService, TSimpleNameSyntax, TExpressionSyntax, TInvocationExpressionSyntax> :
    AbstractGenerateMemberService<TSimpleNameSyntax, TExpressionSyntax>
    where TService : AbstractGenerateParameterizedMemberService<TService, TSimpleNameSyntax, TExpressionSyntax, TInvocationExpressionSyntax>
    where TSimpleNameSyntax : TExpressionSyntax
    where TExpressionSyntax : SyntaxNode
    where TInvocationExpressionSyntax : TExpressionSyntax
{
    protected AbstractGenerateParameterizedMemberService()
    {
    }
 
    protected abstract AbstractInvocationInfo CreateInvocationMethodInfo(SemanticDocument document, State abstractState);
 
    protected abstract bool IsValidSymbol(ISymbol symbol, SemanticModel semanticModel);
    protected abstract bool AreSpecialOptionsActive(SemanticModel semanticModel);
 
    protected virtual bool ContainingTypesOrSelfHasUnsafeKeyword(INamedTypeSymbol containingType)
        => false;
 
    protected virtual string GetImplicitConversionDisplayText(State state)
        => string.Empty;
 
    protected virtual string GetExplicitConversionDisplayText(State state)
        => string.Empty;
 
    protected async ValueTask<ImmutableArray<CodeAction>> GetActionsAsync(Document document, State state, CancellationToken cancellationToken)
    {
        using var _ = ArrayBuilder<CodeAction>.GetInstance(out var result);
        result.Add(new GenerateParameterizedMemberCodeAction((TService)this, document, state, isAbstract: false, generateProperty: false));
 
        // If we're trying to generate an instance method into an abstract class (but not a
        // static class or an interface), then offer to generate it abstractly.
        var canGenerateAbstractly = state.TypeToGenerateIn.IsAbstract &&
            !state.TypeToGenerateIn.IsStatic &&
            state.TypeToGenerateIn.TypeKind != TypeKind.Interface &&
            !state.IsStatic;
 
        if (canGenerateAbstractly)
            result.Add(new GenerateParameterizedMemberCodeAction((TService)this, document, state, isAbstract: true, generateProperty: false));
 
        var semanticFacts = document.Project.Solution.Workspace.Services.GetExtendedLanguageServices(state.TypeToGenerateIn.Language).GetService<ISemanticFactsService>();
 
        if (semanticFacts.SupportsParameterizedProperties &&
            state.InvocationExpressionOpt != null)
        {
            var typeParameters = state.SignatureInfo.DetermineTypeParameters(cancellationToken);
            var returnType = await state.SignatureInfo.DetermineReturnTypeAsync(cancellationToken).ConfigureAwait(false);
 
            if (typeParameters.Length == 0 && returnType.SpecialType != SpecialType.System_Void)
            {
                result.Add(new GenerateParameterizedMemberCodeAction((TService)this, document, state, isAbstract: false, generateProperty: true));
 
                if (canGenerateAbstractly)
                    result.Add(new GenerateParameterizedMemberCodeAction((TService)this, document, state, isAbstract: true, generateProperty: true));
            }
        }
 
        return result.ToImmutableAndClear();
    }
}