From c92305d511f8ce60383330e403329d228b142f51 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Mon, 11 Dec 2023 16:14:06 -0800 Subject: [PATCH 01/10] Put documents state change after project change --- .../Core/Portable/Workspace/Workspace.cs | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs index 1d12dfd022800..3c67d9068547d 100644 --- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs +++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs @@ -10,9 +10,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Xml; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host; @@ -21,7 +19,6 @@ using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Remote; using Microsoft.CodeAnalysis.Shared.Extensions; -using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -1417,8 +1414,8 @@ internal virtual bool TryApplyChanges(Solution newSolution, IProgress projectChanges) + { + using var _1 = PooledHashSet.GetInstance(out var infoChangedDocumentIds); + using var _2 = PooledHashSet.GetInstance(out var infoChangedNewDocument); + foreach (var projectChange in projectChanges) + { + foreach (var docId in projectChange.GetChangedDocuments()) + { + var oldDoc = projectChange.OldProject.GetRequiredDocument(docId); + var newDoc = projectChange.NewProject.GetRequiredDocument(docId); + if (oldDoc.HasInfoChanged(newDoc)) + { + var linkedDocumentIds = oldSolution.GetRequiredDocument(docId).GetLinkedDocumentIds(); + // For linked documents, + if (linkedDocumentIds.All(linkedDocId => !infoChangedDocumentIds.Contains(linkedDocId))) + { + infoChangedDocumentIds.Add(docId); + infoChangedNewDocument.Add(newDoc); + } + } + } + } + + foreach (var newDoc in infoChangedNewDocument) + { + // ApplyDocumentInfoChanged ignores the loader information, so we can pass null for it + ApplyDocumentInfoChanged(newDoc.Id, + new DocumentInfo(newDoc.DocumentState.Attributes, loader: null, documentServiceProvider: newDoc.State.Services)); + } + } + internal virtual void ApplyMappedFileChanges(SolutionChanges solutionChanges) { return; @@ -1830,16 +1860,6 @@ private void ApplyChangedDocument( this.ApplyDocumentTextChanged(documentId, newText); } } - - // Update document info if changed. Updating the info can cause files to move on disk (or have other side effects), - // so we do this after any text changes have been applied. - if (newDoc.HasInfoChanged(oldDoc)) - { - // ApplyDocumentInfoChanged ignores the loader information, so we can pass null for it - ApplyDocumentInfoChanged( - documentId, - new DocumentInfo(newDoc.State.Attributes, loader: null, documentServiceProvider: newDoc.State.Services)); - } } [Conditional("DEBUG")] From 7752c26233d9b14958159b6e1d32ac600fd159f6 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Mon, 11 Dec 2023 16:45:23 -0800 Subject: [PATCH 02/10] Add comment --- src/Workspaces/Core/Portable/Workspace/Workspace.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs index 3c67d9068547d..c13aa4f8f965c 100644 --- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs +++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs @@ -1470,7 +1470,8 @@ private void ApplyDocumentsInfoChange(Solution newSolution, Solution oldSolution if (oldDoc.HasInfoChanged(newDoc)) { var linkedDocumentIds = oldSolution.GetRequiredDocument(docId).GetLinkedDocumentIds(); - // For linked documents, + // For linked documents, when info get changed (e.g. name/folder/filePath) + // only apply one document changed because it will update the 'real' file, causing the other linked documents get changed. if (linkedDocumentIds.All(linkedDocId => !infoChangedDocumentIds.Contains(linkedDocId))) { infoChangedDocumentIds.Add(docId); From 680014bc900ac1c258e300bd16b34d76b907f9de Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Mon, 11 Dec 2023 17:22:01 -0800 Subject: [PATCH 03/10] Fix analyzer warning --- src/Workspaces/Core/Portable/Workspace/Workspace.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs index c13aa4f8f965c..71669d92ea1d4 100644 --- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs +++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs @@ -1423,7 +1423,7 @@ internal virtual bool TryApplyChanges(Solution newSolution, IProgress projectChanges) + private void ApplyDocumentsInfoChange(ImmutableArray projectChanges) { using var _1 = PooledHashSet.GetInstance(out var infoChangedDocumentIds); using var _2 = PooledHashSet.GetInstance(out var infoChangedNewDocument); @@ -1465,6 +1465,7 @@ private void ApplyDocumentsInfoChange(Solution newSolution, Solution oldSolution { foreach (var docId in projectChange.GetChangedDocuments()) { + var oldSolution = projectChange.OldProject.Solution; var oldDoc = projectChange.OldProject.GetRequiredDocument(docId); var newDoc = projectChange.NewProject.GetRequiredDocument(docId); if (oldDoc.HasInfoChanged(newDoc)) From dd66b72f34da8c701815a6f33a5eb4b358d24920 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Tue, 12 Dec 2023 11:57:01 -0800 Subject: [PATCH 04/10] Add test --- .../CSharp/CSharpRename.cs | 53 ++++++++++++++++++- .../InProcess/SolutionExplorerInProcess.cs | 2 +- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs index 3b0c78c162059..2f43d3d0c4811 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs @@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis.Editor.InlineRename; using Microsoft.CodeAnalysis.InlineRename; using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.IntegrationTest.Utilities; @@ -719,5 +718,57 @@ public class Class2 public int LongOtherStuff$$Field; }", HangMitigatingCancellationToken); } + + [IdeFact] + public async Task VerifyRenameLinkedDocumentsAsync() + { + var projectName = "MultiTFMProject"; + await TestServices.SolutionExplorer.AddCustomProjectAsync(projectName, ".csproj", @" + + + Exe + net6.0-windows;net48 + enable + enable + preview + + +", HangMitigatingCancellationToken); + + var startCode = @" +public class TestClass +{ +} +"; + await TestServices.SolutionExplorer.AddFileAsync(projectName, "TestClass.cs", startCode, cancellationToken: HangMitigatingCancellationToken); + + var referencedCode = @" +public class MyClass +{ + void Method() + { + TestClass x = new TestClass(); + } +}"; + await TestServices.SolutionExplorer.AddFileAsync(projectName, "MyClass.cs", referencedCode, cancellationToken: HangMitigatingCancellationToken); + + await TestServices.SolutionExplorer.OpenFileAsync(projectName, "TestClass.cs", HangMitigatingCancellationToken); + await TestServices.SolutionExplorer.OpenFileAsync(projectName, "MyClass.cs", HangMitigatingCancellationToken); + await TestServices.Editor.PlaceCaretAsync("TestClass", charsOffset: 0, HangMitigatingCancellationToken); + await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken); + await TestServices.Input.SendWithoutActivateAsync([VirtualKeyCode.HOME, "M", "y", VirtualKeyCode.RETURN], HangMitigatingCancellationToken); + await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken); + await TestServices.EditorVerifier.TextEqualsAsync( + @" +public class MyClass +{ + void Method() + { + MyTestClass x = new MyTestClass(); + } +}", HangMitigatingCancellationToken); + // Make sure the file is renamed. + await TestServices.SolutionExplorer.GetProjectItemAsync(projectName, "./MyTestClass.cs", HangMitigatingCancellationToken); + } } } diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs index 9d73b7bbd98c4..1db6be3be6c1b 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs @@ -567,7 +567,7 @@ public async Task RenameFileAsync(string projectName, string oldFileName, string projectItem.Name = newFileName; } - private async Task GetProjectItemAsync(string projectName, string relativeFilePath, CancellationToken cancellationToken) + public async Task GetProjectItemAsync(string projectName, string relativeFilePath, CancellationToken cancellationToken) { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); From f25c710f435ea922095f7559d6ba05a5af6664b7 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Tue, 12 Dec 2023 20:00:32 -0800 Subject: [PATCH 05/10] Revert "Add test" This reverts commit dd66b72f34da8c701815a6f33a5eb4b358d24920. --- .../CSharp/CSharpRename.cs | 53 +------------------ .../InProcess/SolutionExplorerInProcess.cs | 2 +- 2 files changed, 2 insertions(+), 53 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs index 2f43d3d0c4811..3b0c78c162059 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs @@ -9,6 +9,7 @@ using Microsoft.CodeAnalysis.Editor.InlineRename; using Microsoft.CodeAnalysis.InlineRename; using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.IntegrationTest.Utilities; @@ -718,57 +719,5 @@ public class Class2 public int LongOtherStuff$$Field; }", HangMitigatingCancellationToken); } - - [IdeFact] - public async Task VerifyRenameLinkedDocumentsAsync() - { - var projectName = "MultiTFMProject"; - await TestServices.SolutionExplorer.AddCustomProjectAsync(projectName, ".csproj", @" - - - Exe - net6.0-windows;net48 - enable - enable - preview - - -", HangMitigatingCancellationToken); - - var startCode = @" -public class TestClass -{ -} -"; - await TestServices.SolutionExplorer.AddFileAsync(projectName, "TestClass.cs", startCode, cancellationToken: HangMitigatingCancellationToken); - - var referencedCode = @" -public class MyClass -{ - void Method() - { - TestClass x = new TestClass(); - } -}"; - await TestServices.SolutionExplorer.AddFileAsync(projectName, "MyClass.cs", referencedCode, cancellationToken: HangMitigatingCancellationToken); - - await TestServices.SolutionExplorer.OpenFileAsync(projectName, "TestClass.cs", HangMitigatingCancellationToken); - await TestServices.SolutionExplorer.OpenFileAsync(projectName, "MyClass.cs", HangMitigatingCancellationToken); - await TestServices.Editor.PlaceCaretAsync("TestClass", charsOffset: 0, HangMitigatingCancellationToken); - await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken); - await TestServices.Input.SendWithoutActivateAsync([VirtualKeyCode.HOME, "M", "y", VirtualKeyCode.RETURN], HangMitigatingCancellationToken); - await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken); - await TestServices.EditorVerifier.TextEqualsAsync( - @" -public class MyClass -{ - void Method() - { - MyTestClass x = new MyTestClass(); - } -}", HangMitigatingCancellationToken); - // Make sure the file is renamed. - await TestServices.SolutionExplorer.GetProjectItemAsync(projectName, "./MyTestClass.cs", HangMitigatingCancellationToken); - } } } diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs index 1db6be3be6c1b..9d73b7bbd98c4 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs @@ -567,7 +567,7 @@ public async Task RenameFileAsync(string projectName, string oldFileName, string projectItem.Name = newFileName; } - public async Task GetProjectItemAsync(string projectName, string relativeFilePath, CancellationToken cancellationToken) + private async Task GetProjectItemAsync(string projectName, string relativeFilePath, CancellationToken cancellationToken) { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); From f8ff21f1ac9393f16ab3c684b378f213da5fa5c5 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Mon, 18 Dec 2023 11:09:19 -0800 Subject: [PATCH 06/10] Reapply "Add test" This reverts commit f25c710f435ea922095f7559d6ba05a5af6664b7. --- .../CSharp/CSharpRename.cs | 53 ++++++++++++++++++- .../InProcess/SolutionExplorerInProcess.cs | 2 +- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs index 3b0c78c162059..2f43d3d0c4811 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs @@ -9,7 +9,6 @@ using Microsoft.CodeAnalysis.Editor.InlineRename; using Microsoft.CodeAnalysis.InlineRename; using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.IntegrationTest.Utilities; @@ -719,5 +718,57 @@ public class Class2 public int LongOtherStuff$$Field; }", HangMitigatingCancellationToken); } + + [IdeFact] + public async Task VerifyRenameLinkedDocumentsAsync() + { + var projectName = "MultiTFMProject"; + await TestServices.SolutionExplorer.AddCustomProjectAsync(projectName, ".csproj", @" + + + Exe + net6.0-windows;net48 + enable + enable + preview + + +", HangMitigatingCancellationToken); + + var startCode = @" +public class TestClass +{ +} +"; + await TestServices.SolutionExplorer.AddFileAsync(projectName, "TestClass.cs", startCode, cancellationToken: HangMitigatingCancellationToken); + + var referencedCode = @" +public class MyClass +{ + void Method() + { + TestClass x = new TestClass(); + } +}"; + await TestServices.SolutionExplorer.AddFileAsync(projectName, "MyClass.cs", referencedCode, cancellationToken: HangMitigatingCancellationToken); + + await TestServices.SolutionExplorer.OpenFileAsync(projectName, "TestClass.cs", HangMitigatingCancellationToken); + await TestServices.SolutionExplorer.OpenFileAsync(projectName, "MyClass.cs", HangMitigatingCancellationToken); + await TestServices.Editor.PlaceCaretAsync("TestClass", charsOffset: 0, HangMitigatingCancellationToken); + await TestServices.InlineRename.InvokeAsync(HangMitigatingCancellationToken); + await TestServices.Input.SendWithoutActivateAsync([VirtualKeyCode.HOME, "M", "y", VirtualKeyCode.RETURN], HangMitigatingCancellationToken); + await TestServices.Workspace.WaitForRenameAsync(HangMitigatingCancellationToken); + await TestServices.EditorVerifier.TextEqualsAsync( + @" +public class MyClass +{ + void Method() + { + MyTestClass x = new MyTestClass(); + } +}", HangMitigatingCancellationToken); + // Make sure the file is renamed. + await TestServices.SolutionExplorer.GetProjectItemAsync(projectName, "./MyTestClass.cs", HangMitigatingCancellationToken); + } } } diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs index 9d73b7bbd98c4..1db6be3be6c1b 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/InProcess/SolutionExplorerInProcess.cs @@ -567,7 +567,7 @@ public async Task RenameFileAsync(string projectName, string oldFileName, string projectItem.Name = newFileName; } - private async Task GetProjectItemAsync(string projectName, string relativeFilePath, CancellationToken cancellationToken) + public async Task GetProjectItemAsync(string projectName, string relativeFilePath, CancellationToken cancellationToken) { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); From 09b617d8e8002e903cd0d7b69d0aadc030980f64 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Mon, 18 Dec 2023 12:48:28 -0800 Subject: [PATCH 07/10] Fix the flakyness in integration test --- .../InlineRename/UI/Adornment/RenameFlyout.xaml | 1 + .../New.IntegrationTests/CSharp/CSharpRename.cs | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/EditorFeatures/Core.Wpf/InlineRename/UI/Adornment/RenameFlyout.xaml b/src/EditorFeatures/Core.Wpf/InlineRename/UI/Adornment/RenameFlyout.xaml index 4c8723a803c53..9e101ddcbdfb3 100644 --- a/src/EditorFeatures/Core.Wpf/InlineRename/UI/Adornment/RenameFlyout.xaml +++ b/src/EditorFeatures/Core.Wpf/InlineRename/UI/Adornment/RenameFlyout.xaml @@ -19,6 +19,7 @@ Focusable="False" UseLayoutRounding="True" Cursor="Arrow" + IsVisibleChanged="Control_IsVisibleChanged" x:Name="control"> diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs index 2f43d3d0c4811..34945b9eea361 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs @@ -719,9 +719,11 @@ public class Class2 }", HangMitigatingCancellationToken); } - [IdeFact] + [IdeFact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1903953/")] public async Task VerifyRenameLinkedDocumentsAsync() { + var globalOptions = await TestServices.Shell.GetComponentModelServiceAsync(HangMitigatingCancellationToken); + globalOptions.SetGlobalOption(InlineRenameUIOptionsStorage.UseInlineAdornment, true); var projectName = "MultiTFMProject"; await TestServices.SolutionExplorer.AddCustomProjectAsync(projectName, ".csproj", @" @@ -751,6 +753,8 @@ void Method() } }"; await TestServices.SolutionExplorer.AddFileAsync(projectName, "MyClass.cs", referencedCode, cancellationToken: HangMitigatingCancellationToken); + // We made csproj changes, so need to wait for PS to finish all the tasks before moving on. + await TestServices.Workspace.WaitForProjectSystemAsync(HangMitigatingCancellationToken); await TestServices.SolutionExplorer.OpenFileAsync(projectName, "TestClass.cs", HangMitigatingCancellationToken); await TestServices.SolutionExplorer.OpenFileAsync(projectName, "MyClass.cs", HangMitigatingCancellationToken); @@ -764,11 +768,11 @@ public class MyClass { void Method() { - MyTestClass x = new MyTestClass(); + MyTestClass$$ x = new MyTestClass(); } }", HangMitigatingCancellationToken); // Make sure the file is renamed. - await TestServices.SolutionExplorer.GetProjectItemAsync(projectName, "./MyTestClass.cs", HangMitigatingCancellationToken); + await TestServices.SolutionExplorer.GetProjectItemAsync(projectName, "MyTestClass.cs", HangMitigatingCancellationToken); } } } From a67c1cab559551f5e67c01e186d33a41a61b60e5 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Mon, 18 Dec 2023 15:04:01 -0800 Subject: [PATCH 08/10] Delete a unnecessary change from branch checking --- .../Core.Wpf/InlineRename/UI/Adornment/RenameFlyout.xaml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/EditorFeatures/Core.Wpf/InlineRename/UI/Adornment/RenameFlyout.xaml b/src/EditorFeatures/Core.Wpf/InlineRename/UI/Adornment/RenameFlyout.xaml index 9e101ddcbdfb3..4c8723a803c53 100644 --- a/src/EditorFeatures/Core.Wpf/InlineRename/UI/Adornment/RenameFlyout.xaml +++ b/src/EditorFeatures/Core.Wpf/InlineRename/UI/Adornment/RenameFlyout.xaml @@ -19,7 +19,6 @@ Focusable="False" UseLayoutRounding="True" Cursor="Arrow" - IsVisibleChanged="Control_IsVisibleChanged" x:Name="control"> From 35a09024b322f69f2bda34c4c76299f6f0cf019a Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Mon, 18 Dec 2023 15:21:22 -0800 Subject: [PATCH 09/10] Remove the usage of All --- .../Core/Portable/Workspace/Workspace.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs index 71669d92ea1d4..0732148b8d2ba 100644 --- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs +++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs @@ -1468,16 +1468,14 @@ private void ApplyDocumentsInfoChange(ImmutableArray projectChan var oldSolution = projectChange.OldProject.Solution; var oldDoc = projectChange.OldProject.GetRequiredDocument(docId); var newDoc = projectChange.NewProject.GetRequiredDocument(docId); - if (oldDoc.HasInfoChanged(newDoc)) + // For linked documents, when info get changed (e.g. name/folder/filePath) + // only apply one document changed because it will update the 'real' file, causing the other linked documents get changed. + if (oldDoc.HasInfoChanged(newDoc) + && infoChangedDocumentIds.Add(docId)) { var linkedDocumentIds = oldSolution.GetRequiredDocument(docId).GetLinkedDocumentIds(); - // For linked documents, when info get changed (e.g. name/folder/filePath) - // only apply one document changed because it will update the 'real' file, causing the other linked documents get changed. - if (linkedDocumentIds.All(linkedDocId => !infoChangedDocumentIds.Contains(linkedDocId))) - { - infoChangedDocumentIds.Add(docId); - infoChangedNewDocument.Add(newDoc); - } + infoChangedDocumentIds.AddRange(linkedDocumentIds); + infoChangedNewDocument.Add(newDoc); } } } From c122ea66616bf441ff9775e3f546f28ec37c85a6 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Wed, 27 Dec 2023 16:06:54 -0800 Subject: [PATCH 10/10] Address feedback --- .../CSharp/CSharpRename.cs | 4 +-- .../Core/Portable/Workspace/Workspace.cs | 26 ++++++++++--------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs index 34945b9eea361..a30f071de61ef 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs @@ -732,7 +732,7 @@ await TestServices.SolutionExplorer.AddCustomProjectAsync(projectName, ".csproj" net6.0-windows;net48 enable enable - preview + preview ", HangMitigatingCancellationToken); @@ -771,7 +771,7 @@ void Method() MyTestClass$$ x = new MyTestClass(); } }", HangMitigatingCancellationToken); - // Make sure the file is renamed. + // Make sure the file is renamed. If the file is not found, this call would throw exception await TestServices.SolutionExplorer.GetProjectItemAsync(projectName, "MyTestClass.cs", HangMitigatingCancellationToken); } } diff --git a/src/Workspaces/Core/Portable/Workspace/Workspace.cs b/src/Workspaces/Core/Portable/Workspace/Workspace.cs index 0732148b8d2ba..36120e4be2f59 100644 --- a/src/Workspaces/Core/Portable/Workspace/Workspace.cs +++ b/src/Workspaces/Core/Portable/Workspace/Workspace.cs @@ -1460,27 +1460,29 @@ internal virtual bool TryApplyChanges(Solution newSolution, IProgress projectChanges) { using var _1 = PooledHashSet.GetInstance(out var infoChangedDocumentIds); - using var _2 = PooledHashSet.GetInstance(out var infoChangedNewDocument); + using var _2 = PooledHashSet.GetInstance(out var infoChangedNewDocuments); foreach (var projectChange in projectChanges) { foreach (var docId in projectChange.GetChangedDocuments()) { - var oldSolution = projectChange.OldProject.Solution; - var oldDoc = projectChange.OldProject.GetRequiredDocument(docId); - var newDoc = projectChange.NewProject.GetRequiredDocument(docId); - // For linked documents, when info get changed (e.g. name/folder/filePath) - // only apply one document changed because it will update the 'real' file, causing the other linked documents get changed. - if (oldDoc.HasInfoChanged(newDoc) - && infoChangedDocumentIds.Add(docId)) + if (!infoChangedDocumentIds.Contains(docId)) { - var linkedDocumentIds = oldSolution.GetRequiredDocument(docId).GetLinkedDocumentIds(); - infoChangedDocumentIds.AddRange(linkedDocumentIds); - infoChangedNewDocument.Add(newDoc); + var oldDoc = projectChange.OldProject.GetRequiredDocument(docId); + var newDoc = projectChange.NewProject.GetRequiredDocument(docId); + // For linked documents, when info get changed (e.g. name/folder/filePath) + // only apply one document changed because it will update the 'real' file, causing the other linked documents get changed. + if (oldDoc.HasInfoChanged(newDoc)) + { + var linkedDocuments = oldDoc.GetLinkedDocumentIds(); + infoChangedDocumentIds.Add(docId); + infoChangedDocumentIds.AddRange(linkedDocuments); + infoChangedNewDocuments.Add(newDoc); + } } } } - foreach (var newDoc in infoChangedNewDocument) + foreach (var newDoc in infoChangedNewDocuments) { // ApplyDocumentInfoChanged ignores the loader information, so we can pass null for it ApplyDocumentInfoChanged(newDoc.Id,