Skip to content

Commit f0cbd16

Browse files
committed
Extract ChangeFolderRefactoringAction out of MoveFolderRefactoringAction
1 parent 7accdd2 commit f0cbd16

File tree

9 files changed

+286
-25
lines changed

9 files changed

+286
-25
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Collections.Generic;
2+
using Rubberduck.Parsing.Symbols;
3+
4+
namespace Rubberduck.Refactorings.ChangeFolder
5+
{
6+
public class ChangeFolderModel : IRefactoringModel
7+
{
8+
public string OriginalFolder { get; }
9+
public ICollection<ModuleDeclaration> ModulesToMove { get; }
10+
public string NewFolder { get; set; }
11+
12+
public ChangeFolderModel(string originalFolder, ICollection<ModuleDeclaration> modulesToMove, string newFolder)
13+
{
14+
OriginalFolder = originalFolder;
15+
ModulesToMove = modulesToMove;
16+
NewFolder = newFolder;
17+
}
18+
}
19+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System.Linq;
2+
using Rubberduck.JunkDrawer.Extensions;
3+
using Rubberduck.Parsing.Rewriter;
4+
using Rubberduck.Refactorings.MoveToFolder;
5+
6+
namespace Rubberduck.Refactorings.ChangeFolder
7+
{
8+
public class ChangeFolderRefactoringAction : CodeOnlyRefactoringActionBase<ChangeFolderModel>
9+
{
10+
private readonly ICodeOnlyRefactoringAction<MoveToFolderModel> _moveToFolder;
11+
12+
public ChangeFolderRefactoringAction(
13+
IRewritingManager rewritingManager,
14+
MoveToFolderRefactoringAction moveToFolder)
15+
: base(rewritingManager)
16+
{
17+
_moveToFolder = moveToFolder;
18+
}
19+
20+
public override void Refactor(ChangeFolderModel model, IRewriteSession rewriteSession)
21+
{
22+
var originalFolder = model.OriginalFolder;
23+
24+
foreach (var module in model.ModulesToMove.Distinct())
25+
{
26+
var currentFolder = module.CustomFolder;
27+
28+
if (!currentFolder.StartsWith(originalFolder))
29+
{
30+
continue;
31+
}
32+
33+
var newFolder = currentFolder.Equals(originalFolder)
34+
? model.NewFolder
35+
: $"{model.NewFolder}{FolderExtensions.FolderDelimiter}{currentFolder.SubFolderPathRelativeTo(model.OriginalFolder)}";
36+
37+
var moduleModel = new MoveToFolderModel(module, newFolder);
38+
_moveToFolder.Refactor(moduleModel, rewriteSession);
39+
}
40+
}
41+
}
42+
}

Rubberduck.Refactorings/MoveFolder/MoveFolderModel.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ namespace Rubberduck.Refactorings.MoveFolder
55
{
66
public class MoveFolderModel : IRefactoringModel
77
{
8-
public string SourceFolder { get; }
9-
public ICollection<ModuleDeclaration> ContainedModules { get; }
8+
public string FolderToMove { get; }
9+
public ICollection<ModuleDeclaration> ModulesToMove { get; }
1010
public string TargetFolder { get; set; }
1111

12-
public MoveFolderModel(string sourceFolder, ICollection<ModuleDeclaration> containedModules, string targetFolder)
12+
public MoveFolderModel(string folderToMove, ICollection<ModuleDeclaration> modulesToMove, string targetFolder)
1313
{
14-
SourceFolder = sourceFolder;
15-
ContainedModules = containedModules;
14+
FolderToMove = folderToMove;
15+
ModulesToMove = modulesToMove;
1616
TargetFolder = targetFolder;
1717
}
1818
}
Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,26 @@
1-
using System.Linq;
2-
using Rubberduck.JunkDrawer.Extensions;
1+
using Rubberduck.JunkDrawer.Extensions;
32
using Rubberduck.Parsing.Rewriter;
4-
using Rubberduck.Refactorings.MoveToFolder;
3+
using Rubberduck.Refactorings.ChangeFolder;
54

65
namespace Rubberduck.Refactorings.MoveFolder
76
{
87
public class MoveFolderRefactoringAction : CodeOnlyRefactoringActionBase<MoveFolderModel>
98
{
10-
private readonly ICodeOnlyRefactoringAction<MoveToFolderModel> _moveToFolder;
9+
private readonly ICodeOnlyRefactoringAction<ChangeFolderModel> _changeFolder;
1110

1211
public MoveFolderRefactoringAction(
1312
IRewritingManager rewritingManager,
14-
MoveToFolderRefactoringAction moveToFolder)
13+
ChangeFolderRefactoringAction changeFolder)
1514
: base(rewritingManager)
1615
{
17-
_moveToFolder = moveToFolder;
16+
_changeFolder = changeFolder;
1817
}
1918

2019
public override void Refactor(MoveFolderModel model, IRewriteSession rewriteSession)
2120
{
22-
var sourceFolderParent = model.SourceFolder.ParentFolder();
23-
24-
foreach (var module in model.ContainedModules.Distinct())
25-
{
26-
var currentFolder = module.CustomFolder;
27-
var subPath = currentFolder.SubFolderPathRelativeTo(sourceFolderParent);
28-
var newFolder = $"{model.TargetFolder}{FolderExtensions.FolderDelimiter}{subPath}";
29-
var moduleModel = new MoveToFolderModel(module, newFolder);
30-
_moveToFolder.Refactor(moduleModel, rewriteSession);
31-
}
21+
var sourceFolderParent = model.FolderToMove.ParentFolder();
22+
var changeFolderModel = new ChangeFolderModel(sourceFolderParent, model.ModulesToMove, model.TargetFolder);
23+
_changeFolder.Refactor(changeFolderModel, rewriteSession);
3224
}
3325
}
3426
}

RubberduckTests/Commands/RefactorCommands/CodePaneMoveContainingFolderCommandTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Rubberduck.Parsing.UIContext;
77
using Rubberduck.Parsing.VBA;
88
using Rubberduck.Refactorings;
9+
using Rubberduck.Refactorings.ChangeFolder;
910
using Rubberduck.Refactorings.MoveFolder;
1011
using Rubberduck.Refactorings.MoveToFolder;
1112
using Rubberduck.UI.Command;
@@ -40,7 +41,8 @@ protected override CommandBase TestCommand(
4041

4142
var annotationUpdater = new AnnotationUpdater();
4243
var moveToFolderAction = new MoveToFolderRefactoringAction(rewritingManager, annotationUpdater);
43-
var moveFolderAction = new MoveFolderRefactoringAction(rewritingManager, moveToFolderAction);
44+
var changeFolderAction = new ChangeFolderRefactoringAction(rewritingManager, moveToFolderAction);
45+
var moveFolderAction = new MoveFolderRefactoringAction(rewritingManager, changeFolderAction);
4446
var moveMultipleFoldersAction = new MoveMultipleFoldersRefactoringAction(rewritingManager, moveFolderAction);
4547

4648
var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state);
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using NUnit.Framework;
5+
using Rubberduck.Parsing.Rewriter;
6+
using Rubberduck.Parsing.Symbols;
7+
using Rubberduck.Parsing.VBA;
8+
using Rubberduck.Refactorings;
9+
using Rubberduck.Refactorings.ChangeFolder;
10+
using Rubberduck.Refactorings.MoveToFolder;
11+
using Rubberduck.VBEditor.SafeComWrappers;
12+
13+
namespace RubberduckTests.Refactoring.ChangeFolder
14+
{
15+
[TestFixture]
16+
public class ChangeFolderRefactoringActionTests : RefactoringActionTestBase<ChangeFolderModel>
17+
{
18+
[Test]
19+
[Category("Refactorings")]
20+
public void ChangeFolderRefactoringAction_TopLevelFolder()
21+
{
22+
const string code = @"
23+
'@Folder(""MyOldFolder"")
24+
Public Sub Foo()
25+
End Sub
26+
";
27+
const string expectedCode = @"
28+
'@Folder ""MyNewFolder.MySubFolder""
29+
Public Sub Foo()
30+
End Sub
31+
";
32+
Func<RubberduckParserState, ChangeFolderModel> modelBuilder = (state) =>
33+
{
34+
var module = state.DeclarationFinder
35+
.UserDeclarations(DeclarationType.ProceduralModule)
36+
.Single() as ModuleDeclaration;
37+
return new ChangeFolderModel("MyOldFolder", new List<ModuleDeclaration> { module }, "MyNewFolder.MySubFolder");
38+
};
39+
40+
var refactoredCode = RefactoredCode(code, modelBuilder);
41+
42+
Assert.AreEqual(expectedCode, refactoredCode);
43+
}
44+
45+
[Test]
46+
[Category("Refactorings")]
47+
public void ChangeFolderRefactoringAction_SubFolder()
48+
{
49+
const string code = @"
50+
'@Folder(""MyOldFolder.MyOldSubFolder.SubSub"")
51+
Public Sub Foo()
52+
End Sub
53+
";
54+
const string expectedCode = @"
55+
'@Folder ""MyNewFolder""
56+
Public Sub Foo()
57+
End Sub
58+
";
59+
Func<RubberduckParserState, ChangeFolderModel> modelBuilder = (state) =>
60+
{
61+
var module = state.DeclarationFinder
62+
.UserDeclarations(DeclarationType.ProceduralModule)
63+
.Single() as ModuleDeclaration;
64+
return new ChangeFolderModel("MyOldFolder.MyOldSubFolder.SubSub", new List<ModuleDeclaration> { module }, "MyNewFolder");
65+
};
66+
67+
var refactoredCode = RefactoredCode(code, modelBuilder);
68+
69+
Assert.AreEqual(expectedCode, refactoredCode);
70+
}
71+
72+
[Test]
73+
[Category("Refactorings")]
74+
public void ChangeFolderRefactoringAction_PreservesSubFolderStructure()
75+
{
76+
const string code = @"
77+
'@Folder(""MyOldFolder.MyOldSubFolder.SubSub.Sub"")
78+
Public Sub Foo()
79+
End Sub
80+
";
81+
const string expectedCode = @"
82+
'@Folder ""MyNewFolder.MySubFolder.SubSub.Sub""
83+
Public Sub Foo()
84+
End Sub
85+
";
86+
Func<RubberduckParserState, ChangeFolderModel> modelBuilder = (state) =>
87+
{
88+
var module = state.DeclarationFinder
89+
.UserDeclarations(DeclarationType.ProceduralModule)
90+
.Single() as ModuleDeclaration;
91+
return new ChangeFolderModel("MyOldFolder.MyOldSubFolder", new List<ModuleDeclaration> { module }, "MyNewFolder.MySubFolder");
92+
};
93+
94+
var refactoredCode = RefactoredCode(code, modelBuilder);
95+
96+
Assert.AreEqual(expectedCode, refactoredCode);
97+
}
98+
99+
[Test]
100+
[Category("Refactorings")]
101+
public void ChangeFolderRefactoringAction_NotInFolder_DoesNothing()
102+
{
103+
const string code = @"
104+
'@Folder(""MyOldFolder.MyOldSubFolder.SubSub.Sub"")
105+
Public Sub Foo()
106+
End Sub
107+
";
108+
const string expectedCode = code;
109+
110+
Func<RubberduckParserState, ChangeFolderModel> modelBuilder = (state) =>
111+
{
112+
var module = state.DeclarationFinder
113+
.UserDeclarations(DeclarationType.ProceduralModule)
114+
.Single() as ModuleDeclaration;
115+
return new ChangeFolderModel("NotMyOldFolder.MyOldSubFolder", new List<ModuleDeclaration> { module }, "MyNewFolder.MySubFolder");
116+
};
117+
118+
var refactoredCode = RefactoredCode(code, modelBuilder);
119+
120+
Assert.AreEqual(expectedCode, refactoredCode);
121+
}
122+
123+
[Test]
124+
[Category("Refactorings")]
125+
public void ChangeFolderRefactoringAction_ChangesExactlyTheSpecifiedModules()
126+
{
127+
const string code1 = @"
128+
'@Folder(""MyOldFolder.MyOldSubfolder.SubSub"")
129+
Public Sub Foo()
130+
End Sub
131+
";
132+
const string code2 = @"
133+
'@Folder(""MyOldFolder.MyOldSubfolder"")
134+
Public Sub Foo()
135+
End Sub
136+
";
137+
const string code3 = @"
138+
'@Folder(""MyOtherFolder.MyOldSubfolder"")
139+
Public Sub Foo()
140+
End Sub
141+
";
142+
const string code4 = @"
143+
'@Folder(""MyOtherFolder.MyOtherSubfolder"")
144+
Public Sub Foo()
145+
End Sub
146+
";
147+
const string code5 = @"
148+
Public Sub Foo()
149+
End Sub
150+
";
151+
const string expectedCode1 = @"
152+
'@Folder ""MyNewFolder.SubSub""
153+
Public Sub Foo()
154+
End Sub
155+
";
156+
const string expectedCode2 = @"
157+
'@Folder ""MyNewFolder""
158+
Public Sub Foo()
159+
End Sub
160+
";
161+
const string expectedCode3 = code3;
162+
const string expectedCode4 = code4;
163+
const string expectedCode5 = code5;
164+
Func<RubberduckParserState, ChangeFolderModel> modelBuilder = (state) =>
165+
{
166+
var modules = state.DeclarationFinder
167+
.UserDeclarations(DeclarationType.Module)
168+
.OfType<ModuleDeclaration>()
169+
.ToList();
170+
171+
var module1 = modules.Single(module => module.IdentifierName.Equals("SubSubFolderModule"));
172+
var module2 = modules.Single(module => module.IdentifierName.Equals("SubFolderModuleIncluded"));
173+
const string originalFolder = "MyOldFolder.MyOldSubfolder";
174+
175+
return new ChangeFolderModel(originalFolder, new List<ModuleDeclaration>{module1, module2}, "MyNewFolder");
176+
};
177+
178+
var refactoredCode = RefactoredCode(
179+
modelBuilder,
180+
("SubSubFolderModule", code1, ComponentType.StandardModule),
181+
("SubFolderModuleIncluded", code2, ComponentType.ClassModule),
182+
("SubFolderModuleNotIncluded", code3, ComponentType.ClassModule),
183+
("UnaffectedSubFolderModule", code4, ComponentType.StandardModule),
184+
("NoFolderModule", code5, ComponentType.StandardModule));
185+
186+
Assert.AreEqual(expectedCode1, refactoredCode["SubSubFolderModule"]);
187+
Assert.AreEqual(expectedCode2, refactoredCode["SubFolderModuleIncluded"]);
188+
Assert.AreEqual(expectedCode3, refactoredCode["SubFolderModuleNotIncluded"]);
189+
Assert.AreEqual(expectedCode4, refactoredCode["UnaffectedSubFolderModule"]);
190+
Assert.AreEqual(expectedCode5, refactoredCode["NoFolderModule"]);
191+
}
192+
193+
protected override IRefactoringAction<ChangeFolderModel> TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager)
194+
{
195+
var annotationUpdater = new AnnotationUpdater();
196+
var moveToFolderAction = new MoveToFolderRefactoringAction(rewritingManager, annotationUpdater);
197+
return new ChangeFolderRefactoringAction(rewritingManager, moveToFolderAction);
198+
}
199+
}
200+
}

RubberduckTests/Refactoring/MoveFolders/MoveContainingFolderRefactoringTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Rubberduck.Parsing.UIContext;
88
using Rubberduck.Parsing.VBA;
99
using Rubberduck.Refactorings;
10+
using Rubberduck.Refactorings.ChangeFolder;
1011
using Rubberduck.Refactorings.MoveFolder;
1112
using Rubberduck.Refactorings.MoveToFolder;
1213
using Rubberduck.VBEditor.SafeComWrappers;
@@ -369,7 +370,8 @@ protected override IRefactoring TestRefactoring(
369370
{
370371
var annotationUpdater = new AnnotationUpdater();
371372
var moveToFolderAction = new MoveToFolderRefactoringAction(rewritingManager, annotationUpdater);
372-
var moveFolderAction = new MoveFolderRefactoringAction(rewritingManager, moveToFolderAction);
373+
var changeFolderAction = new ChangeFolderRefactoringAction(rewritingManager, moveToFolderAction);
374+
var moveFolderAction = new MoveFolderRefactoringAction(rewritingManager, changeFolderAction);
373375
var moveMultipleFoldersAction = new MoveMultipleFoldersRefactoringAction(rewritingManager, moveFolderAction);
374376

375377
var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state);

RubberduckTests/Refactoring/MoveFolders/MoveFolderRefactoringActionTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Rubberduck.Parsing.Symbols;
77
using Rubberduck.Parsing.VBA;
88
using Rubberduck.Refactorings;
9+
using Rubberduck.Refactorings.ChangeFolder;
910
using Rubberduck.Refactorings.MoveFolder;
1011
using Rubberduck.Refactorings.MoveToFolder;
1112
using Rubberduck.VBEditor.SafeComWrappers;
@@ -198,7 +199,8 @@ protected override IRefactoringAction<MoveFolderModel> TestBaseRefactoring(Rubbe
198199
{
199200
var annotationUpdater = new AnnotationUpdater();
200201
var moveToFolderAction = new MoveToFolderRefactoringAction(rewritingManager, annotationUpdater);
201-
return new MoveFolderRefactoringAction(rewritingManager, moveToFolderAction);
202+
var changeFolderAction = new ChangeFolderRefactoringAction(rewritingManager, moveToFolderAction);
203+
return new MoveFolderRefactoringAction(rewritingManager, changeFolderAction);
202204
}
203205
}
204206
}

0 commit comments

Comments
 (0)