diff --git a/src/Workspaces/Remote/Core/RemoteHostOptions.cs b/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs similarity index 67% rename from src/Workspaces/Remote/Core/RemoteHostOptions.cs rename to src/EditorFeatures/Core/Remote/RemoteHostOptions.cs index 17f6a21e1c774..d97aef64a012a 100644 --- a/src/Workspaces/Remote/Core/RemoteHostOptions.cs +++ b/src/EditorFeatures/Core/Remote/RemoteHostOptions.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Immutable; using System.Composition; -using System.Runtime.InteropServices; -using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options.Providers; @@ -35,11 +33,6 @@ internal sealed class RemoteHostOptions : IOptionProvider FeatureName, nameof(OOP64Bit), defaultValue: true, storageLocation: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(OOP64Bit))); - // use Server GC for 64-bit OOP - public static readonly Option2 OOPServerGC = new( - FeatureName, nameof(OOPServerGC), defaultValue: false, - storageLocation: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(OOPServerGC))); - public static readonly Option2 OOPServerGCFeatureFlag = new( FeatureName, nameof(OOPServerGCFeatureFlag), defaultValue: false, new FeatureFlagStorageLocation("Roslyn.OOPServerGC")); @@ -52,7 +45,6 @@ internal sealed class RemoteHostOptions : IOptionProvider ImmutableArray IOptionProvider.Options { get; } = ImmutableArray.Create( SolutionChecksumMonitorBackOffTimeSpanInMS, OOP64Bit, - OOPServerGC, OOPServerGCFeatureFlag, OOPCoreClrFeatureFlag); @@ -61,21 +53,5 @@ internal sealed class RemoteHostOptions : IOptionProvider public RemoteHostOptions() { } - - public static bool IsServiceHubProcessServerGC(IGlobalOptionService globalOptions) - => globalOptions.GetOption(OOPServerGC) || globalOptions.GetOption(OOPServerGCFeatureFlag); - - /// - /// Determines whether ServiceHub out-of-process execution is enabled for Roslyn. - /// - public static bool IsUsingServiceHubOutOfProcess(IGlobalOptionService globalOptions) - => Environment.Is64BitOperatingSystem && globalOptions.GetOption(OOP64Bit); - - public static bool IsServiceHubProcessCoreClr(IGlobalOptionService globalOptions) - => globalOptions.GetOption(OOPCoreClrFeatureFlag); - - public static bool IsCurrentProcessRunningOnCoreClr() - => !RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework") && - !RuntimeInformation.FrameworkDescription.StartsWith(".NET Native"); } } diff --git a/src/Workspaces/Remote/Core/SolutionChecksumUpdater.cs b/src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs similarity index 100% rename from src/Workspaces/Remote/Core/SolutionChecksumUpdater.cs rename to src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs diff --git a/src/VisualStudio/Core/Def/Implementation/Remote/VisualStudioRemoteHostClientProvider.cs b/src/VisualStudio/Core/Def/Implementation/Remote/VisualStudioRemoteHostClientProvider.cs index 280ed5877add2..9ef7d6e85938c 100644 --- a/src/VisualStudio/Core/Def/Implementation/Remote/VisualStudioRemoteHostClientProvider.cs +++ b/src/VisualStudio/Core/Def/Implementation/Remote/VisualStudioRemoteHostClientProvider.cs @@ -54,7 +54,7 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) { // We don't want to bring up the OOP process in a VS cloud environment client instance // Avoids proffering brokered services on the client instance. - if (!RemoteHostOptions.IsUsingServiceHubOutOfProcess(_globalOptions) || + if (!_globalOptions.GetOption(RemoteHostOptions.OOP64Bit) || workspaceServices.Workspace is not VisualStudioWorkspace || workspaceServices.GetRequiredService().IsCloudEnvironmentClient()) { @@ -99,8 +99,12 @@ private VisualStudioRemoteHostClientProvider( var brokeredServiceContainer = await _vsServiceProvider.GetServiceAsync().ConfigureAwait(false); var serviceBroker = brokeredServiceContainer.GetFullAccessServiceBroker(); + var configuration = + (_globalOptions.GetOption(RemoteHostOptions.OOPCoreClrFeatureFlag) ? RemoteProcessConfiguration.Core : 0) | + (_globalOptions.GetOption(RemoteHostOptions.OOPServerGCFeatureFlag) ? RemoteProcessConfiguration.ServerGC : 0); + // VS AsyncLazy does not currently support cancellation: - var client = await ServiceHubRemoteHostClient.CreateAsync(_services, _globalOptions, _listenerProvider, serviceBroker, _callbackDispatchers, CancellationToken.None).ConfigureAwait(false); + var client = await ServiceHubRemoteHostClient.CreateAsync(_services, configuration, _listenerProvider, serviceBroker, _callbackDispatchers, CancellationToken.None).ConfigureAwait(false); // proffer in-proc brokered services: _ = brokeredServiceContainer.Proffer(SolutionAssetProvider.ServiceDescriptor, (_, _, _, _) => ValueTaskFactory.FromResult(new SolutionAssetProvider(_services))); diff --git a/src/VisualStudio/Core/Def/Microsoft.VisualStudio.LanguageServices.csproj b/src/VisualStudio/Core/Def/Microsoft.VisualStudio.LanguageServices.csproj index 2dd33442b401e..efa1ddfddfdd6 100644 --- a/src/VisualStudio/Core/Def/Microsoft.VisualStudio.LanguageServices.csproj +++ b/src/VisualStudio/Core/Def/Microsoft.VisualStudio.LanguageServices.csproj @@ -64,7 +64,6 @@ - diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs index ff147d0b0628e..6d91c44f6f5d0 100644 --- a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs +++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs @@ -83,7 +83,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke _threadingContext = componentModel.GetService(); var globalOptions = componentModel.GetService(); - var workspace = componentModel.GetService(); + _workspace = componentModel.GetService(); _ = new ForceLowMemoryMode(globalOptions); // Add our command handlers for menu (commands must exist in the .vsct file) @@ -96,7 +96,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke } // set logger at start up - PerformanceLoggersPage.SetLoggers(globalOptions, _threadingContext, workspace.Services); + PerformanceLoggersPage.SetLoggers(globalOptions, _threadingContext, _workspace.Services); } #endregion diff --git a/src/Workspaces/CoreTestUtilities/Remote/InProcRemostHostClient.cs b/src/Workspaces/CoreTestUtilities/Remote/InProcRemostHostClient.cs index d9ffbca4b7003..7aba10a48ba24 100644 --- a/src/Workspaces/CoreTestUtilities/Remote/InProcRemostHostClient.cs +++ b/src/Workspaces/CoreTestUtilities/Remote/InProcRemostHostClient.cs @@ -64,7 +64,7 @@ public RemoteWorkspace GetRemoteWorkspace() public override RemoteServiceConnection CreateConnection(object? callbackTarget) where T : class { - var descriptor = ServiceDescriptors.Instance.GetServiceDescriptor(typeof(T), isRemoteHostServerGC: GCSettings.IsServerGC, isRemoteHostCoreClr: RemoteHostOptions.IsCurrentProcessRunningOnCoreClr()); + var descriptor = ServiceDescriptors.Instance.GetServiceDescriptor(typeof(T), RemoteProcessConfiguration.ServerGC | (ServiceDescriptors.IsCurrentProcessRunningOnCoreClr() ? RemoteProcessConfiguration.Core : 0)); var callbackDispatcher = (descriptor.ClientInterface != null) ? _callbackDispatchers.GetDispatcher(typeof(T)) : null; return new BrokeredServiceConnection( diff --git a/src/Workspaces/Remote/Core/ExternalAccess/UnitTesting/Api/UnitTestingRemoteHostClient.cs b/src/Workspaces/Remote/Core/ExternalAccess/UnitTesting/Api/UnitTestingRemoteHostClient.cs index b031bf104c4c2..d74c0d32d26ac 100644 --- a/src/Workspaces/Remote/Core/ExternalAccess/UnitTesting/Api/UnitTestingRemoteHostClient.cs +++ b/src/Workspaces/Remote/Core/ExternalAccess/UnitTesting/Api/UnitTestingRemoteHostClient.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Remote; namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api @@ -33,13 +32,6 @@ internal UnitTestingRemoteHostClient(ServiceHubRemoteHostClient client, UnitTest return new UnitTestingRemoteHostClient((ServiceHubRemoteHostClient)client, serviceDescriptors, callbackDispatchers); } - [Obsolete("Use UnitTestingGlobalOptions.IsServiceHubProcessCoreClr instead")] - public static bool IsServiceHubProcessCoreClr(HostWorkspaceServices services) - { - var optionServices = services.GetRequiredService(); - return optionServices.GetOption(RemoteHostOptions.OOPCoreClrFeatureFlag); - } - public UnitTestingRemoteServiceConnectionWrapper CreateConnection(object? callbackTarget) where TService : class => new(_client.CreateConnection(_serviceDescriptors.UnderlyingObject, _callbackDispatchers, callbackTarget)); diff --git a/src/Workspaces/Remote/Core/RemoteProcessConfiguration.cs b/src/Workspaces/Remote/Core/RemoteProcessConfiguration.cs new file mode 100644 index 0000000000000..aac8916b583d2 --- /dev/null +++ b/src/Workspaces/Remote/Core/RemoteProcessConfiguration.cs @@ -0,0 +1,22 @@ +// 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; + +namespace Microsoft.CodeAnalysis.Remote +{ + [Flags] + internal enum RemoteProcessConfiguration + { + /// + /// Remote host runs on .NET 6+. + /// + Core = 1, + + /// + /// Remote host uses server GC. + /// + ServerGC = 1 << 1 + } +} diff --git a/src/Workspaces/Remote/Core/ServiceDescriptors.cs b/src/Workspaces/Remote/Core/ServiceDescriptors.cs index 339d2fd811c94..f1388af0864f2 100644 --- a/src/Workspaces/Remote/Core/ServiceDescriptors.cs +++ b/src/Workspaces/Remote/Core/ServiceDescriptors.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Runtime; +using System.Runtime.InteropServices; using Microsoft.CodeAnalysis.AddImport; using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.CodeLens; @@ -120,18 +121,23 @@ internal static string GetSimpleName(Type serviceInterface) return (descriptor64, descriptor64ServerGC, descriptorCoreClr64, descriptorCoreClr64ServerGC); } + public static bool IsCurrentProcessRunningOnCoreClr() + => !RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework") && + !RuntimeInformation.FrameworkDescription.StartsWith(".NET Native"); + public ServiceDescriptor GetServiceDescriptorForServiceFactory(Type serviceType) - => GetServiceDescriptor(serviceType, isRemoteHostServerGC: GCSettings.IsServerGC, isRemoteHostCoreClr: RemoteHostOptions.IsCurrentProcessRunningOnCoreClr()); + => GetServiceDescriptor(serviceType, RemoteProcessConfiguration.ServerGC | (IsCurrentProcessRunningOnCoreClr() ? RemoteProcessConfiguration.Core : 0)); - public ServiceDescriptor GetServiceDescriptor(Type serviceType, bool isRemoteHostServerGC, bool isRemoteHostCoreClr) + public ServiceDescriptor GetServiceDescriptor(Type serviceType, RemoteProcessConfiguration configuration) { var (descriptor64, descriptor64ServerGC, descriptorCoreClr64, descriptorCoreClr64ServerGC) = _descriptors[serviceType]; - return (isRemoteHostServerGC, isRemoteHostCoreClr) switch + return (configuration & (RemoteProcessConfiguration.Core | RemoteProcessConfiguration.ServerGC)) switch { - (false, false) => descriptor64, - (false, true) => descriptorCoreClr64, - (true, false) => descriptor64ServerGC, - (true, true) => descriptorCoreClr64ServerGC, + 0 => descriptor64, + RemoteProcessConfiguration.Core => descriptorCoreClr64, + RemoteProcessConfiguration.ServerGC => descriptor64ServerGC, + RemoteProcessConfiguration.Core | RemoteProcessConfiguration.ServerGC => descriptorCoreClr64ServerGC, + _ => throw ExceptionUtilities.Unreachable }; } diff --git a/src/Workspaces/Remote/Core/ServiceHubRemoteHostClient.cs b/src/Workspaces/Remote/Core/ServiceHubRemoteHostClient.cs index 3569e9de6c292..73769d50adacd 100644 --- a/src/Workspaces/Remote/Core/ServiceHubRemoteHostClient.cs +++ b/src/Workspaces/Remote/Core/ServiceHubRemoteHostClient.cs @@ -32,12 +32,11 @@ internal sealed partial class ServiceHubRemoteHostClient : RemoteHostClient private readonly IRemoteHostClientShutdownCancellationService? _shutdownCancellationService; private readonly IRemoteServiceCallbackDispatcherProvider _callbackDispatcherProvider; - private readonly bool _isRemoteHostServerGC; - private readonly bool _isRemoteHostCoreClr; + public readonly RemoteProcessConfiguration Configuration; private ServiceHubRemoteHostClient( HostWorkspaceServices services, - IGlobalOptionService globalOptions, + RemoteProcessConfiguration configuration, ServiceBrokerClient serviceBrokerClient, HubClient hubClient, IRemoteServiceCallbackDispatcherProvider callbackDispatcherProvider) @@ -53,13 +52,12 @@ private ServiceHubRemoteHostClient( _assetStorage = services.GetRequiredService().AssetStorage; _errorReportingService = services.GetService(); _shutdownCancellationService = services.GetService(); - _isRemoteHostServerGC = RemoteHostOptions.IsServiceHubProcessServerGC(globalOptions); - _isRemoteHostCoreClr = RemoteHostOptions.IsServiceHubProcessCoreClr(globalOptions); + Configuration = configuration; } public static async Task CreateAsync( HostWorkspaceServices services, - IGlobalOptionService globalOptions, + RemoteProcessConfiguration configuration, AsynchronousOperationListenerProvider listenerProvider, IServiceBroker serviceBroker, RemoteServiceCallbackDispatcherRegistry callbackDispatchers, @@ -74,7 +72,7 @@ public static async Task CreateAsync( var hubClient = new HubClient("ManagedLanguage.IDE.RemoteHostClient"); - var client = new ServiceHubRemoteHostClient(services, globalOptions, serviceBrokerClient, hubClient, callbackDispatchers); + var client = new ServiceHubRemoteHostClient(services, configuration, serviceBrokerClient, hubClient, callbackDispatchers); var syntaxTreeConfigurationService = services.GetService(); if (syntaxTreeConfigurationService != null) @@ -104,7 +102,7 @@ public override RemoteServiceConnection CreateConnection(object? callbackT /// internal RemoteServiceConnection CreateConnection(ServiceDescriptors descriptors, IRemoteServiceCallbackDispatcherProvider callbackDispatcherProvider, object? callbackTarget) where T : class { - var descriptor = descriptors.GetServiceDescriptor(typeof(T), _isRemoteHostServerGC, _isRemoteHostCoreClr); + var descriptor = descriptors.GetServiceDescriptor(typeof(T), Configuration); var callbackDispatcher = (descriptor.ClientInterface != null) ? callbackDispatcherProvider.GetDispatcher(typeof(T)) : null; return new BrokeredServiceConnection( diff --git a/src/Workspaces/Remote/ServiceHub/Services/AssetSynchronization/RemoteAssetSynchronizationService.cs b/src/Workspaces/Remote/ServiceHub/Services/AssetSynchronization/RemoteAssetSynchronizationService.cs index 6f8a33d9e34ba..b410618048d0c 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/AssetSynchronization/RemoteAssetSynchronizationService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/AssetSynchronization/RemoteAssetSynchronizationService.cs @@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.Remote { /// - /// This service is used by the to proactively update the solution snapshot in + /// This service is used by the SolutionChecksumUpdater to proactively update the solution snapshot in /// the out-of-process workspace. We do this to limit the amount of time required to synchronize a solution over after an edit /// once a feature is asking for a snapshot. ///