From f01431f6237eee1271d7f4d262037213aac96979 Mon Sep 17 00:00:00 2001 From: Richard Stanton Date: Fri, 15 Nov 2024 13:56:28 -0800 Subject: [PATCH] Fix handling of nested solution folders with same name. --- .../Model/SolutionItemModel.cs | 7 +++++++ .../Model/SolutionModel.cs | 9 ++++++--- .../Utilities/ListBuilderStruct`1.cs | 2 +- .../Serialization/RoundTripClassicSln.cs | 3 +++ .../SlnAssets/FolderId.sln.txt | 19 +++++++++++++++++++ .../SlnAssets/FolderId.slnx.xml | 6 ++++++ 6 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/FolderId.sln.txt create mode 100644 test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/FolderId.slnx.xml diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionItemModel.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionItemModel.cs index c863b9cb..57a7984d 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionItemModel.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionItemModel.cs @@ -122,6 +122,13 @@ public void MoveToFolder(SolutionFolderModel? folder) try { this.Parent = folder; + + // Reevaulate the id. + if (this.id == this.DefaultId) + { + this.id = null; + } + if (this is SolutionProjectModel thisProject) { this.Solution.ValidateProjectName(thisProject); diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionModel.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionModel.cs index 2312e453..b59a458e 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionModel.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Model/SolutionModel.cs @@ -193,7 +193,12 @@ public SolutionFolderModel AddFolder(string path) string? parentItemRef = lastSlash > 0 ? folderPath.Slice(0, lastSlash + 1).ToString() : null; StringSpan newName = lastSlash > 0 ? folderPath.Slice(lastSlash + 1) : folderPath.Slice(1); - return this.AddFolder(newName, parentItemRef); + SolutionFolderModel folder = this.AddFolder(newName, parentItemRef); + + // Ensure the project type is in the project type table, if it is not already. + this.solutionItemsById[folder.Id] = folder; + + return folder; } /// @@ -629,8 +634,6 @@ private SolutionFolderModel AddFolder(StringSpan name, string? parentItemRef) this.solutionFolders.Add(folder); this.solutionItems.Add(folder); - // Ensure the project type is in the project type table, if it is not already. - this.solutionItemsById[folder.Id] = folder; return folder; } diff --git a/src/Microsoft.VisualStudio.SolutionPersistence/Utilities/ListBuilderStruct`1.cs b/src/Microsoft.VisualStudio.SolutionPersistence/Utilities/ListBuilderStruct`1.cs index 51c390a7..a08a65fb 100644 --- a/src/Microsoft.VisualStudio.SolutionPersistence/Utilities/ListBuilderStruct`1.cs +++ b/src/Microsoft.VisualStudio.SolutionPersistence/Utilities/ListBuilderStruct`1.cs @@ -111,7 +111,7 @@ internal readonly T[] ToArray() 2 => [this.item0, this.item1], 3 => [this.item0, this.item1, this.item2], 4 => [this.item0, this.item1, this.item2, this.item3], - _ => [this.item0, this.item1, this.item2, this.item3, .. this.items], + _ => [this.item0, this.item1, this.item2, this.item3, .. this.items!], }; } diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs index e4e7efcb..5e6c80f4 100644 --- a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/Serialization/RoundTripClassicSln.cs @@ -39,6 +39,9 @@ public class RoundTripClassicSln [Fact] public Task MissingConfigurationsAsync() => TestRoundTripSerializerAsync(SlnAssets.ClassicSlnMissingConfigurations); + [Fact] + public Task FolderIdAsync() => TestRoundTripSerializerAsync(SlnAssets.LoadResource("FolderId.sln")); + [Theory] [MemberData(nameof(ClassicSlnFiles))] public Task AllClassicSolutionAsync(ResourceName sampleFile) diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/FolderId.sln.txt b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/FolderId.sln.txt new file mode 100644 index 00000000..6b973cf6 --- /dev/null +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/FolderId.sln.txt @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Foo", "Foo", "{A340195B-735B-34A1-F5D5-445C9F08470D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Foo", "Foo", "{F508AC4D-2574-0F7F-5175-5C248303655F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Foo", "Foo", "{45DA1D9E-8A3F-8D58-BB91-EFD6A5B29A17}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Foo", "Foo", "{6647119C-3B2A-3090-A1B3-560120CC3977}" +EndProject +Global + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F508AC4D-2574-0F7F-5175-5C248303655F} = {A340195B-735B-34A1-F5D5-445C9F08470D} + {45DA1D9E-8A3F-8D58-BB91-EFD6A5B29A17} = {F508AC4D-2574-0F7F-5175-5C248303655F} + {6647119C-3B2A-3090-A1B3-560120CC3977} = {45DA1D9E-8A3F-8D58-BB91-EFD6A5B29A17} + EndGlobalSection +EndGlobal diff --git a/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/FolderId.slnx.xml b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/FolderId.slnx.xml new file mode 100644 index 00000000..5b1136f5 --- /dev/null +++ b/test/Microsoft.VisualStudio.SolutionPersistence.Tests/SlnAssets/FolderId.slnx.xml @@ -0,0 +1,6 @@ + + + + + +