Skip to content

Commit 082d93e

Browse files
committed
Enhance CE Rename command to cover folder renames
It incorporates a new RenameFolderCommand.
1 parent a4247f9 commit 082d93e

File tree

6 files changed

+223
-6
lines changed

6 files changed

+223
-6
lines changed
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+
}
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/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
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Rubberduck.JunkDrawer.Extensions;
5+
using Rubberduck.Navigation.CodeExplorer;
6+
using Rubberduck.Parsing.Symbols;
7+
using Rubberduck.Parsing.VBA;
8+
using Rubberduck.Refactorings;
9+
using Rubberduck.Refactorings.Exceptions;
10+
using Rubberduck.Refactorings.RenameFolder;
11+
using Rubberduck.UI.CodeExplorer.Commands.Abstract;
12+
using Rubberduck.UI.Command.Refactorings.Notifiers;
13+
using Rubberduck.VBEditor.Events;
14+
15+
namespace Rubberduck.UI.CodeExplorer.Commands
16+
{
17+
public class RenameFolderCommand : CodeExplorerInteractiveRefactoringCommandBase<RenameFolderModel>
18+
{
19+
private static readonly Type[] ApplicableNodes =
20+
{
21+
typeof(CodeExplorerCustomFolderViewModel)
22+
};
23+
24+
private RubberduckParserState _state;
25+
26+
public RenameFolderCommand(
27+
RenameFolderRefactoringAction refactoringAction,
28+
RefactoringUserInteraction<IRenameFolderPresenter, RenameFolderModel> userInteraction,
29+
RenameFolderFailedNotifier failureNotifier,
30+
IParserStatusProvider parserStatusProvider,
31+
IVbeEvents vbeEvents,
32+
RubberduckParserState state)
33+
: base(refactoringAction, userInteraction, failureNotifier, parserStatusProvider, vbeEvents)
34+
{
35+
_state = state;
36+
}
37+
38+
public override IEnumerable<Type> ApplicableNodeTypes => ApplicableNodes;
39+
40+
protected override RenameFolderModel InitialModelFromParameter(object parameter)
41+
{
42+
if (!(parameter is CodeExplorerCustomFolderViewModel folderModel))
43+
{
44+
throw new ArgumentException(nameof(parameter));
45+
}
46+
47+
return ModelFromNode(folderModel);
48+
}
49+
50+
private static RenameFolderModel ModelFromNode(CodeExplorerCustomFolderViewModel folderModel)
51+
{
52+
var folder = folderModel.FullPath;
53+
var containedModules = ContainedModules(folderModel);
54+
var initialSubFolder = folder.SubFolderName();
55+
return new RenameFolderModel(folder, containedModules, initialSubFolder);
56+
}
57+
58+
private static ICollection<ModuleDeclaration> ContainedModules(ICodeExplorerNode itemModel)
59+
{
60+
if (itemModel is CodeExplorerComponentViewModel componentModel)
61+
{
62+
var component = componentModel.Declaration;
63+
return component is ModuleDeclaration moduleDeclaration
64+
? new List<ModuleDeclaration> { moduleDeclaration }
65+
: new List<ModuleDeclaration>();
66+
}
67+
68+
return itemModel.Children
69+
.SelectMany(ContainedModules)
70+
.ToList();
71+
}
72+
73+
protected override void ValidateInitialModel(RenameFolderModel model)
74+
{
75+
var firstStaleAffectedModules = model.ModulesToMove
76+
.FirstOrDefault(module => _state.IsNewOrModified(module.QualifiedModuleName));
77+
if (firstStaleAffectedModules != null)
78+
{
79+
throw new AffectedModuleIsStaleException(firstStaleAffectedModules.QualifiedModuleName);
80+
}
81+
}
82+
83+
protected override void ValidateModel(RenameFolderModel model)
84+
{ }
85+
}
86+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Rubberduck.Interaction;
2+
3+
namespace Rubberduck.UI.Command.Refactorings.Notifiers
4+
{
5+
public class RenameFolderFailedNotifier : RefactoringFailureNotifierBase
6+
{
7+
public RenameFolderFailedNotifier(IMessageBox messageBox)
8+
: base(messageBox)
9+
{}
10+
11+
protected override string Caption => Resources.RubberduckUI.RenameDialog_Caption;
12+
}
13+
}

Rubberduck.Core/UI/Refactorings/RenameFolder/RenameFolderView.xaml.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
using System.Windows;
22
using Rubberduck.Refactorings;
3+
using Rubberduck.Refactorings.RenameFolder;
34

45
namespace Rubberduck.UI.Refactorings.RenameFolder
56
{
6-
public partial class RenameFolderView : IRefactoringView<RenameFolderView>
7+
public partial class RenameFolderView : IRefactoringView<RenameFolderModel>
78
{
89
public RenameFolderView()
910
{

0 commit comments

Comments
 (0)