diff --git a/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs b/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs index 64007719c6225b502a08384f9b9395f6ba15f33c..69f33938b93c40663d8698c40c936a86ad78f81c 100644 --- a/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs @@ -381,7 +381,7 @@ private static async Task GetSolutionServiceAsync(Solution solu var storage = new AssetStorage(); var source = new TestAssetSource(storage, map); var remoteWorkspace = new RemoteWorkspace(); - var service = new SolutionService(new AssetService(sessionId, storage, remoteWorkspace), remoteWorkspace); + var service = new SolutionService(new AssetService(sessionId, storage, remoteWorkspace)); return service; } diff --git a/src/Workspaces/Remote/Core/Services/RoslynServices.cs b/src/Workspaces/Remote/Core/Services/RoslynServices.cs index 1b6825662b1199ddfadc3a35ddff0d25c2b8d252..ef0dd8703e0f75b1c42f55f1d3c44f652748bb4f 100644 --- a/src/Workspaces/Remote/Core/Services/RoslynServices.cs +++ b/src/Workspaces/Remote/Core/Services/RoslynServices.cs @@ -78,7 +78,7 @@ public RoslynServices(int scopeId, AssetStorage storage, HostServices hostServic var workspace = (RemoteWorkspace)primaryWorkspace.Workspace ?? new RemoteWorkspace(); AssetService = new AssetService(_scopeId, storage, workspace); - SolutionService = new SolutionService(AssetService, workspace); + SolutionService = new SolutionService(AssetService); CompilationService = new CompilationService(SolutionService); } diff --git a/src/Workspaces/Remote/Core/Services/SolutionService.cs b/src/Workspaces/Remote/Core/Services/SolutionService.cs index f3f9a8219048edfe33db3cd4e4aa8f18a3db9806..cc604a54ab6d81894d6abea636940b8d1eadcb61 100644 --- a/src/Workspaces/Remote/Core/Services/SolutionService.cs +++ b/src/Workspaces/Remote/Core/Services/SolutionService.cs @@ -1,8 +1,10 @@ // 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 System; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Host.Mef; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Remote @@ -22,15 +24,27 @@ internal class SolutionService : ISolutionController private volatile static Tuple s_primarySolution; private volatile static Tuple s_lastSolution; - public SolutionService(AssetService assetService, RemoteWorkspace remoteWorkspace) + public SolutionService(AssetService assetService) { _assetService = assetService; - PrimaryWorkspace = remoteWorkspace; } - public RemoteWorkspace PrimaryWorkspace + public static RemoteWorkspace PrimaryWorkspace { - get; + get + { + var exportProvider = (IMefHostExportProvider)RoslynServices.HostServices; + var primaryWorkspace = exportProvider.GetExports().Single().Value; + if (primaryWorkspace.Workspace == null) + { + // The Roslyn OOP service assumes a singleton workspace exists, but doesn't initialize it anywhere. + // If we get here, code is asking for a workspace before it exists, so we create one on the fly. + // The RemoteWorkspace constructor assigns itself as the new singleton instance. + new RemoteWorkspace(); + } + + return (RemoteWorkspace)primaryWorkspace.Workspace; + } } public Task GetSolutionAsync(Checksum solutionChecksum, CancellationToken cancellationToken) diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_Diagnostics.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_Diagnostics.cs index 0fc02ec7971ec1ed8a3f71a604654a16a716f0d4..4c2e6b3fae9f936be679676d6483ff211861ebc5 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_Diagnostics.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_Diagnostics.cs @@ -62,7 +62,7 @@ public void ReportAnalyzerPerformance(List snapshot, in { token.ThrowIfCancellationRequested(); - var service = RoslynServices.SolutionService.PrimaryWorkspace.Services.GetService(); + var service = SolutionService.PrimaryWorkspace.Services.GetService(); if (service == null) { return; diff --git a/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.cs b/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.cs index 7ab6da500f512d2015ae89bc926438fcf486fef8..9c5f3033b1c2c6615d998d9532bfcb28df1582ed 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/RemoteHostService.cs @@ -220,10 +220,10 @@ private void SetGlobalContext(int uiCultureLCID, int cultureLCID, string seriali FatalError.NonFatalHandler = WatsonReporter.Report; // start performance reporter - var diagnosticAnalyzerPerformanceTracker = RoslynServices.SolutionService.PrimaryWorkspace.Services.GetService(); + var diagnosticAnalyzerPerformanceTracker = SolutionService.PrimaryWorkspace.Services.GetService(); if (diagnosticAnalyzerPerformanceTracker != null) { - var globalOperationNotificationService = RoslynServices.SolutionService.PrimaryWorkspace.Services.GetService(); + var globalOperationNotificationService = SolutionService.PrimaryWorkspace.Services.GetService(); _performanceReporter = new PerformanceReporter(Logger, diagnosticAnalyzerPerformanceTracker, globalOperationNotificationService, s_reportInterval, ShutdownCancellationToken); } } @@ -265,12 +265,12 @@ private static TelemetrySession GetTelemetrySession(string serializedSession) private RemotePersistentStorageLocationService GetPersistentStorageService() { - return (RemotePersistentStorageLocationService)RoslynServices.SolutionService.PrimaryWorkspace.Services.GetService(); + return (RemotePersistentStorageLocationService)SolutionService.PrimaryWorkspace.Services.GetService(); } private RemoteGlobalOperationNotificationService GetGlobalOperationNotificationService() { - var notificationService = RoslynServices.SolutionService.PrimaryWorkspace.Services.GetService() as RemoteGlobalOperationNotificationService; + var notificationService = SolutionService.PrimaryWorkspace.Services.GetService() as RemoteGlobalOperationNotificationService; return notificationService; }