diff --git a/PSReadLine/Prediction.cs b/PSReadLine/Prediction.cs index dfa1f1cce..fc790f948 100644 --- a/PSReadLine/Prediction.cs +++ b/PSReadLine/Prediction.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; +using System.Reflection; using System.Threading.Tasks; using System.Management.Automation; +using System.Management.Automation.Runspaces; using System.Management.Automation.Language; using System.Management.Automation.Subsystem.Prediction; using System.Diagnostics.CodeAnalysis; @@ -16,8 +18,42 @@ namespace Microsoft.PowerShell { public partial class PSConsoleReadLine { - private const string PSReadLine = "PSReadLine"; - private static PredictionClient s_predictionClient = new(PSReadLine, PredictionClientKind.Terminal); + private const string DefaultName = "PSReadLine"; + private static readonly PredictionClient s_predictionClient = new(DefaultName, PredictionClientKind.Terminal); + private static PropertyInfo s_pCurrentLocation = null; + + /// + /// Initialize the objects for those public settable properties newly added to + /// . + /// + private static void InitializePropertyInfo() + { + Version ver = typeof(PSObject).Assembly.GetName().Version; + if (ver.Major < 7 || ver.Minor < 4) + { + return; + } + + Type pcType = typeof(PredictionClient); + // Property added in 7.4 + s_pCurrentLocation = pcType.GetProperty("CurrentLocation"); + } + + /// + /// New public settable properties may be added to the type as it evolves to + /// offer more helpful context information. We dynamically set those properties here to avoid any backward + /// compatibility issues. + /// + private static void UpdatePredictionClient(Runspace runspace, EngineIntrinsics engineIntrinsics) + { + // Set the current location if the 'CurrentLocation' property exists. + if (s_pCurrentLocation is not null) + { + // Set the current location if it's a local Runspace. Otherwise, set it to null. + object path = runspace.RunspaceIsRemote ? null : engineIntrinsics.SessionState.Path.CurrentLocation; + s_pCurrentLocation.SetValue(s_predictionClient, path); + } + } // Stub helper methods so prediction can be mocked [ExcludeFromCodeCoverage] diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index 33b65d06d..3b042a448 100644 --- a/PSReadLine/ReadLine.cs +++ b/PSReadLine/ReadLine.cs @@ -652,6 +652,7 @@ static PSConsoleReadLine() { _singleton = new PSConsoleReadLine(); _viRegister = new ViRegister(_singleton); + InitializePropertyInfo(); } private PSConsoleReadLine() @@ -682,13 +683,9 @@ private PSConsoleReadLine() { } } - if (hostName == null) - { - hostName = PSReadLine; - } bool usingLegacyConsole = _console is PlatformWindows.LegacyWin32Console; - _options = new PSConsoleReadLineOptions(hostName, usingLegacyConsole); + _options = new PSConsoleReadLineOptions(hostName ?? DefaultName, usingLegacyConsole); _prediction = new Prediction(this); SetDefaultBindings(_options.EditMode); } @@ -698,6 +695,9 @@ private void Initialize(Runspace runspace, EngineIntrinsics engineIntrinsics) _engineIntrinsics = engineIntrinsics; _runspace = runspace; + // Update the client instance per every call to PSReadLine. + UpdatePredictionClient(runspace, engineIntrinsics); + if (!_delayedOneTimeInitCompleted) { DelayedOneTimeInitialize();