diff --git a/src/Features/Core/Portable/Features.csproj b/src/Features/Core/Portable/Features.csproj
index f3a305c1f9d3de6e76f4a8cb1de26ae84c8ac450..df851812afa1f44b93de300859b88b99d6592712 100644
--- a/src/Features/Core/Portable/Features.csproj
+++ b/src/Features/Core/Portable/Features.csproj
@@ -103,6 +103,7 @@
+
diff --git a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs
index e17452d8317f3f1a770688ee2adbcfa85f6d8459..b15fcae7cf486d6d84dc697a01886c2725ed77e5 100644
--- a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs
+++ b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs
@@ -44,7 +44,15 @@ internal abstract partial class AbstractNavigateToSearchService
}
}
- private static Task GetRemoteHostClientAsync(Project project, CancellationToken cancellationToken)
- => project.Solution.Workspace.GetRemoteHostClientAsync(cancellationToken);
+ private static async Task GetRemoteHostClientAsync(Project project, CancellationToken cancellationToken)
+ {
+ var outOfProcessAllowed = project.Solution.Workspace.Options.GetOption(NavigateToOptions.OutOfProcessAllowed);
+ if (!outOfProcessAllowed)
+ {
+ return null;
+ }
+
+ return await project.Solution.Workspace.GetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false);
+ }
}
}
\ No newline at end of file
diff --git a/src/Features/Core/Portable/NavigateTo/NavigateToOptions.cs b/src/Features/Core/Portable/NavigateTo/NavigateToOptions.cs
new file mode 100644
index 0000000000000000000000000000000000000000..629b947242ca6a2951d34a0b5ae70d37050ec9b1
--- /dev/null
+++ b/src/Features/Core/Portable/NavigateTo/NavigateToOptions.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.CodeAnalysis.Options;
+
+namespace Microsoft.CodeAnalysis.NavigateTo
+{
+ internal static class NavigateToOptions
+ {
+ private const string LocalRegistryPath = @"Roslyn\Features\NavigateTo\";
+
+ public static readonly Option OutOfProcessAllowed = new Option(nameof(NavigateToOptions), nameof(OutOfProcessAllowed), defaultValue: true,
+ storageLocations: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(OutOfProcessAllowed)));
+ }
+}
\ No newline at end of file
diff --git a/src/VisualStudio/Core/Def/Implementation/Remote/RemoteHostOptions.cs b/src/VisualStudio/Core/Def/Implementation/Remote/RemoteHostOptions.cs
index 43b04f6c23bfaa262c745551dcb2150816a43eb0..23d8efbefe3fb924335950c95835f99d08e41d5b 100644
--- a/src/VisualStudio/Core/Def/Implementation/Remote/RemoteHostOptions.cs
+++ b/src/VisualStudio/Core/Def/Implementation/Remote/RemoteHostOptions.cs
@@ -8,7 +8,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Remote
internal static class RemoteHostOptions
{
[ExportOption]
- public static readonly Option RemoteHost = new Option(nameof(InternalFeatureOnOffOptions), nameof(RemoteHost), defaultValue: true,
+ public static readonly Option RemoteHost = new Option(nameof(InternalFeatureOnOffOptions), nameof(RemoteHost), defaultValue: false,
storageLocations: new LocalUserProfileStorageLocation(InternalFeatureOnOffOptions.LocalRegistryPath + nameof(RemoteHost)));
[ExportOption]
diff --git a/src/Workspaces/Core/Desktop/SymbolSearch/SymbolSearchUpdateEngineFactory.cs b/src/Workspaces/Core/Desktop/SymbolSearch/SymbolSearchUpdateEngineFactory.cs
index 12217e4288995e7a8c4b3797597a32490d5fa155..815067846c7405077bf9751da3ba6f6cd8e5f6ae 100644
--- a/src/Workspaces/Core/Desktop/SymbolSearch/SymbolSearchUpdateEngineFactory.cs
+++ b/src/Workspaces/Core/Desktop/SymbolSearch/SymbolSearchUpdateEngineFactory.cs
@@ -18,25 +18,30 @@ internal static class SymbolSearchUpdateEngineFactory
public static async Task CreateEngineAsync(
Workspace workspace, ISymbolSearchLogService logService, CancellationToken cancellationToken)
{
- var client = await workspace.GetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false);
- if (client == null)
+ var outOfProcessAllowed = workspace.Options.GetOption(SymbolSearchOptions.OutOfProcessAllowed);
+ if (outOfProcessAllowed)
{
- return new SymbolSearchUpdateEngine(logService);
- }
+ var client = await workspace.GetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false);
+ if (client != null)
+ {
+ var emptySolution = workspace.CreateSolution(workspace.CurrentSolution.Id);
- var emptySolution = workspace.CreateSolution(workspace.CurrentSolution.Id);
+ // We create a single session and use it for the entire lifetime of this process.
+ // That single session will be used to do all communication with the remote process.
+ // This is because each session will cause a new instance of the RemoteSymbolSearchUpdateEngine
+ // to be created on the remote side. We only want one instance of that type. The
+ // alternative is to make that type static variable on the remote side. But that's
+ // much less clean and would make some of the state management much more complex.
+ var session = await client.CreateServiceSessionAsync(
+ WellKnownServiceHubServices.RemoteSymbolSearchUpdateEngine,
+ emptySolution, logService, cancellationToken).ConfigureAwait(false);
- // We create a single session and use it for the entire lifetime of this process.
- // That single session will be used to do all communication with the remote process.
- // This is because each session will cause a new instance of the RemoteSymbolSearchUpdateEngine
- // to be created on the remote side. We only want one instance of that type. The
- // alternative is to make that type static variable on the remote side. But that's
- // much less clean and would make some of the state management much more complex.
- var session = await client.CreateServiceSessionAsync(
- WellKnownServiceHubServices.RemoteSymbolSearchUpdateEngine,
- emptySolution, logService, cancellationToken).ConfigureAwait(false);
+ return new RemoteUpdateEngine(session);
+ }
+ }
- return new RemoteUpdateEngine(session);
+ // Couldn't go out of proc. Just do everything inside the current process.
+ return new SymbolSearchUpdateEngine(logService);
}
private class RemoteUpdateEngine : ISymbolSearchUpdateEngine
diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinderOptions.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinderOptions.cs
new file mode 100644
index 0000000000000000000000000000000000000000..afa4ebb0437175b445f49b2c0b14ab9678bcdcf2
--- /dev/null
+++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinderOptions.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.CodeAnalysis.Options;
+
+namespace Microsoft.CodeAnalysis.FindSymbols
+{
+ internal static class SymbolFinderOptions
+ {
+ private const string LocalRegistryPath = @"Roslyn\Features\SymbolFinder\";
+
+ public static readonly Option OutOfProcessAllowed = new Option(nameof(SymbolFinderOptions), nameof(OutOfProcessAllowed), defaultValue: true,
+ storageLocations: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(OutOfProcessAllowed)));
+ }
+}
\ No newline at end of file
diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Remote.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Remote.cs
index a452f414eda8701118e22ba7cce3e7113752158b..92f795f7475471e58d64a281c8c2a2fff176f0eb 100644
--- a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Remote.cs
+++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Remote.cs
@@ -17,11 +17,12 @@ public static partial class SymbolFinder
Solution solution,
IStreamingFindReferencesProgress progress,
IImmutableSet documents,
- CancellationToken cancellationToken = default(CancellationToken))
+ CancellationToken cancellationToken)
{
using (Logger.LogBlock(FunctionId.FindReference, cancellationToken))
{
- if (symbolAndProjectId.ProjectId == null)
+ var outOfProcessAllowed = solution.Workspace.Options.GetOption(SymbolFinderOptions.OutOfProcessAllowed);
+ if (symbolAndProjectId.ProjectId == null || !outOfProcessAllowed)
{
// This is a call through our old public API. We don't have the necessary
// data to effectively run the call out of proc.
diff --git a/src/Workspaces/Core/Portable/SymbolSearch/SymbolSearchOptions.cs b/src/Workspaces/Core/Portable/SymbolSearch/SymbolSearchOptions.cs
index 753438afb9acdf1fe024437f8b14dd25126e1a76..a7b1aa6577790fffebcab5d35df9a36c6059aa1f 100644
--- a/src/Workspaces/Core/Portable/SymbolSearch/SymbolSearchOptions.cs
+++ b/src/Workspaces/Core/Portable/SymbolSearch/SymbolSearchOptions.cs
@@ -6,7 +6,15 @@ namespace Microsoft.CodeAnalysis.SymbolSearch
{
internal static class SymbolSearchOptions
{
- public static readonly Option Enabled = new Option(nameof(SymbolSearchOptions), nameof(Enabled), defaultValue: true);
+ private const string LocalRegistryPath = @"Roslyn\Features\SymbolSearch\";
+
+ public static readonly Option Enabled = new Option(
+ nameof(SymbolSearchOptions), nameof(Enabled), defaultValue: true,
+ storageLocations: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(Enabled)));
+
+ public static readonly Option OutOfProcessAllowed = new Option(
+ nameof(SymbolSearchOptions), nameof(OutOfProcessAllowed), defaultValue: true,
+ storageLocations: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(OutOfProcessAllowed)));
public static PerLanguageOption SuggestForTypesInReferenceAssemblies =
new PerLanguageOption(nameof(SymbolSearchOptions), nameof(SuggestForTypesInReferenceAssemblies), defaultValue: false,
diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj
index 7fe788286098ddba3e8fd45497934a69ab371722..257f17e70f4de07d83dc9d62f5e185e0cee77128 100644
--- a/src/Workspaces/Core/Portable/Workspaces.csproj
+++ b/src/Workspaces/Core/Portable/Workspaces.csproj
@@ -386,6 +386,7 @@
+