Skip to content

Commit

Permalink
Introduce RenameFolderRefactoringAction
Browse files Browse the repository at this point in the history
It allows to rename the subfolder part of a folder.
  • Loading branch information
MDoerner committed Jun 7, 2020
1 parent 213bf1c commit 126ffa4
Show file tree
Hide file tree
Showing 4 changed files with 259 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Rubberduck.Refactorings.RenameFolder
{
public interface IRenameFolderPresenter : IRefactoringPresenter<RenameFolderModel>
{ }
}
22 changes: 22 additions & 0 deletions Rubberduck.Refactorings/RenameFolder/RenameFolderModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using Rubberduck.JunkDrawer.Extensions;
using Rubberduck.Parsing.Symbols;

namespace Rubberduck.Refactorings.RenameFolder
{
public class RenameFolderModel : IRefactoringModel
{
public string OriginalFolder { get; }
public ICollection<ModuleDeclaration> ModulesToMove { get; }
public string NewSubFolder { get; set; }

public RenameFolderModel(string originalFolder, ICollection<ModuleDeclaration> modulesToMove, string newSubFolder)
{
OriginalFolder = originalFolder;
ModulesToMove = modulesToMove;
NewSubFolder = newSubFolder;
}

public string SubFolderToRename => OriginalFolder.SubFolderName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Rubberduck.JunkDrawer.Extensions;
using Rubberduck.Parsing.Rewriter;
using Rubberduck.Refactorings.ChangeFolder;

namespace Rubberduck.Refactorings.RenameFolder
{
public class RenameFolderRefactoringAction : CodeOnlyRefactoringActionBase<RenameFolderModel>
{
private readonly ICodeOnlyRefactoringAction<ChangeFolderModel> _changeFolder;

public RenameFolderRefactoringAction(
IRewritingManager rewritingManager,
ChangeFolderRefactoringAction changeFolder)
: base(rewritingManager)
{
_changeFolder = changeFolder;
}

public override void Refactor(RenameFolderModel model, IRewriteSession rewriteSession)
{
var sourceFolderParent = model.OriginalFolder.ParentFolder();
var targetFolder = string.IsNullOrEmpty(sourceFolderParent)
? model.NewSubFolder
: $"{sourceFolderParent}{FolderExtensions.FolderDelimiter}{model.NewSubFolder}";

var changeFolderModel = new ChangeFolderModel(model.OriginalFolder, model.ModulesToMove, targetFolder);
_changeFolder.Refactor(changeFolderModel, rewriteSession);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Rubberduck.Parsing.Rewriter;
using Rubberduck.Parsing.Symbols;
using Rubberduck.Parsing.VBA;
using Rubberduck.Refactorings;
using Rubberduck.Refactorings.ChangeFolder;
using Rubberduck.Refactorings.MoveToFolder;
using Rubberduck.Refactorings.RenameFolder;
using Rubberduck.VBEditor.SafeComWrappers;

namespace RubberduckTests.Refactoring.RenameFolder
{
[TestFixture]
public class RenameFolderRefactoringActionTests : RefactoringActionTestBase<RenameFolderModel>
{
[Test]
[Category("Refactorings")]
public void RenameFolderRefactoringAction_TopLevelFolder()
{
const string code = @"
'@Folder(""MyOldFolder"")
Public Sub Foo()
End Sub
";
const string expectedCode = @"
'@Folder ""MyNewFolder.MySubFolder""
Public Sub Foo()
End Sub
";
Func<RubberduckParserState, RenameFolderModel> modelBuilder = (state) =>
{
var module = state.DeclarationFinder
.UserDeclarations(DeclarationType.ProceduralModule)
.Single() as ModuleDeclaration;
return new RenameFolderModel("MyOldFolder", new List<ModuleDeclaration> { module }, "MyNewFolder.MySubFolder");
};

var refactoredCode = RefactoredCode(code, modelBuilder);

Assert.AreEqual(expectedCode, refactoredCode);
}

[Test]
[Category("Refactorings")]
public void RenameFolderRefactoringAction_SubFolder()
{
const string code = @"
'@Folder(""MyOldFolder.MyOldSubFolder.SubSub"")
Public Sub Foo()
End Sub
";
const string expectedCode = @"
'@Folder ""MyOldFolder.MyOldSubFolder.MyNewFolder""
Public Sub Foo()
End Sub
";
Func<RubberduckParserState, RenameFolderModel> modelBuilder = (state) =>
{
var module = state.DeclarationFinder
.UserDeclarations(DeclarationType.ProceduralModule)
.Single() as ModuleDeclaration;
return new RenameFolderModel("MyOldFolder.MyOldSubFolder.SubSub", new List<ModuleDeclaration> { module }, "MyNewFolder");
};

var refactoredCode = RefactoredCode(code, modelBuilder);

Assert.AreEqual(expectedCode, refactoredCode);
}

[Test]
[Category("Refactorings")]
public void RenameFolderRefactoringAction_PreservesSubFolderStructure()
{
const string code = @"
'@Folder(""MyOldFolder.MyOldSubFolder.SubSub.Sub"")
Public Sub Foo()
End Sub
";
const string expectedCode = @"
'@Folder ""MyOldFolder.MyNewFolder.MySubFolder.SubSub.Sub""
Public Sub Foo()
End Sub
";
Func<RubberduckParserState, RenameFolderModel> modelBuilder = (state) =>
{
var module = state.DeclarationFinder
.UserDeclarations(DeclarationType.ProceduralModule)
.Single() as ModuleDeclaration;
return new RenameFolderModel("MyOldFolder.MyOldSubFolder", new List<ModuleDeclaration> { module }, "MyNewFolder.MySubFolder");
};

var refactoredCode = RefactoredCode(code, modelBuilder);

Assert.AreEqual(expectedCode, refactoredCode);
}

[Test]
[Category("Refactorings")]
public void RenameFolderRefactoringAction_NotInFolder_DoesNothing()
{
const string code = @"
'@Folder(""MyOldFolder.MyOldSubFolder.SubSub.Sub"")
Public Sub Foo()
End Sub
";
const string expectedCode = code;

Func<RubberduckParserState, RenameFolderModel> modelBuilder = (state) =>
{
var module = state.DeclarationFinder
.UserDeclarations(DeclarationType.ProceduralModule)
.Single() as ModuleDeclaration;
return new RenameFolderModel("NotMyOldFolder.MyOldSubFolder", new List<ModuleDeclaration> { module }, "MyNewFolder.MySubFolder");
};

var refactoredCode = RefactoredCode(code, modelBuilder);

Assert.AreEqual(expectedCode, refactoredCode);
}

[Test]
[Category("Refactorings")]
public void RenameFolderRefactoringAction_ChangesExactlyTheSpecifiedModules()
{
const string code1 = @"
'@Folder(""MyOldFolder.MyOldSubfolder.SubSub"")
Public Sub Foo()
End Sub
";
const string code2 = @"
'@Folder(""MyOldFolder.MyOldSubfolder"")
Public Sub Foo()
End Sub
";
const string code3 = @"
'@Folder(""MyOtherFolder.MyOldSubfolder"")
Public Sub Foo()
End Sub
";
const string code4 = @"
'@Folder(""MyOtherFolder.MyOtherSubfolder"")
Public Sub Foo()
End Sub
";
const string code5 = @"
Public Sub Foo()
End Sub
";
const string expectedCode1 = @"
'@Folder ""MyOldFolder.MyNewFolder.SubSub""
Public Sub Foo()
End Sub
";
const string expectedCode2 = @"
'@Folder ""MyOldFolder.MyNewFolder""
Public Sub Foo()
End Sub
";
const string expectedCode3 = code3;
const string expectedCode4 = code4;
const string expectedCode5 = code5;
Func<RubberduckParserState, RenameFolderModel> modelBuilder = (state) =>
{
var modules = state.DeclarationFinder
.UserDeclarations(DeclarationType.Module)
.OfType<ModuleDeclaration>()
.ToList();
var module1 = modules.Single(module => module.IdentifierName.Equals("SubSubFolderModule"));
var module2 = modules.Single(module => module.IdentifierName.Equals("SubFolderModuleIncluded"));
const string originalFolder = "MyOldFolder.MyOldSubfolder";
return new RenameFolderModel(originalFolder, new List<ModuleDeclaration> { module1, module2 }, "MyNewFolder");
};

var refactoredCode = RefactoredCode(
modelBuilder,
("SubSubFolderModule", code1, ComponentType.StandardModule),
("SubFolderModuleIncluded", code2, ComponentType.ClassModule),
("SubFolderModuleNotIncluded", code3, ComponentType.ClassModule),
("UnaffectedSubFolderModule", code4, ComponentType.StandardModule),
("NoFolderModule", code5, ComponentType.StandardModule));

Assert.AreEqual(expectedCode1, refactoredCode["SubSubFolderModule"]);
Assert.AreEqual(expectedCode2, refactoredCode["SubFolderModuleIncluded"]);
Assert.AreEqual(expectedCode3, refactoredCode["SubFolderModuleNotIncluded"]);
Assert.AreEqual(expectedCode4, refactoredCode["UnaffectedSubFolderModule"]);
Assert.AreEqual(expectedCode5, refactoredCode["NoFolderModule"]);
}

protected override IRefactoringAction<RenameFolderModel> TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager)
{
var annotationUpdater = new AnnotationUpdater();
var moveToFolderAction = new MoveToFolderRefactoringAction(rewritingManager, annotationUpdater);
var changeFolderAction = new ChangeFolderRefactoringAction(rewritingManager, moveToFolderAction);
return new RenameFolderRefactoringAction(rewritingManager, changeFolderAction);
}
}
}

0 comments on commit 126ffa4

Please sign in to comment.