Skip to content

Commit 6113d06

Browse files
committed
Introduce the ReplaceProjectContentsFromFilesCommand
It removes all reimportable components from the project before import of the selected files. Asking for user confirmation is still to be implemented.
1 parent afbac3d commit 6113d06

File tree

4 files changed

+175
-4
lines changed

4 files changed

+175
-4
lines changed

Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ private void ExecuteRemoveCommand(object param)
386386
public CommandBase ExpandAllSubnodesCommand { get; }
387387
public ImportCommand ImportCommand { get; set; }
388388
public UpdateFromFilesCommand UpdateFromFilesCommand { get; set; }
389+
public ReplaceProjectContentsFromFilesCommand ReplaceProjectContentsFromFilesCommand { get; set; }
389390
public ExportCommand ExportCommand { get; set; }
390391
public ExportAllCommand ExportAllCommand { get; set; }
391392
public DeleteCommand DeleteCommand { get; set; }
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System.Collections.Generic;
2+
using Rubberduck.Parsing.VBA;
3+
using Rubberduck.VBEditor.Events;
4+
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
5+
6+
namespace Rubberduck.UI.CodeExplorer.Commands
7+
{
8+
public class ReplaceProjectContentsFromFilesCommand : ImportCommand
9+
{
10+
public ReplaceProjectContentsFromFilesCommand(
11+
IVBE vbe,
12+
IFileSystemBrowserFactory dialogFactory,
13+
IVbeEvents vbeEvents,
14+
IParseManager parseManager)
15+
:base(vbe, dialogFactory, vbeEvents, parseManager)
16+
{}
17+
18+
protected override void ImportFiles(ICollection<string> filesToImport, IVBProject targetProject)
19+
{
20+
//TODO: Ask for confirmation to delete the project contents and replace them with the selected modules.
21+
22+
RemoveReimportableComponents(targetProject);
23+
base.ImportFiles(filesToImport, targetProject);
24+
}
25+
26+
private void RemoveReimportableComponents(IVBProject project)
27+
{
28+
var importableComponentTypes = ComponentTypeForExtension.Values;
29+
using(var components = project.VBComponents)
30+
{
31+
foreach(var component in components)
32+
{
33+
using (component)
34+
{
35+
if (importableComponentTypes.Contains(component.Type))
36+
{
37+
components.Remove(component);
38+
}
39+
}
40+
}
41+
}
42+
}
43+
}
44+
}

RubberduckTests/CodeExplorer/CodeExplorerViewModelTests.cs

Lines changed: 124 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
using Rubberduck.UI.Command.ComCommands;
1515
using RubberduckTests.Mocks;
1616
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
17-
using Rubberduck.Parsing.Symbols;
1817

1918
namespace RubberduckTests.CodeExplorer
2019
{
@@ -592,12 +591,133 @@ public void UpdateFromFile_Cancel()
592591
{
593592
const string path = @"C:\Users\Rubberduck\Desktop\StdModule1.bas";
594593

595-
using (var explorer = new MockedCodeExplorer(ProjectType.HostProject)
594+
using (var explorer = new MockedCodeExplorer(
595+
ProjectType.HostProject,
596+
("TestModule", ComponentType.StandardModule, string.Empty))
596597
.ConfigureOpenDialog(new[] { path }, DialogResult.Cancel)
597598
.SelectFirstProject())
598599
{
599-
explorer.ExecuteUpdateFromFileCommand(filename => filename);
600-
explorer.VbComponents.Verify(c => c.Import(path), Times.Never);
600+
explorer.ExecuteUpdateFromFileCommand(filename => "TestModule");
601+
explorer.VbComponents.Verify(c => c.Import(It.IsAny<string>()), Times.Never);
602+
explorer.VbComponents.Verify(c => c.Remove(It.IsAny<IVBComponent>()), Times.Never);
603+
}
604+
}
605+
606+
[Category("Code Explorer")]
607+
[Test]
608+
public void ReplaceProjectContentsFromFiles_Imports()
609+
{
610+
const string path = @"C:\Users\Rubberduck\Desktop\StdModule1.bas";
611+
612+
using (var explorer = new MockedCodeExplorer(
613+
ProjectType.HostProject,
614+
("TestModule", ComponentType.StandardModule, string.Empty))
615+
.ConfigureOpenDialog(new[] { path }, DialogResult.OK)
616+
.SelectFirstProject())
617+
{
618+
explorer.ExecuteReplaceProjectContentsFromFilesCommand();
619+
explorer.VbComponents.Verify(c => c.Import(path), Times.Once);
620+
}
621+
}
622+
623+
[Category("Code Explorer")]
624+
[Test]
625+
public void ReplaceProjectContentsFromFiles_ImportsMultiple()
626+
{
627+
const string path1 = @"C:\Users\Rubberduck\Desktop\StdModule1.bas";
628+
const string path2 = @"C:\Users\Rubberduck\Desktop\Class1.cls";
629+
630+
using (var explorer = new MockedCodeExplorer(
631+
ProjectType.HostProject,
632+
("TestModule", ComponentType.StandardModule, string.Empty))
633+
.ConfigureOpenDialog(new[] { path1, path2 }, DialogResult.OK)
634+
.SelectFirstProject())
635+
{
636+
explorer.ExecuteReplaceProjectContentsFromFilesCommand();
637+
explorer.VbComponents.Verify(c => c.Import(path1), Times.Once);
638+
explorer.VbComponents.Verify(c => c.Import(path2), Times.Once);
639+
}
640+
}
641+
642+
[Category("Code Explorer")]
643+
[Test]
644+
public void ReplaceProjectContentsFromFiles_RemovesReimportableComponents()
645+
{
646+
const string path = @"C:\Users\Rubberduck\Desktop\StdModule1.bas";
647+
648+
using (var explorer = new MockedCodeExplorer(
649+
ProjectType.HostProject,
650+
("TestModule", ComponentType.StandardModule, string.Empty),
651+
("TestClass", ComponentType.ClassModule, string.Empty),
652+
("TestUserForm", ComponentType.UserForm, string.Empty))
653+
.ConfigureOpenDialog(new[] { path }, DialogResult.OK)
654+
.SelectFirstProject())
655+
{
656+
explorer.ExecuteReplaceProjectContentsFromFilesCommand();
657+
658+
var modulesNames = explorer
659+
.VbComponents
660+
.Object
661+
.Select(component => component.Name)
662+
.ToList();
663+
664+
explorer.VbComponents.Verify(c => c.Remove(It.IsAny<IVBComponent>()), Times.Exactly(3));
665+
666+
Assert.IsFalse(modulesNames.Contains("TestModule"));
667+
Assert.IsFalse(modulesNames.Contains("TestClass"));
668+
Assert.IsFalse(modulesNames.Contains("TestUserForm"));
669+
670+
//This depends on the setup of Import on the VBComponents mock, which determines the component name from the filename.
671+
Assert.IsTrue(modulesNames.Contains("StdModule1"));
672+
}
673+
}
674+
675+
[Category("Code Explorer")]
676+
[Test]
677+
public void ReplaceProjectContentsFromFiles_DoesNotRemoveNonReimportableComponents()
678+
{
679+
const string path = @"C:\Users\Rubberduck\Desktop\StdModule1.bas";
680+
681+
using (var explorer = new MockedCodeExplorer(
682+
ProjectType.HostProject,
683+
("TestModule", ComponentType.StandardModule, string.Empty),
684+
("TestDocument", ComponentType.Document, string.Empty))
685+
.ConfigureOpenDialog(new[] { path }, DialogResult.OK)
686+
.SelectFirstProject())
687+
{
688+
explorer.ExecuteReplaceProjectContentsFromFilesCommand();
689+
690+
var modulesNames = explorer
691+
.VbComponents
692+
.Object
693+
.Select(component => component.Name)
694+
.ToList();
695+
696+
explorer.VbComponents.Verify(c => c.Remove(It.IsAny<IVBComponent>()), Times.Once);
697+
698+
Assert.IsTrue(modulesNames.Contains("TestDocument"));
699+
Assert.IsFalse(modulesNames.Contains("TestModule"));
700+
701+
//This depends on the setup of Import on the VBComponents mock, which determines the component name from the filename.
702+
Assert.IsTrue(modulesNames.Contains("StdModule1"));
703+
}
704+
}
705+
706+
[Category("Code Explorer")]
707+
[Test]
708+
public void ReplaceProjectContentsFromFiles_Cancel()
709+
{
710+
const string path = @"C:\Users\Rubberduck\Desktop\StdModule1.bas";
711+
712+
using (var explorer = new MockedCodeExplorer(
713+
ProjectType.HostProject,
714+
("TestModule", ComponentType.StandardModule, string.Empty))
715+
.ConfigureOpenDialog(new[] { path }, DialogResult.Cancel)
716+
.SelectFirstProject())
717+
{
718+
explorer.ExecuteReplaceProjectContentsFromFilesCommand();
719+
explorer.VbComponents.Verify(c => c.Import(It.IsAny<string>()), Times.Never);
720+
explorer.VbComponents.Verify(c => c.Remove(It.IsAny<IVBComponent>()), Times.Never);
601721
}
602722
}
603723

RubberduckTests/CodeExplorer/MockedCodeExplorer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ public void ExecuteUpdateFromFileCommand(Func<string, string> fileNameToModuleNa
384384
ViewModel.UpdateFromFilesCommand.Execute(ViewModel.SelectedItem);
385385
}
386386

387+
public void ExecuteReplaceProjectContentsFromFilesCommand()
388+
{
389+
ViewModel.ReplaceProjectContentsFromFilesCommand = new ReplaceProjectContentsFromFilesCommand(Vbe.Object, BrowserFactory.Object, VbeEvents.Object, State);
390+
ViewModel.ReplaceProjectContentsFromFilesCommand.Execute(ViewModel.SelectedItem);
391+
}
392+
387393
public void ExecuteExportAllCommand()
388394
{
389395
if (ViewModel.ExportAllCommand is null)

0 commit comments

Comments
 (0)