/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/VisualStudio/Core/Def/Remote/VisualStudioRemoteHostClientProvider.cs
153 строки
7 KB
David Wengier
Potential fix for pull request finding
02 июл 2026, 03:42
Не верифицирован
02 июл 2026, 03:42
2dec798
Код
Авторство
О чём код?
// 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.Composition; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Shared.Preview; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Remote; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Settings; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.ServiceBroker; using Microsoft.VisualStudio.Shell.Settings; using Microsoft.VisualStudio.Threading; using Roslyn.Utilities; using VSThreading = Microsoft.VisualStudio.Threading; namespace Microsoft.VisualStudio.LanguageServices.Remote; internal sealed class VisualStudioRemoteHostClientProvider : IRemoteHostClientProvider { [ExportWorkspaceServiceFactory(typeof(IRemoteHostClientProvider), [WorkspaceKind.Host, WorkspaceKind.Preview]), Shared] internal sealed class Factory : IWorkspaceServiceFactory { private readonly VisualStudioWorkspace _vsWorkspace; private readonly IVsService<IBrokeredServiceContainer> _brokeredServiceContainer; private readonly IServiceProvider _serviceProvider; private readonly AsynchronousOperationListenerProvider _listenerProvider; private readonly RemoteServiceCallbackDispatcherRegistry _callbackDispatchers; private readonly IGlobalOptionService _globalOptions; private readonly IThreadingContext _threadingContext; private readonly object _gate = new(); private VisualStudioRemoteHostClientProvider? _cachedVSInstance; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public Factory( VisualStudioWorkspace vsWorkspace, IVsService<SVsBrokeredServiceContainer, IBrokeredServiceContainer> brokeredServiceContainer, SVsServiceProvider serviceProvider, AsynchronousOperationListenerProvider listenerProvider, IGlobalOptionService globalOptions, IThreadingContext threadingContext, [ImportMany] IEnumerable<Lazy<IRemoteServiceCallbackDispatcher, RemoteServiceCallbackDispatcherRegistry.ExportMetadata>> callbackDispatchers) { _globalOptions = globalOptions; _vsWorkspace = vsWorkspace; _brokeredServiceContainer = brokeredServiceContainer; _serviceProvider = serviceProvider; _listenerProvider = listenerProvider; _threadingContext = threadingContext; _callbackDispatchers = new RemoteServiceCallbackDispatcherRegistry(callbackDispatchers); } [Obsolete(MefConstruction.FactoryMethodMessage, error: true)] public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) { Debug.Assert(workspaceServices.Workspace is VisualStudioWorkspace or PreviewWorkspace); // If OOP is disabled, or the host services are different, then we can't use the cached VS instance; fall back to in-proc. // This can happen for preview workspace in Tools|Options. if (!_globalOptions.GetOption(RemoteHostOptionsStorage.OOP64Bit) || workspaceServices.SolutionServices.WorkspaceServices.HostServices != _vsWorkspace.Services.HostServices) { // Run code in the current process return new DefaultRemoteHostClientProvider(); } lock (_gate) { // If we have a cached vs instance, then we can return that instance since we know they have the same host services. // Otherwise, create and cache an instance based on vs workspace for future callers with same services. if (_cachedVSInstance is null) _cachedVSInstance = new VisualStudioRemoteHostClientProvider(_vsWorkspace.Services.SolutionServices, _brokeredServiceContainer, _serviceProvider, _threadingContext, _listenerProvider, _callbackDispatchers); return _cachedVSInstance; } } } public readonly SolutionServices Services; private readonly VSThreading.AsyncLazy<RemoteHostClient?> _lazyClient; private readonly IVsService<IBrokeredServiceContainer> _brokeredServiceContainer; private readonly IServiceProvider _serviceProvider; private readonly AsynchronousOperationListenerProvider _listenerProvider; private readonly RemoteServiceCallbackDispatcherRegistry _callbackDispatchers; private readonly TaskCompletionSource<bool> _clientCreationSource = new(TaskCreationOptions.RunContinuationsAsynchronously); private readonly IThreadingContext _threadingContext; private VisualStudioRemoteHostClientProvider( SolutionServices services, IVsService<IBrokeredServiceContainer> brokeredServiceContainer, IServiceProvider serviceProvider, IThreadingContext threadingContext, AsynchronousOperationListenerProvider listenerProvider, RemoteServiceCallbackDispatcherRegistry callbackDispatchers) { Services = services; _brokeredServiceContainer = brokeredServiceContainer; _serviceProvider = serviceProvider; _listenerProvider = listenerProvider; _callbackDispatchers = callbackDispatchers; _threadingContext = threadingContext; // using VS AsyncLazy here since Roslyn's is not compatible with JTF. // Our ServiceBroker services may be invoked by other VS components under JTF. _lazyClient = new VSThreading.AsyncLazy<RemoteHostClient?>(CreateHostClientAsync, _threadingContext.JoinableTaskFactory); } private async Task<RemoteHostClient?> CreateHostClientAsync() { try { var brokeredServiceContainer = await _brokeredServiceContainer.GetValueAsync().ConfigureAwait(false); var serviceBroker = brokeredServiceContainer.GetFullAccessServiceBroker(); var localSettingsDirectory = new ShellSettingsManager(_serviceProvider).GetApplicationDataFolder(ApplicationDataFolder.LocalSettings); // VS AsyncLazy does not currently support cancellation: var client = await ServiceHubRemoteHostClient.CreateAsync(Services, localSettingsDirectory, _listenerProvider, serviceBroker, _callbackDispatchers, _threadingContext.DisposalToken).ConfigureAwait(false); // proffer in-proc brokered services: _ = brokeredServiceContainer.Proffer(SolutionAssetProvider.ServiceDescriptor, (_, _, _, _) => ValueTask.FromResult<object?>(new SolutionAssetProvider(Services))); return client; } catch (Exception e) when (FatalError.ReportAndCatchUnlessCanceled(e)) { return null; } finally { _clientCreationSource.SetResult(true); } } public Task<RemoteHostClient?> TryGetRemoteHostClientAsync(CancellationToken cancellationToken) => _lazyClient.GetValueAsync(cancellationToken); public Task WaitForClientCreationAsync(CancellationToken cancellationToken) => _clientCreationSource.Task.WithCancellation(cancellationToken); }