File: GenerateMember\GenerateParameterizedMember\AbstractGenerateParameterizedMemberService.cs
Web Access
Project: ..\..\..\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.CodeGeneration;
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, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken)
        {
            using var _ = ArrayBuilder<CodeAction>.GetInstance(out var result);
            result.Add(new GenerateParameterizedMemberCodeAction((TService)this, document, state, fallbackOptions, 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, fallbackOptions, isAbstract: true, generateProperty: false));
 
            var semanticFacts = document.Project.Solution.Services.GetLanguageServices(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, fallbackOptions, isAbstract: false, generateProperty: true));
 
                    if (canGenerateAbstractly)
                        result.Add(new GenerateParameterizedMemberCodeAction((TService)this, document, state, fallbackOptions, isAbstract: true, generateProperty: true));
                }
            }
 
            return result.ToImmutable();
        }
    }
}