Skip to content

Commit 1cbeb60

Browse files
ipmo modules correctly and don't sync while debugging
1 parent f4fbcf1 commit 1cbeb60

File tree

2 files changed

+51
-39
lines changed

2 files changed

+51
-39
lines changed

src/PowerShellEditorServices/Language/AstOperations.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@
1212
using System.Threading;
1313
using System.Threading.Tasks;
1414
using System.Management.Automation.Language;
15-
using System.Management.Automation.Runspaces;
1615

1716
namespace Microsoft.PowerShell.EditorServices
1817
{
1918
using System.Management.Automation;
20-
using System.Management.Automation.Language;
2119

2220
/// <summary>
2321
/// Provides common operations for the syntax tree of a parsed script.
@@ -73,6 +71,7 @@ static public async Task<CommandCompletion> GetCompletionsAsync(
7371

7472
if (!RunspaceSynchronizer.IsReadyForEvents)
7573
{
74+
pwsh.Runspace.Name = "RunspaceSynchronizerTargetRunspace";
7675
RunspaceSynchronizer.InitializeRunspaces(powerShellContext.CurrentRunspace.Runspace, pwsh.Runspace);
7776
}
7877

@@ -97,7 +96,10 @@ static public async Task<CommandCompletion> GetCompletionsAsync(
9796

9897
var stopwatch = new Stopwatch();
9998

100-
if (powerShellContext.IsPSReadLineEnabled)
99+
// Static class members in Windows PowerShell had a thread synchronization issue.
100+
// This issue was fixed in PowerShell 6+ so we only use the new completions if PSReadLine is enabled
101+
// and we're running in .NET Core.
102+
if (powerShellContext.IsPSReadLineEnabled && Utils.IsNetCore)
101103
{
102104
stopwatch.Start();
103105

src/PowerShellEditorServices/Language/RunspaceSynchronizer.cs

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
//
55

66
using System;
7+
using System.Collections;
78
using System.Collections.Generic;
89
using System.Collections.ObjectModel;
910
using System.Management.Automation.Runspaces;
1011
using System.Reflection;
12+
using Microsoft.PowerShell.Commands;
1113

1214
namespace Microsoft.PowerShell.EditorServices
1315
{
@@ -23,6 +25,7 @@ namespace Microsoft.PowerShell.EditorServices
2325
/// </summary>
2426
public class RunspaceSynchronizer
2527
{
28+
private static readonly Version versionZero = new Version(0, 0);
2629
// Determines whether the HandleRunspaceStateChange event should attempt to sync the runspaces.
2730
private static bool SourceActionEnabled = false;
2831

@@ -71,9 +74,9 @@ public class RunspaceSynchronizer
7174
public static void InitializeRunspaces(Runspace runspaceSource, Runspace runspaceTarget)
7275
{
7376
sourceRunspace = runspaceSource;
74-
sourceEngineIntrinsics = ReflectionUtils.GetEngineIntrinsics(sourceRunspace);
77+
sourceEngineIntrinsics = sourceRunspace.GetEngineIntrinsics();
7578
targetRunspace = runspaceTarget;
76-
targetEngineIntrinsics = ReflectionUtils.GetEngineIntrinsics(runspaceTarget);
79+
targetEngineIntrinsics = runspaceTarget.GetEngineIntrinsics();
7780
IsReadyForEvents = true;
7881

7982
sourceEngineIntrinsics.Events.SubscribeEvent(
@@ -104,15 +107,15 @@ public static void Activate()
104107

105108
private static void HandleRunspaceStateChange(object sender, PSEventArgs args)
106109
{
107-
if (!SourceActionEnabled)
110+
if (!SourceActionEnabled || sourceRunspace.Debugger.IsActive)
108111
{
109112
return;
110113
}
111114

112115
SourceActionEnabled = false;
113116

114117
var newOrChangedModules = new List<PSModuleInfo>();
115-
List<PSModuleInfo> modules = ReflectionUtils.GetModules(sourceRunspace);
118+
List<PSModuleInfo> modules = sourceRunspace.GetModules();
116119
foreach (PSModuleInfo module in modules)
117120
{
118121
if (moduleCache.Add(module))
@@ -150,8 +153,16 @@ private static void HandleRunspaceStateChange(object sender, PSEventArgs args)
150153
{
151154
if(moduleInfo.Path != null)
152155
{
156+
string nameParameterValue = moduleInfo.Path;
157+
// If the version is greater than zero, the module info was probably imported by the psd1 or module base.
158+
// If so, we can just import from the module base which is the root of the module folder.
159+
if (moduleInfo.Version > versionZero)
160+
{
161+
nameParameterValue = moduleInfo.ModuleBase;
162+
}
163+
153164
pwsh.AddCommand("Import-Module")
154-
.AddParameter("Name", moduleInfo.Path)
165+
.AddParameter("Name", nameParameterValue)
155166
.AddParameter("Force")
156167
.AddStatement();
157168
}
@@ -172,40 +183,39 @@ private static void HandleRunspaceStateChange(object sender, PSEventArgs args)
172183
}
173184

174185
#endregion
186+
}
175187

176-
// A collection of helper methods that use Reflection in some form.
177-
private class ReflectionUtils
178-
{
179-
private static BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default;
188+
internal static class RunspaceExtensions
189+
{
190+
private static BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default;
180191

181-
// Gets the modules loaded in a runspace.
182-
// This exists in runspace.ExecutionContext.Modules.GetModule(string[] patterns, bool all)
183-
internal static List<PSModuleInfo> GetModules(Runspace runspace)
184-
{
185-
var executionContext = typeof(Runspace)
186-
.GetProperty("ExecutionContext", bindingFlags)
187-
.GetValue(runspace);
188-
var ModuleIntrinsics = executionContext.GetType()
189-
.GetProperty("Modules", bindingFlags)
190-
.GetValue(executionContext);
191-
var modules = ModuleIntrinsics.GetType()
192-
.GetMethod("GetModules", bindingFlags, null, new Type[] { typeof(string[]), typeof(bool) }, null)
193-
.Invoke(ModuleIntrinsics, new object[] { new string[] { "*" }, false }) as List<PSModuleInfo>;
194-
return modules;
195-
}
192+
// Gets the modules loaded in a runspace.
193+
// This exists in runspace.ExecutionContext.Modules.GetModule(string[] patterns, bool all)
194+
internal static List<PSModuleInfo> GetModules(this Runspace runspace)
195+
{
196+
var executionContext = typeof(Runspace)
197+
.GetProperty("ExecutionContext", bindingFlags)
198+
.GetValue(runspace);
199+
var ModuleIntrinsics = executionContext.GetType()
200+
.GetProperty("Modules", bindingFlags)
201+
.GetValue(executionContext);
202+
var modules = ModuleIntrinsics.GetType()
203+
.GetMethod("GetModules", bindingFlags, null, new Type[] { typeof(string[]), typeof(bool) }, null)
204+
.Invoke(ModuleIntrinsics, new object[] { new string[] { "*" }, false }) as List<PSModuleInfo>;
205+
return modules;
206+
}
196207

197-
// Gets the engine intrinsics object on a Runspace.
198-
// This exists in runspace.ExecutionContext.EngineIntrinsics.
199-
internal static EngineIntrinsics GetEngineIntrinsics(Runspace runspace)
200-
{
201-
var executionContext = typeof(Runspace)
202-
.GetProperty("ExecutionContext", bindingFlags)
203-
.GetValue(runspace);
204-
var engineIntrinsics = executionContext.GetType()
205-
.GetProperty("EngineIntrinsics", bindingFlags)
206-
.GetValue(executionContext) as EngineIntrinsics;
207-
return engineIntrinsics;
208-
}
208+
// Gets the engine intrinsics object on a Runspace.
209+
// This exists in runspace.ExecutionContext.EngineIntrinsics.
210+
internal static EngineIntrinsics GetEngineIntrinsics(this Runspace runspace)
211+
{
212+
var executionContext = typeof(Runspace)
213+
.GetProperty("ExecutionContext", bindingFlags)
214+
.GetValue(runspace);
215+
var engineIntrinsics = executionContext.GetType()
216+
.GetProperty("EngineIntrinsics", bindingFlags)
217+
.GetValue(executionContext) as EngineIntrinsics;
218+
return engineIntrinsics;
209219
}
210220
}
211221

0 commit comments

Comments
 (0)