Skip to content

Commit 126ffa4

Browse files
committed
Introduce RenameFolderRefactoringAction
It allows to rename the subfolder part of a folder.
1 parent 213bf1c commit 126ffa4

File tree

4 files changed

+259
-0
lines changed

4 files changed

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

0 commit comments

Comments
 (0)