diff --git a/PowerShellEditorServices.build.ps1 b/PowerShellEditorServices.build.ps1 index d0b4a7844..3bf93fe33 100644 --- a/PowerShellEditorServices.build.ps1 +++ b/PowerShellEditorServices.build.ps1 @@ -107,8 +107,8 @@ task SetupDotNet -Before Clean, Build, TestServerWinPS, TestServerPS7, TestServe $dotnetExePath = if ($script:IsNix) { "$dotnetPath/dotnet" } else { "$dotnetPath/dotnet.exe" } if (!(Test-Path $dotnetExePath)) { - # TODO: Test .NET 5 with PowerShell 7.1, and add that channel here. - Install-Dotnet -Channel '3.1','release/6.0.1xx-preview2' + # TODO: Test .NET 5 with PowerShell 7.1 + Install-Dotnet -Channel '3.1','5.0','6.0' } # This variable is used internally by 'dotnet' to know where it's installed @@ -174,6 +174,7 @@ task GetProductVersion -Before PackageModule, UploadArtifacts { task CreateBuildInfo -Before Build { $buildVersion = "" $buildOrigin = "Development" + $buildCommit = git rev-parse HEAD # Set build info fields on build platforms if ($env:TF_BUILD) { @@ -215,6 +216,7 @@ namespace Microsoft.PowerShell.EditorServices.Hosting { public static readonly string BuildVersion = "$buildVersion"; public static readonly string BuildOrigin = "$buildOrigin"; + public static readonly string BuildCommit = "$buildCommit"; public static readonly System.DateTime? BuildTime = System.DateTime.Parse("$buildTime", CultureInfo.InvariantCulture.DateTimeFormat); } } @@ -446,4 +448,4 @@ task UploadArtifacts -If ($null -ne $env:TF_BUILD) { } # The default task is to run the entire CI build -task . GetProductVersion, Clean, Build, Test, BuildCmdletHelp, PackageModule, UploadArtifacts +task . GetProductVersion, Clean, Build, Test, BuildCmdletHelp, PackageModule, UploadArtifacts \ No newline at end of file diff --git a/build.ps1 b/build.ps1 index 913e907e4..8dd89bb13 100644 --- a/build.ps1 +++ b/build.ps1 @@ -100,4 +100,4 @@ if ($Bootstrap) { if($Test) { Invoke-Build Test } -} +} \ No newline at end of file diff --git a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs index 018a70224..26b4b06d1 100644 --- a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs +++ b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs @@ -349,6 +349,7 @@ private EditorServicesConfig CreateConfigObject() var profile = (PSObject)GetVariableValue("profile"); var hostInfo = new HostInfo(HostName, HostProfileId, HostVersion); + var initialSessionState = Runspace.DefaultRunspace.InitialSessionState; var editorServicesConfig = new EditorServicesConfig(hostInfo, Host, SessionDetailsPath, bundledModulesPath, LogPath) { FeatureFlags = FeatureFlags, @@ -357,7 +358,7 @@ private EditorServicesConfig CreateConfigObject() AdditionalModules = AdditionalModules, LanguageServiceTransport = GetLanguageServiceTransport(), DebugServiceTransport = GetDebugServiceTransport(), - LanguageMode = Runspace.DefaultRunspace.SessionStateProxy.LanguageMode, + InitialSessionState = initialSessionState, ProfilePaths = new ProfilePathConfig { AllUsersAllHosts = GetProfilePathFromProfileObject(profile, ProfileUserKind.AllUsers, ProfileHostKind.AllHosts), diff --git a/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs b/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs index 5228ceced..79d49b83c 100644 --- a/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs +++ b/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Management.Automation; using System.Management.Automation.Host; +using System.Management.Automation.Runspaces; namespace Microsoft.PowerShell.EditorServices.Hosting { @@ -111,10 +112,9 @@ public EditorServicesConfig( public ProfilePathConfig ProfilePaths { get; set; } /// - /// The language mode inherited from the orginal PowerShell process. - /// This will be used when creating runspaces so that we honor the same language mode. + /// The InitialSessionState to use when creating runspaces. LanguageMode can be set here. /// - public PSLanguageMode LanguageMode { get; internal set; } + public InitialSessionState InitialSessionState { get; internal set; } public string StartupBanner { get; set; } = @" diff --git a/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs b/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs index b55d7a70a..59956df1a 100644 --- a/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs +++ b/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs @@ -269,6 +269,7 @@ private void LogHostInformation() == Build Details == - Editor Services version: {BuildInfo.BuildVersion} - Build origin: {BuildInfo.BuildOrigin} +- Build commit: {BuildInfo.BuildCommit} - Build time: {BuildInfo.BuildTime} "); diff --git a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs index b4dbf7c63..62998d340 100644 --- a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs +++ b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs @@ -288,7 +288,7 @@ private HostStartupInfo CreateHostStartupInfo() profilePaths, _config.FeatureFlags, _config.AdditionalModules, - _config.LanguageMode, + _config.InitialSessionState, _config.LogPath, (int)_config.LogLevel, consoleReplEnabled: _config.ConsoleRepl != ConsoleReplKind.None, diff --git a/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs b/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs index 5f3ae7647..06b51826a 100644 --- a/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs +++ b/src/PowerShellEditorServices/Hosting/HostStartupInfo.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Management.Automation; using System.Management.Automation.Host; +using System.Management.Automation.Runspaces; namespace Microsoft.PowerShell.EditorServices.Hosting { @@ -92,10 +93,10 @@ public sealed class HostStartupInfo public string LogPath { get; } /// - /// The language mode inherited from the orginal PowerShell process. - /// This will be used when creating runspaces so that we honor the same language mode. + /// The initialSessionState will be inherited from the orginal PowerShell process. + /// This will be used when creating runspaces so that we honor the same initialSessionState including allowed modules, cmdlets and language mode. /// - public PSLanguageMode LanguageMode { get; } + public InitialSessionState InitialSessionState { get; } /// /// The minimum log level of log events to be logged. @@ -130,7 +131,7 @@ public sealed class HostStartupInfo /// The path to the user specific profile. /// Flags of features to enable. /// Names or paths of additional modules to import. - /// The language mode inherited from the orginal PowerShell process. This will be used when creating runspaces so that we honor the same language mode. + /// The language mode inherited from the orginal PowerShell process. This will be used when creating runspaces so that we honor the same initialSessionState including allowed modules, cmdlets and language mode. /// The path to log to. /// The minimum log event level. /// Enable console if true. @@ -143,7 +144,7 @@ public HostStartupInfo( ProfilePathInfo profilePaths, IReadOnlyList featureFlags, IReadOnlyList additionalModules, - PSLanguageMode languageMode, + InitialSessionState initialSessionState, string logPath, int logLevel, bool consoleReplEnabled, @@ -156,7 +157,7 @@ public HostStartupInfo( ProfilePaths = profilePaths; FeatureFlags = featureFlags ?? Array.Empty(); AdditionalModules = additionalModules ?? Array.Empty(); - LanguageMode = languageMode; + InitialSessionState = initialSessionState; LogPath = logPath; LogLevel = logLevel; ConsoleReplEnabled = consoleReplEnabled; diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index 11c604ccc..30d251d66 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -86,7 +86,7 @@ internal static string GetUniqueIdFromDiagnostic(Diagnostic diagnostic) private readonly ConfigurationService _configurationService; - private readonly WorkspaceService _workplaceService; + private readonly WorkspaceService _workspaceService; private readonly int _analysisDelayMillis; @@ -115,7 +115,7 @@ public AnalysisService( _logger = loggerFactory.CreateLogger(); _languageServer = languageServer; _configurationService = configurationService; - _workplaceService = workspaceService; + _workspaceService = workspaceService; _analysisDelayMillis = 750; _mostRecentCorrectionsByFile = new ConcurrentDictionary(); _analysisEngineLazy = new Lazy(InstantiateAnalysisEngine); @@ -223,9 +223,10 @@ public async Task GetCommentHelpText(string functionText, string helpLoc /// /// The URI string of the file to get code actions for. /// A threadsafe readonly dictionary of the code actions of the particular file. - public async Task> GetMostRecentCodeActionsForFileAsync(ScriptFile scriptFile) + public async Task> GetMostRecentCodeActionsForFileAsync(DocumentUri uri) { - if (!_mostRecentCorrectionsByFile.TryGetValue(scriptFile, out CorrectionTableEntry corrections)) + if (!_workspaceService.TryGetFile(uri, out ScriptFile file) + || !_mostRecentCorrectionsByFile.TryGetValue(file, out CorrectionTableEntry corrections)) { return null; } @@ -334,7 +335,7 @@ private bool TryFindSettingsFile(out string settingsFilePath) return false; } - settingsFilePath = _workplaceService.ResolveWorkspacePath(configuredPath); + settingsFilePath = _workspaceService.ResolveWorkspacePath(configuredPath); if (settingsFilePath == null || !File.Exists(settingsFilePath)) @@ -349,7 +350,7 @@ private bool TryFindSettingsFile(out string settingsFilePath) private void ClearOpenFileMarkers() { - foreach (ScriptFile file in _workplaceService.GetOpenedFiles()) + foreach (ScriptFile file in _workspaceService.GetOpenedFiles()) { ClearMarkers(file); } @@ -455,10 +456,10 @@ private static DiagnosticSeverity MapDiagnosticSeverity(ScriptFileMarkerLevel ma { switch (markerLevel) { - case ScriptFileMarkerLevel.Error: return DiagnosticSeverity.Error; - case ScriptFileMarkerLevel.Warning: return DiagnosticSeverity.Warning; + case ScriptFileMarkerLevel.Error: return DiagnosticSeverity.Error; + case ScriptFileMarkerLevel.Warning: return DiagnosticSeverity.Warning; case ScriptFileMarkerLevel.Information: return DiagnosticSeverity.Information; - default: return DiagnosticSeverity.Error; + default: return DiagnosticSeverity.Error; }; } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index a6ea9ee45..29c3dcbbc 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -20,10 +20,15 @@ using Microsoft.PowerShell.EditorServices.Logging; using Microsoft.PowerShell.EditorServices.Services.PowerShellContext; using Microsoft.PowerShell.EditorServices.Utility; +using Microsoft.PowerShell.Commands; namespace Microsoft.PowerShell.EditorServices.Services { using System.Management.Automation; + using Microsoft.PowerShell.Commands; + using Microsoft.PowerShell.EditorServices.Handlers; + using Microsoft.PowerShell.EditorServices.Hosting; + using Microsoft.PowerShell.EditorServices.Services.PowerShellContext; /// /// Manages the lifetime and usage of a PowerShell session. @@ -83,7 +88,61 @@ static PowerShellContextService() private readonly Stack runspaceStack = new Stack(); private int isCommandLoopRestarterSet; + /// + /// This is the default function to use for tab expansion. + /// + private static string tabExpansionFunctionText = @" +<# Options include: + RelativeFilePaths - [bool] + Always resolve file paths using Resolve-Path -Relative. + The default is to use some heuristics to guess if relative or absolute is better. + + To customize your own custom options, pass a hashtable to CompleteInput, e.g. + return [System.Management.Automation.CommandCompletion]::CompleteInput($inputScript, $cursorColumn, + @{ RelativeFilePaths=$false } +#> + +[CmdletBinding(DefaultParameterSetName = 'ScriptInputSet')] +Param( + [Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 0)] + [string] $inputScript, + + [Parameter(ParameterSetName = 'ScriptInputSet', Position = 1)] + [int] $cursorColumn = $inputScript.Length, + + [Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 0)] + [System.Management.Automation.Language.Ast] $ast, + + [Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 1)] + [System.Management.Automation.Language.Token[]] $tokens, + + [Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 2)] + [System.Management.Automation.Language.IScriptPosition] $positionOfCursor, + + [Parameter(ParameterSetName = 'ScriptInputSet', Position = 2)] + [Parameter(ParameterSetName = 'AstInputSet', Position = 3)] + [Hashtable] $options = $null +) +End +{ + if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet') + { + return [System.Management.Automation.CommandCompletion]::CompleteInput( + <#inputScript#> $inputScript, + <#cursorColumn#> $cursorColumn, + <#options#> $options) + } + else + { + return [System.Management.Automation.CommandCompletion]::CompleteInput( + <#ast#> $ast, + <#tokens#> $tokens, + <#positionOfCursor#> $positionOfCursor, + <#options#> $options) + } +} + "; #endregion #region Properties @@ -214,26 +273,60 @@ public static PowerShellContextService Create( logger); logger.LogTrace("Creating initial PowerShell runspace"); - Runspace initialRunspace = PowerShellContextService.CreateRunspace(psHost, hostStartupInfo.LanguageMode); - powerShellContext.Initialize(hostStartupInfo.ProfilePaths, initialRunspace, true, hostUserInterface); - powerShellContext.ImportCommandsModuleAsync(); + if (hostStartupInfo.InitialSessionState.LanguageMode != PSLanguageMode.FullLanguage) + { + // Loading modules with ImportPSModule into the InitialSessionState because in constrained language mode there is no file system access. + // Import-Module provides the user with better errors, but may not be allowed within a constrained runspace + // ImportPSModule throws System.Management.Automation.DriveNotFoundException: 'Cannot find drive. A drive with the name 'C' does not exist.' + // ImportPSModulesFromPath loads the modules fine + if (hostStartupInfo.AdditionalModules.Count > 0) + hostStartupInfo.InitialSessionState.ImportPSModule(hostStartupInfo.AdditionalModules as string[]); + hostStartupInfo.InitialSessionState.ImportPSModulesFromPath(s_commandsModulePath); + // Autocomplete will fail if there isn't an implementation of TabExpansion2 + // The default TabExpansion2 implementation may not be available in a Constrained Runspace, therefore we check and add it if not. + // Note: Attempting to set the visibility of these commands to Private will cause Autocomplete to fail + if (!hostStartupInfo.InitialSessionState.Commands.Any(a => a.Name.ToLower() == "tabexpansion2")) + { + hostStartupInfo.InitialSessionState.Commands.Add(new SessionStateFunctionEntry("TabExpansion2", tabExpansionFunctionText)); + } + if (!hostStartupInfo.InitialSessionState.Commands.Any(a => a.Name == "Get-Command")) + { + hostStartupInfo.InitialSessionState.Commands.Add(new SessionStateCmdletEntry("Get-Command", typeof(GetCommandCommand), null)); + // PSES called Get-Command by its Module Qualified Syntax "Microsoft.PowerShell.Core\Get-Command", but this fails in a Constrained Runspace + // Adding an alias to Get-Command by its module qualified syntax allows PSES to call it by "Microsoft.PowerShell.Core\Get-Command". + hostStartupInfo.InitialSessionState.Commands.Add(new SessionStateAliasEntry(@"Microsoft.PowerShell.Core\Get-Command", "Get-Command", null)); + } + if (!hostStartupInfo.InitialSessionState.Commands.Any(a => a.Name == "Get-Help")) + { + hostStartupInfo.InitialSessionState.Commands.Add(new SessionStateCmdletEntry("Get-Help", typeof(GetHelpCommand), null)); + hostStartupInfo.InitialSessionState.Commands.Add(new SessionStateAliasEntry(@"Microsoft.PowerShell.Core\Get-Help", "Get-Help", null)); + } + } + + // DO NOT MOVE THIS. The initialization above has to get done before we create the initial runspace. + Runspace initialRunspace = PowerShellContextService.CreateRunspace(psHost, hostStartupInfo.InitialSessionState); + powerShellContext.Initialize(hostStartupInfo.ProfilePaths, initialRunspace, true, hostUserInterface); // TODO: This can be moved to the point after the $psEditor object // gets initialized when that is done earlier than LanguageServer.Initialize - foreach (string module in hostStartupInfo.AdditionalModules) + // When importing modules like this in a Constrained Runspace it fails with System.Management.Automation.DriveNotFoundException: 'Cannot find drive. A drive with the name 'C' does not exist.' + if (hostStartupInfo.InitialSessionState.LanguageMode == PSLanguageMode.FullLanguage) { - var command = - new PSCommand() - .AddCommand("Microsoft.PowerShell.Core\\Import-Module") - .AddParameter("Name", module); - + foreach (string module in hostStartupInfo.AdditionalModules) + { + var command = + new PSCommand() + .AddCommand("Microsoft.PowerShell.Core\\Import-Module") + .AddParameter("Name", module); + #pragma warning disable CS4014 - // This call queues the loading on the pipeline thread, so no need to await - powerShellContext.ExecuteCommandAsync( - command, - sendOutputToHost: false, - sendErrorToHost: true); + // This call queues the loading on the pipeline thread, so no need to await + powerShellContext.ExecuteCommandAsync( + command, + sendOutputToHost: false, + sendErrorToHost: true); #pragma warning restore CS4014 + } } return powerShellContext; @@ -258,29 +351,17 @@ public static Runspace CreateRunspace( var psHost = new EditorServicesPSHost(powerShellContext, hostDetails, hostUserInterface, logger); powerShellContext.ConsoleWriter = hostUserInterface; powerShellContext.ConsoleReader = hostUserInterface; - return CreateRunspace(psHost, hostDetails.LanguageMode); + return CreateRunspace(psHost, hostDetails.InitialSessionState); } /// /// /// /// The PSHost that will be used for this Runspace. - /// The language mode inherited from the orginal PowerShell process. This will be used when creating runspaces so that we honor the same language mode. + /// The initialSessionState inherited from the orginal PowerShell process. This will be used when creating runspaces so that we honor the same initialSessionState including allowed modules, cmdlets and language mode. /// - public static Runspace CreateRunspace(PSHost psHost, PSLanguageMode languageMode) + internal static Runspace CreateRunspace(PSHost psHost, InitialSessionState initialSessionState) { - InitialSessionState initialSessionState; - if (Environment.GetEnvironmentVariable("PSES_TEST_USE_CREATE_DEFAULT") == "1") { - initialSessionState = InitialSessionState.CreateDefault(); - } else { - initialSessionState = InitialSessionState.CreateDefault2(); - } - - // Create and initialize a new Runspace while honoring the LanguageMode of the original runspace - // that started PowerShell Editor Services. This is because the PowerShell Integrated Console - // should have the same LanguageMode of whatever is set by the system. - initialSessionState.LanguageMode = languageMode; - Runspace runspace = RunspaceFactory.CreateRunspace(psHost, initialSessionState); // Windows PowerShell must be hosted in STA mode @@ -424,7 +505,7 @@ public void Initialize( this.PromptContext = new LegacyReadLineContext(this); } - if (VersionUtils.IsWindows) + if (VersionUtils.IsWindows && initialRunspace.InitialSessionState.LanguageMode == PSLanguageMode.FullLanguage) { this.SetExecutionPolicy(); } @@ -626,7 +707,7 @@ public async Task> ExecuteCommandAsync( // via PowerShell eventing // 4. The command cannot be for a PSReadLine pipeline while we // are currently in a out of process runspace - var threadController = PromptNest.GetThreadController(); + var threadController = PromptNest?.GetThreadController(); if (!(threadController == null || !threadController.IsPipelineThread || threadController.IsCurrentThread() || @@ -745,7 +826,7 @@ public async Task> ExecuteCommandAsync( // Due to the following PowerShell bug, we can't just assign shell.Commands to psCommand // because PowerShell strips out CommandInfo: - // https://github.com/PowerShell/PowerShell/issues/12297 + // https://github.com/PowerShell/PowerShell/hostStartupInfo.InitialSessionStateues/12297 shell.Commands.Clear(); foreach (Command command in psCommand.Commands) { @@ -1082,7 +1163,7 @@ public async Task ExecuteScriptWithArgsAsync(string script, string arguments = n // . Any embedded single quotes are escaped. // If the provided path is already quoted, then File.Exists will not find it. // This keeps us from quoting an already quoted path. - // Related to issue #123. + // Related to hostStartupInfo.InitialSessionState Issue #123. if (File.Exists(script) || File.Exists(scriptAbsPath)) { // Dot-source the launched script path and single quote the path in case it includes @@ -2723,7 +2804,7 @@ Runspace IHostSupportsInteractiveSession.Runspace { get { - return this.CurrentRunspace.Runspace; + return this.CurrentRunspace?.Runspace; } } diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/CodeActionHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/CodeActionHandler.cs index 5c2529225..d550c0f7b 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/CodeActionHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/CodeActionHandler.cs @@ -31,7 +31,7 @@ public PsesCodeActionHandler(ILoggerFactory factory, AnalysisService analysisSer } protected override CodeActionRegistrationOptions CreateRegistrationOptions(CodeActionCapability capability, ClientCapabilities clientCapabilities) => new CodeActionRegistrationOptions - { + { // TODO: What do we do with the arguments? DocumentSelector = LspUtils.PowerShellDocumentSelector, CodeActionKinds = new CodeActionKind[] { CodeActionKind.QuickFix } @@ -52,13 +52,13 @@ public override async Task Handle(CodeActionParams { if (cancellationToken.IsCancellationRequested) { - _logger.LogDebug("CodeAction request canceled at range: {0}", request.Range); + _logger.LogDebug($"CodeAction request canceled at range: {request.Range}"); return Array.Empty(); } - // On Windows, VSCode still gives us file URIs like "file:///c%3a/...", so we need to escape them IReadOnlyDictionary corrections = await _analysisService.GetMostRecentCodeActionsForFileAsync( - _workspaceService.GetFile(request.TextDocument.Uri)).ConfigureAwait(false); + request.TextDocument.Uri) + .ConfigureAwait(false); if (corrections == null) { diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/CompletionHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/CompletionHandler.cs index 94f74a5b2..13b351098 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/CompletionHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/CompletionHandler.cs @@ -117,6 +117,12 @@ public async Task Handle(CompletionItem request, CancellationTok return request; } + // No details means the module hasn't been imported yet and Intellisense shouldn't import the module to get this info. + if (request.Detail is null) + { + return request; + } + try { await _completionResolveLock.WaitAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/FoldingRangeHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/FoldingRangeHandler.cs index effe2af58..fda42bf0f 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/FoldingRangeHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/FoldingRangeHandler.cs @@ -57,12 +57,13 @@ public override Task> Handle(FoldingRangeRequestParam re foreach (FoldingReference fold in TokenOperations.FoldableReferences(scriptFile.ScriptTokens).References) { - result.Add(new FoldingRange { - EndCharacter = fold.EndCharacter, - EndLine = fold.EndLine + endLineOffset, - Kind = fold.Kind, + result.Add(new FoldingRange + { + EndCharacter = fold.EndCharacter, + EndLine = fold.EndLine + endLineOffset, + Kind = fold.Kind, StartCharacter = fold.StartCharacter, - StartLine = fold.StartLine + StartLine = fold.StartLine }); } diff --git a/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs b/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs index 073c176cb..2f4ca781f 100644 --- a/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs +++ b/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs @@ -51,7 +51,7 @@ public override async Task Handle(DidChangeConfigurationParams request, Ca { LanguageServerSettingsWrapper incomingSettings = request.Settings.ToObject(); this._logger.LogTrace("Handling DidChangeConfiguration"); - if (incomingSettings == null) + if (incomingSettings == null || incomingSettings.Powershell == null) { this._logger.LogTrace("Incoming settings were null"); return await Unit.Task.ConfigureAwait(false); diff --git a/src/PowerShellEditorServices/Services/Workspace/WorkspaceService.cs b/src/PowerShellEditorServices/Services/Workspace/WorkspaceService.cs index 8ea3b77f5..0d6d95766 100644 --- a/src/PowerShellEditorServices/Services/Workspace/WorkspaceService.cs +++ b/src/PowerShellEditorServices/Services/Workspace/WorkspaceService.cs @@ -45,7 +45,7 @@ internal class WorkspaceService }; // An array of globs which includes everything. - private static readonly string[] s_psIncludeAllGlob = new [] + private static readonly string[] s_psIncludeAllGlob = new[] { "**/*" }; @@ -192,6 +192,7 @@ public bool TryGetFile(DocumentUri documentUri, out ScriptFile scriptFile) { // List supported schemes here case "file": + case "inmemory": case "untitled": case "vscode-notebook-cell": break; diff --git a/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs b/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs index c08142ebd..e5a4db0c9 100644 --- a/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs +++ b/test/PowerShellEditorServices.Test/PowerShellContextFactory.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.IO; using System.Management.Automation; +using System.Management.Automation.Runspaces; using System.Threading; using System.Threading.Tasks; @@ -44,7 +45,7 @@ public static PowerShellContextService Create(ILogger logger) TestProfilePaths, new List(), new List(), - PSLanguageMode.FullLanguage, + InitialSessionState.CreateDefault(), null, 0, consoleReplEnabled: false,