Skip to content

Commit 97bdd9a

Browse files
authored
Merge pull request #5515 from MDoerner/RenameFolder
Rename folder CE command
2 parents 7accdd2 + 53e2b49 commit 97bdd9a

35 files changed

+1381
-57
lines changed

Rubberduck.Core/Rubberduck.Core.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@
126126
<Compile Update="UI\Refactorings\MoveToFolder\MoveMultipleToFolderView.xaml.cs">
127127
<DependentUpon>MoveMultipleToFolderView.xaml</DependentUpon>
128128
</Compile>
129+
<Compile Update="UI\Refactorings\RenameFolder\RenameFolderView.xaml.cs">
130+
<DependentUpon>RenameFolderView.xaml</DependentUpon>
131+
</Compile>
129132
</ItemGroup>
130133
<ItemGroup>
131134
<EmbeddedResource Update="Properties\Resources.resx">
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Rubberduck.Parsing.VBA;
2+
using Rubberduck.Refactorings;
3+
using Rubberduck.UI.Command.Refactorings.Notifiers;
4+
using Rubberduck.VBEditor.Events;
5+
6+
namespace Rubberduck.UI.CodeExplorer.Commands.Abstract
7+
{
8+
public abstract class CodeExplorerInteractiveRefactoringCommandBase<TModel> : CodeExplorerRefactoringCommandBase<TModel>
9+
where TModel : class, IRefactoringModel
10+
{
11+
private readonly IRefactoringAction<TModel> _refactoringAction;
12+
private readonly IRefactoringUserInteraction<TModel> _refactoringUserInteraction;
13+
private readonly IRefactoringFailureNotifier _failureNotifier;
14+
15+
protected CodeExplorerInteractiveRefactoringCommandBase(
16+
IRefactoringAction<TModel> refactoringAction,
17+
IRefactoringUserInteraction<TModel> refactoringUserInteraction,
18+
IRefactoringFailureNotifier failureNotifier,
19+
IParserStatusProvider parserStatusProvider,
20+
IVbeEvents vbeEvents)
21+
: base(refactoringAction, failureNotifier, parserStatusProvider, vbeEvents)
22+
{
23+
_refactoringUserInteraction = refactoringUserInteraction;
24+
_refactoringAction = refactoringAction;
25+
_failureNotifier = failureNotifier;
26+
}
27+
28+
protected abstract TModel InitialModelFromParameter(object parameter);
29+
protected abstract void ValidateInitialModel(TModel model);
30+
31+
protected override TModel ModelFromParameter(object parameter)
32+
{
33+
var initialModel = InitialModelFromParameter(parameter);
34+
ValidateInitialModel(initialModel);
35+
return _refactoringUserInteraction.UserModifiedModel(initialModel);
36+
}
37+
}
38+
}

Rubberduck.Core/UI/CodeExplorer/Commands/Abstract/CodeExplorerMoveToFolderCommandBase.cs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,27 @@ public abstract class CodeExplorerMoveToFolderCommandBase : CodeExplorerCommandB
2323
};
2424

2525
private readonly IParserStatusProvider _parserStatusProvider;
26+
private readonly RubberduckParserState _state;
2627

2728
private readonly IRefactoringAction<MoveMultipleFoldersModel> _moveFolders;
2829
private readonly IRefactoringAction<MoveMultipleToFolderModel> _moveToFolder;
2930

3031
private readonly IRefactoringFailureNotifier _failureNotifier;
3132

32-
public CodeExplorerMoveToFolderCommandBase(
33+
protected CodeExplorerMoveToFolderCommandBase(
3334
MoveMultipleFoldersRefactoringAction moveFolders,
3435
MoveMultipleToFolderRefactoringAction moveToFolder,
3536
MoveToFolderRefactoringFailedNotifier failureNotifier,
3637
IParserStatusProvider parserStatusProvider,
37-
IVbeEvents vbeEvents)
38+
IVbeEvents vbeEvents,
39+
RubberduckParserState state)
3840
: base(vbeEvents)
3941
{
4042
_moveFolders = moveFolders;
4143
_moveToFolder = moveToFolder;
4244

4345
_parserStatusProvider = parserStatusProvider;
46+
_state = state;
4447
_failureNotifier = failureNotifier;
4548

4649
AddToCanExecuteEvaluation(SpecialEvaluateCanExecute);
@@ -67,15 +70,13 @@ protected override void OnExecute(object parameter)
6770
if (node is CodeExplorerComponentViewModel componentViewModel)
6871
{
6972
var model = ComponentModel(componentViewModel);
70-
var modifiedModel = ModifiedComponentModel(model, parameter);
71-
ExecuteRefactoringAction(modifiedModel, _moveToFolder, _failureNotifier);
73+
ExecuteRefactoringAction(model, parameter, ValidateInitialComponentModel, ModifiedComponentModel, _moveToFolder, _failureNotifier);
7274
}
7375

7476
if (node is CodeExplorerCustomFolderViewModel folderViewModel)
7577
{
7678
var model = FolderModel(folderViewModel);
77-
var modifiedModel = ModifiedFolderModel(model, parameter);
78-
ExecuteRefactoringAction(modifiedModel, _moveFolders, _failureNotifier);
79+
ExecuteRefactoringAction(model, parameter, ValidateInitialFolderModel, ModifiedFolderModel, _moveFolders, _failureNotifier);
7980
}
8081
}
8182

@@ -103,6 +104,17 @@ private static ICollection<ModuleDeclaration> ContainedModules(ICodeExplorerNode
103104
.ToList();
104105
}
105106

107+
private void ValidateInitialFolderModel(MoveMultipleFoldersModel model)
108+
{
109+
var firstStaleAffectedModules = model.ModulesBySourceFolder.Values
110+
.SelectMany(modules => modules)
111+
.FirstOrDefault(module => _state.IsNewOrModified(module.QualifiedModuleName));
112+
if (firstStaleAffectedModules != null)
113+
{
114+
throw new AffectedModuleIsStaleException(firstStaleAffectedModules.QualifiedModuleName);
115+
}
116+
}
117+
106118
private MoveMultipleToFolderModel ComponentModel(CodeExplorerComponentViewModel componentViewModel)
107119
{
108120
if (!(componentViewModel.Declaration is ModuleDeclaration moduleDeclaration))
@@ -113,14 +125,32 @@ private MoveMultipleToFolderModel ComponentModel(CodeExplorerComponentViewModel
113125
var targets = new List<ModuleDeclaration>{moduleDeclaration};
114126
var targetFolder = moduleDeclaration.CustomFolder;
115127
return new MoveMultipleToFolderModel(targets, targetFolder);
116-
}
128+
}
129+
130+
private void ValidateInitialComponentModel(MoveMultipleToFolderModel model)
131+
{
132+
var firstStaleAffectedModules = model.Targets
133+
.FirstOrDefault(module => _state.IsNewOrModified(module.QualifiedModuleName));
134+
if (firstStaleAffectedModules != null)
135+
{
136+
throw new AffectedModuleIsStaleException(firstStaleAffectedModules.QualifiedModuleName);
137+
}
138+
}
117139

118-
private static void ExecuteRefactoringAction<TModel>(TModel model, IRefactoringAction<TModel> refactoringAction, IRefactoringFailureNotifier failureNotifier)
140+
private static void ExecuteRefactoringAction<TModel>(
141+
TModel model,
142+
object parameter,
143+
Action<TModel> initialModelValidation,
144+
Func<TModel,object,TModel> modelModification,
145+
IRefactoringAction<TModel> refactoringAction,
146+
IRefactoringFailureNotifier failureNotifier)
119147
where TModel : class, IRefactoringModel
120148
{
121149
try
122150
{
123-
refactoringAction.Refactor(model);
151+
initialModelValidation(model);
152+
var modifiedModel = modelModification(model, parameter);
153+
refactoringAction.Refactor(modifiedModel);
124154
}
125155
catch (RefactoringAbortedException)
126156
{}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using Rubberduck.Parsing.VBA;
2+
using Rubberduck.Refactorings;
3+
using Rubberduck.Refactorings.Exceptions;
4+
using Rubberduck.UI.Command.Refactorings.Notifiers;
5+
using Rubberduck.VBEditor.Events;
6+
7+
namespace Rubberduck.UI.CodeExplorer.Commands.Abstract
8+
{
9+
public abstract class CodeExplorerRefactoringCommandBase<TModel> : CodeExplorerCommandBase
10+
where TModel : class, IRefactoringModel
11+
{
12+
private readonly IParserStatusProvider _parserStatusProvider;
13+
14+
private readonly IRefactoringAction<TModel> _refactoringAction;
15+
private readonly IRefactoringFailureNotifier _failureNotifier;
16+
17+
protected CodeExplorerRefactoringCommandBase(
18+
IRefactoringAction<TModel> refactoringAction,
19+
IRefactoringFailureNotifier failureNotifier,
20+
IParserStatusProvider parserStatusProvider,
21+
IVbeEvents vbeEvents)
22+
: base(vbeEvents)
23+
{
24+
_refactoringAction = refactoringAction;
25+
_failureNotifier = failureNotifier;
26+
27+
_parserStatusProvider = parserStatusProvider;
28+
29+
AddToCanExecuteEvaluation(SpecialEvaluateCanExecute);
30+
}
31+
32+
private bool SpecialEvaluateCanExecute(object parameter)
33+
{
34+
return _parserStatusProvider.Status == ParserState.Ready;
35+
}
36+
37+
protected abstract TModel ModelFromParameter(object parameter);
38+
protected abstract void ValidateModel(TModel model);
39+
40+
protected override void OnExecute(object parameter)
41+
{
42+
if (!CanExecute(parameter))
43+
{
44+
return;
45+
}
46+
47+
try
48+
{
49+
var model = ModelFromParameter(parameter);
50+
ValidateModel(model);
51+
_refactoringAction.Refactor(model);
52+
}
53+
catch (RefactoringAbortedException)
54+
{ }
55+
catch (RefactoringException exception)
56+
{
57+
_failureNotifier.Notify(exception);
58+
}
59+
}
60+
}
61+
}

Rubberduck.Core/UI/CodeExplorer/Commands/CodeExplorerMoveToFolderCommand.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ public CodeExplorerMoveToFolderCommand(
2424
RefactoringUserInteraction<IMoveMultipleToFolderPresenter, MoveMultipleToFolderModel> moveToFolderInteraction,
2525
MoveToFolderRefactoringFailedNotifier failureNotifier,
2626
IParserStatusProvider parserStatusProvider,
27-
IVbeEvents vbeEvents)
28-
: base(moveFolders, moveToFolder, failureNotifier, parserStatusProvider, vbeEvents)
27+
IVbeEvents vbeEvents,
28+
RubberduckParserState state)
29+
: base(moveFolders, moveToFolder, failureNotifier, parserStatusProvider, vbeEvents, state)
2930
{
3031
_moveFoldersInteraction = moveFoldersInteraction;
3132
_moveToFolderInteraction = moveToFolderInteraction;

Rubberduck.Core/UI/CodeExplorer/Commands/DragAndDrop/CodeExplorerMoveToFolderDragAndDropCommand.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Rubberduck.Navigation.CodeExplorer;
77
using Rubberduck.Parsing.Symbols;
88
using Rubberduck.Parsing.VBA;
9+
using Rubberduck.Refactorings.Exceptions;
910
using Rubberduck.Refactorings.MoveFolder;
1011
using Rubberduck.Refactorings.MoveToFolder;
1112
using Rubberduck.Resources;
@@ -27,8 +28,9 @@ public CodeExplorerMoveToFolderDragAndDropCommand(
2728
IParserStatusProvider parserStatusProvider,
2829
IVbeEvents vbeEvents,
2930
IMessageBox messageBox,
30-
IDeclarationFinderProvider declarationFinderProvider)
31-
: base(moveFolders, moveToFolder, failureNotifier, parserStatusProvider, vbeEvents)
31+
IDeclarationFinderProvider declarationFinderProvider,
32+
RubberduckParserState state)
33+
: base(moveFolders, moveToFolder, failureNotifier, parserStatusProvider, vbeEvents, state)
3234
{
3335
_declarationFinderProvider = declarationFinderProvider;
3436
_messageBox = messageBox;
@@ -69,6 +71,11 @@ protected override MoveMultipleFoldersModel ModifiedFolderModel(MoveMultipleFold
6971
{
7072
model.TargetFolder = targetFolder;
7173
}
74+
else
75+
{
76+
throw new RefactoringAbortedException();
77+
}
78+
7279
return model;
7380
}
7481

Rubberduck.Core/UI/CodeExplorer/Commands/RenameCommand.cs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Rubberduck.Refactorings;
66
using Rubberduck.Refactorings.Exceptions;
77
using Rubberduck.Refactorings.Rename;
8+
using Rubberduck.UI.Command;
89
using Rubberduck.VBEditor.Events;
910
using Rubberduck.UI.Command.Refactorings.Notifiers;
1011

@@ -16,23 +17,28 @@ public sealed class RenameCommand : CodeExplorerCommandBase
1617
{
1718
typeof(CodeExplorerProjectViewModel),
1819
typeof(CodeExplorerComponentViewModel),
19-
typeof(CodeExplorerMemberViewModel)
20+
typeof(CodeExplorerMemberViewModel),
21+
typeof(CodeExplorerCustomFolderViewModel)
2022
};
2123

2224
private readonly IParserStatusProvider _parserStatusProvider;
2325
private readonly IRefactoring _refactoring;
2426
private readonly IRefactoringFailureNotifier _failureNotifier;
2527

28+
private readonly CommandBase _renameFolderCommand;
29+
2630
public RenameCommand(
2731
RenameRefactoring refactoring,
2832
RenameFailedNotifier renameFailedNotifier,
2933
IParserStatusProvider parserStatusProvider,
30-
IVbeEvents vbeEvents)
34+
IVbeEvents vbeEvents,
35+
RenameFolderCommand renameFolderCommand)
3136
: base(vbeEvents)
3237
{
3338
_refactoring = refactoring;
3439
_failureNotifier = renameFailedNotifier;
3540
_parserStatusProvider = parserStatusProvider;
41+
_renameFolderCommand = renameFolderCommand;
3642

3743
AddToCanExecuteEvaluation(SpecialEvaluateCanExecute);
3844
}
@@ -41,14 +47,26 @@ public RenameCommand(
4147

4248
private bool SpecialEvaluateCanExecute(object parameter)
4349
{
44-
return _parserStatusProvider.Status == ParserState.Ready;
50+
return _parserStatusProvider.Status == ParserState.Ready
51+
&& (!(parameter is CodeExplorerCustomFolderViewModel folderModel)
52+
|| _renameFolderCommand.CanExecute(folderModel));
4553
}
4654

4755
protected override void OnExecute(object parameter)
4856
{
4957
if (!CanExecute(parameter) ||
50-
!(parameter is CodeExplorerItemViewModel node) ||
51-
node.Declaration == null)
58+
!(parameter is CodeExplorerItemViewModel node))
59+
{
60+
return;
61+
}
62+
63+
if (node is CodeExplorerCustomFolderViewModel folderNode)
64+
{
65+
_renameFolderCommand.Execute(folderNode);
66+
return;
67+
}
68+
69+
if (node.Declaration == null)
5270
{
5371
return;
5472
}

0 commit comments

Comments
 (0)