1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . IO ;
3
4
using System . Linq ;
4
5
using System . Windows . Forms ;
5
6
using Rubberduck . Navigation . CodeExplorer ;
7
+ using Rubberduck . Parsing . VBA ;
6
8
using Rubberduck . Resources ;
7
9
using Rubberduck . VBEditor . Events ;
8
10
using Rubberduck . VBEditor . SafeComWrappers ;
@@ -24,15 +26,18 @@ public class ImportCommand : CodeExplorerCommandBase
24
26
private readonly IFileSystemBrowserFactory _dialogFactory ;
25
27
private readonly IList < string > _importableExtensions ;
26
28
private readonly string _filterExtensions ;
29
+ private readonly IParseManager _parseManager ;
27
30
28
31
public ImportCommand (
29
- IVBE vbe ,
30
- IFileSystemBrowserFactory dialogFactory ,
31
- IVbeEvents vbeEvents )
32
+ IVBE vbe ,
33
+ IFileSystemBrowserFactory dialogFactory ,
34
+ IVbeEvents vbeEvents ,
35
+ IParseManager parseManager )
32
36
: base ( vbeEvents )
33
37
{
34
38
_vbe = vbe ;
35
39
_dialogFactory = dialogFactory ;
40
+ _parseManager = parseManager ;
36
41
37
42
AddToCanExecuteEvaluation ( SpecialEvaluateCanExecute ) ;
38
43
@@ -44,6 +49,7 @@ public ImportCommand(
44
49
_filterExtensions = string . Join ( "; " , _importableExtensions . Select ( ext => $ "*.{ ext } ") ) ;
45
50
46
51
AddToCanExecuteEvaluation ( SpecialEvaluateCanExecute ) ;
52
+ AddToOnExecuteEvaluation ( SpecialEvaluateCanExecute ) ;
47
53
}
48
54
49
55
public sealed override IEnumerable < Type > ApplicableNodeTypes => ApplicableNodes ;
@@ -61,37 +67,42 @@ private bool ThereIsAValidActiveProject()
61
67
}
62
68
}
63
69
64
- protected override void OnExecute ( object parameter )
70
+ private ( IVBProject project , bool needsDisposal ) TargetProject ( object parameter )
65
71
{
66
- if ( ! CanExecute ( parameter ) )
72
+ var targetProject = TargetProjectFromParameter ( parameter ) ;
73
+ if ( targetProject != null )
67
74
{
68
- return ;
75
+ return ( targetProject , false ) ;
69
76
}
70
77
71
- var usingFreshProjectWrapper = false ;
72
- var project = ( parameter as CodeExplorerItemViewModel ) ? . Declaration ? . Project ;
78
+ targetProject = TargetProjectFromVbe ( ) ;
79
+
80
+ return ( targetProject , targetProject != null ) ;
81
+ }
82
+
83
+ private static IVBProject TargetProjectFromParameter ( object parameter )
84
+ {
85
+ return ( parameter as CodeExplorerItemViewModel ) ? . Declaration ? . Project ;
86
+ }
73
87
74
- if ( project == null )
88
+ private IVBProject TargetProjectFromVbe ( )
89
+ {
90
+ if ( _vbe . ProjectsCount == 1 )
75
91
{
76
- if ( _vbe . ProjectsCount == 1 )
77
- {
78
- usingFreshProjectWrapper = true ;
79
- using ( var projects = _vbe . VBProjects )
80
- {
81
- project = projects [ 1 ] ;
82
- }
83
- }
84
- else if ( ThereIsAValidActiveProject ( ) )
92
+ using ( var projects = _vbe . VBProjects )
85
93
{
86
- usingFreshProjectWrapper = true ;
87
- project = _vbe . ActiveVBProject ;
88
- }
89
- else
90
- {
91
- return ;
94
+ return projects [ 1 ] ;
92
95
}
93
96
}
94
97
98
+ var activeProject = _vbe . ActiveVBProject ;
99
+ return activeProject != null && ! activeProject . IsWrappingNullReference
100
+ ? activeProject
101
+ : null ;
102
+ }
103
+
104
+ protected virtual ICollection < string > FilesToImport ( object parameter )
105
+ {
95
106
using ( var dialog = _dialogFactory . CreateOpenFileDialog ( ) )
96
107
{
97
108
dialog . AddExtension = true ;
@@ -100,42 +111,71 @@ protected override void OnExecute(object parameter)
100
111
dialog . CheckPathExists = true ;
101
112
dialog . Multiselect = true ;
102
113
dialog . ShowHelp = false ;
103
- dialog . Title = RubberduckUI . ImportCommand_OpenDialog_Title ;
104
- dialog . Filter =
114
+ dialog . Title = FileDialogTitle ;
115
+ dialog . Filter =
105
116
$ "{ RubberduckUI . ImportCommand_OpenDialog_Filter_VBFiles } ({ _filterExtensions } )|{ _filterExtensions } |" +
106
117
$ "{ RubberduckUI . ImportCommand_OpenDialog_Filter_AllFiles } , (*.*)|*.*";
107
118
108
- if ( project == null || dialog . ShowDialog ( ) != DialogResult . OK )
119
+ if ( dialog . ShowDialog ( ) != DialogResult . OK )
109
120
{
110
- if ( usingFreshProjectWrapper )
111
- {
112
- project ? . Dispose ( ) ;
113
- }
114
- return ;
121
+ return new List < string > ( ) ;
115
122
}
116
123
117
- var fileExists = dialog . FileNames . Select ( s => s . Split ( '.' ) . Last ( ) ) ;
118
- if ( fileExists . Any ( fileExt => ! _importableExtensions . Contains ( fileExt ) ) )
124
+ var fileNames = dialog . FileNames ;
125
+ var fileExtensions = fileNames . Select ( Path . GetExtension ) ;
126
+ if ( fileExtensions . Any ( fileExt => ! _importableExtensions . Contains ( fileExt ) ) )
119
127
{
120
- if ( usingFreshProjectWrapper )
121
- {
122
- project . Dispose ( ) ;
123
- }
124
- return ;
128
+ return new List < string > ( ) ;
125
129
}
126
130
127
- foreach ( var filename in dialog . FileNames )
131
+ return fileNames ;
132
+ }
133
+ }
134
+
135
+ protected virtual string FileDialogTitle => RubberduckUI . ImportCommand_OpenDialog_Title ;
136
+
137
+ private void ImportFilesWithSuspension ( IEnumerable < string > filesToImport , IVBProject targetProject )
138
+ {
139
+ var suspensionResult = _parseManager . OnSuspendParser ( this , new [ ] { ParserState . Ready } , ( ) => ImportFiles ( filesToImport , targetProject ) ) ;
140
+ if ( suspensionResult != SuspensionResult . Completed )
141
+ {
142
+ Logger . Warn ( "File import failed due to suspension failure." ) ;
143
+ }
144
+ }
145
+
146
+ protected virtual void ImportFiles ( ICollection < string > filesToImport , IVBProject targetProject )
147
+ {
148
+ using ( var components = targetProject . VBComponents )
149
+ {
150
+ foreach ( var filename in filesToImport )
128
151
{
129
- using ( var components = project . VBComponents )
130
- {
131
- components . Import ( filename ) ;
132
- }
152
+ //We have to dispose the return value.
153
+ using ( components . Import ( filename ) ) { }
133
154
}
134
155
}
156
+ }
157
+
158
+ protected override void OnExecute ( object parameter )
159
+ {
160
+ var ( targetProject , targetProjectNeedsDisposal ) = TargetProject ( parameter ) ;
161
+
162
+ if ( targetProject == null )
163
+ {
164
+ return ;
165
+ }
166
+
167
+ var filesToImport = FilesToImport ( parameter ) ;
168
+
169
+ if ( ! filesToImport . Any ( ) )
170
+ {
171
+ return ;
172
+ }
173
+
174
+ ImportFilesWithSuspension ( filesToImport , targetProject ) ;
135
175
136
- if ( usingFreshProjectWrapper )
176
+ if ( targetProjectNeedsDisposal )
137
177
{
138
- project . Dispose ( ) ;
178
+ targetProject . Dispose ( ) ;
139
179
}
140
180
}
141
181
}
0 commit comments