From 161cfdf4398959ad50440b9f812eafb0b7fcb0e5 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 22 Mar 2024 15:23:58 -0700 Subject: [PATCH 1/3] Simplify updating the primary workspace without passing in a version --- .../Core/Remote/SolutionChecksumUpdater.cs | 9 +- .../Services/ServiceHubServicesTests.cs | 12 +-- .../Services/SolutionServiceTests.cs | 97 +++++++++---------- .../IRemoteAssetSynchronizationService.cs | 19 ++-- .../Remote/ServiceHub/Host/RemoteWorkspace.cs | 48 ++------- .../Host/RemoteWorkspace_SolutionCaching.cs | 5 +- .../RemoteAssetSynchronizationService.cs | 4 +- 7 files changed, 75 insertions(+), 119 deletions(-) diff --git a/src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs b/src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs index 12dd252c7bec2..9febf4218e7e5 100644 --- a/src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs +++ b/src/EditorFeatures/Core/Remote/SolutionChecksumUpdater.cs @@ -60,9 +60,6 @@ public SolutionChecksumUpdater( listener, shutdownToken); - // Use an equality comparer here as we will commonly get lots of change notifications that will all be - // associated with the same cancellation token controlling that batch of work. No need to enqueue the same - // token a huge number of times when we only need the single value of it when doing the work. _synchronizeWorkspaceQueue = new AsyncBatchingWorkQueue( DelayTimeSpan.NearImmediate, SynchronizePrimaryWorkspaceAsync, @@ -142,17 +139,15 @@ private void OnWorkspaceChanged(object? sender, WorkspaceChangeEventArgs e) private async ValueTask SynchronizePrimaryWorkspaceAsync(CancellationToken cancellationToken) { - var solution = _workspace.CurrentSolution; var client = await RemoteHostClient.TryGetClientAsync(_workspace, cancellationToken).ConfigureAwait(false); if (client == null) return; using (Logger.LogBlock(FunctionId.SolutionChecksumUpdater_SynchronizePrimaryWorkspace, cancellationToken)) { - var workspaceVersion = solution.WorkspaceVersion; await client.TryInvokeAsync( - solution, - (service, solution, cancellationToken) => service.SynchronizePrimaryWorkspaceAsync(solution, workspaceVersion, cancellationToken), + _workspace.CurrentSolution, + (service, solution, cancellationToken) => service.SynchronizePrimaryWorkspaceAsync(solution, cancellationToken), cancellationToken).ConfigureAwait(false); } } diff --git a/src/VisualStudio/Core/Test.Next/Services/ServiceHubServicesTests.cs b/src/VisualStudio/Core/Test.Next/Services/ServiceHubServicesTests.cs index 30022d8d436a0..9ba50f5f37516 100644 --- a/src/VisualStudio/Core/Test.Next/Services/ServiceHubServicesTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/ServiceHubServicesTests.cs @@ -137,7 +137,7 @@ public async Task TestDesignerAttributes() // Ensure remote workspace is in sync with normal workspace. var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, solution); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, solution.WorkspaceVersion, CancellationToken.None); + await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, CancellationToken.None); var callback = new DesignerAttributeComputerCallback(); @@ -188,7 +188,7 @@ public async Task TestDesignerAttributesUnsupportedLanguage() // Ensure remote workspace is in sync with normal workspace. var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, solution); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, solution.WorkspaceVersion, CancellationToken.None); + await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, CancellationToken.None); var callback = new DesignerAttributeComputerCallback(); @@ -359,9 +359,8 @@ public async Task TestRemoteWorkspaceCircularReferences() using var remoteWorkspace = new RemoteWorkspace(FeaturesTestCompositions.RemoteHost.GetHostServices()); // this shouldn't throw exception - var (solution, updated) = await remoteWorkspace.GetTestAccessor().TryUpdateWorkspaceCurrentSolutionAsync( - remoteWorkspace.GetTestAccessor().CreateSolutionFromInfo(solutionInfo), workspaceVersion: 1); - Assert.True(updated); + var solution = await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync( + remoteWorkspace.GetTestAccessor().CreateSolutionFromInfo(solutionInfo)); Assert.NotNull(solution); } @@ -828,10 +827,9 @@ private static (Project project, ImmutableArray documents) GetProjectA private static async Task UpdatePrimaryWorkspace(RemoteHostClient client, Solution solution) { - var workspaceVersion = solution.WorkspaceVersion; await client.TryInvokeAsync( solution, - async (service, solutionInfo, cancellationToken) => await service.SynchronizePrimaryWorkspaceAsync(solutionInfo, workspaceVersion, cancellationToken), + async (service, solutionInfo, cancellationToken) => await service.SynchronizePrimaryWorkspaceAsync(solutionInfo, cancellationToken), CancellationToken.None); } diff --git a/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs b/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs index 3f6703acfb73d..d4957a9b777d2 100644 --- a/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs @@ -48,7 +48,7 @@ public async Task TestCreation() var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, solution); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(solutionChecksum, await synched.CompilationState.GetChecksumAsync(CancellationToken.None)); } @@ -66,7 +66,7 @@ public async Task TestGetSolutionWithPrimaryFlag(bool updatePrimaryBranch) var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, solution); - var synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch, solution.WorkspaceVersion, cancellationToken: CancellationToken.None); + var synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch, cancellationToken: CancellationToken.None); Assert.Equal(solutionChecksum, await synched.CompilationState.GetChecksumAsync(CancellationToken.None)); Assert.Equal(WorkspaceKind.RemoteWorkspace, synched.WorkspaceKind); @@ -88,7 +88,7 @@ public async Task TestStrongNameProvider() var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, workspace.CurrentSolution); var solutionChecksum = await workspace.CurrentSolution.CompilationState.GetChecksumAsync(CancellationToken.None); - var solution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var solution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, CancellationToken.None); var compilationOptions = solution.Projects.First().CompilationOptions; @@ -117,7 +117,7 @@ public async Task TestStrongNameProviderEmpty() var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, workspace.CurrentSolution); var solutionChecksum = await workspace.CurrentSolution.CompilationState.GetChecksumAsync(CancellationToken.None); - var solution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var solution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, CancellationToken.None); var compilationOptions = solution.Projects.First().CompilationOptions; @@ -141,8 +141,8 @@ public async Task TestCache() var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, solution); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var first = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); - var second = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var first = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, CancellationToken.None); + var second = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, CancellationToken.None); // same instance from cache Assert.True(object.ReferenceEquals(first, second)); @@ -345,44 +345,39 @@ public async Task TestRemoteWorkspace() var remoteSolution1 = await GetInitialOOPSolutionAsync(remoteWorkspace, assetProvider, solution1); await Verify(remoteWorkspace, solution1, remoteSolution1, expectRemoteSolutionToCurrent: true); - var version = solution1.WorkspaceVersion; // update remote workspace var currentSolution = remoteSolution1.WithDocumentText(remoteSolution1.Projects.First().Documents.First().Id, SourceText.From(code + " class Test2 { }")); - var (oopSolution2, _) = await remoteWorkspace.GetTestAccessor().TryUpdateWorkspaceCurrentSolutionAsync(currentSolution, ++version); + var oopSolution2 = await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync(currentSolution); await Verify(remoteWorkspace, currentSolution, oopSolution2, expectRemoteSolutionToCurrent: true); // move backward - await Verify(remoteWorkspace, remoteSolution1, (await remoteWorkspace.GetTestAccessor().TryUpdateWorkspaceCurrentSolutionAsync(remoteSolution1, solution1.WorkspaceVersion)).solution, expectRemoteSolutionToCurrent: false); + await Verify(remoteWorkspace, remoteSolution1, await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync(remoteSolution1), expectRemoteSolutionToCurrent: false); // move forward currentSolution = oopSolution2.WithDocumentText(oopSolution2.Projects.First().Documents.First().Id, SourceText.From(code + " class Test3 { }")); - var remoteSolution3 = (await remoteWorkspace.GetTestAccessor().TryUpdateWorkspaceCurrentSolutionAsync(currentSolution, ++version)).solution; + var remoteSolution3 = await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync(currentSolution); await Verify(remoteWorkspace, currentSolution, remoteSolution3, expectRemoteSolutionToCurrent: true); // move to new solution backward var solutionInfo2 = await assetProvider.CreateSolutionInfoAsync(await solution1.CompilationState.GetChecksumAsync(CancellationToken.None), CancellationToken.None); var solution2 = remoteWorkspace.GetTestAccessor().CreateSolutionFromInfo(solutionInfo2); - Assert.False((await remoteWorkspace.GetTestAccessor().TryUpdateWorkspaceCurrentSolutionAsync( - solution2, solution1.WorkspaceVersion)).updated); // move to new solution forward - var (solution3, updated3) = await remoteWorkspace.GetTestAccessor().TryUpdateWorkspaceCurrentSolutionAsync( - solution2, ++version); + var solution3 = await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync(solution2); Assert.NotNull(solution3); - Assert.True(updated3); await Verify(remoteWorkspace, solution1, solution3, expectRemoteSolutionToCurrent: true); static async Task GetInitialOOPSolutionAsync(RemoteWorkspace remoteWorkspace, AssetProvider assetProvider, Solution solution) { // set up initial solution var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, solution.WorkspaceVersion, CancellationToken.None); + await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, CancellationToken.None); // get solution in remote host - return await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + return await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, CancellationToken.None); } static async Task Verify(RemoteWorkspace remoteWorkspace, Solution givenSolution, Solution remoteSolution, bool expectRemoteSolutionToCurrent) @@ -407,7 +402,7 @@ public async Task TestAddingProjectsWithExplicitOptions(bool useDefaultOptionVal solution = solution.RemoveProject(solution.ProjectIds.Single()); var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, solution); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: 0, CancellationToken.None); + var synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, CancellationToken.None); Assert.Equal(solutionChecksum, await synched.CompilationState.GetChecksumAsync(CancellationToken.None)); // Add a C# project and a VB project, set some options, and check again @@ -429,7 +424,7 @@ public async Task TestAddingProjectsWithExplicitOptions(bool useDefaultOptionVal assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, solution); solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: 2, CancellationToken.None); + synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, CancellationToken.None); Assert.Equal(solutionChecksum, await synched.CompilationState.GetChecksumAsync(CancellationToken.None)); } @@ -447,7 +442,7 @@ public async Task TestFrozenSourceGeneratedDocument() // First sync the solution over that has a generator var assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, solution); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: 0, CancellationToken.None); + var synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, CancellationToken.None); Assert.Equal(solutionChecksum, await synched.CompilationState.GetChecksumAsync(CancellationToken.None)); // Now freeze with some content @@ -457,7 +452,7 @@ public async Task TestFrozenSourceGeneratedDocument() assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, frozenSolution1); solutionChecksum = await frozenSolution1.CompilationState.GetChecksumAsync(CancellationToken.None); - synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: 1, CancellationToken.None); + synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, CancellationToken.None); Assert.Equal(solutionChecksum, await synched.CompilationState.GetChecksumAsync(CancellationToken.None)); // Try freezing with some different content from the original solution @@ -466,7 +461,7 @@ public async Task TestFrozenSourceGeneratedDocument() assetProvider = await GetAssetProviderAsync(workspace, remoteWorkspace, frozenSolution2); solutionChecksum = await frozenSolution2.CompilationState.GetChecksumAsync(CancellationToken.None); - synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: 2, CancellationToken.None); + synched = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, CancellationToken.None); Assert.Equal(solutionChecksum, await synched.CompilationState.GetChecksumAsync(CancellationToken.None)); } @@ -493,7 +488,7 @@ public async Task TestPartialProjectSync_GetSolutionFirst() await solution.AppendAssetMapAsync(map, CancellationToken.None); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var syncedFullSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: solution.WorkspaceVersion, CancellationToken.None); + var syncedFullSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, CancellationToken.None); Assert.Equal(solutionChecksum, await syncedFullSolution.CompilationState.GetChecksumAsync(CancellationToken.None)); Assert.Equal(2, syncedFullSolution.Projects.Count()); @@ -501,13 +496,13 @@ public async Task TestPartialProjectSync_GetSolutionFirst() // Syncing project1 should do nothing as syncing the solution already synced it over. var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); - var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(2, project1SyncedSolution.Projects.Count()); // Syncing project2 should do nothing as syncing the solution already synced it over. var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); - var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(2, project2SyncedSolution.Projects.Count()); } @@ -533,20 +528,20 @@ public async Task TestPartialProjectSync_GetSolutionLast() // Syncing project 1 should just since it over. await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); - var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project1SyncedSolution.Projects.Count()); Assert.Equal(project1.Name, project1SyncedSolution.Projects.Single().Name); // Syncing project 2 should end up with only p2 synced over. await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); - var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project2SyncedSolution.Projects.Count()); // then syncing the whole project should now copy both over. await solution.AppendAssetMapAsync(map, CancellationToken.None); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var syncedFullSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: solution.WorkspaceVersion, CancellationToken.None); + var syncedFullSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, CancellationToken.None); Assert.Equal(solutionChecksum, await syncedFullSolution.CompilationState.GetChecksumAsync(CancellationToken.None)); Assert.Equal(2, syncedFullSolution.Projects.Count()); @@ -574,14 +569,14 @@ public async Task TestPartialProjectSync_GetDependentProjects1() await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); - var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project2SyncedSolution.Projects.Count()); Assert.Equal(project2.Name, project2SyncedSolution.Projects.Single().Name); // syncing project 3 should sync project 2 as well because of the p2p ref await solution.AppendAssetMapAsync(map, project3.Id, CancellationToken.None); var project3Checksum = await solution.CompilationState.GetChecksumAsync(project3.Id, CancellationToken.None); - var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(2, project3SyncedSolution.Projects.Count()); } @@ -608,20 +603,20 @@ public async Task TestPartialProjectSync_GetDependentProjects2() // syncing P3 should since project P2 as well because of the p2p ref await solution.AppendAssetMapAsync(map, project3.Id, CancellationToken.None); var project3Checksum = await solution.CompilationState.GetChecksumAsync(project3.Id, CancellationToken.None); - var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(2, project3SyncedSolution.Projects.Count()); // if we then sync just P2, we should still have only P2 in the synced cone await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); - var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project2SyncedSolution.Projects.Count()); AssertEx.Equal(project2.Name, project2SyncedSolution.Projects.Single().Name); // if we then sync just P1, we should only have it in its own cone. await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); - var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project1SyncedSolution.Projects.Count()); AssertEx.Equal(project1.Name, project1SyncedSolution.Projects.Single().Name); } @@ -650,19 +645,19 @@ public async Task TestPartialProjectSync_GetDependentProjects3() // syncing project3 should since project2 and project1 as well because of the p2p ref await solution.AppendAssetMapAsync(map, project3.Id, CancellationToken.None); var project3Checksum = await solution.CompilationState.GetChecksumAsync(project3.Id, CancellationToken.None); - var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(3, project3SyncedSolution.Projects.Count()); // syncing project2 should only have it and project 1. await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); - var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(2, project2SyncedSolution.Projects.Count()); // syncing project1 should only be itself await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); - var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project1SyncedSolution.Projects.Count()); } @@ -690,19 +685,19 @@ public async Task TestPartialProjectSync_GetDependentProjects4() // syncing project3 should since project2 and project1 as well because of the p2p ref await solution.AppendAssetMapAsync(map, project3.Id, CancellationToken.None); var project3Checksum = await solution.CompilationState.GetChecksumAsync(project3.Id, CancellationToken.None); - var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project3SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project3Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(3, project3SyncedSolution.Projects.Count()); // Syncing project2 should only have a cone with itself. await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); - var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project2SyncedSolution.Projects.Count()); // Syncing project1 should only have a cone with itself. await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); - var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project1SyncedSolution.Projects.Count()); } @@ -728,14 +723,14 @@ public async Task TestPartialProjectSync_Options1() // Syncing over project1 should give us 1 set of options on the OOP side. await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); - var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project1SyncedSolution.Projects.Count()); Assert.Equal(project1.Name, project1SyncedSolution.Projects.Single().Name); // Syncing over project2 should also only be one set of options. await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); - var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(1, project2SyncedSolution.Projects.Count()); } @@ -761,7 +756,7 @@ public async Task TestPartialProjectSync_DoesNotSeeChangesOutsideOfCone() // Do the initial full sync await solution.AppendAssetMapAsync(map, CancellationToken.None); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var fullSyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: solution.WorkspaceVersion, CancellationToken.None); + var fullSyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, CancellationToken.None); Assert.Equal(2, fullSyncedSolution.Projects.Count()); // Mutate both projects to each have a document in it. @@ -773,7 +768,7 @@ public async Task TestPartialProjectSync_DoesNotSeeChangesOutsideOfCone() { await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); - var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(2, project1SyncedSolution.Projects.Count()); var csharpProject = project1SyncedSolution.Projects.Single(p => p.Language == LanguageNames.CSharp); var vbProject = project1SyncedSolution.Projects.Single(p => p.Language == LanguageNames.VisualBasic); @@ -785,7 +780,7 @@ public async Task TestPartialProjectSync_DoesNotSeeChangesOutsideOfCone() { await solution.AppendAssetMapAsync(map, project2.Id, CancellationToken.None); var project2Checksum = await solution.CompilationState.GetChecksumAsync(project2.Id, CancellationToken.None); - var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project2SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project2Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(2, project2SyncedSolution.Projects.Count()); var csharpProject = project2SyncedSolution.Projects.Single(p => p.Language == LanguageNames.CSharp); var vbProject = project2SyncedSolution.Projects.Single(p => p.Language == LanguageNames.VisualBasic); @@ -816,7 +811,7 @@ public async Task TestPartialProjectSync_AddP2PRef() // Do the initial full sync await solution.AppendAssetMapAsync(map, CancellationToken.None); var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); - var fullSyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, workspaceVersion: solution.WorkspaceVersion, CancellationToken.None); + var fullSyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: true, CancellationToken.None); Assert.Equal(2, fullSyncedSolution.Projects.Count()); // Mutate both projects to have a document in it, and add a p2p ref from project1 to project2 @@ -829,7 +824,7 @@ public async Task TestPartialProjectSync_AddP2PRef() { await solution.AppendAssetMapAsync(map, project1.Id, CancellationToken.None); var project1Checksum = await solution.CompilationState.GetChecksumAsync(project1.Id, CancellationToken.None); - var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var project1SyncedSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, project1Checksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(2, project1SyncedSolution.Projects.Count()); var project1Synced = project1SyncedSolution.GetRequiredProject(project1.Id); var project2Synced = project1SyncedSolution.GetRequiredProject(project2.Id); @@ -885,8 +880,8 @@ private static async Task VerifySolutionUpdate( var solutionChecksum = await solution.CompilationState.GetChecksumAsync(CancellationToken.None); // update primary workspace - await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, solution.WorkspaceVersion, CancellationToken.None); - var recoveredSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, CancellationToken.None); + var recoveredSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, CancellationToken.None); oldSolutionValidator?.Invoke(recoveredSolution); Assert.Equal(WorkspaceKind.RemoteWorkspace, recoveredSolution.WorkspaceKind); @@ -898,13 +893,13 @@ private static async Task VerifySolutionUpdate( await newSolution.AppendAssetMapAsync(map, CancellationToken.None); // get solution without updating primary workspace - var recoveredNewSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, newSolutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + var recoveredNewSolution = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, newSolutionChecksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(newSolutionChecksum, await recoveredNewSolution.CompilationState.GetChecksumAsync(CancellationToken.None)); // do same once updating primary workspace - await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, newSolutionChecksum, solution.WorkspaceVersion + 1, CancellationToken.None); - var third = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, newSolutionChecksum, updatePrimaryBranch: false, workspaceVersion: -1, CancellationToken.None); + await remoteWorkspace.UpdatePrimaryBranchSolutionAsync(assetProvider, newSolutionChecksum, CancellationToken.None); + var third = await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, newSolutionChecksum, updatePrimaryBranch: false, CancellationToken.None); Assert.Equal(newSolutionChecksum, await third.CompilationState.GetChecksumAsync(CancellationToken.None)); diff --git a/src/Workspaces/Remote/Core/IRemoteAssetSynchronizationService.cs b/src/Workspaces/Remote/Core/IRemoteAssetSynchronizationService.cs index 0b3c0f3a0bc77..455c83c4177ed 100644 --- a/src/Workspaces/Remote/Core/IRemoteAssetSynchronizationService.cs +++ b/src/Workspaces/Remote/Core/IRemoteAssetSynchronizationService.cs @@ -7,15 +7,14 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Remote +namespace Microsoft.CodeAnalysis.Remote; + +internal interface IRemoteAssetSynchronizationService { - internal interface IRemoteAssetSynchronizationService - { - /// - /// Synchronize data to OOP proactively so that the corresponding solution is often already available when - /// features call into it. - /// - ValueTask SynchronizePrimaryWorkspaceAsync(Checksum solutionChecksum, int workspaceVersion, CancellationToken cancellationToken); - ValueTask SynchronizeTextAsync(DocumentId documentId, Checksum baseTextChecksum, IEnumerable textChanges, CancellationToken cancellationToken); - } + /// + /// Synchronize data to OOP proactively so that the corresponding solution is often already available when features + /// call into it. + /// + ValueTask SynchronizePrimaryWorkspaceAsync(Checksum solutionChecksum, CancellationToken cancellationToken); + ValueTask SynchronizeTextAsync(DocumentId documentId, Checksum baseTextChecksum, IEnumerable textChanges, CancellationToken cancellationToken); } diff --git a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace.cs b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace.cs index 0471dfcde019e..3ac0f34a4bf9e 100644 --- a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace.cs +++ b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace.cs @@ -25,12 +25,6 @@ internal sealed partial class RemoteWorkspace : Workspace /// private readonly SemaphoreSlim _gate = new(initialCount: 1); - /// - /// Used to make sure we never move remote workspace backward. this version is the WorkspaceVersion of primary - /// solution in client (VS) we are currently caching. - /// - private int _currentRemoteWorkspaceVersion = -1; - // internal for testing purposes. internal RemoteWorkspace(HostServices hostServices) : base(hostServices, WorkspaceKind.RemoteWorkspace) @@ -52,7 +46,7 @@ public AssetProvider CreateAssetProvider(Checksum solutionChecksum, SolutionAsse /// them to be pre-populated for feature requests that come in soon after this call completes. /// public async Task UpdatePrimaryBranchSolutionAsync( - AssetProvider assetProvider, Checksum solutionChecksum, int workspaceVersion, CancellationToken cancellationToken) + AssetProvider assetProvider, Checksum solutionChecksum, CancellationToken cancellationToken) { // See if the current snapshot we're pointing at is the same one the host wants us to sync to. If so, we // don't need to do anything. @@ -65,7 +59,6 @@ public async Task UpdatePrimaryBranchSolutionAsync( await RunWithSolutionAsync( assetProvider, solutionChecksum, - workspaceVersion, updatePrimaryBranch: true, implementation: static _ => ValueTaskFactory.FromResult(false), cancellationToken).ConfigureAwait(false); @@ -90,13 +83,12 @@ await RunWithSolutionAsync( Func> implementation, CancellationToken cancellationToken) { - return RunWithSolutionAsync(assetProvider, solutionChecksum, workspaceVersion: -1, updatePrimaryBranch: false, implementation, cancellationToken); + return RunWithSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, implementation, cancellationToken); } private async ValueTask<(Solution solution, T result)> RunWithSolutionAsync( AssetProvider assetProvider, Checksum solutionChecksum, - int workspaceVersion, bool updatePrimaryBranch, Func> implementation, CancellationToken cancellationToken) @@ -131,7 +123,7 @@ await RunWithSolutionAsync( try { inFlightSolution = GetOrCreateSolutionAndAddInFlightCount_NoLock( - assetProvider, solutionChecksum, workspaceVersion, updatePrimaryBranch); + assetProvider, solutionChecksum, updatePrimaryBranch); solutionTask = inFlightSolution.PreferredSolutionTask_NoLock; // We must have at least 1 for the in-flight-count (representing this current in-flight call). @@ -268,34 +260,15 @@ private Solution CreateSolutionFromInfo(SolutionInfo solutionInfo) } /// - /// Attempts to update this workspace with the given . If this succeeds, will be returned in the tuple result as well as the actual solution that the workspace is - /// updated to point at. If we cannot update this workspace, then will be returned, - /// along with the solution passed in. The only time the solution can not be updated is if it would move backwards. + /// Updates this workspace with the given . The solution returned is the actual + /// one the workspace now points to. /// - private async Task TryUpdateWorkspaceCurrentSolutionAsync( - int workspaceVersion, - Solution newSolution, - CancellationToken cancellationToken) - { - var (solution, _) = await TryUpdateWorkspaceCurrentSolutionWorkerAsync(workspaceVersion, newSolution, cancellationToken).ConfigureAwait(false); - return solution; - } - - private async ValueTask<(Solution solution, bool updated)> TryUpdateWorkspaceCurrentSolutionWorkerAsync( - int workspaceVersion, + private async Task UpdateWorkspaceCurrentSolutionAsync( Solution newSolution, CancellationToken cancellationToken) { using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { - // Never move workspace backward - if (workspaceVersion <= _currentRemoteWorkspaceVersion) - return (newSolution, updated: false); - - _currentRemoteWorkspaceVersion = workspaceVersion; - // if either solution id or file path changed, then we consider it as new solution. Otherwise, // update the current solution in place. @@ -316,7 +289,7 @@ private async Task TryUpdateWorkspaceCurrentSolutionAsync( } }); - return (newSolution, updated: true); + return newSolution; } static bool IsAddingSolution(Solution oldSolution, Solution newSolution) @@ -338,18 +311,17 @@ public TestAccessor(RemoteWorkspace remoteWorkspace) public Solution CreateSolutionFromInfo(SolutionInfo solutionInfo) => _remoteWorkspace.CreateSolutionFromInfo(solutionInfo); - public ValueTask<(Solution solution, bool updated)> TryUpdateWorkspaceCurrentSolutionAsync(Solution newSolution, int workspaceVersion) - => _remoteWorkspace.TryUpdateWorkspaceCurrentSolutionWorkerAsync(workspaceVersion, newSolution, CancellationToken.None); + public Task UpdateWorkspaceCurrentSolutionAsync(Solution newSolution) + => _remoteWorkspace.UpdateWorkspaceCurrentSolutionAsync(newSolution, CancellationToken.None); public async ValueTask GetSolutionAsync( AssetProvider assetProvider, Checksum solutionChecksum, bool updatePrimaryBranch, - int workspaceVersion, CancellationToken cancellationToken) { var (solution, _) = await _remoteWorkspace.RunWithSolutionAsync( - assetProvider, solutionChecksum, workspaceVersion, updatePrimaryBranch, _ => ValueTaskFactory.FromResult(false), cancellationToken).ConfigureAwait(false); + assetProvider, solutionChecksum, updatePrimaryBranch, _ => ValueTaskFactory.FromResult(false), cancellationToken).ConfigureAwait(false); return solution; } } diff --git a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace_SolutionCaching.cs b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace_SolutionCaching.cs index d6c82aee29f98..abe37845c2122 100644 --- a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace_SolutionCaching.cs +++ b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace_SolutionCaching.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using Microsoft.CodeAnalysis.Internal.Log; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Remote @@ -40,7 +39,6 @@ internal sealed partial class RemoteWorkspace private InFlightSolution GetOrCreateSolutionAndAddInFlightCount_NoLock( AssetProvider assetProvider, Checksum solutionChecksum, - int workspaceVersion, bool updatePrimaryBranch) { Contract.ThrowIfFalse(_gate.CurrentCount == 0); @@ -56,8 +54,7 @@ private InFlightSolution GetOrCreateSolutionAndAddInFlightCount_NoLock( // to compute the primary branch as well, let it know so it can start that now. if (updatePrimaryBranch) { - solution.TryKickOffPrimaryBranchWork_NoLock((disconnectedSolution, cancellationToken) => - this.TryUpdateWorkspaceCurrentSolutionAsync(workspaceVersion, disconnectedSolution, cancellationToken)); + solution.TryKickOffPrimaryBranchWork_NoLock(this.UpdateWorkspaceCurrentSolutionAsync); } CheckCacheInvariants_NoLock(); diff --git a/src/Workspaces/Remote/ServiceHub/Services/AssetSynchronization/RemoteAssetSynchronizationService.cs b/src/Workspaces/Remote/ServiceHub/Services/AssetSynchronization/RemoteAssetSynchronizationService.cs index ea25f6948ee99..3f5c2974b6b0b 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/AssetSynchronization/RemoteAssetSynchronizationService.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/AssetSynchronization/RemoteAssetSynchronizationService.cs @@ -30,7 +30,7 @@ public RemoteAssetSynchronizationService(in ServiceConstructionArguments argumen { } - public ValueTask SynchronizePrimaryWorkspaceAsync(Checksum solutionChecksum, int workspaceVersion, CancellationToken cancellationToken) + public ValueTask SynchronizePrimaryWorkspaceAsync(Checksum solutionChecksum, CancellationToken cancellationToken) { return RunServiceAsync(async cancellationToken => { @@ -38,7 +38,7 @@ public ValueTask SynchronizePrimaryWorkspaceAsync(Checksum solutionChecksum, int { var workspace = GetWorkspace(); var assetProvider = workspace.CreateAssetProvider(solutionChecksum, WorkspaceManager.SolutionAssetCache, SolutionAssetSource); - await workspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, workspaceVersion, cancellationToken).ConfigureAwait(false); + await workspace.UpdatePrimaryBranchSolutionAsync(assetProvider, solutionChecksum, cancellationToken).ConfigureAwait(false); } }, cancellationToken); } From 93f27ca5f09cd80e6a7c97bd5a675e0003e801a0 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 22 Mar 2024 15:31:50 -0700 Subject: [PATCH 2/3] Whitespace --- .../Remote/ServiceHub/Host/RemoteWorkspace_SolutionCaching.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace_SolutionCaching.cs b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace_SolutionCaching.cs index abe37845c2122..edfb339611d09 100644 --- a/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace_SolutionCaching.cs +++ b/src/Workspaces/Remote/ServiceHub/Host/RemoteWorkspace_SolutionCaching.cs @@ -8,7 +8,6 @@ namespace Microsoft.CodeAnalysis.Remote { - internal sealed partial class RemoteWorkspace { /// From 048ebd5f3402c8d78f20c8c6c096baa5eab65e38 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 22 Mar 2024 17:25:05 -0700 Subject: [PATCH 3/3] Fix test --- .../Test.Next/Services/SolutionServiceTests.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs b/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs index d4957a9b777d2..3e43f88c1d6c3 100644 --- a/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs +++ b/src/VisualStudio/Core/Test.Next/Services/SolutionServiceTests.cs @@ -344,22 +344,22 @@ public async Task TestRemoteWorkspace() var remoteSolution1 = await GetInitialOOPSolutionAsync(remoteWorkspace, assetProvider, solution1); - await Verify(remoteWorkspace, solution1, remoteSolution1, expectRemoteSolutionToCurrent: true); + await Verify(remoteWorkspace, solution1, remoteSolution1); // update remote workspace var currentSolution = remoteSolution1.WithDocumentText(remoteSolution1.Projects.First().Documents.First().Id, SourceText.From(code + " class Test2 { }")); var oopSolution2 = await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync(currentSolution); - await Verify(remoteWorkspace, currentSolution, oopSolution2, expectRemoteSolutionToCurrent: true); + await Verify(remoteWorkspace, currentSolution, oopSolution2); // move backward - await Verify(remoteWorkspace, remoteSolution1, await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync(remoteSolution1), expectRemoteSolutionToCurrent: false); + await Verify(remoteWorkspace, remoteSolution1, await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync(remoteSolution1)); // move forward currentSolution = oopSolution2.WithDocumentText(oopSolution2.Projects.First().Documents.First().Id, SourceText.From(code + " class Test3 { }")); var remoteSolution3 = await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync(currentSolution); - await Verify(remoteWorkspace, currentSolution, remoteSolution3, expectRemoteSolutionToCurrent: true); + await Verify(remoteWorkspace, currentSolution, remoteSolution3); // move to new solution backward var solutionInfo2 = await assetProvider.CreateSolutionInfoAsync(await solution1.CompilationState.GetChecksumAsync(CancellationToken.None), CancellationToken.None); @@ -368,7 +368,7 @@ public async Task TestRemoteWorkspace() // move to new solution forward var solution3 = await remoteWorkspace.GetTestAccessor().UpdateWorkspaceCurrentSolutionAsync(solution2); Assert.NotNull(solution3); - await Verify(remoteWorkspace, solution1, solution3, expectRemoteSolutionToCurrent: true); + await Verify(remoteWorkspace, solution1, solution3); static async Task GetInitialOOPSolutionAsync(RemoteWorkspace remoteWorkspace, AssetProvider assetProvider, Solution solution) { @@ -380,13 +380,13 @@ static async Task GetInitialOOPSolutionAsync(RemoteWorkspace remoteWor return await remoteWorkspace.GetTestAccessor().GetSolutionAsync(assetProvider, solutionChecksum, updatePrimaryBranch: false, CancellationToken.None); } - static async Task Verify(RemoteWorkspace remoteWorkspace, Solution givenSolution, Solution remoteSolution, bool expectRemoteSolutionToCurrent) + static async Task Verify(RemoteWorkspace remoteWorkspace, Solution givenSolution, Solution remoteSolution) { // verify we got solution expected Assert.Equal(await givenSolution.CompilationState.GetChecksumAsync(CancellationToken.None), await remoteSolution.CompilationState.GetChecksumAsync(CancellationToken.None)); // verify remote workspace got updated - Assert.True(expectRemoteSolutionToCurrent == (remoteSolution == remoteWorkspace.CurrentSolution)); + Assert.Equal(remoteSolution, remoteWorkspace.CurrentSolution); } }