@@ -19,28 +19,6 @@ internal class RemoveProjectFromSolutionCommand : CommandBase
19
19
private readonly string _fileOrDirectory ;
20
20
private readonly IReadOnlyCollection < string > _projects ;
21
21
22
- private int CountNonFolderDescendants (
23
- SolutionModel solution ,
24
- SolutionFolderModel item ,
25
- Dictionary < SolutionFolderModel , SolutionItemModel [ ] > solutionItemsGroupedByParent ,
26
- Dictionary < SolutionFolderModel , int > cached )
27
- {
28
- if ( cached . ContainsKey ( item ) )
29
- {
30
- return cached [ item ] ;
31
- }
32
- int count = item . Files ? . Count ?? 0 ;
33
- var children = solutionItemsGroupedByParent . TryGetValue ( item , out var items ) ? items : Array . Empty < SolutionItemModel > ( ) ;
34
- foreach ( var child in children )
35
- {
36
- count += child is SolutionFolderModel folderModel
37
- ? CountNonFolderDescendants ( solution , folderModel , solutionItemsGroupedByParent , cached )
38
- : 1 ;
39
- }
40
- cached . Add ( item , count ) ;
41
- return count ;
42
- }
43
-
44
22
public RemoveProjectFromSolutionCommand ( ParseResult parseResult ) : base ( parseResult )
45
23
{
46
24
_fileOrDirectory = parseResult . GetValue ( SlnCommandParser . SlnArgument ) ;
@@ -91,7 +69,7 @@ private async Task RemoveProjectsAsync(string solutionFileFullPath, IEnumerable<
91
69
ISolutionSerializer serializer = SlnCommandParser . GetSolutionSerializer ( solutionFileFullPath ) ;
92
70
SolutionModel solution = await serializer . OpenAsync ( solutionFileFullPath , cancellationToken ) ;
93
71
94
- // set UTF8 BOM encoding for .sln
72
+ // set UTF-8 BOM encoding for .sln
95
73
if ( serializer is ISolutionSerializer < SlnV12SerializerSettings > v12Serializer )
96
74
{
97
75
solution . SerializerExtension = v12Serializer . CreateModelExtension ( new ( )
@@ -114,21 +92,40 @@ private async Task RemoveProjectsAsync(string solutionFileFullPath, IEnumerable<
114
92
}
115
93
}
116
94
117
- Dictionary < SolutionFolderModel , SolutionItemModel [ ] > solutionItemsGroupedByParent = solution . SolutionItems
118
- . Where ( i => i . Parent != null )
119
- . GroupBy ( i => i . Parent )
120
- . ToDictionary ( g => g . Key , g => g . ToArray ( ) ) ;
121
-
122
- Dictionary < SolutionFolderModel , int > nonFolderDescendantsCount = new ( ) ;
123
- foreach ( var item in solution . SolutionFolders )
95
+ for ( int i = 0 ; i < solution . SolutionFolders . Count ; i ++ )
124
96
{
125
- CountNonFolderDescendants ( solution , item , solutionItemsGroupedByParent , nonFolderDescendantsCount ) ;
126
- }
97
+ var folder = solution . SolutionFolders [ i ] ;
98
+ int nonFolderDescendants = 0 ;
99
+ Stack < SolutionFolderModel > stack = new ( ) ;
100
+ stack . Push ( folder ) ;
127
101
128
- var emptyFolders = nonFolderDescendantsCount . Where ( i => i . Value == 0 ) . Select ( i => i . Key ) ;
129
- foreach ( var folder in emptyFolders )
130
- {
131
- solution . RemoveFolder ( folder ) ;
102
+ while ( stack . Count > 0 )
103
+ {
104
+ var current = stack . Pop ( ) ;
105
+
106
+ nonFolderDescendants += current . Files ? . Count ?? 0 ;
107
+ foreach ( var child in solution . SolutionItems )
108
+ {
109
+ if ( child is { Parent : var parent } && parent == current )
110
+ {
111
+ if ( child is SolutionFolderModel childFolder )
112
+ {
113
+ stack . Push ( childFolder ) ;
114
+ }
115
+ else
116
+ {
117
+ nonFolderDescendants ++ ;
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ if ( nonFolderDescendants == 0 )
124
+ {
125
+ solution . RemoveFolder ( folder ) ;
126
+ // After removal, adjust index and continue to avoid skipping folders after removal
127
+ i -- ;
128
+ }
132
129
}
133
130
134
131
await serializer . SaveAsync ( solutionFileFullPath , solution , cancellationToken ) ;
0 commit comments