Skip to content

Commit b9e6e70

Browse files
committed
Introduce IRefactoringUserInteraction
This moves interactive refactorings from using inheritance to deal with the interaction to composition. Consequently, the interaction can be reused elsewhere.
1 parent f17b1f7 commit b9e6e70

32 files changed

+324
-190
lines changed

Rubberduck.Core/UI/Command/Refactorings/CodePaneRefactorMoveToFolderCommand.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ private bool SpecializedEvaluateCanExecute(object parameter)
2929
{
3030
var target = GetTarget();
3131

32-
return target != null
33-
&& target is ModuleDeclaration
32+
return target is ModuleDeclaration
3433
&& !_state.IsNewOrModified(target.QualifiedModuleName);
3534
}
3635

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Rubberduck.Refactorings
2+
{
3+
public interface IRefactoringUserInteraction<TModel>
4+
where TModel : class, IRefactoringModel
5+
{
6+
TModel UserModifiedModel(TModel model);
7+
}
8+
}

Rubberduck.Refactorings/Abstract/InteractiveRefactoringBase.cs

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
using Rubberduck.VBEditor.Utility;
2-
using System;
32
using Rubberduck.Parsing.Symbols;
4-
using Rubberduck.Parsing.UIContext;
5-
using Rubberduck.Refactorings.Exceptions;
63

74
namespace Rubberduck.Refactorings
85
{
9-
public abstract class InteractiveRefactoringBase<TPresenter, TModel> : RefactoringBase
10-
where TPresenter : class, IRefactoringPresenter<TModel>
6+
public abstract class InteractiveRefactoringBase<TModel> : RefactoringBase
117
where TModel : class, IRefactoringModel
128
{
13-
private readonly Func<TModel, IDisposalActionContainer<TPresenter>> _presenterFactory;
9+
private readonly IRefactoringUserInteraction<TModel> _userInteraction;
1410

1511
protected InteractiveRefactoringBase(
1612
ISelectionProvider selectionProvider,
17-
IRefactoringPresenterFactory factory,
18-
IUiDispatcher uiDispatcher)
13+
IRefactoringUserInteraction<TModel> userInteraction)
1914
:base(selectionProvider)
2015
{
21-
Action<TPresenter> presenterDisposalAction = (TPresenter presenter) => uiDispatcher.Invoke(() => factory.Release(presenter));
22-
_presenterFactory = ((model) => DisposalActionContainer.Create(factory.Create<TPresenter, TModel>(model), presenterDisposalAction));
16+
_userInteraction = userInteraction;
2317
}
2418

2519
public override void Refactor(Declaration target)
@@ -29,27 +23,7 @@ public override void Refactor(Declaration target)
2923

3024
protected void Refactor(TModel initialModel)
3125
{
32-
var model = initialModel;
33-
if (model == null)
34-
{
35-
throw new InvalidRefactoringModelException();
36-
}
37-
38-
using (var presenterContainer = _presenterFactory(model))
39-
{
40-
var presenter = presenterContainer.Value;
41-
if (presenter == null)
42-
{
43-
throw new InvalidRefactoringPresenterException();
44-
}
45-
46-
model = presenter.Show();
47-
if (model == null)
48-
{
49-
throw new InvalidRefactoringModelException();
50-
}
51-
}
52-
26+
var model = _userInteraction.UserModifiedModel(initialModel);
5327
RefactorImpl(model);
5428
}
5529

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using Rubberduck.Parsing.UIContext;
3+
using Rubberduck.Refactorings.Exceptions;
4+
using Rubberduck.VBEditor.Utility;
5+
6+
namespace Rubberduck.Refactorings
7+
{
8+
public class RefactoringUserInteraction<TPresenter, TModel> : IRefactoringUserInteraction<TModel>
9+
where TPresenter : class, IRefactoringPresenter<TModel>
10+
where TModel : class, IRefactoringModel
11+
{
12+
private readonly Func<TModel, IDisposalActionContainer<TPresenter>> _presenterFactory;
13+
14+
public RefactoringUserInteraction(IRefactoringPresenterFactory factory, IUiDispatcher uiDispatcher)
15+
{
16+
Action<TPresenter> presenterDisposalAction = (TPresenter presenter) => uiDispatcher.Invoke(() => factory.Release(presenter));
17+
_presenterFactory = ((model) => DisposalActionContainer.Create(factory.Create<TPresenter, TModel>(model), presenterDisposalAction));
18+
}
19+
20+
public TModel UserModifiedModel(TModel model)
21+
{
22+
using (var presenterContainer = _presenterFactory(model))
23+
{
24+
var presenter = presenterContainer.Value;
25+
if (presenter == null)
26+
{
27+
throw new InvalidRefactoringPresenterException();
28+
}
29+
30+
model = presenter.Show();
31+
if (model == null)
32+
{
33+
throw new InvalidRefactoringModelException();
34+
}
35+
}
36+
37+
return model;
38+
}
39+
}
40+
}

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System.Linq;
22
using Rubberduck.Parsing.Rewriter;
33
using Rubberduck.Parsing.Symbols;
4-
using Rubberduck.Parsing.UIContext;
54
using Rubberduck.Parsing.VBA;
65
using Rubberduck.Refactorings.Exceptions;
76
using Rubberduck.VBEditor;
@@ -17,12 +16,7 @@ public enum EncapsulateFieldStrategy
1716
ConvertFieldsToUDTMembers
1817
}
1918

20-
public interface IEncapsulateFieldRefactoringTestAccess
21-
{
22-
EncapsulateFieldModel TestUserInteractionOnly(Declaration target, Func<EncapsulateFieldModel, EncapsulateFieldModel> userInteraction);
23-
}
24-
25-
public class EncapsulateFieldRefactoring : InteractiveRefactoringBase<IEncapsulateFieldPresenter, EncapsulateFieldModel>, IEncapsulateFieldRefactoringTestAccess
19+
public class EncapsulateFieldRefactoring : InteractiveRefactoringBase<EncapsulateFieldModel>
2620
{
2721
private readonly IDeclarationFinderProvider _declarationFinderProvider;
2822
private readonly ISelectedDeclarationProvider _selectedDeclarationProvider;
@@ -32,25 +26,18 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase<IEncapsula
3226
public EncapsulateFieldRefactoring(
3327
IDeclarationFinderProvider declarationFinderProvider,
3428
IIndenter indenter,
35-
IRefactoringPresenterFactory factory,
29+
RefactoringUserInteraction<IEncapsulateFieldPresenter, EncapsulateFieldModel> userInteraction,
3630
IRewritingManager rewritingManager,
3731
ISelectionProvider selectionProvider,
38-
ISelectedDeclarationProvider selectedDeclarationProvider,
39-
IUiDispatcher uiDispatcher)
40-
:base(selectionProvider, factory, uiDispatcher)
32+
ISelectedDeclarationProvider selectedDeclarationProvider)
33+
:base(selectionProvider, userInteraction)
4134
{
4235
_declarationFinderProvider = declarationFinderProvider;
4336
_selectedDeclarationProvider = selectedDeclarationProvider;
4437
_indenter = indenter;
4538
_rewritingManager = rewritingManager;
4639
}
4740

48-
public EncapsulateFieldModel TestUserInteractionOnly(Declaration target, Func<EncapsulateFieldModel, EncapsulateFieldModel> userInteraction)
49-
{
50-
var model = InitializeModel(target);
51-
return userInteraction(model);
52-
}
53-
5441
protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection)
5542
{
5643
var selectedDeclaration = _selectedDeclarationProvider.SelectedDeclaration(targetSelection);

Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,24 @@
22
using Rubberduck.Parsing;
33
using Rubberduck.Parsing.Grammar;
44
using Rubberduck.Parsing.Symbols;
5-
using Rubberduck.Parsing.UIContext;
65
using Rubberduck.Parsing.VBA;
76
using Rubberduck.Refactorings.Exceptions;
87
using Rubberduck.VBEditor;
98
using Rubberduck.VBEditor.Utility;
109

1110
namespace Rubberduck.Refactorings.ExtractInterface
1211
{
13-
public class ExtractInterfaceRefactoring : InteractiveRefactoringBase<IExtractInterfacePresenter, ExtractInterfaceModel>
12+
public class ExtractInterfaceRefactoring : InteractiveRefactoringBase<ExtractInterfaceModel>
1413
{
1514
private readonly IRefactoringAction<ExtractInterfaceModel> _refactoringAction;
1615
private readonly IDeclarationFinderProvider _declarationFinderProvider;
1716

1817
public ExtractInterfaceRefactoring(
1918
ExtractInterfaceRefactoringAction refactoringAction,
20-
IDeclarationFinderProvider declarationFinderProvider,
21-
IRefactoringPresenterFactory factory,
22-
ISelectionProvider selectionProvider,
23-
IUiDispatcher uiDispatcher)
24-
:base(selectionProvider, factory, uiDispatcher)
19+
IDeclarationFinderProvider declarationFinderProvider,
20+
RefactoringUserInteraction<IExtractInterfacePresenter, ExtractInterfaceModel> userInteraction,
21+
ISelectionProvider selectionProvider)
22+
:base(selectionProvider, userInteraction)
2523
{
2624
_refactoringAction = refactoringAction;
2725
_declarationFinderProvider = declarationFinderProvider;

Rubberduck.Refactorings/MoveFolder/MoveContainingFolderRefactoring.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Linq;
33
using Rubberduck.JunkDrawer.Extensions;
44
using Rubberduck.Parsing.Symbols;
5-
using Rubberduck.Parsing.UIContext;
65
using Rubberduck.Parsing.VBA;
76
using Rubberduck.Refactorings.Exceptions;
87
using Rubberduck.Refactorings.Exceptions.MoveToFolder;
@@ -11,7 +10,7 @@
1110

1211
namespace Rubberduck.Refactorings.MoveFolder
1312
{
14-
public class MoveContainingFolderRefactoring : InteractiveRefactoringBase<IMoveMultipleFoldersPresenter, MoveMultipleFoldersModel>
13+
public class MoveContainingFolderRefactoring : InteractiveRefactoringBase<MoveMultipleFoldersModel>
1514
{
1615
private readonly IRefactoringAction<MoveMultipleFoldersModel> _moveFoldersAction;
1716
private readonly ISelectedDeclarationProvider _selectedDeclarationProvider;
@@ -21,12 +20,11 @@ public class MoveContainingFolderRefactoring : InteractiveRefactoringBase<IMoveM
2120
public MoveContainingFolderRefactoring(
2221
MoveMultipleFoldersRefactoringAction moveFoldersAction,
2322
ISelectedDeclarationProvider selectedDeclarationProvider,
24-
ISelectionProvider selectionProvider,
25-
IRefactoringPresenterFactory factory,
26-
IUiDispatcher uiDispatcher,
23+
ISelectionProvider selectionProvider,
24+
RefactoringUserInteraction<IMoveMultipleFoldersPresenter, MoveMultipleFoldersModel> userInteraction,
2725
IDeclarationFinderProvider declarationFinderProvider,
2826
RubberduckParserState state)
29-
: base(selectionProvider, factory, uiDispatcher)
27+
: base(selectionProvider, userInteraction)
3028
{
3129
_moveFoldersAction = moveFoldersAction;
3230
_selectedDeclarationProvider = selectedDeclarationProvider;

Rubberduck.Refactorings/MoveToFolder/MoveToFolderRefactoring.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System.Collections.Generic;
22
using System.Linq;
33
using Rubberduck.Parsing.Symbols;
4-
using Rubberduck.Parsing.UIContext;
54
using Rubberduck.Parsing.VBA;
65
using Rubberduck.Refactorings.Exceptions;
76
using Rubberduck.Refactorings.Exceptions.MoveToFolder;
@@ -10,7 +9,7 @@
109

1110
namespace Rubberduck.Refactorings.MoveToFolder
1211
{
13-
public class MoveToFolderRefactoring : InteractiveRefactoringBase<IMoveMultipleToFolderPresenter, MoveMultipleToFolderModel>
12+
public class MoveToFolderRefactoring : InteractiveRefactoringBase<MoveMultipleToFolderModel>
1413
{
1514
private readonly IRefactoringAction<MoveMultipleToFolderModel> _moveToFolderAction;
1615
private readonly ISelectedDeclarationProvider _selectedDeclarationProvider;
@@ -20,10 +19,9 @@ public MoveToFolderRefactoring(
2019
MoveMultipleToFolderRefactoringAction moveToFolderAction,
2120
ISelectedDeclarationProvider selectedDeclarationProvider,
2221
ISelectionProvider selectionProvider,
23-
IRefactoringPresenterFactory factory,
24-
IUiDispatcher uiDispatcher,
22+
RefactoringUserInteraction<IMoveMultipleToFolderPresenter, MoveMultipleToFolderModel> userInteraction,
2523
RubberduckParserState state)
26-
: base(selectionProvider, factory, uiDispatcher)
24+
: base(selectionProvider, userInteraction)
2725
{
2826
_moveToFolderAction = moveToFolderAction;
2927
_selectedDeclarationProvider = selectedDeclarationProvider;

Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Linq;
22
using Rubberduck.Parsing.Symbols;
3-
using Rubberduck.Parsing.UIContext;
43
using Rubberduck.Parsing.VBA;
54
using Rubberduck.Refactorings.Exceptions;
65
using Rubberduck.Refactorings.Exceptions.RemoveParameter;
@@ -9,20 +8,19 @@
98

109
namespace Rubberduck.Refactorings.RemoveParameters
1110
{
12-
public class RemoveParametersRefactoring : InteractiveRefactoringBase<IRemoveParametersPresenter, RemoveParametersModel>
11+
public class RemoveParametersRefactoring : InteractiveRefactoringBase<RemoveParametersModel>
1312
{
1413
private readonly IRefactoringAction<RemoveParametersModel> _refactoringAction;
1514
private readonly IDeclarationFinderProvider _declarationFinderProvider;
1615
private readonly ISelectedDeclarationProvider _selectedDeclarationProvider;
1716

1817
public RemoveParametersRefactoring(
1918
RemoveParameterRefactoringAction refactoringAction,
20-
IDeclarationFinderProvider declarationFinderProvider,
21-
IRefactoringPresenterFactory factory,
19+
IDeclarationFinderProvider declarationFinderProvider,
20+
RefactoringUserInteraction<IRemoveParametersPresenter, RemoveParametersModel> userInteraction,
2221
ISelectionProvider selectionProvider,
23-
ISelectedDeclarationProvider selectedDeclarationProvider,
24-
IUiDispatcher uiDispatcher)
25-
:base(selectionProvider, factory, uiDispatcher)
22+
ISelectedDeclarationProvider selectedDeclarationProvider)
23+
:base(selectionProvider, userInteraction)
2624
{
2725
_refactoringAction = refactoringAction;
2826
_declarationFinderProvider = declarationFinderProvider;

Rubberduck.Refactorings/Rename/RenameRefactoring.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@
77
using Rubberduck.Refactorings.Exceptions.Rename;
88
using Rubberduck.VBEditor.ComManagement;
99
using Rubberduck.VBEditor.Utility;
10-
using Rubberduck.Parsing.UIContext;
1110

1211
namespace Rubberduck.Refactorings.Rename
1312
{
14-
public class RenameRefactoring : InteractiveRefactoringBase<IRenamePresenter, RenameModel>
13+
public class RenameRefactoring : InteractiveRefactoringBase<RenameModel>
1514
{
1615
private readonly IRefactoringAction<RenameModel> _refactoringAction;
1716
private readonly IDeclarationFinderProvider _declarationFinderProvider;
@@ -20,13 +19,12 @@ public class RenameRefactoring : InteractiveRefactoringBase<IRenamePresenter, Re
2019

2120
public RenameRefactoring(
2221
RenameRefactoringAction refactoringAction,
23-
IRefactoringPresenterFactory factory,
22+
RefactoringUserInteraction<IRenamePresenter, RenameModel> userInteraction,
2423
IDeclarationFinderProvider declarationFinderProvider,
2524
IProjectsProvider projectsProvider,
2625
ISelectionProvider selectionProvider,
27-
ISelectedDeclarationProvider selectedDeclarationProvider,
28-
IUiDispatcher uiDispatcher)
29-
: base(selectionProvider, factory, uiDispatcher)
26+
ISelectedDeclarationProvider selectedDeclarationProvider)
27+
: base(selectionProvider, userInteraction)
3028
{
3129
_refactoringAction = refactoringAction;
3230
_declarationFinderProvider = declarationFinderProvider;

0 commit comments

Comments
 (0)