Skip to content

Commit c080d18

Browse files
authored
Merge pull request #354 from PowerShell/kapilmb/fix-formatter-crash
Fix crash caused when formatting document
2 parents b6c10be + ed1841a commit c080d18

File tree

1 file changed

+33
-77
lines changed

1 file changed

+33
-77
lines changed

src/PowerShellEditorServices/Analysis/AnalysisService.cs

Lines changed: 33 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System;
88
using System.Linq;
99
using System.Management.Automation.Runspaces;
10-
using System.Threading;
1110
using System.Threading.Tasks;
1211
using Microsoft.PowerShell.EditorServices.Console;
1312
using System.Management.Automation;
@@ -28,6 +27,15 @@ public class AnalysisService : IDisposable
2827
private const int NumRunspaces = 2;
2928
private RunspacePool analysisRunspacePool;
3029
private PSModuleInfo scriptAnalyzerModuleInfo;
30+
31+
private bool hasScriptAnalyzerModule
32+
{
33+
get
34+
{
35+
return scriptAnalyzerModuleInfo != null;
36+
}
37+
}
38+
3139
private string[] activeRules;
3240
private string settingsPath;
3341

@@ -102,7 +110,10 @@ public AnalysisService(IConsoleHost consoleHost, string settingsPath = null)
102110
try
103111
{
104112
this.SettingsPath = settingsPath;
113+
114+
scriptAnalyzerModuleInfo = FindPSScriptAnalyzerModule();
105115
var sessionState = InitialSessionState.CreateDefault2();
116+
sessionState.ImportPSModulesFromPath(scriptAnalyzerModuleInfo.ModuleBase);
106117

107118
// runspacepool takes care of queuing commands for us so we do not
108119
// need to worry about executing concurrent commands
@@ -115,7 +126,7 @@ public AnalysisService(IConsoleHost consoleHost, string settingsPath = null)
115126
this.analysisRunspacePool.Open();
116127

117128
ActiveRules = IncludedRules.ToArray();
118-
InitializePSScriptAnalyzer();
129+
EnumeratePSScriptAnalyzerRules();
119130
}
120131
catch (Exception e)
121132
{
@@ -158,7 +169,7 @@ public async Task<ScriptFileMarker[]> GetSemanticMarkersAsync(ScriptFile file, H
158169
public IEnumerable<string> GetPSScriptAnalyzerRules()
159170
{
160171
List<string> ruleNames = new List<string>();
161-
if (scriptAnalyzerModuleInfo != null)
172+
if (hasScriptAnalyzerModule)
162173
{
163174
var ruleObjects = InvokePowerShell("Get-ScriptAnalyzerRule", new Dictionary<string, object>());
164175
foreach (var rule in ruleObjects)
@@ -213,7 +224,7 @@ private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
213224
string[] rules,
214225
TSettings settings) where TSettings : class
215226
{
216-
if (this.scriptAnalyzerModuleInfo != null
227+
if (hasScriptAnalyzerModule
217228
&& file.IsAnalysisEnabled
218229
&& (typeof(TSettings) == typeof(string) || typeof(TSettings) == typeof(Hashtable))
219230
&& (rules != null || settings != null))
@@ -228,12 +239,10 @@ private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
228239
}
229240
}
230241

231-
private void FindPSScriptAnalyzer()
242+
private static PSModuleInfo FindPSScriptAnalyzerModule()
232243
{
233244
using (var ps = System.Management.Automation.PowerShell.Create())
234245
{
235-
ps.RunspacePool = this.analysisRunspacePool;
236-
237246
ps.AddCommand("Get-Module")
238247
.AddParameter("ListAvailable")
239248
.AddParameter("Name", "PSScriptAnalyzer");
@@ -245,65 +254,29 @@ private void FindPSScriptAnalyzer()
245254
ps.AddCommand("Select-Object")
246255
.AddParameter("First", 1);
247256

248-
var modules = ps.Invoke();
249-
250-
var psModule = modules == null ? null : modules.FirstOrDefault();
251-
if (psModule != null)
257+
var modules = ps.Invoke<PSModuleInfo>();
258+
var psModuleInfo = modules == null ? null : modules.FirstOrDefault();
259+
if (psModuleInfo != null)
252260
{
253-
scriptAnalyzerModuleInfo = psModule.ImmediateBaseObject as PSModuleInfo;
254261
Logger.Write(
255262
LogLevel.Normal,
256263
string.Format(
257264
"PSScriptAnalyzer found at {0}",
258-
scriptAnalyzerModuleInfo.Path));
259-
}
260-
else
261-
{
262-
Logger.Write(
263-
LogLevel.Normal,
264-
"PSScriptAnalyzer module was not found.");
265-
}
266-
}
267-
}
268-
269-
private async Task<bool> ImportPSScriptAnalyzerAsync()
270-
{
271-
if (scriptAnalyzerModuleInfo != null)
272-
{
273-
var module =
274-
await InvokePowerShellAsync(
275-
"Import-Module",
276-
new Dictionary<string, object>
277-
{
278-
{ "ModuleInfo", scriptAnalyzerModuleInfo },
279-
{ "PassThru", true },
280-
});
281-
282-
if (module.Count() == 0)
283-
{
284-
this.scriptAnalyzerModuleInfo = null;
285-
Logger.Write(LogLevel.Warning,
286-
String.Format("Cannot Import PSScriptAnalyzer: {0}"));
265+
psModuleInfo.Path));
287266

288-
return false;
267+
return psModuleInfo;
289268
}
290-
else
291-
{
292-
Logger.Write(LogLevel.Normal,
293-
String.Format(
294-
"Successfully imported PSScriptAnalyzer {0}",
295-
scriptAnalyzerModuleInfo.Version));
296269

297-
return true;
298-
}
270+
Logger.Write(
271+
LogLevel.Normal,
272+
"PSScriptAnalyzer module was not found.");
273+
return null;
299274
}
300-
301-
return false;
302275
}
303276

304277
private void EnumeratePSScriptAnalyzerRules()
305278
{
306-
if (scriptAnalyzerModuleInfo != null)
279+
if (hasScriptAnalyzerModule)
307280
{
308281
var rules = GetPSScriptAnalyzerRules();
309282
var sb = new StringBuilder();
@@ -317,31 +290,14 @@ private void EnumeratePSScriptAnalyzerRules()
317290
}
318291
}
319292

320-
private void InitializePSScriptAnalyzer()
321-
{
322-
FindPSScriptAnalyzer();
323-
324-
List<Task> importTasks = new List<Task>();
325-
for (int i = 0; i < NumRunspaces; i++)
326-
{
327-
importTasks.Add(
328-
ImportPSScriptAnalyzerAsync());
329-
}
330-
331-
// Wait for the import requests to complete or fail
332-
Task.WaitAll(importTasks.ToArray());
333-
334-
EnumeratePSScriptAnalyzerRules();
335-
}
336-
337-
private async Task<IEnumerable<PSObject>> GetDiagnosticRecordsAsync<TSettings>(
293+
private async Task<PSObject[]> GetDiagnosticRecordsAsync<TSettings>(
338294
ScriptFile file,
339295
string[] rules,
340296
TSettings settings) where TSettings : class
341297
{
342-
IEnumerable<PSObject> diagnosticRecords = Enumerable.Empty<PSObject>();
298+
var diagnosticRecords = new PSObject[0];
343299

344-
if (this.scriptAnalyzerModuleInfo != null
300+
if (hasScriptAnalyzerModule
345301
&& (typeof(TSettings) == typeof(string)
346302
|| typeof(TSettings) == typeof(Hashtable)))
347303
{
@@ -375,14 +331,14 @@ private async Task<IEnumerable<PSObject>> GetDiagnosticRecordsAsync<TSettings>(
375331
return diagnosticRecords;
376332
}
377333

378-
private IEnumerable<PSObject> InvokePowerShell(string command, IDictionary<string, object> paramArgMap)
334+
private PSObject[] InvokePowerShell(string command, IDictionary<string, object> paramArgMap)
379335
{
380336
var task = InvokePowerShellAsync(command, paramArgMap);
381337
task.Wait();
382338
return task.Result;
383339
}
384340

385-
private async Task<IEnumerable<PSObject>> InvokePowerShellAsync(string command, IDictionary<string, object> paramArgMap)
341+
private async Task<PSObject[]> InvokePowerShellAsync(string command, IDictionary<string, object> paramArgMap)
386342
{
387343
using (var powerShell = System.Management.Automation.PowerShell.Create())
388344
{
@@ -396,10 +352,10 @@ private async Task<IEnumerable<PSObject>> InvokePowerShellAsync(string command,
396352
var result = await Task.Factory.FromAsync(powerShell.BeginInvoke(), powerShell.EndInvoke);
397353
if (result == null)
398354
{
399-
return Enumerable.Empty<PSObject>();
355+
return new PSObject[0];
400356
}
401357

402-
return result;
358+
return result.ToArray(); ;
403359
}
404360
}
405361

0 commit comments

Comments
 (0)