File: PullMemberUp\VisualStudioPullMemberUpService.cs
Web Access
Project: src\src\VisualStudio\Core\Def\Microsoft.VisualStudio.LanguageServices_pxr0p0dn_wpftmp.csproj (Microsoft.VisualStudio.LanguageServices)
// 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;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeRefactorings.PullMemberUp.Dialog;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.PullMemberUp;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.LanguageServices.Implementation.PullMemberUp.MainDialog;
using Microsoft.VisualStudio.LanguageServices.Utilities;
using Microsoft.VisualStudio.Utilities;
using Roslyn.Utilities;
 
namespace Microsoft.VisualStudio.LanguageServices.Implementation.PullMemberUp;
 
[ExportWorkspaceService(typeof(IPullMemberUpOptionsService), ServiceLayer.Host), Shared]
internal class VisualStudioPullMemberUpService : IPullMemberUpOptionsService
{
    private readonly IGlyphService _glyphService;
    private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor;
 
    [ImportingConstructor]
    [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
    public VisualStudioPullMemberUpService(IGlyphService glyphService, IUIThreadOperationExecutor uiThreadOperationExecutor)
    {
        _glyphService = glyphService;
        _uiThreadOperationExecutor = uiThreadOperationExecutor;
    }
 
    public PullMembersUpOptions GetPullMemberUpOptions(Document document, ImmutableArray<ISymbol> selectedMembers)
    {
        // all selected members must have the same containing type
        var containingType = selectedMembers[0].ContainingType;
        var membersInType = containingType.GetMembers().
            WhereAsArray(MemberAndDestinationValidator.IsMemberValid);
        var memberViewModels = membersInType
            .SelectAsArray(member =>
                new MemberSymbolViewModel(member, _glyphService)
                {
                    // The member user selected will be checked at the beginning.
                    IsChecked = selectedMembers.Any(SymbolEquivalenceComparer.Instance.Equals, member),
                    MakeAbstract = false,
                    IsMakeAbstractCheckable = !member.IsKind(SymbolKind.Field) && !member.IsAbstract,
                    IsCheckable = true
                });
 
        using var cancellationTokenSource = new CancellationTokenSource();
        var baseTypeRootViewModel = BaseTypeTreeNodeViewModel.CreateBaseTypeTree(
            _glyphService,
            document.Project.Solution,
            containingType,
            cancellationTokenSource.Token);
        var memberToDependentsMap = SymbolDependentsBuilder.FindMemberToDependentsMap(membersInType, document.Project, cancellationTokenSource.Token);
        var viewModel = new PullMemberUpDialogViewModel(_uiThreadOperationExecutor, memberViewModels, baseTypeRootViewModel, memberToDependentsMap);
        var dialog = new PullMemberUpDialog(viewModel);
        var result = dialog.ShowModal();
 
        // Dialog has finshed its work, cancel finding dependents task.
        cancellationTokenSource.Cancel();
        if (result.GetValueOrDefault())
        {
            return dialog.ViewModel.CreatePullMemberUpOptions();
        }
        else
        {
            return null;
        }
    }
}