diff --git a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProject.cs b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProject.cs index f110bdd46d2b7..765ed6efbaad7 100644 --- a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProject.cs +++ b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProject.cs @@ -607,10 +607,11 @@ await _projectSystemProjectFactory.ApplyBatchChangeToWorkspaceMaybeAsync(useAsyn else { // TODO: find a cleaner way to fetch this - var metadataReference = _projectSystemProjectFactory.Workspace.CurrentSolution.GetRequiredProject(Id).MetadataReferences.Cast() - .Single(m => m.FilePath == path && m.Properties == properties); + var metadataReference = _projectSystemProjectFactory.Workspace.CurrentSolution.GetRequiredProject(Id).MetadataReferences + .Cast() + .Single(m => m.FilePath == path && m.Properties == properties); - projectUpdateState = projectUpdateState.WithIncrementalReferenceRemoved(metadataReference); + projectUpdateState = projectUpdateState.WithIncrementalMetadataReferenceRemoved(metadataReference); solutionChanges.UpdateSolutionForProjectAction( Id, @@ -634,15 +635,16 @@ await _projectSystemProjectFactory.ApplyBatchChangeToWorkspaceMaybeAsync(useAsyn } else { - var metadataReference = CreateReference_NoLock(path, properties, _projectSystemProjectFactory.SolutionServices); - projectUpdateState = projectUpdateState.WithIncrementalReferenceAdded(metadataReference); + var metadataReference = CreateMetadataReference_NoLock(path, properties, _projectSystemProjectFactory.SolutionServices); + projectUpdateState = projectUpdateState.WithIncrementalMetadataReferenceAdded(metadataReference); } } solutionChanges.UpdateSolutionForProjectAction( Id, - solutionChanges.Solution.AddProjectReferences(Id, projectReferencesCreated) - .AddMetadataReferences(Id, projectUpdateState.AddedReferences)); + solutionChanges.Solution + .AddProjectReferences(Id, projectReferencesCreated) + .AddMetadataReferences(Id, projectUpdateState.AddedMetadataReferences)); } // Project reference adding... @@ -1118,8 +1120,8 @@ public void AddMetadataReference(string fullPath, MetadataReferenceProperties pr } else { - var metadataReference = CreateReference_NoLock(fullPath, properties, _projectSystemProjectFactory.SolutionServices); - projectUpdateState = projectUpdateState.WithIncrementalReferenceAdded(metadataReference); + var metadataReference = CreateMetadataReference_NoLock(fullPath, properties, _projectSystemProjectFactory.SolutionServices); + projectUpdateState = projectUpdateState.WithIncrementalMetadataReferenceAdded(metadataReference); w.OnMetadataReferenceAdded(Id, metadataReference); } @@ -1193,9 +1195,10 @@ public void RemoveMetadataReference(string fullPath, MetadataReferenceProperties else { // TODO: find a cleaner way to fetch this - var metadataReference = w.CurrentSolution.GetRequiredProject(Id).MetadataReferences.Cast() - .Single(m => m.FilePath == fullPath && m.Properties == properties); - projectUpdateState = projectUpdateState.WithIncrementalReferenceRemoved(metadataReference); + var metadataReference = w.CurrentSolution.GetRequiredProject(Id).MetadataReferences + .Cast() + .Single(m => m.FilePath == fullPath && m.Properties == properties); + projectUpdateState = projectUpdateState.WithIncrementalMetadataReferenceRemoved(metadataReference); w.OnMetadataReferenceRemoved(Id, metadataReference); } diff --git a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.ProjectUpdateState.cs b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.ProjectUpdateState.cs index f376d94df707c..c534c72370f9f 100644 --- a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.ProjectUpdateState.cs +++ b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.ProjectUpdateState.cs @@ -34,17 +34,17 @@ internal sealed partial class ProjectSystemProjectFactory /// /// Global state containing output paths and converted project reference information for each project. /// - /// + /// /// Incremental state containing references removed in the current update. /// - /// + /// /// Incremental state containing references added in the current update. /// public sealed record class ProjectUpdateState( ImmutableDictionary> ProjectsByOutputPath, ImmutableDictionary ProjectReferenceInfos, - ImmutableArray RemovedReferences, - ImmutableArray AddedReferences) + ImmutableArray RemovedMetadataReferences, + ImmutableArray AddedMetadataReferences) { public static ProjectUpdateState Empty = new( ImmutableDictionary>.Empty.WithComparers(StringComparer.OrdinalIgnoreCase), @@ -104,19 +104,19 @@ static ImmutableDictionary> RemoveProject(stri } } - public ProjectUpdateState WithIncrementalReferenceRemoved(PortableExecutableReference reference) + public ProjectUpdateState WithIncrementalMetadataReferenceRemoved(PortableExecutableReference reference) { return this with { - RemovedReferences = RemovedReferences.Add(reference) + RemovedMetadataReferences = RemovedMetadataReferences.Add(reference) }; } - public ProjectUpdateState WithIncrementalReferenceAdded(PortableExecutableReference reference) + public ProjectUpdateState WithIncrementalMetadataReferenceAdded(PortableExecutableReference reference) { return this with { - AddedReferences = AddedReferences.Add(reference) + AddedMetadataReferences = AddedMetadataReferences.Add(reference) }; } @@ -127,8 +127,8 @@ public ProjectUpdateState ClearIncrementalState() { return this with { - RemovedReferences = [], - AddedReferences = [] + RemovedMetadataReferences = [], + AddedMetadataReferences = [] }; } } diff --git a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs index cf8c3a1fbe1c3..5053f2ae45192 100644 --- a/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs +++ b/src/Workspaces/Core/Portable/Workspace/ProjectSystem/ProjectSystemProjectFactory.cs @@ -400,37 +400,17 @@ internal void ApplyProjectUpdateState(ProjectUpdateState projectUpdateState) { Contract.ThrowIfFalse(_gate.CurrentCount == 0); - UpdateReferenceFileWatchers(projectUpdateState.RemovedReferences, projectUpdateState.AddedReferences); + // Now that we've removed the references from the sln, we can stop watching them. + foreach (var reference in projectUpdateState.RemovedMetadataReferences) + FileWatchedReferenceFactory.StopWatchingReference(reference); + + // Now that we've added the references to the sln, we can start watching them. + foreach (var reference in projectUpdateState.AddedMetadataReferences) + FileWatchedReferenceFactory.StartWatchingReference(reference, reference.FilePath!); // Clear the state from the this update in preparation for the next. projectUpdateState = projectUpdateState.ClearIncrementalState(); _projectUpdateState = projectUpdateState; - return; - - void UpdateReferenceFileWatchers( - ImmutableArray removedReferences, - ImmutableArray addedReferences) - { - // Remove file watchers for any references we're no longer watching. - if (removedReferences.Count() > 0) - { - // Now that we've removed the references from the sln, we can stop watching them. - foreach (var reference in removedReferences) - { - FileWatchedReferenceFactory.StopWatchingReference(reference); - } - } - - // Add file watchers for any references we are now watching. - if (addedReferences.Count() > 0) - { - // Now that we've added the references to the sln, we can start watching them. - foreach (var reference in addedReferences) - { - FileWatchedReferenceFactory.StartWatchingReference(reference, reference.FilePath!); - } - } - } } internal void RemoveSolution_NoLock() @@ -548,7 +528,7 @@ private static ProjectUpdateState ConvertMetadataReferencesToProjectReferences_N { if (string.Equals(reference.FilePath, outputPath, StringComparison.OrdinalIgnoreCase)) { - projectUpdateState = projectUpdateState.WithIncrementalReferenceRemoved(reference); + projectUpdateState = projectUpdateState.WithIncrementalMetadataReferenceRemoved(reference); var projectReference = new ProjectReference(projectIdToReference, reference.Properties.Aliases, reference.Properties.EmbedInteropTypes); var newSolution = solutionChanges.Solution.RemoveMetadataReference(projectIdToRetarget, reference) @@ -640,14 +620,13 @@ private static ProjectUpdateState ConvertProjectReferencesToMetadataReferences_N if (string.Equals(convertedReference.path, outputPath, StringComparison.OrdinalIgnoreCase) && convertedReference.ProjectReference.ProjectId == projectId) { - var metadataReference = - CreateReference_NoLock( - convertedReference.path, - new MetadataReferenceProperties( - aliases: convertedReference.ProjectReference.Aliases, - embedInteropTypes: convertedReference.ProjectReference.EmbedInteropTypes), - solutionServices); - projectUpdateState = projectUpdateState.WithIncrementalReferenceAdded(metadataReference); + var metadataReference = CreateMetadataReference_NoLock( + convertedReference.path, + new MetadataReferenceProperties( + aliases: convertedReference.ProjectReference.Aliases, + embedInteropTypes: convertedReference.ProjectReference.EmbedInteropTypes), + solutionServices); + projectUpdateState = projectUpdateState.WithIncrementalMetadataReferenceAdded(metadataReference); var newSolution = solutionChanges.Solution.RemoveProjectReference(projectIdToRetarget, convertedReference.ProjectReference) .AddMetadataReference(projectIdToRetarget, metadataReference); @@ -797,7 +776,7 @@ public static ProjectUpdateState RemoveProjectOutputPath_NoLock( /// Gets or creates a PortableExecutableReference instance for the given file path and properties. /// Calls to this are expected to be serialized by the caller. /// - public static PortableExecutableReference CreateReference_NoLock(string fullFilePath, MetadataReferenceProperties properties, SolutionServices solutionServices) + public static PortableExecutableReference CreateMetadataReference_NoLock(string fullFilePath, MetadataReferenceProperties properties, SolutionServices solutionServices) { var reference = solutionServices.GetRequiredService().GetReference(fullFilePath, properties); return reference; @@ -822,15 +801,14 @@ await ApplyBatchChangeToWorkspaceAsync((solutionChanges, projectUpdateState) => { if (portableExecutableReference.FilePath == fullFilePath) { - projectUpdateState = projectUpdateState.WithIncrementalReferenceRemoved(portableExecutableReference); + projectUpdateState = projectUpdateState.WithIncrementalMetadataReferenceRemoved(portableExecutableReference); - var newPortableExecutableReference = - CreateReference_NoLock( - portableExecutableReference.FilePath, - portableExecutableReference.Properties, - SolutionServices); + var newPortableExecutableReference = CreateMetadataReference_NoLock( + portableExecutableReference.FilePath, + portableExecutableReference.Properties, + SolutionServices); - projectUpdateState = projectUpdateState.WithIncrementalReferenceAdded(newPortableExecutableReference); + projectUpdateState = projectUpdateState.WithIncrementalMetadataReferenceAdded(newPortableExecutableReference); var newSolution = solutionChanges.Solution.RemoveMetadataReference(project.Id, portableExecutableReference) .AddMetadataReference(project.Id, newPortableExecutableReference); @@ -839,6 +817,7 @@ await ApplyBatchChangeToWorkspaceAsync((solutionChanges, projectUpdateState) => } } } + return projectUpdateState; }, onAfterUpdateAlways: null).ConfigureAwait(false); }