diff --git a/.editorconfig b/.editorconfig index 1dd0a2a9e..335885163 100644 --- a/.editorconfig +++ b/.editorconfig @@ -21,6 +21,3 @@ trim_trailing_whitespace = true [*.{ps1xml,props,xml,yaml}] indent_size = 2 - -# CA1303: Do not pass literals as localized parameters -dotnet_diagnostic.CA1303.severity = none diff --git a/PowerShellEditorServices.build.ps1 b/PowerShellEditorServices.build.ps1 index 612ba27bf..be7be6c1c 100644 --- a/PowerShellEditorServices.build.ps1 +++ b/PowerShellEditorServices.build.ps1 @@ -186,13 +186,15 @@ task CreateBuildInfo -Before Build { [string]$buildTime = [datetime]::Now.ToString("s", [System.Globalization.CultureInfo]::InvariantCulture) $buildInfoContents = @" +using System.Globalization; + namespace Microsoft.PowerShell.EditorServices.Hosting { public static class BuildInfo { public static readonly string BuildVersion = "$buildVersion"; public static readonly string BuildOrigin = "$buildOrigin"; - public static readonly System.DateTime? BuildTime = System.DateTime.Parse("$buildTime"); + public static readonly System.DateTime? BuildTime = System.DateTime.Parse("$buildTime", CultureInfo.InvariantCulture.DateTimeFormat); } } "@ diff --git a/src/PowerShellEditorServices.Hosting/BuildInfo.cs b/src/PowerShellEditorServices.Hosting/BuildInfo.cs index 386ac95a3..f516c8a8e 100644 --- a/src/PowerShellEditorServices.Hosting/BuildInfo.cs +++ b/src/PowerShellEditorServices.Hosting/BuildInfo.cs @@ -1,9 +1,11 @@ +using System.Globalization; + namespace Microsoft.PowerShell.EditorServices.Hosting { public static class BuildInfo { public static readonly string BuildVersion = ""; public static readonly string BuildOrigin = ""; - public static readonly System.DateTime? BuildTime = System.DateTime.Parse("2019-12-06T21:43:41"); + public static readonly System.DateTime? BuildTime = System.DateTime.Parse("2019-12-06T21:43:41", CultureInfo.InvariantCulture.DateTimeFormat); } } diff --git a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs index 09d643e3b..0630c33f1 100644 --- a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs +++ b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs @@ -12,6 +12,7 @@ using System.Reflection; using SMA = System.Management.Automation; using Microsoft.PowerShell.EditorServices.Hosting; +using System.Globalization; #if DEBUG using System.Diagnostics; @@ -25,6 +26,7 @@ namespace Microsoft.PowerShell.EditorServices.Commands /// /// The Start-EditorServices command, the conventional entrypoint for PowerShell Editor Services. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "Cmdlet parameters can be arrays")] [Cmdlet(VerbsLifecycle.Start, "EditorServices", DefaultParameterSetName = "NamedPipe")] public sealed class StartEditorServicesCommand : PSCmdlet { @@ -200,6 +202,7 @@ protected override void BeginProcessing() StartLogging(); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Uses ThrowTerminatingError() instead")] protected override void EndProcessing() { _logger.Log(PsesLogLevel.Diagnostic, "Beginning EndProcessing block"); @@ -264,7 +267,7 @@ private void StartLogging() if (File.Exists(logPath)) { int randomInt = new Random().Next(); - logPath = Path.Combine(logDirPath, $"StartEditorServices-temp{randomInt.ToString("X")}.log"); + logPath = Path.Combine(logDirPath, $"StartEditorServices-temp{randomInt.ToString("X", CultureInfo.InvariantCulture.NumberFormat)}.log"); } var fileLogger = StreamLogger.CreateWithNewFile(logPath); diff --git a/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs b/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs index 707feb543..3993ff752 100644 --- a/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs +++ b/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs @@ -27,9 +27,10 @@ namespace Microsoft.PowerShell.EditorServices.Hosting /// public sealed class EditorServicesLoader : IDisposable { - private const int Net461Version = 394254; #if !CoreCLR + private const int Net461Version = 394254; + private static readonly string s_psesBaseDirPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); #endif @@ -369,6 +370,7 @@ private string GetOSArchitecture() return RuntimeInformation.OSArchitecture.ToString(); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2208:Instantiate argument exceptions correctly", Justification = "Checking user-defined configuration")] private void ValidateConfiguration() { _logger.Log(PsesLogLevel.Diagnostic, "Validating configuration"); diff --git a/src/PowerShellEditorServices.Hosting/GlobalSuppressions.cs b/src/PowerShellEditorServices.Hosting/GlobalSuppressions.cs new file mode 100644 index 000000000..10fd0c205 --- /dev/null +++ b/src/PowerShellEditorServices.Hosting/GlobalSuppressions.cs @@ -0,0 +1,6 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "PSES is not localized", Scope = "module")] diff --git a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs index ecac2a3e0..dba26d2e7 100644 --- a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs +++ b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs @@ -115,11 +115,17 @@ private async Task CreateEditorServicesAndRunUntilShutdown() debugServerCreation = CreateDebugServerWithLanguageServerAsync(languageServer, usePSReadLine: _config.ConsoleRepl == ConsoleReplKind.PSReadLine); } +#pragma warning disable CS4014 + // We don't need to wait for this to start, since we instead wait for it to complete later languageServer.StartAsync(); +#pragma warning restore CS4014 if (creatingDebugServer) { +#pragma warning disable CS4014 + // We don't need to wait for this to start, since we instead wait for it to complete later StartDebugServer(debugServerCreation); +#pragma warning restore CS4014 } await languageServer.WaitForShutdown().ConfigureAwait(false); @@ -155,7 +161,11 @@ private async Task StartDebugServer(Task debugServerCreation) } _logger.Log(PsesLogLevel.Diagnostic, "Starting debug server"); + +#pragma warning disable CS4014 + // No need to await, since we just want to kick it off debugServer.StartAsync(); +#pragma warning restore CS4014 } private Task RestartDebugServerAsync(PsesDebugServer debugServer, bool usePSReadLine) diff --git a/src/PowerShellEditorServices.Hosting/Internal/PsesLoadContext.cs b/src/PowerShellEditorServices.Hosting/Internal/PsesLoadContext.cs index 7ed121e05..ed2583df7 100644 --- a/src/PowerShellEditorServices.Hosting/Internal/PsesLoadContext.cs +++ b/src/PowerShellEditorServices.Hosting/Internal/PsesLoadContext.cs @@ -54,6 +54,7 @@ protected override Assembly Load(AssemblyName assemblyName) return null; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Best effort; we must not throw if we fail")] private void TrySetName(string name) { try diff --git a/src/PowerShellEditorServices/GlobalSuppressions.cs b/src/PowerShellEditorServices/GlobalSuppressions.cs new file mode 100644 index 000000000..10fd0c205 --- /dev/null +++ b/src/PowerShellEditorServices/GlobalSuppressions.cs @@ -0,0 +1,6 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "PSES is not localized", Scope = "module")] diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs index 3eeefb041..421c29b78 100644 --- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs +++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs @@ -117,7 +117,7 @@ public async Task StartAsync() .WithHandler(); logger.LogInformation("Handlers added"); - }); + }).ConfigureAwait(false); } public void Dispose() @@ -129,7 +129,7 @@ public void Dispose() public async Task WaitForShutdown() { - await _serverStopped.Task; + await _serverStopped.Task.ConfigureAwait(false); } #region Events diff --git a/src/PowerShellEditorServices/Server/PsesLanguageServer.cs b/src/PowerShellEditorServices/Server/PsesLanguageServer.cs index b2ffff59f..1ad1eb081 100644 --- a/src/PowerShellEditorServices/Server/PsesLanguageServer.cs +++ b/src/PowerShellEditorServices/Server/PsesLanguageServer.cs @@ -110,10 +110,10 @@ public async Task StartAsync() { await serviceProvider.GetService().SetWorkingDirectoryAsync( workspaceService.WorkspacePath, - isPathAlreadyEscaped: false); + isPathAlreadyEscaped: false).ConfigureAwait(false); } }); - }); + }).ConfigureAwait(false); _serverStart.SetResult(true); } @@ -124,8 +124,8 @@ await serviceProvider.GetService().SetWorkingDirectory /// A task that completes when the server is shut down. public async Task WaitForShutdown() { - await _serverStart.Task; - await LanguageServer.WaitForExit; + await _serverStart.Task.ConfigureAwait(false); + await LanguageServer.WaitForExit.ConfigureAwait(false); } } } diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index a44e73427..75ab0c5ba 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -17,6 +17,7 @@ using System.Threading; using System.Collections.Concurrent; using Microsoft.PowerShell.EditorServices.Services.TextDocument; +using Microsoft.PowerShell.EditorServices.Utility; namespace Microsoft.PowerShell.EditorServices.Services { @@ -53,9 +54,9 @@ public class AnalysisService : IDisposable /// /// An empty diagnostic result to return when a script fails analysis. /// - private static readonly PSObject[] s_emptyDiagnosticResult = new PSObject[0]; + private static readonly PSObject[] s_emptyDiagnosticResult = Array.Empty(); - private static readonly string[] s_emptyGetRuleResult = new string[0]; + private static readonly string[] s_emptyGetRuleResult = Array.Empty(); private static CancellationTokenSource s_existingRequestCancellation; @@ -171,6 +172,7 @@ private AnalysisService( /// public static AnalysisService Create(ConfigurationService configurationService, ILanguageServer languageServer, ILogger logger) { + Validate.IsNotNull(nameof(configurationService), configurationService); string settingsPath = configurationService.CurrentSettings.ScriptAnalysis.SettingsPath; try { @@ -260,6 +262,8 @@ public static Hashtable GetCommentHelpRuleSettings( /// public static Hashtable GetPSSASettingsHashtable(IDictionary ruleSettingsMap) { + Validate.IsNotNull(nameof(ruleSettingsMap), ruleSettingsMap); + var hashtable = new Hashtable(); var ruleSettingsHashtable = new Hashtable(); @@ -280,9 +284,9 @@ public static Hashtable GetPSSASettingsHashtable(IDictionary /// /// The ScriptFile which will be analyzed for semantic markers. /// An array of ScriptFileMarkers containing semantic analysis results. - public async Task> GetSemanticMarkersAsync(ScriptFile file) + public Task> GetSemanticMarkersAsync(ScriptFile file) { - return await GetSemanticMarkersAsync(file, ActiveRules, SettingsPath); + return GetSemanticMarkersAsync(file, ActiveRules, SettingsPath); } /// @@ -291,9 +295,9 @@ public async Task> GetSemanticMarkersAsync(ScriptFile fil /// The ScriptFile to be analyzed. /// ScriptAnalyzer settings /// - public async Task> GetSemanticMarkersAsync(ScriptFile file, Hashtable settings) + public Task> GetSemanticMarkersAsync(ScriptFile file, Hashtable settings) { - return await GetSemanticMarkersAsync(file, null, settings); + return GetSemanticMarkersAsync(file, null, settings); } /// @@ -302,11 +306,11 @@ public async Task> GetSemanticMarkersAsync(ScriptFile fil /// The script content to be analyzed. /// ScriptAnalyzer settings /// - public async Task> GetSemanticMarkersAsync( + public Task> GetSemanticMarkersAsync( string scriptContent, Hashtable settings) { - return await GetSemanticMarkersAsync(scriptContent, null, settings); + return GetSemanticMarkersAsync(scriptContent, null, settings); } /// @@ -358,7 +362,7 @@ public async Task FormatAsync( argsDict.Add("Range", rangeList); } - PowerShellResult result = await InvokePowerShellAsync("Invoke-Formatter", argsDict); + PowerShellResult result = await InvokePowerShellAsync("Invoke-Formatter", argsDict).ConfigureAwait(false); if (result == null) { @@ -403,7 +407,7 @@ private async Task> GetSemanticMarkersAsync( return await GetSemanticMarkersAsync( file.Contents, rules, - settings); + settings).ConfigureAwait(false); } else { @@ -420,7 +424,7 @@ private async Task> GetSemanticMarkersAsync( if ((typeof(TSettings) == typeof(string) || typeof(TSettings) == typeof(Hashtable)) && (rules != null || settings != null)) { - var scriptFileMarkers = await GetDiagnosticRecordsAsync(scriptContent, rules, settings); + var scriptFileMarkers = await GetDiagnosticRecordsAsync(scriptContent, rules, settings).ConfigureAwait(false); return scriptFileMarkers.Select(ScriptFileMarker.FromDiagnosticRecord).ToList(); } else @@ -496,48 +500,42 @@ private async Task GetDiagnosticRecordsAsync( string[] rules, TSettings settings) where TSettings : class { - var diagnosticRecords = s_emptyDiagnosticResult; - // When a new, empty file is created there are by definition no issues. // Furthermore, if you call Invoke-ScriptAnalyzer with an empty ScriptDefinition // it will generate a ParameterBindingValidationException. - if (string.IsNullOrEmpty(scriptContent)) + if (string.IsNullOrEmpty(scriptContent) + || !(typeof(TSettings) == typeof(string) || typeof(TSettings) == typeof(Hashtable))) { - return diagnosticRecords; + return s_emptyDiagnosticResult; } - if (typeof(TSettings) == typeof(string) || typeof(TSettings) == typeof(Hashtable)) + //Use a settings file if one is provided, otherwise use the default rule list. + string settingParameter; + object settingArgument; + if (settings != null) { - //Use a settings file if one is provided, otherwise use the default rule list. - string settingParameter; - object settingArgument; - if (settings != null) - { - settingParameter = "Settings"; - settingArgument = settings; - } - else - { - settingParameter = "IncludeRule"; - settingArgument = rules; - } - - PowerShellResult result = await InvokePowerShellAsync( - "Invoke-ScriptAnalyzer", - new Dictionary - { - { "ScriptDefinition", scriptContent }, - { settingParameter, settingArgument }, - // We ignore ParseErrors from PSSA because we already send them when we parse the file. - { "Severity", new [] { ScriptFileMarkerLevel.Error, ScriptFileMarkerLevel.Information, ScriptFileMarkerLevel.Warning }} - }); - - diagnosticRecords = result?.Output; + settingParameter = "Settings"; + settingArgument = settings; + } + else + { + settingParameter = "IncludeRule"; + settingArgument = rules; } - _logger.LogDebug(String.Format("Found {0} violations", diagnosticRecords.Count())); - - return diagnosticRecords; + PowerShellResult result = await InvokePowerShellAsync( + "Invoke-ScriptAnalyzer", + new Dictionary + { + { "ScriptDefinition", scriptContent }, + { settingParameter, settingArgument }, + // We ignore ParseErrors from PSSA because we already send them when we parse the file. + { "Severity", new [] { ScriptFileMarkerLevel.Error, ScriptFileMarkerLevel.Information, ScriptFileMarkerLevel.Warning }} + }).ConfigureAwait(false); + + var diagnosticResults = result?.Output ?? s_emptyDiagnosticResult; + _logger.LogDebug(String.Format("Found {0} violations", diagnosticResults.Length)); + return diagnosticResults; } private PowerShellResult InvokePowerShell(string command, IDictionary paramArgMap = null) @@ -587,7 +585,7 @@ private async Task InvokePowerShellAsync(string command, IDict return InvokePowerShell(command, paramArgMap); }); - return await task; + return await task.ConfigureAwait(false); } /// @@ -746,7 +744,7 @@ await Task.Factory.StartNew( s_existingRequestCancellation.Token), CancellationToken.None, TaskCreationOptions.None, - TaskScheduler.Default); + TaskScheduler.Default).ConfigureAwait(false); } private async Task DelayThenInvokeDiagnosticsAsync( @@ -759,7 +757,7 @@ private async Task DelayThenInvokeDiagnosticsAsync( // analyzing the provided list of files try { - await Task.Delay(delayMilliseconds, cancellationToken); + await Task.Delay(delayMilliseconds, cancellationToken).ConfigureAwait(false); } catch (TaskCanceledException) { @@ -787,7 +785,7 @@ private async Task DelayThenInvokeDiagnosticsAsync( List semanticMarkers = null; if (isScriptAnalysisEnabled) { - semanticMarkers = await GetSemanticMarkersAsync(scriptFile); + semanticMarkers = await GetSemanticMarkersAsync(scriptFile).ConfigureAwait(false); } else { @@ -884,7 +882,7 @@ public async Task> GetMostRecentCo return null; } - await fileCorrectionsEntry.fileLock.WaitAsync(); + await fileCorrectionsEntry.fileLock.WaitAsync().ConfigureAwait(false); // We must copy the dictionary for thread safety var corrections = new Dictionary(fileCorrectionsEntry.corrections.Count); try diff --git a/src/PowerShellEditorServices/Services/CodeLens/ReferencesCodeLensProvider.cs b/src/PowerShellEditorServices/Services/CodeLens/ReferencesCodeLensProvider.cs index 68c36aa1f..75244caff 100644 --- a/src/PowerShellEditorServices/Services/CodeLens/ReferencesCodeLensProvider.cs +++ b/src/PowerShellEditorServices/Services/CodeLens/ReferencesCodeLensProvider.cs @@ -20,7 +20,7 @@ namespace Microsoft.PowerShell.EditorServices.CodeLenses /// internal class ReferencesCodeLensProvider : ICodeLensProvider { - private static readonly Location[] s_emptyLocationArray = new Location[0]; + private static readonly Location[] s_emptyLocationArray = Array.Empty(); /// /// The document symbol provider to supply symbols to generate the code lenses. diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs b/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs index 66e106730..d2f5a7a7a 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs @@ -186,7 +186,7 @@ public async Task SetLineBreakpointsAsync( { if (clearExisting) { - await this.ClearBreakpointsInFileAsync(scriptFile); + await this.ClearBreakpointsInFileAsync(scriptFile).ConfigureAwait(false); } PSCommand psCommand = null; @@ -240,7 +240,7 @@ public async Task SetLineBreakpointsAsync( if (psCommand != null) { IEnumerable configuredBreakpoints = - await this.powerShellContext.ExecuteCommandAsync(psCommand); + await this.powerShellContext.ExecuteCommandAsync(psCommand).ConfigureAwait(false); // The order in which the breakpoints are returned is significant to the // VSCode client and should match the order in which they are passed in. @@ -252,9 +252,9 @@ public async Task SetLineBreakpointsAsync( { resultBreakpointDetails = await dscBreakpoints.SetLineBreakpointsAsync( - this.powerShellContext, + powerShellContext, escapedScriptPath, - breakpoints); + breakpoints).ConfigureAwait(false); } return resultBreakpointDetails.ToArray(); @@ -274,7 +274,7 @@ public async Task SetCommandBreakpointsAsync( if (clearExisting) { - await this.ClearCommandBreakpointsAsync(); + await this.ClearCommandBreakpointsAsync().ConfigureAwait(false); } if (breakpoints.Length > 0) @@ -303,7 +303,7 @@ public async Task SetCommandBreakpointsAsync( } IEnumerable configuredBreakpoints = - await this.powerShellContext.ExecuteCommandAsync(psCommand); + await this.powerShellContext.ExecuteCommandAsync(psCommand).ConfigureAwait(false); // The order in which the breakpoints are returned is significant to the // VSCode client and should match the order in which they are passed in. @@ -386,7 +386,7 @@ public VariableDetailsBase[] GetVariables(int variableReferenceId) if ((variableReferenceId < 0) || (variableReferenceId >= this.variables.Count)) { logger.LogWarning($"Received request for variableReferenceId {variableReferenceId} that is out of range of valid indices."); - return new VariableDetailsBase[0]; + return Array.Empty(); } VariableDetailsBase parentVariable = this.variables[variableReferenceId]; @@ -405,7 +405,7 @@ public VariableDetailsBase[] GetVariables(int variableReferenceId) } else { - childVariables = new VariableDetailsBase[0]; + childVariables = Array.Empty(); } return childVariables; @@ -508,7 +508,7 @@ await this.powerShellContext.ExecuteCommandAsync( psCommand, errorMessages, false, - false); + false).ConfigureAwait(false); // Check if PowerShell's evaluation of the expression resulted in an error. object psobject = results.FirstOrDefault(); @@ -527,7 +527,7 @@ await this.powerShellContext.ExecuteCommandAsync( // OK, now we have a PS object from the supplied value string (expression) to assign to a variable. // Get the variable referenced by variableContainerReferenceId and variable name. VariableContainerDetails variableContainer = null; - await this.debugInfoHandle.WaitAsync(); + await this.debugInfoHandle.WaitAsync().ConfigureAwait(false); try { variableContainer = (VariableContainerDetails)this.variables[variableContainerReferenceId]; @@ -551,7 +551,7 @@ await this.powerShellContext.ExecuteCommandAsync( else { // Determine which stackframe's local scope the variable is in. - StackFrameDetails[] stackFrames = await this.GetStackFramesAsync(); + StackFrameDetails[] stackFrames = await this.GetStackFramesAsync().ConfigureAwait(false); for (int i = 0; i < stackFrames.Length; i++) { var stackFrame = stackFrames[i]; @@ -576,7 +576,7 @@ await this.powerShellContext.ExecuteCommandAsync( psCommand.AddParameter("Name", name.TrimStart('$')); psCommand.AddParameter("Scope", scope); - IEnumerable result = await this.powerShellContext.ExecuteCommandAsync(psCommand, sendErrorToHost: false); + IEnumerable result = await this.powerShellContext.ExecuteCommandAsync(psCommand, sendErrorToHost: false).ConfigureAwait(false); PSVariable psVariable = result.FirstOrDefault(); if (psVariable == null) { @@ -608,7 +608,7 @@ await this.powerShellContext.ExecuteCommandAsync( await this.powerShellContext.ExecuteCommandAsync( psCommand, errorMessages, - sendErrorToHost: false); + sendErrorToHost: false).ConfigureAwait(false); EngineIntrinsics executionContext = getExecContextResults.OfType().FirstOrDefault(); @@ -652,7 +652,7 @@ public async Task EvaluateExpressionAsync( await this.powerShellContext.ExecuteScriptStringAsync( expressionString, false, - writeResultAsOutput); + writeResultAsOutput).ConfigureAwait(false); // Since this method should only be getting invoked in the debugger, // we can assume that Out-String will be getting used to format results @@ -708,7 +708,7 @@ internal StackFrameDetails[] GetStackFrames(CancellationToken cancellationToken) internal async Task GetStackFramesAsync() { - await this.debugInfoHandle.WaitAsync(); + await this.debugInfoHandle.WaitAsync().ConfigureAwait(false); try { return this.stackFrameDetails; @@ -721,7 +721,7 @@ internal async Task GetStackFramesAsync() internal async Task GetStackFramesAsync(CancellationToken cancellationToken) { - await this.debugInfoHandle.WaitAsync(cancellationToken); + await this.debugInfoHandle.WaitAsync(cancellationToken).ConfigureAwait(false); try { return this.stackFrameDetails; @@ -764,7 +764,7 @@ public async Task ClearAllBreakpointsAsync() psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Get-PSBreakpoint"); psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Remove-PSBreakpoint"); - await this.powerShellContext.ExecuteCommandAsync(psCommand); + await this.powerShellContext.ExecuteCommandAsync(psCommand).ConfigureAwait(false); } catch (Exception e) { @@ -787,7 +787,7 @@ private async Task ClearBreakpointsInFileAsync(ScriptFile scriptFile) psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Remove-PSBreakpoint"); psCommand.AddParameter("Id", breakpoints.Select(b => b.Id).ToArray()); - await this.powerShellContext.ExecuteCommandAsync(psCommand); + await this.powerShellContext.ExecuteCommandAsync(psCommand).ConfigureAwait(false); // Clear the existing breakpoints list for the file breakpoints.Clear(); @@ -802,12 +802,12 @@ private async Task ClearCommandBreakpointsAsync() psCommand.AddParameter("Type", "Command"); psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Remove-PSBreakpoint"); - await this.powerShellContext.ExecuteCommandAsync(psCommand); + await this.powerShellContext.ExecuteCommandAsync(psCommand).ConfigureAwait(false); } private async Task FetchStackFramesAndVariablesAsync(string scriptNameOverride) { - await this.debugInfoHandle.WaitAsync(); + await this.debugInfoHandle.WaitAsync().ConfigureAwait(false); try { this.nextVariableId = VariableDetailsBase.FirstVariableId; @@ -820,8 +820,8 @@ private async Task FetchStackFramesAndVariablesAsync(string scriptNameOverride) // Must retrieve global/script variales before stack frame variables // as we check stack frame variables against globals. - await FetchGlobalAndScriptVariablesAsync(); - await FetchStackFramesAsync(scriptNameOverride); + await FetchGlobalAndScriptVariablesAsync().ConfigureAwait(false); + await FetchStackFramesAsync(scriptNameOverride).ConfigureAwait(false); } finally { @@ -833,10 +833,10 @@ private async Task FetchGlobalAndScriptVariablesAsync() { // Retrieve globals first as script variable retrieval needs to search globals. this.globalScopeVariables = - await FetchVariableContainerAsync(VariableContainerDetails.GlobalScopeName, null); + await FetchVariableContainerAsync(VariableContainerDetails.GlobalScopeName, null).ConfigureAwait(false); this.scriptScopeVariables = - await FetchVariableContainerAsync(VariableContainerDetails.ScriptScopeName, null); + await FetchVariableContainerAsync(VariableContainerDetails.ScriptScopeName, null).ConfigureAwait(false); } private async Task FetchVariableContainerAsync( @@ -851,7 +851,7 @@ private async Task FetchVariableContainerAsync( new VariableContainerDetails(this.nextVariableId++, "Scope: " + scope); this.variables.Add(scopeVariableContainer); - var results = await this.powerShellContext.ExecuteCommandAsync(psCommand, sendErrorToHost: false); + var results = await this.powerShellContext.ExecuteCommandAsync(psCommand, sendErrorToHost: false).ConfigureAwait(false); if (results != null) { foreach (PSObject psVariableObject in results) @@ -955,7 +955,7 @@ private async Task FetchStackFramesAsync(string scriptNameOverride) var callStackVarName = $"$global:{PsesGlobalVariableNamePrefix}CallStack"; psCommand.AddScript($"{callStackVarName} = Get-PSCallStack; {callStackVarName}"); - var results = await this.powerShellContext.ExecuteCommandAsync(psCommand); + var results = await this.powerShellContext.ExecuteCommandAsync(psCommand).ConfigureAwait(false); var callStackFrames = results.ToArray(); @@ -971,7 +971,7 @@ private async Task FetchStackFramesAsync(string scriptNameOverride) this.variables.Add(autoVariables); VariableContainerDetails localVariables = - await FetchVariableContainerAsync(i.ToString(), autoVariables); + await FetchVariableContainerAsync(i.ToString(), autoVariables).ConfigureAwait(false); // When debugging, this is the best way I can find to get what is likely the workspace root. // This is controlled by the "cwd:" setting in the launch config. @@ -1221,7 +1221,7 @@ internal async void OnDebuggerStopAsync(object sender, DebuggerStopEventArgs e) IEnumerable scriptListingLines = await this.powerShellContext.ExecuteCommandAsync( - command, false, false); + command, false, false).ConfigureAwait(false); if (scriptListingLines != null) { @@ -1254,7 +1254,7 @@ await this.powerShellContext.ExecuteCommandAsync( // Get call stack and variables. await this.FetchStackFramesAndVariablesAsync( - noScriptName ? localScriptPath : null); + noScriptName ? localScriptPath : null).ConfigureAwait(false); // If this is a remote connection and the debugger stopped at a line // in a script file, get the file contents @@ -1265,7 +1265,7 @@ await this.FetchStackFramesAndVariablesAsync( localScriptPath = await this.remoteFileManager.FetchRemoteFileAsync( e.InvocationInfo.ScriptName, - this.powerShellContext.CurrentRunspace); + powerShellContext.CurrentRunspace).ConfigureAwait(false); } if (this.stackFrameDetails.Length > 0) diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Debugging/VariableDetails.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Debugging/VariableDetails.cs index 43d3c9d62..5980ca1cd 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Debugging/VariableDetails.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Debugging/VariableDetails.cs @@ -118,7 +118,7 @@ public override VariableDetailsBase[] GetChildren(ILogger logger) } else { - childVariables = new VariableDetails[0]; + childVariables = Array.Empty(); } return childVariables; diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/BreakpointHandlers.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/BreakpointHandlers.cs index 637976fbc..45db430fe 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/BreakpointHandlers.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/BreakpointHandlers.cs @@ -48,13 +48,13 @@ public async Task Handle(SetFunctionBreakpointsA CommandBreakpointDetails[] updatedBreakpointDetails = breakpointDetails; if (!_debugStateService.NoDebug) { - await _debugStateService.WaitForSetBreakpointHandleAsync(); + await _debugStateService.WaitForSetBreakpointHandleAsync().ConfigureAwait(false); try { updatedBreakpointDetails = await _debugService.SetCommandBreakpointsAsync( - breakpointDetails); + breakpointDetails).ConfigureAwait(false); } catch (Exception e) { @@ -196,14 +196,14 @@ public async Task Handle(SetBreakpointsArguments request BreakpointDetails[] updatedBreakpointDetails = breakpointDetails; if (!_debugStateService.NoDebug) { - await _debugStateService.WaitForSetBreakpointHandleAsync(); + await _debugStateService.WaitForSetBreakpointHandleAsync().ConfigureAwait(false); try { updatedBreakpointDetails = await _debugService.SetLineBreakpointsAsync( scriptFile, - breakpointDetails); + breakpointDetails).ConfigureAwait(false); } catch (Exception e) { diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs index 747a8a9b2..8a1f00c7e 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs @@ -98,12 +98,12 @@ private async Task LaunchScriptAsync(string scriptToLaunch) ScriptFile untitledScript = _workspaceService.GetFile(scriptToLaunch); await _powerShellContextService - .ExecuteScriptStringAsync(untitledScript.Contents, true, true); + .ExecuteScriptStringAsync(untitledScript.Contents, true, true).ConfigureAwait(false); } else { await _powerShellContextService - .ExecuteScriptWithArgsAsync(scriptToLaunch, _debugStateService.Arguments, writeInputToHost: true); + .ExecuteScriptWithArgsAsync(scriptToLaunch, _debugStateService.Arguments, writeInputToHost: true).ConfigureAwait(false); } _jsonRpcServer.SendNotification(EventNames.Terminated); diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DebugEvaluateHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DebugEvaluateHandler.cs index 246621ce7..91886270e 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DebugEvaluateHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DebugEvaluateHandler.cs @@ -65,7 +65,7 @@ public async Task Handle(EvaluateRequestArguments request, await _debugService.EvaluateExpressionAsync( request.Expression, request.FrameId, - isFromRepl); + isFromRepl).ConfigureAwait(false); } } diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DisconnectHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DisconnectHandler.cs index 61df26447..10ad9cc33 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DisconnectHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DisconnectHandler.cs @@ -55,12 +55,12 @@ public async Task Handle(DisconnectArguments request, Cancel { try { - await _powerShellContextService.ExecuteScriptStringAsync("Exit-PSHostProcess"); + await _powerShellContextService.ExecuteScriptStringAsync("Exit-PSHostProcess").ConfigureAwait(false); if (_debugStateService.IsRemoteAttach && _powerShellContextService.CurrentRunspace.Location == RunspaceLocation.Remote) { - await _powerShellContextService.ExecuteScriptStringAsync("Exit-PSSession"); + await _powerShellContextService.ExecuteScriptStringAsync("Exit-PSSession").ConfigureAwait(false); } } catch (Exception e) @@ -75,8 +75,10 @@ public async Task Handle(DisconnectArguments request, Cancel _logger.LogInformation("Debug adapter is shutting down..."); - // Trigger the clean up of the debugger. +#pragma warning disable CS4014 + // Trigger the clean up of the debugger. No need to wait for it. Task.Run(_psesDebugServer.OnSessionEnded); +#pragma warning restore CS4014 return new DisconnectResponse(); } diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/InitializeHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/InitializeHandler.cs index 77861d443..fda53620f 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/InitializeHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/InitializeHandler.cs @@ -27,7 +27,7 @@ public InitializeHandler( public async Task Handle(InitializeRequestArguments request, CancellationToken cancellationToken) { // Clear any existing breakpoints before proceeding - await _debugService.ClearAllBreakpointsAsync(); + await _debugService.ClearAllBreakpointsAsync().ConfigureAwait(false); // Now send the Initialize response to continue setup return new InitializeResponse diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs index 9e0e9910f..fa99f0e2f 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs @@ -162,7 +162,7 @@ public async Task Handle(PsesLaunchRequestArguments request, CancellationT // the working dir should not be changed. if (!string.IsNullOrEmpty(workingDir)) { - await _powerShellContextService.SetWorkingDirectoryAsync(workingDir, isPathAlreadyEscaped: false); + await _powerShellContextService.SetWorkingDirectoryAsync(workingDir, isPathAlreadyEscaped: false).ConfigureAwait(false); } _logger.LogTrace($"Working dir " + (string.IsNullOrEmpty(workingDir) ? "not set." : $"set to '{workingDir}'")); @@ -272,7 +272,7 @@ public async Task Handle(PsesAttachRequestArguments request, CancellationT await _powerShellContextService.ExecuteScriptStringAsync( $"Enter-PSSession -ComputerName \"{request.ComputerName}\"", - errorMessages); + errorMessages).ConfigureAwait(false); if (errorMessages.Length > 0) { @@ -291,7 +291,7 @@ await _powerShellContextService.ExecuteScriptStringAsync( await _powerShellContextService.ExecuteScriptStringAsync( $"Enter-PSHostProcess -Id {processId}", - errorMessages); + errorMessages).ConfigureAwait(false); if (errorMessages.Length > 0) { @@ -307,7 +307,7 @@ await _powerShellContextService.ExecuteScriptStringAsync( await _powerShellContextService.ExecuteScriptStringAsync( $"Enter-PSHostProcess -CustomPipeName {request.CustomPipeName}", - errorMessages); + errorMessages).ConfigureAwait(false); if (errorMessages.Length > 0) { @@ -364,7 +364,7 @@ private async Task OnExecutionCompletedAsync(Task executeTask) { try { - await executeTask; + await executeTask.ConfigureAwait(false); } catch (Exception e) { diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/SetVariableHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/SetVariableHandler.cs index dbd4e0939..f1f7881b7 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/SetVariableHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/SetVariableHandler.cs @@ -39,7 +39,7 @@ public async Task Handle(SetVariableArguments request, Canc await _debugService.SetVariableAsync( (int) request.VariablesReference, request.Name, - request.Value); + request.Value).ConfigureAwait(false); return new SetVariableResponse { diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/StackTraceHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/StackTraceHandler.cs index 57061c317..114cc30a9 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/StackTraceHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/StackTraceHandler.cs @@ -40,7 +40,7 @@ public Task Handle(StackTraceArguments request, Cancellation { return Task.FromResult(new StackTraceResponse { - StackFrames = new StackFrame[0], + StackFrames = Array.Empty(), TotalFrames = 0 }); } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Console/ChoicePromptHandler.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Console/ChoicePromptHandler.cs index ecfe1ffde..d03facc8a 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Console/ChoicePromptHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Console/ChoicePromptHandler.cs @@ -110,7 +110,7 @@ public ChoicePromptHandler(ILogger logger) : base(logger) /// A Task instance that can be monitored for completion to get /// the user's choice. /// - public async Task PromptForChoiceAsync( + public Task PromptForChoiceAsync( string promptCaption, string promptMessage, ChoiceDetails[] choices, @@ -125,14 +125,14 @@ public async Task PromptForChoiceAsync( this.DefaultChoices = defaultChoice == -1 - ? new int[] { } + ? Array.Empty() : new int[] { defaultChoice }; // Cancel the TaskCompletionSource if the caller cancels the task cancellationToken.Register(this.CancelPrompt, true); // Convert the int[] result to int - return await this.WaitForTaskAsync( + return this.WaitForTaskAsync( this.StartPromptLoopAsync(this.promptCancellationTokenSource.Token) .ContinueWith( task => @@ -173,7 +173,7 @@ public async Task PromptForChoiceAsync( /// A Task instance that can be monitored for completion to get /// the user's choices. /// - public async Task PromptForChoiceAsync( + public Task PromptForChoiceAsync( string promptCaption, string promptMessage, ChoiceDetails[] choices, @@ -191,17 +191,14 @@ public async Task PromptForChoiceAsync( // Cancel the TaskCompletionSource if the caller cancels the task cancellationToken.Register(this.CancelPrompt, true); - return await this.WaitForTaskAsync( + return this.WaitForTaskAsync( this.StartPromptLoopAsync( this.promptCancellationTokenSource.Token)); } private async Task WaitForTaskAsync(Task taskToWait) { - Task finishedTask = - await Task.WhenAny( - this.cancelTask.Task, - taskToWait); + _ = await Task.WhenAny(cancelTask.Task, taskToWait).ConfigureAwait(false); if (this.cancelTask.Task.IsCanceled) { @@ -221,7 +218,7 @@ private async Task StartPromptLoopAsync( while (!cancellationToken.IsCancellationRequested) { - string responseString = await this.ReadInputStringAsync(cancellationToken); + string responseString = await ReadInputStringAsync(cancellationToken).ConfigureAwait(false); if (responseString == null) { // If the response string is null, the prompt has been cancelled diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleProxy.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleProxy.cs index a6e056b82..2f0bb282b 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleProxy.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleProxy.cs @@ -18,6 +18,7 @@ internal static class ConsoleProxy { private static IConsoleOperations s_consoleProxy; + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline", Justification = "Platform specific initialization")] static ConsoleProxy() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleReadLine.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleReadLine.cs index 0c306944e..8234264ff 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleReadLine.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleReadLine.cs @@ -19,7 +19,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShellContext internal class ConsoleReadLine { #region Private Field - private PowerShellContextService powerShellContext; + private readonly PowerShellContextService powerShellContext; #endregion @@ -48,8 +48,9 @@ public async Task ReadSecureLineAsync(CancellationToken cancellati { SecureString secureString = new SecureString(); - int initialPromptRow = await ConsoleProxy.GetCursorTopAsync(cancellationToken); - int initialPromptCol = await ConsoleProxy.GetCursorLeftAsync(cancellationToken); + // TODO: Are these values used? + int initialPromptRow = await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false); + int initialPromptCol = await ConsoleProxy.GetCursorLeftAsync(cancellationToken).ConfigureAwait(false); int previousInputLength = 0; Console.TreatControlCAsInput = true; @@ -58,7 +59,7 @@ public async Task ReadSecureLineAsync(CancellationToken cancellati { while (!cancellationToken.IsCancellationRequested) { - ConsoleKeyInfo keyInfo = await ReadKeyAsync(cancellationToken); + ConsoleKeyInfo keyInfo = await ReadKeyAsync(cancellationToken).ConfigureAwait(false); if ((int)keyInfo.Key == 3 || keyInfo.Key == ConsoleKey.C && keyInfo.Modifiers.HasFlag(ConsoleModifiers.Control)) @@ -96,8 +97,8 @@ public async Task ReadSecureLineAsync(CancellationToken cancellati } else if (previousInputLength > 0 && currentInputLength < previousInputLength) { - int row = await ConsoleProxy.GetCursorTopAsync(cancellationToken); - int col = await ConsoleProxy.GetCursorLeftAsync(cancellationToken); + int row = await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false); + int col = await ConsoleProxy.GetCursorLeftAsync(cancellationToken).ConfigureAwait(false); // Back up the cursor before clearing the character col--; @@ -127,14 +128,14 @@ public async Task ReadSecureLineAsync(CancellationToken cancellati #region Private Methods - private static async Task ReadKeyAsync(CancellationToken cancellationToken) + private static Task ReadKeyAsync(CancellationToken cancellationToken) { - return await ConsoleProxy.ReadKeyAsync(intercept: true, cancellationToken); + return ConsoleProxy.ReadKeyAsync(intercept: true, cancellationToken); } - private async Task ReadLineAsync(bool isCommandLine, CancellationToken cancellationToken) + private Task ReadLineAsync(bool isCommandLine, CancellationToken cancellationToken) { - return await this.powerShellContext.InvokeReadLineAsync(isCommandLine, cancellationToken); + return this.powerShellContext.InvokeReadLineAsync(isCommandLine, cancellationToken); } /// @@ -154,6 +155,7 @@ private async Task ReadLineAsync(bool isCommandLine, CancellationToken c /// internal async Task InvokeLegacyReadLineAsync(bool isCommandLine, CancellationToken cancellationToken) { + // TODO: Is inputBeforeCompletion used? string inputBeforeCompletion = null; string inputAfterCompletion = null; CommandCompletion currentCompletion = null; @@ -163,9 +165,10 @@ internal async Task InvokeLegacyReadLineAsync(bool isCommandLine, Cancel StringBuilder inputLine = new StringBuilder(); - int initialCursorCol = await ConsoleProxy.GetCursorLeftAsync(cancellationToken); - int initialCursorRow = await ConsoleProxy.GetCursorTopAsync(cancellationToken); + int initialCursorCol = await ConsoleProxy.GetCursorLeftAsync(cancellationToken).ConfigureAwait(false); + int initialCursorRow = await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false); + // TODO: Are these used? int initialWindowLeft = Console.WindowLeft; int initialWindowTop = Console.WindowTop; @@ -177,7 +180,7 @@ internal async Task InvokeLegacyReadLineAsync(bool isCommandLine, Cancel { while (!cancellationToken.IsCancellationRequested) { - ConsoleKeyInfo keyInfo = await ReadKeyAsync(cancellationToken); + ConsoleKeyInfo keyInfo = await ReadKeyAsync(cancellationToken).ConfigureAwait(false); // Do final position calculation after the key has been pressed // because the window could have been resized before then @@ -207,14 +210,15 @@ internal async Task InvokeLegacyReadLineAsync(bool isCommandLine, Cancel command.AddParameter("CursorColumn", currentCursorIndex); command.AddParameter("Options", null); - var results = - await this.powerShellContext.ExecuteCommandAsync(command, false, false); + var results = await this.powerShellContext + .ExecuteCommandAsync(command, sendOutputToHost: false, sendErrorToHost: false) + .ConfigureAwait(false); currentCompletion = results.FirstOrDefault(); } else { - using (RunspaceHandle runspaceHandle = await this.powerShellContext.GetRunspaceHandleAsync()) + using (RunspaceHandle runspaceHandle = await this.powerShellContext.GetRunspaceHandleAsync().ConfigureAwait(false)) using (PowerShell powerShell = PowerShell.Create()) { powerShell.Runspace = runspaceHandle.Runspace; @@ -325,11 +329,9 @@ internal async Task InvokeLegacyReadLineAsync(bool isCommandLine, Cancel PSCommand command = new PSCommand(); command.AddCommand("Get-History"); - currentHistory = - await this.powerShellContext.ExecuteCommandAsync( - command, - false, - false) as Collection; + currentHistory = await this.powerShellContext.ExecuteCommandAsync(command, sendOutputToHost: false, sendErrorToHost: false) + .ConfigureAwait(false) + as Collection; if (currentHistory != null) { @@ -475,7 +477,7 @@ await this.powerShellContext.ExecuteCommandAsync( inputLine, promptStartCol, promptStartRow, - keyInfo.KeyChar.ToString(), + keyInfo.KeyChar.ToString(), // TODO: Determine whether this should take culture into account currentCursorIndex, finalCursorIndex: currentCursorIndex + 1); } @@ -489,6 +491,7 @@ await this.powerShellContext.ExecuteCommandAsync( return null; } + // TODO: Is this used? private int CalculateIndexFromCursor( int promptStartCol, int promptStartRow, diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Console/InputPromptHandler.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Console/InputPromptHandler.cs index ed95b9120..85ddd6d16 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Console/InputPromptHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Console/InputPromptHandler.cs @@ -122,10 +122,7 @@ public async Task> PromptForInputAsync( Task> promptTask = this.StartPromptLoopAsync(this.promptCancellationTokenSource.Token); - Task finishedTask = - await Task.WhenAny( - cancelTask.Task, - promptTask); + _ = await Task.WhenAny(cancelTask.Task, promptTask).ConfigureAwait(false); if (this.cancelTask.Task.IsCanceled) { @@ -255,13 +252,13 @@ private async Task> StartPromptLoopAsync( // Read input depending on field type if (this.currentField.FieldType == typeof(SecureString)) { - SecureString secureString = await this.ReadSecureStringAsync(cancellationToken); + SecureString secureString = await this.ReadSecureStringAsync(cancellationToken).ConfigureAwait(false); responseValue = secureString; enteredValue = secureString != null; } else { - responseString = await this.ReadInputStringAsync(cancellationToken); + responseString = await this.ReadInputStringAsync(cancellationToken).ConfigureAwait(false); responseValue = responseString; enteredValue = responseString != null && responseString.Length > 0; diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Console/TerminalChoicePromptHandler.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Console/TerminalChoicePromptHandler.cs index f49c6ca39..926235433 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Console/TerminalChoicePromptHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Console/TerminalChoicePromptHandler.cs @@ -53,7 +53,7 @@ public TerminalChoicePromptHandler( /// A Task that can be awaited to get the user's response. protected override async Task ReadInputStringAsync(CancellationToken cancellationToken) { - string inputString = await this.consoleReadLine.ReadSimpleLineAsync(cancellationToken); + string inputString = await this.consoleReadLine.ReadSimpleLineAsync(cancellationToken).ConfigureAwait(false); this.hostOutput.WriteOutput(string.Empty); return inputString; diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Console/TerminalInputPromptHandler.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Console/TerminalInputPromptHandler.cs index dacb51f32..0b780aabc 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Console/TerminalInputPromptHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Console/TerminalInputPromptHandler.cs @@ -55,7 +55,7 @@ public TerminalInputPromptHandler( /// A Task that can be awaited to get the user's response. protected override async Task ReadInputStringAsync(CancellationToken cancellationToken) { - string inputString = await this.consoleReadLine.ReadSimpleLineAsync(cancellationToken); + string inputString = await this.consoleReadLine.ReadSimpleLineAsync(cancellationToken).ConfigureAwait(false); this.hostOutput.WriteOutput(string.Empty); return inputString; @@ -68,7 +68,7 @@ protected override async Task ReadInputStringAsync(CancellationToken can /// A Task that can be awaited to get the user's response. protected override async Task ReadSecureStringAsync(CancellationToken cancellationToken) { - SecureString secureString = await this.consoleReadLine.ReadSecureLineAsync(cancellationToken); + SecureString secureString = await this.consoleReadLine.ReadSecureLineAsync(cancellationToken).ConfigureAwait(false); this.hostOutput.WriteOutput(string.Empty); return secureString; diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Console/UnixConsoleOperations.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Console/UnixConsoleOperations.cs index 7df7b186e..e1c0e43e4 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Console/UnixConsoleOperations.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Console/UnixConsoleOperations.cs @@ -85,7 +85,7 @@ public ConsoleKeyInfo ReadKey(bool intercept, CancellationToken cancellationToke public async Task ReadKeyAsync(bool intercept, CancellationToken cancellationToken) { - await s_readKeyHandle.WaitAsync(cancellationToken); + await s_readKeyHandle.WaitAsync(cancellationToken).ConfigureAwait(false); // I tried to replace this library with a call to `stty -echo`, but unfortunately // the library also sets up allowing backspace to trigger `Console.KeyAvailable`. @@ -96,7 +96,7 @@ public async Task ReadKeyAsync(bool intercept, CancellationToken try { - while (!await WaitForKeyAvailableAsync(cancellationToken)); + while (!await WaitForKeyAvailableAsync(cancellationToken).ConfigureAwait(false)) ; } finally { @@ -107,7 +107,7 @@ public async Task ReadKeyAsync(bool intercept, CancellationToken s_readKeyHandle.Release(); } - await s_stdInHandle.WaitAsync(cancellationToken); + await s_stdInHandle.WaitAsync(cancellationToken).ConfigureAwait(false); try { return System.Console.ReadKey(intercept); @@ -136,14 +136,14 @@ public int GetCursorLeft(CancellationToken cancellationToken) } } - public async Task GetCursorLeftAsync() + public Task GetCursorLeftAsync() { - return await GetCursorLeftAsync(CancellationToken.None); + return GetCursorLeftAsync(CancellationToken.None); } public async Task GetCursorLeftAsync(CancellationToken cancellationToken) { - await s_stdInHandle.WaitAsync(cancellationToken); + await s_stdInHandle.WaitAsync(cancellationToken).ConfigureAwait(false); try { return System.Console.CursorLeft; @@ -172,14 +172,14 @@ public int GetCursorTop(CancellationToken cancellationToken) } } - public async Task GetCursorTopAsync() + public Task GetCursorTopAsync() { - return await GetCursorTopAsync(CancellationToken.None); + return GetCursorTopAsync(CancellationToken.None); } public async Task GetCursorTopAsync(CancellationToken cancellationToken) { - await s_stdInHandle.WaitAsync(cancellationToken); + await s_stdInHandle.WaitAsync(cancellationToken).ConfigureAwait(false); try { return System.Console.CursorTop; @@ -207,9 +207,9 @@ private bool LongWaitForKey(CancellationToken cancellationToken) private async Task LongWaitForKeyAsync(CancellationToken cancellationToken) { - while (!await IsKeyAvailableAsync(cancellationToken)) + while (!await IsKeyAvailableAsync(cancellationToken).ConfigureAwait(false)) { - await Task.Delay(LongWaitForKeySleepTime, cancellationToken); + await Task.Delay(LongWaitForKeySleepTime, cancellationToken).ConfigureAwait(false); } WaitForKeyAvailableAsync = ShortWaitForKeyAsync; @@ -234,7 +234,7 @@ private bool ShortWaitForKey(CancellationToken cancellationToken) private async Task ShortWaitForKeyAsync(CancellationToken cancellationToken) { - if (await SpinUntilKeyAvailableAsync(ShortWaitForKeyTimeout, cancellationToken)) + if (await SpinUntilKeyAvailableAsync(ShortWaitForKeyTimeout, cancellationToken).ConfigureAwait(false)) { cancellationToken.ThrowIfCancellationRequested(); return true; @@ -256,9 +256,9 @@ private bool SpinUntilKeyAvailable(int millisecondsTimeout, CancellationToken ca millisecondsTimeout); } - private async Task SpinUntilKeyAvailableAsync(int millisecondsTimeout, CancellationToken cancellationToken) + private Task SpinUntilKeyAvailableAsync(int millisecondsTimeout, CancellationToken cancellationToken) { - return await Task.Factory.StartNew( + return Task.Factory.StartNew( () => SpinWait.SpinUntil( () => { @@ -284,7 +284,7 @@ private bool IsKeyAvailable(CancellationToken cancellationToken) private async Task IsKeyAvailableAsync(CancellationToken cancellationToken) { - await s_stdInHandle.WaitAsync(cancellationToken); + await s_stdInHandle.WaitAsync(cancellationToken).ConfigureAwait(false); try { return System.Console.KeyAvailable; diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Console/WindowsConsoleOperations.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Console/WindowsConsoleOperations.cs index 69c6ac91e..b8000abfb 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Console/WindowsConsoleOperations.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Console/WindowsConsoleOperations.cs @@ -34,7 +34,7 @@ internal class WindowsConsoleOperations : IConsoleOperations public async Task ReadKeyAsync(bool intercept, CancellationToken cancellationToken) { - await _readKeyHandle.WaitAsync(cancellationToken); + await _readKeyHandle.WaitAsync(cancellationToken).ConfigureAwait(false); try { return diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/EditorOperationsService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/EditorOperationsService.cs index 0c1774065..d67f449e8 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/EditorOperationsService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/EditorOperationsService.cs @@ -40,7 +40,7 @@ public async Task GetEditorContextAsync() ClientEditorContext clientContext = await _languageServer.SendRequest( "editor/getEditorContext", - new GetEditorContextRequest()); + new GetEditorContextRequest()).ConfigureAwait(false); return this.ConvertClientEditorContext(clientContext); } @@ -52,7 +52,7 @@ public async Task InsertTextAsync(string filePath, string text, BufferRange inse return; }; - await _languageServer.SendRequest("editor/insertText", new InsertTextRequest + await _languageServer.SendRequest("editor/insertText", new InsertTextRequest { FilePath = filePath, InsertText = text, @@ -70,7 +70,7 @@ public async Task InsertTextAsync(string filePath, string text, BufferRange inse Character = insertRange.End.Column - 1 } } - }); + }).ConfigureAwait(false); } public async Task SetSelectionAsync(BufferRange selectionRange) @@ -80,7 +80,7 @@ public async Task SetSelectionAsync(BufferRange selectionRange) return; }; - await _languageServer.SendRequest("editor/setSelection", new SetSelectionRequest + await _languageServer.SendRequest("editor/setSelection", new SetSelectionRequest { SelectionRange = new Range @@ -96,7 +96,7 @@ public async Task SetSelectionAsync(BufferRange selectionRange) Character = selectionRange.End.Column - 1 } } - }); + }).ConfigureAwait(false); } public EditorContext ConvertClientEditorContext( @@ -128,7 +128,7 @@ public async Task NewFileAsync() return; }; - await _languageServer.SendRequest("editor/newFile", null); + await _languageServer.SendRequest("editor/newFile", null).ConfigureAwait(false); } public async Task OpenFileAsync(string filePath) @@ -138,11 +138,11 @@ public async Task OpenFileAsync(string filePath) return; }; - await _languageServer.SendRequest("editor/openFile", new OpenFileDetails + await _languageServer.SendRequest("editor/openFile", new OpenFileDetails { FilePath = filePath, Preview = DefaultPreviewSetting - }); + }).ConfigureAwait(false); } public async Task OpenFileAsync(string filePath, bool preview) @@ -152,11 +152,11 @@ public async Task OpenFileAsync(string filePath, bool preview) return; }; - await _languageServer.SendRequest("editor/openFile", new OpenFileDetails + await _languageServer.SendRequest("editor/openFile", new OpenFileDetails { FilePath = filePath, Preview = preview - }); + }).ConfigureAwait(false); } public async Task CloseFileAsync(string filePath) @@ -166,12 +166,12 @@ public async Task CloseFileAsync(string filePath) return; }; - await _languageServer.SendRequest("editor/closeFile", filePath); + await _languageServer.SendRequest("editor/closeFile", filePath).ConfigureAwait(false); } - public async Task SaveFileAsync(string filePath) + public Task SaveFileAsync(string filePath) { - await SaveFileAsync(filePath, null); + return SaveFileAsync(filePath, null); } public async Task SaveFileAsync(string currentPath, string newSavePath) @@ -181,11 +181,11 @@ public async Task SaveFileAsync(string currentPath, string newSavePath) return; }; - await _languageServer.SendRequest("editor/saveFile", new SaveFileDetails + await _languageServer.SendRequest("editor/saveFile", new SaveFileDetails { FilePath = currentPath, NewPath = newSavePath - }); + }).ConfigureAwait(false); } public string GetWorkspacePath() @@ -205,7 +205,7 @@ public async Task ShowInformationMessageAsync(string message) return; }; - await _languageServer.SendRequest("editor/showInformationMessage", message); + await _languageServer.SendRequest("editor/showInformationMessage", message).ConfigureAwait(false); } public async Task ShowErrorMessageAsync(string message) @@ -215,7 +215,7 @@ public async Task ShowErrorMessageAsync(string message) return; }; - await _languageServer.SendRequest("editor/showErrorMessage", message); + await _languageServer.SendRequest("editor/showErrorMessage", message).ConfigureAwait(false); } public async Task ShowWarningMessageAsync(string message) @@ -225,7 +225,7 @@ public async Task ShowWarningMessageAsync(string message) return; }; - await _languageServer.SendRequest("editor/showWarningMessage", message); + await _languageServer.SendRequest("editor/showWarningMessage", message).ConfigureAwait(false); } public async Task SetStatusBarMessageAsync(string message, int? timeout) @@ -235,11 +235,11 @@ public async Task SetStatusBarMessageAsync(string message, int? timeout) return; } - await _languageServer.SendRequest("editor/setStatusBarMessage", new StatusBarMessageDetails + await _languageServer.SendRequest("editor/setStatusBarMessage", new StatusBarMessageDetails { Message = message, Timeout = timeout - }); + }).ConfigureAwait(false); } public void ClearTerminal() diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/ExtensionService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/ExtensionService.cs index baeffd925..f4e60bc53 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/ExtensionService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/ExtensionService.cs @@ -4,6 +4,7 @@ // using Microsoft.PowerShell.EditorServices.Services.PowerShellContext; +using Microsoft.PowerShell.EditorServices.Utility; using OmniSharp.Extensions.LanguageServer.Protocol.Server; using System; using System.Collections.Generic; @@ -20,7 +21,7 @@ public class ExtensionService { #region Fields - private Dictionary editorCommands = + private readonly Dictionary editorCommands = new Dictionary(); private readonly ILanguageServer _languageServer; @@ -88,7 +89,7 @@ public async Task InitializeAsync( // Register the editor object in the runspace PSCommand variableCommand = new PSCommand(); - using (RunspaceHandle handle = await this.PowerShellContext.GetRunspaceHandleAsync()) + using (RunspaceHandle handle = await this.PowerShellContext.GetRunspaceHandleAsync().ConfigureAwait(false)) { handle.Runspace.SessionStateProxy.PSVariable.Set( "psEditor", @@ -104,9 +105,8 @@ public async Task InitializeAsync( /// A Task that can be awaited for completion. public async Task InvokeCommandAsync(string commandName, EditorContext editorContext) { - EditorCommand editorCommand; - if (this.editorCommands.TryGetValue(commandName, out editorCommand)) + if (this.editorCommands.TryGetValue(commandName, out EditorCommand editorCommand)) { PSCommand executeCommand = new PSCommand(); executeCommand.AddCommand("Invoke-Command"); @@ -115,8 +115,8 @@ public async Task InvokeCommandAsync(string commandName, EditorContext editorCon await this.PowerShellContext.ExecuteCommandAsync( executeCommand, - !editorCommand.SuppressOutput, - true); + sendOutputToHost: !editorCommand.SuppressOutput, + sendErrorToHost: true).ConfigureAwait(false); } else { @@ -135,6 +135,8 @@ await this.PowerShellContext.ExecuteCommandAsync( /// True if the command is newly registered, false if the command already exists. public bool RegisterCommand(EditorCommand editorCommand) { + Validate.IsNotNull(nameof(editorCommand), editorCommand); + bool commandExists = this.editorCommands.ContainsKey( editorCommand.Name); @@ -160,8 +162,7 @@ public bool RegisterCommand(EditorCommand editorCommand) /// The name of the command to be unregistered. public void UnregisterCommand(string commandName) { - EditorCommand existingCommand = null; - if (this.editorCommands.TryGetValue(commandName, out existingCommand)) + if (this.editorCommands.TryGetValue(commandName, out EditorCommand existingCommand)) { this.editorCommands.Remove(commandName); this.OnCommandRemoved(existingCommand); diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/EvaluateHandler.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/EvaluateHandler.cs index f0579667c..8399ce38b 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/EvaluateHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/EvaluateHandler.cs @@ -27,7 +27,7 @@ await _powerShellContextService.ExecuteScriptStringAsync( request.Expression, writeInputToHost: true, writeOutputToHost: true, - addToHistory: true); + addToHistory: true).ConfigureAwait(false); return new EvaluateResponseBody { diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ExpandAliasHandler.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ExpandAliasHandler.cs index 336ebd8f6..662b91098 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ExpandAliasHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ExpandAliasHandler.cs @@ -71,7 +71,7 @@ function __Expand-Alias { .AddStatement() .AddCommand("__Expand-Alias") .AddArgument(request.Text); - var result = await _powerShellContextService.ExecuteCommandAsync(psCommand); + var result = await _powerShellContextService.ExecuteCommandAsync(psCommand).ConfigureAwait(false); return new ExpandAliasResult { diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/GetCommandHandler.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/GetCommandHandler.cs index fd1bdb3e0..59c73bb65 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/GetCommandHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/GetCommandHandler.cs @@ -57,7 +57,7 @@ public async Task> Handle(GetCommandParams request, Cance .AddCommand("Microsoft.PowerShell.Utility\\Sort-Object") .AddParameter("Property", "Name"); - IEnumerable result = await _powerShellContextService.ExecuteCommandAsync(psCommand); + IEnumerable result = await _powerShellContextService.ExecuteCommandAsync(psCommand).ConfigureAwait(false); var commandList = new List(); if (result != null) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/InvokeExtensionCommandHandler.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/InvokeExtensionCommandHandler.cs index 01c4c869f..7773096a6 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/InvokeExtensionCommandHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/InvokeExtensionCommandHandler.cs @@ -38,9 +38,9 @@ public async Task Handle(InvokeExtensionCommandParams request, Cancellatio await _extensionService.InvokeCommandAsync( request.Name, - editorContext); + editorContext).ConfigureAwait(false); - return await Unit.Task; + return await Unit.Task.ConfigureAwait(false); } } } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/PSHostProcessAndRunspaceHandlers.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/PSHostProcessAndRunspaceHandlers.cs index 9f82983ad..bdb0e0c77 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/PSHostProcessAndRunspaceHandlers.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/PSHostProcessAndRunspaceHandlers.cs @@ -89,7 +89,7 @@ public async Task Handle(GetRunspaceParams request, Cancella var psCommand = new PSCommand().AddCommand("Microsoft.PowerShell.Utility\\Get-Runspace"); var sb = new StringBuilder(); // returns (not deserialized) Runspaces. For simpler code, we use PSObject and rely on dynamic later. - runspaces = await _powerShellContextService.ExecuteCommandAsync(psCommand, sb); + runspaces = await _powerShellContextService.ExecuteCommandAsync(psCommand, sb).ConfigureAwait(false); } var runspaceResponses = new List(); diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ShowHelpHandler.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ShowHelpHandler.cs index 41b94be29..5c48e9937 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ShowHelpHandler.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ShowHelpHandler.cs @@ -74,7 +74,7 @@ public async Task Handle(ShowHelpParams request, CancellationToken cancell // TODO: Rather than print the help in the console, we should send the string back // to VSCode to display in a help pop-up (or similar) - await _powerShellContextService.ExecuteCommandAsync(checkHelpPSCommand, sendOutputToHost: true); + await _powerShellContextService.ExecuteCommandAsync(checkHelpPSCommand, sendOutputToHost: true).ConfigureAwait(false); return Unit.Value; } } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/TemplateHandlers.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/TemplateHandlers.cs index 210ff3ca3..48a2d2b34 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/TemplateHandlers.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Handlers/TemplateHandlers.cs @@ -27,13 +27,13 @@ public TemplateHandlers( public async Task Handle(GetProjectTemplatesRequest request, CancellationToken cancellationToken) { - bool plasterInstalled = await _templateService.ImportPlasterIfInstalledAsync(); + bool plasterInstalled = await _templateService.ImportPlasterIfInstalledAsync().ConfigureAwait(false); if (plasterInstalled) { var availableTemplates = await _templateService.GetAvailableTemplatesAsync( - request.IncludeInstalledModules); + request.IncludeInstalledModules).ConfigureAwait(false); return new GetProjectTemplatesResponse @@ -45,16 +45,17 @@ await _templateService.GetAvailableTemplatesAsync( return new GetProjectTemplatesResponse { NeedsModuleInstall = true, - Templates = new TemplateDetails[0] + Templates = Array.Empty() }; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Want to log any exception")] public async Task Handle(NewProjectFromTemplateRequest request, CancellationToken cancellationToken) { bool creationSuccessful; try { - await _templateService.CreateFromTemplateAsync(request.TemplatePath, request.DestinationPath); + await _templateService.CreateFromTemplateAsync(request.TemplatePath, request.DestinationPath).ConfigureAwait(false); creationSuccessful = true; } catch (Exception e) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index 452e64003..30eff8760 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -21,6 +21,7 @@ namespace Microsoft.PowerShell.EditorServices.Services { + using System.Diagnostics.CodeAnalysis; using System.Management.Automation; using Microsoft.PowerShell.EditorServices.Handlers; using Microsoft.PowerShell.EditorServices.Hosting; @@ -41,6 +42,7 @@ public class PowerShellContextService : IDisposable, IHostSupportsInteractiveSes private static readonly Action s_runspaceApartmentStateSetter; + [SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline", Justification = "cctor needed for version specific initialization")] static PowerShellContextService() { // PowerShell ApartmentState APIs aren't available in PSStandard, so we need to use reflection @@ -57,8 +59,9 @@ static PowerShellContextService() private readonly SemaphoreSlim resumeRequestHandle = AsyncUtils.CreateSimpleLockingSemaphore(); private readonly OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer _languageServer; - private bool isPSReadLineEnabled; - private ILogger logger; + private readonly bool isPSReadLineEnabled; + private readonly ILogger logger; + private PowerShell powerShell; private bool ownsInitialRunspace; private RunspaceDetails initialRunspace; @@ -68,7 +71,7 @@ static PowerShellContextService() private IVersionSpecificOperations versionSpecificOperations; - private Stack runspaceStack = new Stack(); + private readonly Stack runspaceStack = new Stack(); private int isCommandLoopRestarterSet; @@ -170,11 +173,14 @@ public PowerShellContextService( ExecutionStatusChanged += PowerShellContext_ExecutionStatusChangedAsync; } + [SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "Checked by Validate call")] public static PowerShellContextService Create( ILoggerFactory factory, OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer languageServer, HostStartupInfo hostStartupInfo) { + Validate.IsNotNull(nameof(hostStartupInfo), hostStartupInfo); + var logger = factory.CreateLogger(); // We should only use PSReadLine if we specificied that we want a console repl @@ -217,10 +223,13 @@ public static PowerShellContextService Create( .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); +#pragma warning restore CS4014 } return powerShellContext; @@ -242,6 +251,8 @@ public static Runspace CreateRunspace( EditorServicesPSHostUserInterface hostUserInterface, ILogger logger) { + Validate.IsNotNull(nameof(powerShellContext), powerShellContext); + var psHost = new EditorServicesPSHost(powerShellContext, hostDetails, hostUserInterface, logger); powerShellContext.ConsoleWriter = hostUserInterface; powerShellContext.ConsoleReader = hostUserInterface; @@ -512,7 +523,7 @@ public async Task> ExecuteCommandAsync( bool sendOutputToHost = false, bool sendErrorToHost = true) { - return await ExecuteCommandAsync(psCommand, null, sendOutputToHost, sendErrorToHost); + return await ExecuteCommandAsync(psCommand, errorMessages: null, sendOutputToHost, sendErrorToHost).ConfigureAwait(false); } /// @@ -554,6 +565,7 @@ public Task> ExecuteCommandAsync( }); } + /// /// Executes a PSCommand against the session's runspace and returns /// a collection of results of the expected type. @@ -566,11 +578,16 @@ public Task> ExecuteCommandAsync( /// An awaitable Task which will provide results once the command /// execution completes. /// + [SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "Checked by Validate call")] + [SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "PowerShellContext must catch and log all exceptions to be robust")] public async Task> ExecuteCommandAsync( PSCommand psCommand, StringBuilder errorMessages, ExecutionOptions executionOptions) { + Validate.IsNotNull(nameof(psCommand), psCommand); + Validate.IsNotNull(nameof(executionOptions), executionOptions); + // Add history to PSReadLine before cancelling, otherwise it will be restored as the // cancelled prompt when it's called again. if (executionOptions.AddToHistory) @@ -620,7 +637,7 @@ public async Task> ExecuteCommandAsync( this, psCommand, errorMessages, - executionOptions)); + executionOptions)).ConfigureAwait(false); } else { @@ -644,10 +661,10 @@ public async Task> ExecuteCommandAsync( // don't write output (e.g. command completion) if (executionTarget == ExecutionTarget.InvocationEvent) { - return (await this.InvocationEventQueue.ExecuteCommandOnIdleAsync( + return await this.InvocationEventQueue.ExecuteCommandOnIdleAsync( psCommand, errorMessages, - executionOptions)); + executionOptions).ConfigureAwait(false); } // Prompt is stopped and started based on the execution status, so naturally @@ -660,7 +677,7 @@ public async Task> ExecuteCommandAsync( false); } - runspaceHandle = await this.GetRunspaceHandleAsync(executionOptions.IsReadLine); + runspaceHandle = await this.GetRunspaceHandleAsync(executionOptions.IsReadLine).ConfigureAwait(false); if (executionOptions.WriteInputToHost) { this.WriteOutput(psCommand.Commands[0].CommandText, true); @@ -721,7 +738,7 @@ public async Task> ExecuteCommandAsync( // Don't change our SessionState for ReadLine. if (!executionOptions.IsReadLine) { - shell.InvocationStateChanged += powerShell_InvocationStateChanged; + shell.InvocationStateChanged += PowerShell_InvocationStateChanged; } shell.Runspace = executionOptions.ShouldExecuteInOriginalRunspace @@ -740,13 +757,13 @@ public async Task> ExecuteCommandAsync( () => shell.Invoke(null, invocationSettings), CancellationToken.None, // Might need a cancellation token TaskCreationOptions.None, - TaskScheduler.Default); + TaskScheduler.Default).ConfigureAwait(false); } finally { if (!executionOptions.IsReadLine) { - shell.InvocationStateChanged -= powerShell_InvocationStateChanged; + shell.InvocationStateChanged -= PowerShell_InvocationStateChanged; } if (shell.HadErrors) @@ -856,7 +873,7 @@ public async Task> ExecuteCommandAsync( // will exist already so we need to create one and then use it if (runspaceHandle == null) { - runspaceHandle = await this.GetRunspaceHandleAsync(); + runspaceHandle = await this.GetRunspaceHandleAsync().ConfigureAwait(false); } sessionDetails = this.GetSessionDetailsInRunspace(runspaceHandle.Runspace); @@ -972,6 +989,8 @@ public async Task> ExecuteScriptStringAsync( bool writeOutputToHost, bool addToHistory) { + Validate.IsNotNull(nameof(scriptString), scriptString); + return await this.ExecuteCommandAsync( new PSCommand().AddScript(scriptString.Trim()), errorMessages, @@ -980,7 +999,7 @@ public async Task> ExecuteScriptStringAsync( WriteOutputToHost = writeOutputToHost, AddToHistory = addToHistory, WriteInputToHost = writeInputToHost - }); + }).ConfigureAwait(false); } /// @@ -992,6 +1011,8 @@ public async Task> ExecuteScriptStringAsync( /// A Task that can be awaited for completion. public async Task ExecuteScriptWithArgsAsync(string script, string arguments = null, bool writeInputToHost = false) { + Validate.IsNotNull(nameof(script), script); + PSCommand command = new PSCommand(); if (arguments != null) @@ -1005,8 +1026,8 @@ public async Task ExecuteScriptWithArgsAsync(string script, string arguments = n new PSCommand() .AddCommand("Microsoft.PowerShell.Management\\Get-Location") .AddParameter("PSProvider", "FileSystem"), - false, - false)) + sendOutputToHost: false, + sendErrorToHost: false).ConfigureAwait(false)) .FirstOrDefault() .ProviderPath; @@ -1062,9 +1083,9 @@ public async Task ExecuteScriptWithArgsAsync(string script, string arguments = n await this.ExecuteCommandAsync( command, - null, + errorMessages: null, sendOutputToHost: true, - addToHistory: true); + addToHistory: true).ConfigureAwait(false); } /// @@ -1101,7 +1122,7 @@ internal async Task InvokeOnPipelineThreadAsync(Action invocationAct { if (this.PromptNest.IsReadLineBusy()) { - await this.InvocationEventQueue.InvokeOnPipelineThreadAsync(invocationAction); + await this.InvocationEventQueue.InvokeOnPipelineThreadAsync(invocationAction).ConfigureAwait(false); return; } @@ -1115,10 +1136,10 @@ internal async Task InvokeReadLineAsync(bool isCommandLine, Cancellation { return await PromptContext.InvokeReadLineAsync( isCommandLine, - cancellationToken); + cancellationToken).ConfigureAwait(false); } - internal static TResult ExecuteScriptAndGetItem(string scriptToExecute, Runspace runspace, TResult defaultValue = default(TResult)) + internal static TResult ExecuteScriptAndGetItem(string scriptToExecute, Runspace runspace, TResult defaultValue = default) { using (PowerShell pwsh = PowerShell.Create()) { @@ -1143,12 +1164,12 @@ public async Task LoadHostProfilesAsync() { PSCommand command = new PSCommand(); command.AddCommand(profilePath, false); - await this.ExecuteCommandAsync(command, true, true); + await this.ExecuteCommandAsync(command, sendOutputToHost: true, sendErrorToHost: true).ConfigureAwait(false); } // Gather the session details (particularly the prompt) after // loading the user's profiles. - await this.GetSessionDetailsInRunspaceAsync(); + await this.GetSessionDetailsInRunspaceAsync().ConfigureAwait(false); } } @@ -1235,7 +1256,7 @@ internal async Task ExitAllNestedPromptsAsync() { while (this.PromptNest.IsNestedPrompt) { - await this.PromptNest.WaitForCurrentFrameExitAsync(frame => this.ExitNestedPrompt()); + await this.PromptNest.WaitForCurrentFrameExitAsync(frame => this.ExitNestedPrompt()).ConfigureAwait(false); this.versionSpecificOperations.ExitNestedPrompt(ExternalHost); } } @@ -1345,14 +1366,14 @@ public void Dispose() this.initialRunspace = null; } - private async Task GetRunspaceHandleAsync(bool isReadLine) + private Task GetRunspaceHandleAsync(bool isReadLine) { - return await this.GetRunspaceHandleImplAsync(CancellationToken.None, isReadLine); + return this.GetRunspaceHandleImplAsync(CancellationToken.None, isReadLine); } - private async Task GetRunspaceHandleImplAsync(CancellationToken cancellationToken, bool isReadLine) + private Task GetRunspaceHandleImplAsync(CancellationToken cancellationToken, bool isReadLine) { - return await this.PromptNest.GetRunspaceHandleAsync(cancellationToken, isReadLine); + return this.PromptNest.GetRunspaceHandleAsync(cancellationToken, isReadLine); } private ExecutionTarget GetExecutionTarget(ExecutionOptions options = null) @@ -1461,7 +1482,7 @@ internal void ReleaseRunspaceHandle(RunspaceHandle runspaceHandle) if (PromptNest.IsMainThreadBusy() || (runspaceHandle.IsReadLine && PromptNest.IsReadLineBusy())) { - var unusedTask = PromptNest + _ = PromptNest .ReleaseRunspaceHandleAsync(runspaceHandle) .ConfigureAwait(false); } @@ -1557,9 +1578,9 @@ internal void ExitNestedPrompt() /// unescaped before calling this method. /// /// - public async Task SetWorkingDirectoryAsync(string path) + public Task SetWorkingDirectoryAsync(string path) { - await this.SetWorkingDirectoryAsync(path, true); + return this.SetWorkingDirectoryAsync(path, isPathAlreadyEscaped: true); } /// @@ -1569,6 +1590,7 @@ public async Task SetWorkingDirectoryAsync(string path) /// Specify false to have the path escaped, otherwise specify true if the path has already been escaped. public async Task SetWorkingDirectoryAsync(string path, bool isPathAlreadyEscaped) { + Validate.IsNotNull(nameof(path), path); this.InitialWorkingDirectory = path; if (!isPathAlreadyEscaped) @@ -1578,10 +1600,10 @@ public async Task SetWorkingDirectoryAsync(string path, bool isPathAlreadyEscape await ExecuteCommandAsync( new PSCommand().AddCommand("Set-Location").AddParameter("Path", path), - null, + errorMessages: null, sendOutputToHost: false, sendErrorToHost: false, - addToHistory: false); + addToHistory: false).ConfigureAwait(false); } /// @@ -1675,6 +1697,8 @@ internal static string WildcardEscapePath(string path, bool escapeSpaces = false [Obsolete("This API is not meant for public usage and should not be used.")] public static string EscapePath(string path, bool escapeSpaces) { + Validate.IsNotNull(nameof(path), path); + return WildcardEscapePath(path, escapeSpaces); } @@ -1728,6 +1752,8 @@ internal static string UnescapeWildcardEscapedPath(string wildcardEscapedPath) [Obsolete("This API is not meant for public usage and should not be used.")] public static string UnescapePath(string path) { + Validate.IsNotNull(nameof(path), path); + return UnescapeWildcardEscapedPath(path); } @@ -1816,6 +1842,8 @@ public MinifiedRunspaceDetails() public MinifiedRunspaceDetails(RunspaceDetails eventArgs) { + Validate.IsNotNull(nameof(eventArgs), eventArgs); + this.PowerShellVersion = new PowerShellVersion(eventArgs.PowerShellVersion); this.RunspaceType = eventArgs.Location; this.ConnectionString = eventArgs.ConnectionString; @@ -1899,9 +1927,7 @@ private void WriteExceptionToHost(Exception e) const string ExceptionFormat = "{0}\r\n{1}\r\n + CategoryInfo : {2}\r\n + FullyQualifiedErrorId : {3}"; - IContainsErrorRecord containsErrorRecord = e as IContainsErrorRecord; - - if (containsErrorRecord == null || + if (!(e is IContainsErrorRecord containsErrorRecord) || containsErrorRecord.ErrorRecord == null) { this.WriteError(e.Message, null, 0, 0); @@ -1966,7 +1992,7 @@ private void WriteError(string errorMessage) } } - void powerShell_InvocationStateChanged(object sender, PSInvocationStateChangedEventArgs e) + void PowerShell_InvocationStateChanged(object sender, PSInvocationStateChangedEventArgs e) { SessionStateChangedEventArgs eventArgs = TranslateInvocationStateInfo(e.InvocationStateInfo); this.OnSessionStateChanged(this, eventArgs); @@ -1974,9 +2000,9 @@ void powerShell_InvocationStateChanged(object sender, PSInvocationStateChangedEv private static SessionStateChangedEventArgs TranslateInvocationStateInfo(PSInvocationStateInfo invocationState) { - PowerShellContextState newState = PowerShellContextState.Unknown; PowerShellExecutionResult executionResult = PowerShellExecutionResult.NotFinished; + PowerShellContextState newState; switch (invocationState.State) { case PSInvocationState.NotStarted: @@ -2150,7 +2176,7 @@ private SessionDetails GetSessionDetails(Func invokeAction) private async Task GetSessionDetailsInRunspaceAsync() { - using (RunspaceHandle runspaceHandle = await this.GetRunspaceHandleAsync()) + using (RunspaceHandle runspaceHandle = await this.GetRunspaceHandleAsync().ConfigureAwait(false)) { return this.GetSessionDetailsInRunspace(runspaceHandle.Runspace); } @@ -2302,8 +2328,7 @@ private void StartCommandLoopOnRunspaceAvailable() return; } - EventHandler handler = null; - handler = (runspace, eventArgs) => + void availabilityChangedHandler(object runspace, RunspaceAvailabilityEventArgs eventArgs) { if (eventArgs.RunspaceAvailability != RunspaceAvailability.Available || this.versionSpecificOperations.IsDebuggerStopped(this.PromptNest, (Runspace)runspace)) @@ -2311,12 +2336,12 @@ private void StartCommandLoopOnRunspaceAvailable() return; } - ((Runspace)runspace).AvailabilityChanged -= handler; + ((Runspace)runspace).AvailabilityChanged -= availabilityChangedHandler; Interlocked.Exchange(ref this.isCommandLoopRestarterSet, 0); this.ConsoleReader?.StartCommandLoop(); - }; + } - this.CurrentRunspace.Runspace.AvailabilityChanged += handler; + this.CurrentRunspace.Runspace.AvailabilityChanged += availabilityChangedHandler; Interlocked.Exchange(ref this.isCommandLoopRestarterSet, 1); } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/RemoteFileManagerService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/RemoteFileManagerService.cs index cca85a199..ac44f445d 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/RemoteFileManagerService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/RemoteFileManagerService.cs @@ -315,7 +315,7 @@ public async Task FetchRemoteFileAsync( command.AddParameter("Encoding", "Byte"); byte[] fileContent = - (await this.powerShellContext.ExecuteCommandAsync(command, false, false)) + (await this.powerShellContext.ExecuteCommandAsync(command, false, false).ConfigureAwait(false)) .FirstOrDefault(); if (fileContent != null) @@ -382,11 +382,11 @@ public async Task SaveRemoteFileAsync(string localFilePath) StringBuilder errorMessages = new StringBuilder(); - await this.powerShellContext.ExecuteCommandAsync( + await powerShellContext.ExecuteCommandAsync( saveCommand, errorMessages, false, - false); + false).ConfigureAwait(false); if (errorMessages.Length > 0) { @@ -528,7 +528,7 @@ private async void HandleRunspaceChangedAsync(object sender, RunspaceChangedEven { foreach (string remotePath in remotePathMappings.OpenedPaths) { - await this.editorOperations?.CloseFileAsync(remotePath); + await (this.editorOperations?.CloseFileAsync(remotePath)).ConfigureAwait(false); } } } @@ -577,7 +577,7 @@ private async void HandlePSEventReceivedAsync(object sender, PSEventArgs args) // If fileContent is still null after trying to // unpack the contents, just return an empty byte // array. - fileContent = fileContent ?? new byte[0]; + fileContent = fileContent ?? Array.Empty(); if (remoteFilePath != null) { @@ -589,8 +589,8 @@ private async void HandlePSEventReceivedAsync(object sender, PSEventArgs args) } else { - await this.editorOperations?.NewFileAsync(); - EditorContext context = await this.editorOperations?.GetEditorContextAsync(); + await (this.editorOperations?.NewFileAsync()).ConfigureAwait(false); + EditorContext context = await (editorOperations?.GetEditorContextAsync()).ConfigureAwait(false); context?.CurrentFile.InsertText(Encoding.UTF8.GetString(fileContent, 0, fileContent.Length)); } } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/Capabilities/DscBreakpointCapability.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/Capabilities/DscBreakpointCapability.cs index 64e459ecb..220801dfa 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/Capabilities/DscBreakpointCapability.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/Capabilities/DscBreakpointCapability.cs @@ -19,7 +19,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShellContext internal class DscBreakpointCapability : IRunspaceCapability { - private string[] dscResourceRootPaths = new string[0]; + private string[] dscResourceRootPaths = Array.Empty(); private Dictionary breakpointsPerFile = new Dictionary(); @@ -60,7 +60,7 @@ await powerShellContext.ExecuteScriptStringAsync( ? $"Enable-DscDebug -Breakpoint {hashtableString}" : "Disable-DscDebug", false, - false); + false).ConfigureAwait(false); // Verify all the breakpoints and return them foreach (var breakpoint in breakpoints) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/Host/EditorServicesPSHostUserInterface.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/Host/EditorServicesPSHostUserInterface.cs index edd9f3879..adb20b7ef 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/Host/EditorServicesPSHostUserInterface.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/Host/EditorServicesPSHostUserInterface.cs @@ -149,12 +149,10 @@ private void ShowCommandPrompt() { this.commandLoopCancellationToken = new CancellationTokenSource(); - var commandLoopThreadTask = - Task.Factory.StartNew( - async () => - { - await this.StartReplLoopAsync(this.commandLoopCancellationToken.Token); - }); + var commandLoopThreadTask = Task.Factory.StartNew(() => + { + return this.StartReplLoopAsync(this.commandLoopCancellationToken.Token); + }); } else { @@ -719,8 +717,8 @@ private async Task WritePromptStringToHostAsync(CancellationToken cancellationTo try { if (this.lastPromptLocation != null && - this.lastPromptLocation.X == await ConsoleProxy.GetCursorLeftAsync(cancellationToken) && - this.lastPromptLocation.Y == await ConsoleProxy.GetCursorTopAsync(cancellationToken)) + this.lastPromptLocation.X == await ConsoleProxy.GetCursorLeftAsync(cancellationToken).ConfigureAwait(false) && + this.lastPromptLocation.Y == await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false)) { return; } @@ -735,7 +733,7 @@ private async Task WritePromptStringToHostAsync(CancellationToken cancellationTo cancellationToken.ThrowIfCancellationRequested(); string promptString = - (await this.powerShellContext.ExecuteCommandAsync(promptCommand, false, false)) + (await this.powerShellContext.ExecuteCommandAsync(promptCommand, false, false).ConfigureAwait(false)) .Select(pso => pso.BaseObject) .OfType() .FirstOrDefault() ?? "PS> "; @@ -768,8 +766,8 @@ private async Task WritePromptStringToHostAsync(CancellationToken cancellationTo // Write the prompt string this.WriteOutput(promptString, false); this.lastPromptLocation = new Coordinates( - await ConsoleProxy.GetCursorLeftAsync(cancellationToken), - await ConsoleProxy.GetCursorTopAsync(cancellationToken)); + await ConsoleProxy.GetCursorLeftAsync(cancellationToken).ConfigureAwait(false), + await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false)); } private void WriteDebuggerBanner(DebuggerStopEventArgs eventArgs) @@ -816,7 +814,7 @@ private async Task StartReplLoopAsync(CancellationToken cancellationToken) try { - await this.WritePromptStringToHostAsync(cancellationToken); + await this.WritePromptStringToHostAsync(cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -825,8 +823,8 @@ private async Task StartReplLoopAsync(CancellationToken cancellationToken) try { - originalCursorTop = await ConsoleProxy.GetCursorTopAsync(cancellationToken); - commandString = await this.ReadCommandLineAsync(cancellationToken); + originalCursorTop = await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false); + commandString = await this.ReadCommandLineAsync(cancellationToken).ConfigureAwait(false); } catch (PipelineStoppedException) { @@ -853,7 +851,7 @@ private async Task StartReplLoopAsync(CancellationToken cancellationToken) finally { if (!cancellationToken.IsCancellationRequested && - originalCursorTop == await ConsoleProxy.GetCursorTopAsync(cancellationToken)) + originalCursorTop == await ConsoleProxy.GetCursorTopAsync(cancellationToken).ConfigureAwait(false)) { this.WriteLine(); } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/InvocationEventQueue.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/InvocationEventQueue.cs index b28f0e2d2..3ce2f8786 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/InvocationEventQueue.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/InvocationEventQueue.cs @@ -87,15 +87,15 @@ internal async Task> ExecuteCommandOnIdleAsync( await SetInvocationRequestAsync( new InvocationRequest( - pwsh => request.ExecuteAsync().GetAwaiter().GetResult())); + pwsh => request.ExecuteAsync().GetAwaiter().GetResult())).ConfigureAwait(false); try { - return await request.Results; + return await request.Results.ConfigureAwait(false); } finally { - await SetInvocationRequestAsync(request: null); + await SetInvocationRequestAsync(request: null).ConfigureAwait(false); } } @@ -122,21 +122,21 @@ internal async Task InvokeOnPipelineThreadAsync(Action invocationAct } }); - await SetInvocationRequestAsync(request); + await SetInvocationRequestAsync(request).ConfigureAwait(false); try { - await request.Task; + await request.Task.ConfigureAwait(false); } finally { - await SetInvocationRequestAsync(null); + await SetInvocationRequestAsync(null).ConfigureAwait(false); } } private async Task WaitForExistingRequestAsync() { InvocationRequest existingRequest; - await _lock.WaitAsync(); + await _lock.WaitAsync().ConfigureAwait(false); try { existingRequest = _invocationRequest; @@ -150,13 +150,13 @@ private async Task WaitForExistingRequestAsync() _lock.Release(); } - await existingRequest.Task; + await existingRequest.Task.ConfigureAwait(false); } private async Task SetInvocationRequestAsync(InvocationRequest request) { - await WaitForExistingRequestAsync(); - await _lock.WaitAsync(); + await WaitForExistingRequestAsync().ConfigureAwait(false); + await _lock.WaitAsync().ConfigureAwait(false); try { _invocationRequest = request; diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/LegacyReadLineContext.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/LegacyReadLineContext.cs index 8f116a201..9c62e2083 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/LegacyReadLineContext.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/LegacyReadLineContext.cs @@ -22,9 +22,9 @@ public Task AbortReadLineAsync() return Task.FromResult(true); } - public async Task InvokeReadLineAsync(bool isCommandLine, CancellationToken cancellationToken) + public Task InvokeReadLineAsync(bool isCommandLine, CancellationToken cancellationToken) { - return await _legacyReadLine.InvokeLegacyReadLineAsync(isCommandLine, cancellationToken); + return _legacyReadLine.InvokeLegacyReadLineAsync(isCommandLine, cancellationToken); } public Task WaitForReadLineExitAsync() diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs index f03e17f07..99ea3b40a 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs @@ -46,15 +46,15 @@ internal class PSReadLinePromptContext : IPromptContext private readonly PowerShellContextService _powerShellContext; - private PromptNest _promptNest; + private readonly PromptNest _promptNest; - private InvocationEventQueue _invocationEventQueue; + private readonly InvocationEventQueue _invocationEventQueue; - private ConsoleReadLine _consoleReadLine; + private readonly ConsoleReadLine _consoleReadLine; - private CancellationTokenSource _readLineCancellationSource; + private readonly PSReadLineProxy _readLineProxy; - private PSReadLineProxy _readLineProxy; + private CancellationTokenSource _readLineCancellationSource; internal PSReadLinePromptContext( PowerShellContextService powerShellContext, @@ -124,15 +124,15 @@ public async Task InvokeReadLineAsync(bool isCommandLine, CancellationTo if (!isCommandLine) { return await _consoleReadLine.InvokeLegacyReadLineAsync( - false, - _readLineCancellationSource.Token); + isCommandLine: false, + _readLineCancellationSource.Token).ConfigureAwait(false); } var result = (await _powerShellContext.ExecuteCommandAsync( new PSCommand() .AddScript(ReadLineScript) .AddArgument(_readLineCancellationSource.Token), - null, + errorMessages: null, new ExecutionOptions() { WriteErrorsToHost = false, @@ -140,7 +140,7 @@ public async Task InvokeReadLineAsync(bool isCommandLine, CancellationTo InterruptCommandPrompt = false, AddToHistory = false, IsReadLine = isCommandLine - })) + }).ConfigureAwait(false)) .FirstOrDefault(); return cancellationToken.IsCancellationRequested @@ -173,7 +173,7 @@ public async Task AbortReadLineAsync() { _readLineCancellationSource.Cancel(); - await WaitForReadLineExitAsync(); + await WaitForReadLineExitAsync().ConfigureAwait(false); } public void WaitForReadLineExit() @@ -183,7 +183,7 @@ public void WaitForReadLineExit() } public async Task WaitForReadLineExitAsync() { - using (await _promptNest.GetRunspaceHandleAsync(CancellationToken.None, isReadLine: true)) + using (await _promptNest.GetRunspaceHandleAsync(CancellationToken.None, isReadLine: true).ConfigureAwait(false)) { } } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PipelineExecutionRequest.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PipelineExecutionRequest.cs index 21af0280f..fafd1faca 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PipelineExecutionRequest.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PipelineExecutionRequest.cs @@ -72,9 +72,9 @@ public async Task ExecuteAsync() await _powerShellContext.ExecuteCommandAsync( _psCommand, _errorMessages, - _executionOptions); + _executionOptions).ConfigureAwait(false); - var unusedTask = Task.Run(() => _resultsTask.SetResult(results)); + _ = Task.Run(() => _resultsTask.SetResult(results)); } } } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PromptNest.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PromptNest.cs index 380c4bb81..0bed49d3a 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PromptNest.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PromptNest.cs @@ -18,21 +18,21 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShellContext /// internal class PromptNest : IDisposable { - private ConcurrentStack _frameStack; + private readonly ConcurrentStack _frameStack; - private PromptNestFrame _readLineFrame; + private readonly PromptNestFrame _readLineFrame; - private IHostInput _consoleReader; + private readonly IVersionSpecificOperations _versionSpecificOperations; - private PowerShellContextService _powerShellContext; + private readonly object _syncObject = new object(); - private IVersionSpecificOperations _versionSpecificOperations; + private readonly object _disposeSyncObject = new object(); - private bool _isDisposed; + private IHostInput _consoleReader; - private object _syncObject = new object(); + private PowerShellContextService _powerShellContext; - private object _disposeSyncObject = new object(); + private bool _isDisposed; /// /// Initializes a new instance of the class. @@ -297,10 +297,10 @@ internal async Task GetRunspaceHandleAsync(CancellationToken can // is in process. if (isReadLine && !_powerShellContext.IsCurrentRunspaceOutOfProcess()) { - await GetRunspaceHandleImplAsync(cancellationToken, isReadLine: false); + await GetRunspaceHandleImplAsync(cancellationToken, isReadLine: false).ConfigureAwait(false); } - return await GetRunspaceHandleImplAsync(cancellationToken, isReadLine); + return await GetRunspaceHandleImplAsync(cancellationToken, isReadLine).ConfigureAwait(false); } /// @@ -340,10 +340,10 @@ internal async Task ReleaseRunspaceHandleAsync(RunspaceHandle runspaceHandle) return; } - await ReleaseRunspaceHandleImplAsync(runspaceHandle.IsReadLine); + await ReleaseRunspaceHandleImplAsync(runspaceHandle.IsReadLine).ConfigureAwait(false); if (runspaceHandle.IsReadLine && !_powerShellContext.IsCurrentRunspaceOutOfProcess()) { - await ReleaseRunspaceHandleImplAsync(isReadLine: false); + await ReleaseRunspaceHandleImplAsync(isReadLine: false).ConfigureAwait(false); } } @@ -442,11 +442,11 @@ internal async Task WaitForCurrentFrameExitAsync(Func ini var currentFrame = CurrentFrame; try { - await initiator.Invoke(currentFrame); + await initiator.Invoke(currentFrame).ConfigureAwait(false); } finally { - await currentFrame.WaitForFrameExitAsync(CancellationToken.None); + await currentFrame.WaitForFrameExitAsync(CancellationToken.None).ConfigureAwait(false); } } @@ -473,7 +473,7 @@ internal async Task WaitForCurrentFrameExitAsync(Action initiat } finally { - await currentFrame.WaitForFrameExitAsync(CancellationToken.None); + await currentFrame.WaitForFrameExitAsync(CancellationToken.None).ConfigureAwait(false); } } @@ -490,7 +490,7 @@ internal async Task WaitForCurrentFrameExitAsync() return; } - await WaitForCurrentFrameExitAsync(CancellationToken.None); + await WaitForCurrentFrameExitAsync(CancellationToken.None).ConfigureAwait(false); } /// @@ -509,7 +509,7 @@ internal async Task WaitForCurrentFrameExitAsync(CancellationToken cancellationT return; } - await CurrentFrame.WaitForFrameExitAsync(cancellationToken); + await CurrentFrame.WaitForFrameExitAsync(cancellationToken).ConfigureAwait(false); } private AsyncQueue NewHandleQueue() @@ -533,10 +533,10 @@ private async Task GetRunspaceHandleImplAsync(CancellationToken { if (isReadLine) { - return await _readLineFrame.Queue.DequeueAsync(cancellationToken); + return await _readLineFrame.Queue.DequeueAsync(cancellationToken).ConfigureAwait(false); } - return await CurrentFrame.Queue.DequeueAsync(cancellationToken); + return await CurrentFrame.Queue.DequeueAsync(cancellationToken).ConfigureAwait(false); } private void ReleaseRunspaceHandleImpl(bool isReadLine) @@ -554,11 +554,11 @@ private async Task ReleaseRunspaceHandleImplAsync(bool isReadLine) { if (isReadLine) { - await _readLineFrame.Queue.EnqueueAsync(new RunspaceHandle(_powerShellContext, true)); + await _readLineFrame.Queue.EnqueueAsync(new RunspaceHandle(_powerShellContext, true)).ConfigureAwait(false); return; } - await CurrentFrame.Queue.EnqueueAsync(new RunspaceHandle(_powerShellContext, false)); + await CurrentFrame.Queue.EnqueueAsync(new RunspaceHandle(_powerShellContext, false)).ConfigureAwait(false); } } } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PromptNestFrame.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PromptNestFrame.cs index 2d6a1a473..fee9f740d 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/PromptNestFrame.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/PromptNestFrame.cs @@ -130,7 +130,7 @@ internal void WaitForFrameExit(CancellationToken cancellationToken) /// internal async Task WaitForFrameExitAsync(CancellationToken cancellationToken) { - await _frameExited.WaitAsync(cancellationToken); + await _frameExited.WaitAsync(cancellationToken).ConfigureAwait(false); _frameExited.Release(); } } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Session/ThreadController.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Session/ThreadController.cs index c84dcae3d..ee42a8a1b 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Session/ThreadController.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Session/ThreadController.cs @@ -66,8 +66,8 @@ internal bool IsCurrentThread() internal async Task> RequestPipelineExecutionAsync( PipelineExecutionRequest executionRequest) { - await PipelineRequestQueue.EnqueueAsync(executionRequest); - return await executionRequest.Results; + await PipelineRequestQueue.EnqueueAsync(executionRequest).ConfigureAwait(false); + return await executionRequest.Results.ConfigureAwait(false); } /// diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/TemplateService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/TemplateService.cs index ed0846481..7dfd8e022 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/TemplateService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/TemplateService.cs @@ -77,7 +77,7 @@ public async Task ImportPlasterIfInstalledAsync() var getResult = await this.powerShellContext.ExecuteCommandAsync( - psCommand, false, false); + psCommand, false, false).ConfigureAwait(false); PSObject moduleObject = getResult.First(); this.isPlasterInstalled = moduleObject != null; @@ -100,7 +100,7 @@ await this.powerShellContext.ExecuteCommandAsync( var importResult = await this.powerShellContext.ExecuteCommandAsync( - psCommand, false, false); + psCommand, false, false).ConfigureAwait(false); this.isPlasterLoaded = importResult.Any(); string loadedQualifier = @@ -141,7 +141,7 @@ public async Task GetAvailableTemplatesAsync( var templateObjects = await this.powerShellContext.ExecuteCommandAsync( - psCommand, false, false); + psCommand, false, false).ConfigureAwait(false); this.logger.LogTrace($"Found {templateObjects.Count()} Plaster templates"); @@ -180,7 +180,7 @@ await this.powerShellContext.ExecuteCommandAsync( WriteOutputToHost = false, WriteErrorsToHost = true, InterruptCommandPrompt = true - }); + }).ConfigureAwait(false); // If any errors were written out, creation was not successful return errorString.Length == 0; diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/Utilities/CommandHelpers.cs b/src/PowerShellEditorServices/Services/PowerShellContext/Utilities/CommandHelpers.cs index ced8732f7..347b2faa8 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/Utilities/CommandHelpers.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/Utilities/CommandHelpers.cs @@ -43,6 +43,7 @@ public static async Task GetCommandInfoAsync( PowerShellContextService powerShellContext) { Validate.IsNotNull(nameof(commandName), commandName); + Validate.IsNotNull(nameof(powerShellContext), powerShellContext); // Make sure the command's noun isn't blacklisted. This is // currently necessary to make sure that Get-Command doesn't @@ -59,12 +60,10 @@ public static async Task GetCommandInfoAsync( command.AddArgument(commandName); command.AddParameter("ErrorAction", "Ignore"); - return - (await powerShellContext - .ExecuteCommandAsync(command, false, false)) - .Select(o => o.BaseObject) - .OfType() - .FirstOrDefault(); + return (await powerShellContext.ExecuteCommandAsync(command, sendOutputToHost: false, sendErrorToHost: false).ConfigureAwait(false)) + .Select(o => o.BaseObject) + .OfType() + .FirstOrDefault(); } /// @@ -77,6 +76,8 @@ public static async Task GetCommandSynopsisAsync( CommandInfo commandInfo, PowerShellContextService powerShellContext) { + Validate.IsNotNull(nameof(powerShellContext), powerShellContext); + string synopsisString = string.Empty; if (commandInfo != null && @@ -89,7 +90,7 @@ public static async Task GetCommandSynopsisAsync( command.AddArgument(commandInfo); command.AddParameter("ErrorAction", "Ignore"); - var results = await powerShellContext.ExecuteCommandAsync(command, false, false); + var results = await powerShellContext.ExecuteCommandAsync(command, sendOutputToHost: false, sendErrorToHost: false).ConfigureAwait(false); PSObject helpObject = results.FirstOrDefault(); if (helpObject != null) diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs index a8272d375..a11fe38f2 100644 --- a/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs +++ b/src/PowerShellEditorServices/Services/Symbols/SymbolDetails.cs @@ -52,14 +52,14 @@ static internal async Task CreateAsync( case SymbolType.Function: CommandInfo commandInfo = await CommandHelpers.GetCommandInfoAsync( symbolReference.SymbolName, - powerShellContext); + powerShellContext).ConfigureAwait(false); if (commandInfo != null) { symbolDetails.Documentation = await CommandHelpers.GetCommandSynopsisAsync( commandInfo, - powerShellContext); + powerShellContext).ConfigureAwait(false); if (commandInfo.CommandType == CommandTypes.Application) { diff --git a/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs b/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs index a9a36923d..a87467789 100644 --- a/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs +++ b/src/PowerShellEditorServices/Services/Symbols/SymbolsService.cs @@ -269,7 +269,7 @@ public async Task FindSymbolDetailsAtLocationAsync( symbolReference.FilePath = scriptFile.FilePath; SymbolDetails symbolDetails = await SymbolDetails.CreateAsync( symbolReference, - _powerShellContextService); + _powerShellContextService).ConfigureAwait(false); return symbolDetails; } @@ -301,7 +301,7 @@ public async Task FindParameterSetsInFileAsync( CommandInfo commandInfo = await CommandHelpers.GetCommandInfoAsync( foundSymbol.SymbolName, - powerShellContext); + powerShellContext).ConfigureAwait(false); if (commandInfo == null) { @@ -414,7 +414,7 @@ public async Task GetDefinitionOfSymbolAsync( CommandInfo cmdInfo = await CommandHelpers.GetCommandInfoAsync( foundSymbol.SymbolName, - _powerShellContextService); + _powerShellContextService).ConfigureAwait(false); foundDefinition = FindDeclarationForBuiltinCommand( @@ -474,7 +474,7 @@ private ScriptFile[] GetBuiltinCommandScriptFiles( { if (moduleInfo == null) { - return new ScriptFile[0]; + return Array.Empty(); } string modPath = moduleInfo.Path; diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs index 4dc284340..50c7c4155 100644 --- a/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs +++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/AstOperations.cs @@ -94,7 +94,7 @@ public static async Task GetCompletionsAsync( // main runspace. if (powerShellContext.IsCurrentRunspaceOutOfProcess()) { - using (RunspaceHandle runspaceHandle = await powerShellContext.GetRunspaceHandleAsync(cancellationToken)) + using (RunspaceHandle runspaceHandle = await powerShellContext.GetRunspaceHandleAsync(cancellationToken).ConfigureAwait(false)) using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create()) { powerShell.Runspace = runspaceHandle.Runspace; @@ -127,7 +127,7 @@ await powerShellContext.InvokeOnPipelineThreadAsync( cursorPosition, options: null, powershell: pwsh); - }); + }).ConfigureAwait(false); stopwatch.Stop(); logger.LogTrace($"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms."); diff --git a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs index 7ca206dae..33aa11419 100644 --- a/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs +++ b/src/PowerShellEditorServices/Services/Symbols/Vistors/FindReferencesVisitor.cs @@ -94,7 +94,7 @@ public override AstVisitAction VisitCommand(CommandAst commandAst) if (commandName.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase) || alaises.Contains(symbolRef.ScriptRegion.Text.ToLower()) || command.Equals(symbolRef.ScriptRegion.Text, StringComparison.CurrentCultureIgnoreCase) || - (!command.Equals(string.Empty) && command.Equals(symbolRefCommandName, StringComparison.CurrentCultureIgnoreCase))) + (!string.IsNullOrEmpty(command) && command.Equals(symbolRefCommandName, StringComparison.CurrentCultureIgnoreCase))) { this.FoundReferences.Add(new SymbolReference( SymbolType.Function, diff --git a/src/PowerShellEditorServices/Services/TextDocument/CompletionResults.cs b/src/PowerShellEditorServices/Services/TextDocument/CompletionResults.cs index e267eb0a1..26c5d7515 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/CompletionResults.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/CompletionResults.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -40,7 +41,7 @@ public sealed class CompletionResults /// public CompletionResults() { - this.Completions = new CompletionDetails[0]; + this.Completions = Array.Empty(); this.ReplacedRange = new BufferRange(0, 0, 0, 0); } diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/CodeActionHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/CodeActionHandler.cs index 36d5a5a92..ec1a8bd2d 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/CodeActionHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/CodeActionHandler.cs @@ -55,7 +55,7 @@ public void SetCapability(CodeActionCapability capability) public async Task Handle(CodeActionParams request, CancellationToken cancellationToken) { - IReadOnlyDictionary corrections = await _analysisService.GetMostRecentCodeActionsForFileAsync(request.TextDocument.Uri.OriginalString); + IReadOnlyDictionary corrections = await _analysisService.GetMostRecentCodeActionsForFileAsync(request.TextDocument.Uri.OriginalString).ConfigureAwait(false); if (corrections == null) { diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/CompletionHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/CompletionHandler.cs index a86f7ccf4..a176af218 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/CompletionHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/CompletionHandler.cs @@ -24,7 +24,7 @@ namespace Microsoft.PowerShell.EditorServices.Handlers internal class CompletionHandler : ICompletionHandler, ICompletionResolveHandler { const int DefaultWaitTimeoutMilliseconds = 5000; - private readonly CompletionItem[] s_emptyCompletionResult = new CompletionItem[0]; + private readonly CompletionItem[] s_emptyCompletionResult = Array.Empty(); private readonly ILogger _logger; private readonly PowerShellContextService _powerShellContextService; @@ -71,7 +71,7 @@ public async Task Handle(CompletionParams request, CancellationT await GetCompletionsInFileAsync( scriptFile, cursorLine, - cursorColumn); + cursorColumn).ConfigureAwait(false); CompletionItem[] completionItems = s_emptyCompletionResult; @@ -99,14 +99,14 @@ public async Task Handle(CompletionItem request, CancellationTok CommandInfo commandInfo = await CommandHelpers.GetCommandInfoAsync( request.Label, - _powerShellContextService); + _powerShellContextService).ConfigureAwait(false); if (commandInfo != null) { request.Documentation = await CommandHelpers.GetCommandSynopsisAsync( commandInfo, - _powerShellContextService); + _powerShellContextService).ConfigureAwait(false); } // Send back the updated CompletionItem @@ -158,7 +158,7 @@ await AstOperations.GetCompletionsAsync( fileOffset, _powerShellContextService, _logger, - cts.Token); + cts.Token).ConfigureAwait(false); } if (commandCompletion == null) diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DefinitionHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DefinitionHandler.cs index 1b59f9d7f..fae3aea65 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DefinitionHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DefinitionHandler.cs @@ -65,7 +65,7 @@ public async Task Handle(DefinitionParams request, Canc { SymbolReference foundDefinition = await _symbolsService.GetDefinitionOfSymbolAsync( scriptFile, - foundSymbol); + foundSymbol).ConfigureAwait(false); if (foundDefinition != null) { diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentHighlightHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentHighlightHandler.cs index afc90f7f3..c984b1489 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentHighlightHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentHighlightHandler.cs @@ -8,7 +8,6 @@ using Microsoft.PowerShell.EditorServices.Services.Symbols; using Microsoft.PowerShell.EditorServices.Services.TextDocument; using Microsoft.PowerShell.EditorServices.Utility; -using Microsoft.PowerShell.EditorServices.Utility; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Models; using OmniSharp.Extensions.LanguageServer.Protocol.Server; diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs index 9cd9aed2e..53ffb1f2b 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DocumentSymbolHandler.cs @@ -91,7 +91,7 @@ public Task Handle(DocumentSymbolPar } else { - symbols = new SymbolInformationOrDocumentSymbol[0]; + symbols = Array.Empty(); } diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/FormattingHandlers.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/FormattingHandlers.cs index 160587fa1..d3f4a467a 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/FormattingHandlers.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/FormattingHandlers.cs @@ -75,7 +75,7 @@ public async Task Handle(DocumentFormattingParams request, Ca formattedScript = await _analysisService.FormatAsync( scriptFile.Contents, pssaSettings, - null); + null).ConfigureAwait(false); formattedScript = formattedScript ?? scriptFile.Contents; return new TextEditContainer(new TextEdit @@ -159,7 +159,7 @@ public async Task Handle(DocumentRangeFormattingParams reques formattedScript = await _analysisService.FormatAsync( scriptFile.Contents, pssaSettings, - rangeList); + rangeList).ConfigureAwait(false); formattedScript = formattedScript ?? scriptFile.Contents; return new TextEditContainer(new TextEdit diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/HoverHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/HoverHandler.cs index 21de3b42a..722b03d78 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/HoverHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/HoverHandler.cs @@ -60,7 +60,7 @@ public async Task Handle(HoverParams request, CancellationToken cancellat await _symbolsService.FindSymbolDetailsAtLocationAsync( scriptFile, (int) request.Position.Line + 1, - (int) request.Position.Character + 1); + (int) request.Position.Character + 1).ConfigureAwait(false); List symbolInfo = new List(); Range symbolRange = null; diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/SignatureHelpHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/SignatureHelpHandler.cs index b89755cf0..2220a921d 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/SignatureHelpHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/SignatureHelpHandler.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -18,7 +19,7 @@ namespace Microsoft.PowerShell.EditorServices.Handlers { public class SignatureHelpHandler : ISignatureHelpHandler { - private static readonly SignatureInformation[] s_emptySignatureResult = new SignatureInformation[0]; + private static readonly SignatureInformation[] s_emptySignatureResult = Array.Empty(); private readonly DocumentSelector _documentSelector = new DocumentSelector( new DocumentFilter() @@ -65,7 +66,7 @@ await _symbolsService.FindParameterSetsInFileAsync( scriptFile, (int) request.Position.Line + 1, (int) request.Position.Character + 1, - _powerShellContextService); + _powerShellContextService).ConfigureAwait(false); SignatureInformation[] signatures = s_emptySignatureResult; diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/TextDocumentHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/TextDocumentHandler.cs index e54779af3..e9f844386 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/TextDocumentHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/TextDocumentHandler.cs @@ -62,8 +62,11 @@ public Task Handle(DidChangeTextDocumentParams notification, CancellationT textChange.Text)); } +#pragma warning disable CS4014 + // Kick off script diagnostics without blocking the response // TODO: Get all recently edited files in the workspace _analysisService.RunScriptDiagnosticsAsync(new ScriptFile[] { changedFile }); +#pragma warning restore CS4014 return Unit.Task; } @@ -88,8 +91,11 @@ public Task Handle(DidOpenTextDocumentParams notification, CancellationTok notification.TextDocument.Uri, notification.TextDocument.Text); +#pragma warning disable CS4014 + // Kick off script diagnostics without blocking the response // TODO: Get all recently edited files in the workspace _analysisService.RunScriptDiagnosticsAsync(new ScriptFile[] { openedFile }); +#pragma warning restore CS4014 _logger.LogTrace("Finished opening document."); return Unit.Task; @@ -126,7 +132,7 @@ public async Task Handle(DidSaveTextDocumentParams notification, Cancellat { if (_remoteFileManagerService.IsUnderRemoteTempPath(savedFile.FilePath)) { - await _remoteFileManagerService.SaveRemoteFileAsync(savedFile.FilePath); + await _remoteFileManagerService.SaveRemoteFileAsync(savedFile.FilePath).ConfigureAwait(false); } } return Unit.Value; diff --git a/src/PowerShellEditorServices/Services/TextDocument/ScriptFile.cs b/src/PowerShellEditorServices/Services/TextDocument/ScriptFile.cs index 5b1b58bd5..51ddd7f1a 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/ScriptFile.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/ScriptFile.cs @@ -649,7 +649,7 @@ private void ParseFileContents() ex.Message); parseErrors = new[] { parseError }; - this.ScriptTokens = new Token[0]; + this.ScriptTokens = Array.Empty(); this.ScriptAst = null; } @@ -666,7 +666,7 @@ private void ParseFileContents() if (IsUntitledPath(this.FilePath)) { // Need to initialize the ReferencedFiles property to an empty array. - this.ReferencedFiles = new string[0]; + this.ReferencedFiles = Array.Empty(); return; } diff --git a/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs b/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs index 7cc0cdc8e..949ba04dd 100644 --- a/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs +++ b/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs @@ -52,7 +52,7 @@ public async Task Handle(DidChangeConfigurationParams request, Cancellatio LanguageServerSettingsWrapper incomingSettings = request.Settings.ToObject(); if(incomingSettings == null) { - return await Unit.Task; + return await Unit.Task.ConfigureAwait(false); } bool oldLoadProfiles = _configurationService.CurrentSettings.EnableProfileLoading; @@ -70,7 +70,7 @@ public async Task Handle(DidChangeConfigurationParams request, Cancellatio _configurationService.CurrentSettings.EnableProfileLoading && oldLoadProfiles != _configurationService.CurrentSettings.EnableProfileLoading) { - await _powerShellContextService.LoadHostProfilesAsync(); + await _powerShellContextService.LoadHostProfilesAsync().ConfigureAwait(false); this._profilesLoaded = true; } @@ -139,7 +139,7 @@ public async Task Handle(DidChangeConfigurationParams request, Cancellatio _workspaceService.FollowSymlinks = incomingSettings.Search.FollowSymlinks; } - return await Unit.Task; + return await Unit.Task.ConfigureAwait(false); } public void SetCapability(DidChangeConfigurationCapability capability) diff --git a/src/PowerShellEditorServices/Utility/AsyncQueue.cs b/src/PowerShellEditorServices/Utility/AsyncQueue.cs index 44585762f..98cbed9bf 100644 --- a/src/PowerShellEditorServices/Utility/AsyncQueue.cs +++ b/src/PowerShellEditorServices/Utility/AsyncQueue.cs @@ -71,7 +71,7 @@ public AsyncQueue(IEnumerable initialItems) /// public async Task EnqueueAsync(T item) { - using (await queueLock.LockAsync()) + using (await queueLock.LockAsync().ConfigureAwait(false)) { TaskCompletionSource requestTaskSource = null;