| File: GenerateType\AbstractGenerateTypeService.CodeAction.cs | Web Access |
| Project: src\roslyn\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. using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.Notification; using Microsoft.CodeAnalysis.ProjectManagement; using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.GenerateType; internal abstract partial class AbstractGenerateTypeService<TService, TSimpleNameSyntax, TObjectCreationExpressionSyntax, TExpressionSyntax, TTypeDeclarationSyntax, TArgumentSyntax> { private sealed class GenerateTypeCodeAction : CodeAction { private readonly bool _intoNamespace; private readonly bool _inNewFile; private readonly TService _service; private readonly Document _document; private readonly State _state; private readonly string _equivalenceKey; public GenerateTypeCodeAction( TService service, Document document, State state, bool intoNamespace, bool inNewFile) { _service = service; _document = document; _state = state; _intoNamespace = intoNamespace; _inNewFile = inNewFile; _equivalenceKey = Title; } private static string FormatDisplayText( State state, bool inNewFile, bool isNested) { if (inNewFile) { return string.Format(FeaturesResources.Generate_0_1_in_new_file, state.IsStruct ? "struct" : state.IsInterface ? "interface" : "class", state.Name); } else { return string.Format(isNested ? FeaturesResources.Generate_nested_0_1 : FeaturesResources.Generate_0_1, state.IsStruct ? "struct" : state.IsInterface ? "interface" : "class", state.Name); } } protected override async Task<ImmutableArray<CodeActionOperation>> ComputeOperationsAsync( IProgress<CodeAnalysisProgress> progress, CancellationToken cancellationToken) { var semanticDocument = await SemanticDocument.CreateAsync(_document, cancellationToken).ConfigureAwait(false); var editor = new Editor(_service, semanticDocument, _state, _intoNamespace, _inNewFile, cancellationToken); return await editor.GetOperationsAsync().ConfigureAwait(false); } public override string Title => _intoNamespace ? FormatDisplayText(_state, _inNewFile, isNested: false) : FormatDisplayText(_state, inNewFile: false, isNested: true); public override string EquivalenceKey => _equivalenceKey; } private sealed class GenerateTypeCodeActionWithOption : CodeActionWithOptions { private readonly TService _service; private readonly Document _document; private readonly State _state; internal GenerateTypeCodeActionWithOption(TService service, Document document, State state) { _service = service; _document = document; _state = state; } public override string Title => FeaturesResources.Generate_new_type; public override string EquivalenceKey => _state.Name; public override object GetOptions(CancellationToken cancellationToken) { var generateTypeOptionsService = _document.Project.Solution.Services.GetRequiredService<IGenerateTypeOptionsService>(); var notificationService = _document.Project.Solution.Services.GetService<INotificationService>(); var projectManagementService = _document.Project.Solution.Services.GetService<IProjectManagementService>(); var syntaxFactsService = _document.GetRequiredLanguageService<ISyntaxFactsService>(); var typeKindValue = GetTypeKindOption(_state); var isPublicOnlyAccessibility = IsPublicOnlyAccessibility(_state, _document.Project); return generateTypeOptionsService.GetGenerateTypeOptions( _state.Name, new GenerateTypeDialogOptions(isPublicOnlyAccessibility, typeKindValue, _state.IsAttribute), _document, notificationService, projectManagementService, syntaxFactsService); } private bool IsPublicOnlyAccessibility(State state, Project project) => _service.IsPublicOnlyAccessibility(state.NameOrMemberAccessExpression, project) || _service.IsPublicOnlyAccessibility(state.SimpleName, project); private TypeKindOptions GetTypeKindOption(State state) { var gotPreassignedTypeOptions = GetPredefinedTypeKindOption(state, out var typeKindValue); if (!gotPreassignedTypeOptions) { typeKindValue = state.IsSimpleNameGeneric ? TypeKindOptionsHelper.RemoveOptions(typeKindValue, TypeKindOptions.GenericInCompatibleTypes) : typeKindValue; typeKindValue = state.IsMembersWithModule ? TypeKindOptionsHelper.AddOption(typeKindValue, TypeKindOptions.Module) : typeKindValue; typeKindValue = state.IsInterfaceOrEnumNotAllowedInTypeContext ? TypeKindOptionsHelper.RemoveOptions(typeKindValue, TypeKindOptions.Interface, TypeKindOptions.Enum) : typeKindValue; typeKindValue = state.IsDelegateAllowed ? typeKindValue : TypeKindOptionsHelper.RemoveOptions(typeKindValue, TypeKindOptions.Delegate); typeKindValue = state.IsEnumNotAllowed ? TypeKindOptionsHelper.RemoveOptions(typeKindValue, TypeKindOptions.Enum) : typeKindValue; } return typeKindValue; } private bool GetPredefinedTypeKindOption(State state, out TypeKindOptions typeKindValueFinal) { if (state.IsAttribute) { typeKindValueFinal = TypeKindOptions.Attribute; return true; } if (_service.TryGetBaseList(state.NameOrMemberAccessExpression, out var typeKindValue)) { typeKindValueFinal = typeKindValue; return true; } if (state.IsClassInterfaceTypes) { typeKindValueFinal = TypeKindOptions.BaseList; return true; } if (state.IsDelegateOnly) { typeKindValueFinal = TypeKindOptions.Delegate; return true; } if (state.IsTypeGeneratedIntoNamespaceFromMemberAccess) { typeKindValueFinal = state.IsSimpleNameGeneric ? TypeKindOptionsHelper.RemoveOptions(TypeKindOptions.MemberAccessWithNamespace, TypeKindOptions.GenericInCompatibleTypes) : TypeKindOptions.MemberAccessWithNamespace; typeKindValueFinal = state.IsEnumNotAllowed ? TypeKindOptionsHelper.RemoveOptions(typeKindValueFinal, TypeKindOptions.Enum) : typeKindValueFinal; return true; } typeKindValueFinal = TypeKindOptions.AllOptions; return false; } protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync( object options, IProgress<CodeAnalysisProgress> progressTracker, CancellationToken cancellationToken) { var operations = SpecializedCollections.EmptyEnumerable<CodeActionOperation>(); if (options is GenerateTypeOptionsResult generateTypeOptions && !generateTypeOptions.IsCancelled) { var semanticDocument = await SemanticDocument.CreateAsync(_document, cancellationToken).ConfigureAwait(false); var editor = new Editor(_service, semanticDocument, _state, fromDialog: true, generateTypeOptions, cancellationToken); operations = await editor.GetOperationsAsync().ConfigureAwait(false); } return operations; } } }