diff --git a/.editorconfig b/.editorconfig index b1bfe93a1..0786fbe27 100644 --- a/.editorconfig +++ b/.editorconfig @@ -54,11 +54,11 @@ dotnet_diagnostic.CA1068.severity = error # CA1501: Avoid excessive inheritance dotnet_diagnostic.CA1501.severity = error # CA1502: Avoid excessive complexity -dotnet_diagnostic.CA1502.severity = warning +dotnet_diagnostic.CA1502.severity = silent # CA1505: Avoid unmaintainable code dotnet_diagnostic.CA1505.severity = error # CA1506: Avoid excessive class coupling -dotnet_diagnostic.CA1506.severity = warning +dotnet_diagnostic.CA1506.severity = silent # CA1507: Use nameof in place of string dotnet_diagnostic.CA1507.severity = error # CA1508: Avoid dead conditional code @@ -95,22 +95,22 @@ dotnet_diagnostic.RCS1210.severity = error # RCS1036: Remove unnecessary blank line dotnet_diagnostic.RCS1036.severity = error # RCS1075: Avoid empty catch clause that catches System.Exception -dotnet_diagnostic.RCS1075.severity = suggestion +dotnet_diagnostic.RCS1075.severity = error # RCS1170: Use read-only auto-implemented property dotnet_diagnostic.RCS1170.severity = error # VSTHRD002: Avoid problematic synchronous waits -dotnet_diagnostic.VSTHRD002.severity = suggestion +dotnet_diagnostic.VSTHRD002.severity = error # VSTHRD003: Avoid awaiting foreign Tasks -dotnet_diagnostic.VSTHRD003.severity = suggestion +dotnet_diagnostic.VSTHRD003.severity = error # VSTHRD105: Avoid method overloads that assume TaskScheduler.Current -dotnet_diagnostic.VSTHRD105.severity = suggestion +dotnet_diagnostic.VSTHRD105.severity = error # VSTHRD100: Avoid async void methods -dotnet_diagnostic.VSTHRD100.severity = suggestion +dotnet_diagnostic.VSTHRD100.severity = error # VSTHRD103: Call async methods when in an async method -dotnet_diagnostic.VSTHRD103.severity = suggestion +dotnet_diagnostic.VSTHRD103.severity = error # VSTHRD110: Observe result of async calls -dotnet_diagnostic.VSTHRD110.severity = suggestion +dotnet_diagnostic.VSTHRD110.severity = error # VSTHRD114: Avoid returning a null Task dotnet_diagnostic.VSTHRD114.severity = error # VSTHRD200: Use "Async" suffix for awaitable methods diff --git a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs index 0eddc622b..69aa7b97f 100644 --- a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs +++ b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs @@ -215,7 +215,7 @@ protected override void BeginProcessing() } #pragma warning restore IDE0022 - [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Uses ThrowTerminatingError() instead")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "We have to wait here, it's the whole program.")] protected override void EndProcessing() { _logger.Log(PsesLogLevel.Diagnostic, "Beginning EndProcessing block"); @@ -232,9 +232,7 @@ protected override void EndProcessing() using EditorServicesLoader psesLoader = EditorServicesLoader.Create(_logger, editorServicesConfig, SessionDetailsPath, _loggerUnsubscribers); _logger.Log(PsesLogLevel.Verbose, "Loading EditorServices"); // Synchronously start editor services and wait here until it shuts down. -#pragma warning disable VSTHRD002 psesLoader.LoadAndRunEditorServicesAsync().GetAwaiter().GetResult(); -#pragma warning restore VSTHRD002 } catch (Exception e) { diff --git a/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs b/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs index f2da0eb4e..cf5c45c75 100644 --- a/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs +++ b/src/PowerShellEditorServices.Hosting/EditorServicesLoader.cs @@ -382,6 +382,7 @@ private void ValidateConfiguration() } } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1825:Avoid zero-length array allocations", Justification = "Cannot use Array.Empty, since it must work in net452")] private static Version GetPSVersion() { // In order to read the $PSVersionTable variable, @@ -389,12 +390,10 @@ private static Version GetPSVersion() // which is expensive. // Rather than do that, we instead go straight to the source, // which is a static property, internal in WinPS and public in PS 6+ -#pragma warning disable CA1825 return typeof(PSObject).Assembly .GetType("System.Management.Automation.PSVersionInfo") .GetMethod("get_PSVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) - .Invoke(null, new object[0] /* Cannot use Array.Empty, since it must work in net452 */) as Version; -#pragma warning restore CA1825 + .Invoke(null, new object[0]) as Version; } } } diff --git a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs index 8f868d393..0f47bdad8 100644 --- a/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs +++ b/src/PowerShellEditorServices.Hosting/Internal/EditorServicesRunner.cs @@ -201,6 +201,7 @@ private async Task RunTempDebugSessionAsync(HostStartupInfo hostDetails) await debugServer.WaitForShutdown().ConfigureAwait(false); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD003:Avoid awaiting foreign Tasks", Justification = "It's a wrapper.")] private async Task StartDebugServer(Task debugServerCreation) { PsesDebugServer debugServer = await debugServerCreation.ConfigureAwait(false); @@ -304,6 +305,7 @@ private void WriteStartupBanner() _config.PSHost.UI.WriteLine(_config.StartupBanner); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD110:Observe result of async calls", Justification = "Intentionally fire and forget.")] private void DebugServer_OnSessionEnded(object sender, EventArgs args) { _logger.Log(PsesLogLevel.Verbose, "Debug session ended, restarting debug service..."); diff --git a/src/PowerShellEditorServices/Extensions/EditorContext.cs b/src/PowerShellEditorServices/Extensions/EditorContext.cs index f2ab42e8c..e79eb8c3b 100644 --- a/src/PowerShellEditorServices/Extensions/EditorContext.cs +++ b/src/PowerShellEditorServices/Extensions/EditorContext.cs @@ -92,9 +92,8 @@ public void SetSelection( /// Sets a selection in the host editor's active buffer. /// /// The range of the selection. - #pragma warning disable VSTHRD002 + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void SetSelection(FileRange selectionRange) => editorOperations.SetSelectionAsync(selectionRange.ToBufferRange()).Wait(); - #pragma warning restore VSTHRD002 #endregion } diff --git a/src/PowerShellEditorServices/Extensions/EditorObject.cs b/src/PowerShellEditorServices/Extensions/EditorObject.cs index 17006baf2..a43ab2995 100644 --- a/src/PowerShellEditorServices/Extensions/EditorObject.cs +++ b/src/PowerShellEditorServices/Extensions/EditorObject.cs @@ -115,13 +115,12 @@ internal EditorObject( /// at the time this method is invoked. /// /// A instance of the EditorContext class. - #pragma warning disable VSTHRD002, VSTHRD104 + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public EditorContext GetEditorContext() => _editorOperations.GetEditorContextAsync().Result; - #pragma warning restore VSTHRD002, VSTHRD104 internal void SetAsStaticInstance() { - EditorObject.Instance = this; + Instance = this; s_editorObjectReady.TrySetResult(true); } } diff --git a/src/PowerShellEditorServices/Extensions/EditorWindow.cs b/src/PowerShellEditorServices/Extensions/EditorWindow.cs index 8c9048c3c..6d9d4c3ff 100644 --- a/src/PowerShellEditorServices/Extensions/EditorWindow.cs +++ b/src/PowerShellEditorServices/Extensions/EditorWindow.cs @@ -43,24 +43,28 @@ internal EditorWindow(IEditorOperations editorOperations) /// Shows an informational message to the user. /// /// The message to be shown. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void ShowInformationMessage(string message) => editorOperations.ShowInformationMessageAsync(message).Wait(); /// /// Shows an error message to the user. /// /// The message to be shown. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void ShowErrorMessage(string message) => editorOperations.ShowErrorMessageAsync(message).Wait(); /// /// Shows a warning message to the user. /// /// The message to be shown. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void ShowWarningMessage(string message) => editorOperations.ShowWarningMessageAsync(message).Wait(); /// /// Sets the status bar message in the editor UI (if applicable). /// /// The message to be shown. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void SetStatusBarMessage(string message) => editorOperations.SetStatusBarMessageAsync(message, null).Wait(); /// @@ -68,6 +72,7 @@ internal EditorWindow(IEditorOperations editorOperations) /// /// The message to be shown. /// A timeout in milliseconds for how long the message should remain visible. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void SetStatusBarMessage(string message, int timeout) => editorOperations.SetStatusBarMessageAsync(message, timeout).Wait(); #endregion diff --git a/src/PowerShellEditorServices/Extensions/EditorWorkspace.cs b/src/PowerShellEditorServices/Extensions/EditorWorkspace.cs index b01c6eca7..e1e0824cb 100644 --- a/src/PowerShellEditorServices/Extensions/EditorWorkspace.cs +++ b/src/PowerShellEditorServices/Extensions/EditorWorkspace.cs @@ -42,12 +42,14 @@ public sealed class EditorWorkspace /// /// Creates a new file in the editor. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void NewFile() => editorOperations.NewFileAsync(string.Empty).Wait(); /// /// Creates a new file in the editor. /// /// The content to place in the new file. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void NewFile(string content) => editorOperations.NewFileAsync(content).Wait(); /// @@ -55,6 +57,7 @@ public sealed class EditorWorkspace /// its buffer will be made active. /// /// The path to the file to be opened. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void OpenFile(string filePath) => editorOperations.OpenFileAsync(filePath).Wait(); /// @@ -64,18 +67,21 @@ public sealed class EditorWorkspace /// /// The path to the file to be opened. /// Determines wether the file is opened as a preview or as a durable editor. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void OpenFile(string filePath, bool preview) => editorOperations.OpenFileAsync(filePath, preview).Wait(); /// /// Closes a file in the workspace. /// /// The path to the file to be closed. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void CloseFile(string filePath) => editorOperations.CloseFileAsync(filePath).Wait(); /// /// Saves an open file in the workspace. /// /// The path to the file to be saved. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void SaveFile(string filePath) => editorOperations.SaveFileAsync(filePath).Wait(); /// @@ -83,6 +89,7 @@ public sealed class EditorWorkspace /// /// The file to copy. /// The file to create. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void SaveFile(string oldFilePath, string newFilePath) => editorOperations.SaveFileAsync(oldFilePath, newFilePath).Wait(); #endregion diff --git a/src/PowerShellEditorServices/Extensions/FileContext.cs b/src/PowerShellEditorServices/Extensions/FileContext.cs index c8c32e58e..39a4a275e 100644 --- a/src/PowerShellEditorServices/Extensions/FileContext.cs +++ b/src/PowerShellEditorServices/Extensions/FileContext.cs @@ -208,14 +208,13 @@ public void InsertText( /// /// The text string to insert. /// The buffer range which will be replaced by the string. - #pragma warning disable VSTHRD002 + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void InsertText(string textToInsert, IFileRange insertRange) { editorOperations .InsertTextAsync(scriptFile.DocumentUri.ToString(), textToInsert, insertRange.ToBufferRange()) .Wait(); } - #pragma warning restore VSTHRD002 #endregion @@ -224,6 +223,7 @@ public void InsertText(string textToInsert, IFileRange insertRange) /// /// Saves this file. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD110:Observe result of async calls", Justification = "Supporting synchronous API.")] public void Save() => editorOperations.SaveFileAsync(scriptFile.FilePath); /// @@ -233,7 +233,7 @@ public void InsertText(string textToInsert, IFileRange insertRange) /// the path where the file should be saved, /// including the file name with extension as the leaf /// - #pragma warning disable VSTHRD002 + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] public void SaveAs(string newFilePath) { // Do some validation here so that we can provide a helpful error if the path won't work @@ -248,7 +248,6 @@ public void SaveAs(string newFilePath) editorOperations.SaveFileAsync(scriptFile.FilePath, newFilePath).Wait(); } - #pragma warning restore VSTHRD002 #endregion } diff --git a/src/PowerShellEditorServices/GlobalSuppressions.cs b/src/PowerShellEditorServices/GlobalSuppressions.cs deleted file mode 100644 index 3c0be1568..000000000 --- a/src/PowerShellEditorServices/GlobalSuppressions.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -// 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/IsExternalInit.cs b/src/PowerShellEditorServices/IsExternalInit.cs index c2a9d8275..c690a1820 100644 --- a/src/PowerShellEditorServices/IsExternalInit.cs +++ b/src/PowerShellEditorServices/IsExternalInit.cs @@ -1,4 +1,6 @@ -#pragma warning disable IDE0073 +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + #if NET5_0_OR_GREATER [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.IsExternalInit))] #else diff --git a/src/PowerShellEditorServices/Server/PsesLanguageServer.cs b/src/PowerShellEditorServices/Server/PsesLanguageServer.cs index c2e25f64b..03cd75307 100644 --- a/src/PowerShellEditorServices/Server/PsesLanguageServer.cs +++ b/src/PowerShellEditorServices/Server/PsesLanguageServer.cs @@ -70,9 +70,7 @@ public PsesLanguageServer( /// cref="PsesServiceCollectionExtensions.AddPsesLanguageServices"/>. /// /// A task that completes when the server is ready and listening. -#pragma warning disable CA1506 // Coupling complexity we don't care about public async Task StartAsync() -#pragma warning restore CA1506 { LanguageServer = await OmniSharp.Extensions.LanguageServer.Server.LanguageServer.From(options => { diff --git a/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs b/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs index 3c02510b9..243a9ebf9 100644 --- a/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs +++ b/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs @@ -17,6 +17,7 @@ namespace Microsoft.PowerShell.EditorServices.Server { internal static class PsesServiceCollectionExtensions { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD110:Observe result of async calls", Justification = "Using lazy initialization.")] public static IServiceCollection AddPsesLanguageServices( this IServiceCollection collection, HostStartupInfo hostStartupInfo) @@ -48,9 +49,7 @@ public static IServiceCollection AddPsesLanguageServices( // is ready, it will be available. NOTE: We cannot await this because it // uses a lazy initialization to avoid a race with the dependency injection // framework, see the EditorObject class for that! -#pragma warning disable VSTHRD110 extensionService.InitializeAsync(); -#pragma warning restore VSTHRD110 return extensionService; }) .AddSingleton(); diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs b/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs index 90faceda4..667a26bdd 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs @@ -923,6 +923,7 @@ private static string TrimScriptListingLine(PSObject scriptLineObj, ref int pref /// public event EventHandler DebuggerStopped; + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "It has to be async.")] internal async void OnDebuggerStopAsync(object sender, DebuggerStopEventArgs e) { try diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs index 700c154b9..1ec1557ed 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs @@ -440,6 +440,7 @@ public async Task OnStarted(IDebugAdapterServer server, CancellationToken cancel // be sent to the client. await _debugStateService.ServerStarted.Task.ConfigureAwait(false); + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD003:Avoid awaiting foreign Tasks", Justification = "It's a wrapper.")] private async Task OnExecutionCompletedAsync(Task executeTask) { bool isRunspaceClosed = false; diff --git a/src/PowerShellEditorServices/Services/PowerShell/Console/LegacyReadLine.cs b/src/PowerShellEditorServices/Services/PowerShell/Console/LegacyReadLine.cs index 3c5e7a1d2..28d29baa1 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Console/LegacyReadLine.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Console/LegacyReadLine.cs @@ -35,9 +35,7 @@ public LegacyReadLine( _onIdleAction = onIdleAction; } -#pragma warning disable CA1502 // Cyclomatic complexity we don't care about public override string ReadLine(CancellationToken cancellationToken) -#pragma warning restore CA1502 { string inputBeforeCompletion = null; string inputAfterCompletion = null; @@ -394,6 +392,7 @@ protected override ConsoleKeyInfo ReadKey(CancellationToken cancellationToken) } } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "This is a legacy implementation.")] private ConsoleKeyInfo ReadKeyWithIdleSupport(CancellationToken cancellationToken) { // We run the readkey function on another thread so we can run an idle handler diff --git a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs index 6c77daa82..a2072b2d9 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs @@ -29,9 +29,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShell.Host using Microsoft.PowerShell.EditorServices.Server; using OmniSharp.Extensions.DebugAdapter.Protocol.Server; -#pragma warning disable CA1506 // Coupling complexity we don't care about internal class PsesInternalHost : PSHost, IHostSupportsInteractiveSession, IRunspaceContext, IInternalPowerShellExecutionService -#pragma warning restore CA1506 { internal const string DefaultPrompt = "> "; diff --git a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DidChangeWatchedFilesHandler.cs b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DidChangeWatchedFilesHandler.cs index edbe9b0ad..aa4c0a969 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/Handlers/DidChangeWatchedFilesHandler.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/Handlers/DidChangeWatchedFilesHandler.cs @@ -41,6 +41,7 @@ public DidChangeWatchedFilesHandler( public DidChangeWatchedFilesRegistrationOptions GetRegistrationOptions( DidChangeWatchedFilesCapability capability, ClientCapabilities clientCapabilities) +#pragma warning disable CS8601 // Possible null reference assignment (it's from the library). => new() { Watchers = new[] @@ -52,6 +53,7 @@ public DidChangeWatchedFilesRegistrationOptions GetRegistrationOptions( }, }, }; +#pragma warning restore CS8601 // Possible null reference assignment. public Task Handle(DidChangeWatchedFilesParams request, CancellationToken cancellationToken) { diff --git a/src/PowerShellEditorServices/Services/TextDocument/TokenOperations.cs b/src/PowerShellEditorServices/Services/TextDocument/TokenOperations.cs index 6a6f789ff..9ed65db20 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/TokenOperations.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/TokenOperations.cs @@ -25,9 +25,7 @@ internal static class TokenOperations /// /// Extracts all of the unique foldable regions in a script given the list tokens /// -#pragma warning disable CA1502 // Cyclomatic complexity we don't care about internal static FoldingReferenceList FoldableReferences(Token[] tokens) -#pragma warning restore CA1502 { FoldingReferenceList refList = new(); diff --git a/src/PowerShellEditorServices/Services/Workspace/RemoteFileManagerService.cs b/src/PowerShellEditorServices/Services/Workspace/RemoteFileManagerService.cs index a3e46f4f1..961338023 100644 --- a/src/PowerShellEditorServices/Services/Workspace/RemoteFileManagerService.cs +++ b/src/PowerShellEditorServices/Services/Workspace/RemoteFileManagerService.cs @@ -252,6 +252,7 @@ function New-EditorFile { /// /// The IEditorOperations instance to use for opening/closing files in the editor. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD110:Observe result of async calls", Justification = "Intentionally fire and forget.")] public RemoteFileManagerService( ILoggerFactory factory, IRunspaceContext runspaceContext, @@ -275,7 +276,6 @@ public RemoteFileManagerService( // Delete existing temporary file cache path if it already exists TryDeleteTemporaryPath(); - // TODO: Do this somewhere other than the constructor and make it async // Register the psedit function in the current runspace RegisterPSEditFunctionAsync().HandleErrorsAsync(logger); } @@ -519,6 +519,8 @@ private RemotePathMappings GetPathMappings(IRunspaceInfo runspaceInfo) return remotePathMappings; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD002:Avoid problematic synchronous waits", Justification = "Supporting synchronous API.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD110:Observe result of async calls", Justification = "Intentionally fire and forget.")] private void HandleRunspaceChanged(object sender, RunspaceChangedEventArgs e) { if (e.ChangeAction == RunspaceChangeAction.Enter) @@ -572,6 +574,7 @@ private static bool ShouldTearDownRemoteFiles(RunspaceChangedEventArgs runspaceC StringComparison.CurrentCultureIgnoreCase); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "It has to be async.")] private async void HandlePSEventReceivedAsync(object sender, PSEventArgs args) { if (!string.Equals(RemoteSessionOpenFile, args.SourceIdentifier, StringComparison.CurrentCultureIgnoreCase)) diff --git a/src/PowerShellEditorServices/Utility/AsyncUtils.cs b/src/PowerShellEditorServices/Utility/AsyncUtils.cs index c3f146bb7..c94023a7e 100644 --- a/src/PowerShellEditorServices/Utility/AsyncUtils.cs +++ b/src/PowerShellEditorServices/Utility/AsyncUtils.cs @@ -33,6 +33,7 @@ internal static Task HandleErrorsAsync( : LogTaskErrors(task, logger, callerName, callerSourceFile, callerLineNumber); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD003:Avoid awaiting foreign Tasks", Justification = "It's a wrapper.")] private static async Task LogTaskErrors(Task task, ILogger logger, string callerName, string callerSourceFile, int callerLineNumber) { try diff --git a/test/PowerShellEditorServices.Test.E2E/PowerShellEditorServices.Test.E2E.csproj b/test/PowerShellEditorServices.Test.E2E/PowerShellEditorServices.Test.E2E.csproj index 77eacbd87..ec30df02e 100644 --- a/test/PowerShellEditorServices.Test.E2E/PowerShellEditorServices.Test.E2E.csproj +++ b/test/PowerShellEditorServices.Test.E2E/PowerShellEditorServices.Test.E2E.csproj @@ -9,7 +9,7 @@ - + diff --git a/test/PowerShellEditorServices.Test.E2E/Processes/StdioServerProcess.cs b/test/PowerShellEditorServices.Test.E2E/Processes/StdioServerProcess.cs index 0cfc516ec..9cc19810b 100644 --- a/test/PowerShellEditorServices.Test.E2E/Processes/StdioServerProcess.cs +++ b/test/PowerShellEditorServices.Test.E2E/Processes/StdioServerProcess.cs @@ -23,9 +23,8 @@ public class StdioServerProcess : ServerProcess /// /// The current server process (if any). /// -#pragma warning disable CA2213 + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2213:Disposable fields should be disposed", Justification = "It is diposed but with a lock.")] private Process _serverProcess; -#pragma warning restore CA2213 /// /// Create a new . diff --git a/test/PowerShellEditorServices.Test.E2E/packages.lock.json b/test/PowerShellEditorServices.Test.E2E/packages.lock.json index 59dfb28f8..91fccbf9e 100644 --- a/test/PowerShellEditorServices.Test.E2E/packages.lock.json +++ b/test/PowerShellEditorServices.Test.E2E/packages.lock.json @@ -41,13 +41,13 @@ }, "xunit": { "type": "Direct", - "requested": "[2.6.6, )", - "resolved": "2.6.6", - "contentHash": "MAbOOMtZIKyn2lrAmMlvhX0BhDOX/smyrTB+8WTXnSKkrmTGBS2fm8g1PZtHBPj91Dc5DJA7fY+/81TJ/yUFZw==", + "requested": "[2.7.0, )", + "resolved": "2.7.0", + "contentHash": "KcCI5zxh8zbUfQTeErc4oT7YokViVND2V0p4vDJ2VD4lhF9V5qCYMMDNixme7FdwYy3SwPHF+2xC2Dq4Z9GSlA==", "dependencies": { - "xunit.analyzers": "1.10.0", - "xunit.assert": "2.6.6", - "xunit.core": "[2.6.6]" + "xunit.analyzers": "1.11.0", + "xunit.assert": "2.7.0", + "xunit.core": "[2.7.0]" } }, "xunit.runner.visualstudio": { @@ -444,37 +444,37 @@ }, "xunit.analyzers": { "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "Lw8CiDy5NaAWcO6keqD7iZHYUTIuCOcoFrUHw5Sv84ITZ9gFeDybdkVdH0Y2maSlP9fUjtENyiykT44zwFQIHA==" + "resolved": "1.11.0", + "contentHash": "SCv+Ihxv+fCqotGeM8sVwLhw8nzAJ2aFRN5lcoKn9QtGdbVJ79JqDc+4u8/Ddnp2udxtmv+xYFWkHNlb/sk01w==" }, "xunit.assert": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "74Cm9lAZOk5TKCz2MvCBCByKsS23yryOKDIMxH3XRDHXmfGM02jKZWzRA7g4mGB41GnBnv/pcWP3vUYkrCtEcg==" + "resolved": "2.7.0", + "contentHash": "CCTs3bUhmIS4tDwK6Cn/IiabG3RhYzdf65eIkO7u9/grKoN9MrN780LzVED3E8v+vwmmj7b5TW3/GFuZHPAzWA==" }, "xunit.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "tqi7RfaNBqM7t8zx6QHryuBPzmotsZXKGaWnopQG2Ez5UV7JoWuyoNdT6gLpDIcKdGYey6YTXJdSr9IXDMKwjg==", + "resolved": "2.7.0", + "contentHash": "98tzqYAbtc/p/2Ba455XTNbD12Qoo8kPehjC4oDT46CAsLli5JOCU9hFF2MV3HHWMw/Y3yFUV2Vcukplbs6kuA==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]", - "xunit.extensibility.execution": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]", + "xunit.extensibility.execution": "[2.7.0]" } }, "xunit.extensibility.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "ty6VKByzbx4Toj4/VGJLEnlmOawqZiMv0in/tLju+ftA+lbWuAWDERM+E52Jfhj4ZYHrAYVa14KHK5T+dq0XxA==", + "resolved": "2.7.0", + "contentHash": "JLnx4PI0vn1Xr1Ust6ydrp2t/ktm2dyGPAVoDJV5gQuvBMSbd2K7WGzODa2ttiz030CeQ8nbsXl05+cvf7QNyA==", "dependencies": { "xunit.abstractions": "2.0.3" } }, "xunit.extensibility.execution": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "UDjIVGj2TepVKN3n32/qXIdb3U6STwTb9L6YEwoQO2A8OxiJS5QAVv2l1aT6tDwwv/9WBmm8Khh/LyHALipcng==", + "resolved": "2.7.0", + "contentHash": "bjY+crT1jOyxKagFjCMdEVzoenO2v66ru8+CK/0UaXvyG4U9Q3UTieJkbQXbi7/1yZIK1sGh01l5/jh2CwLJtQ==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]" } }, "Microsoft.PowerShell.EditorServices": { diff --git a/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs b/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs index 30b020c30..05386d43a 100644 --- a/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs +++ b/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs @@ -33,21 +33,21 @@ internal class TestReadLine : IReadLine } [Trait("Category", "DebugService")] - public class DebugServiceTests : IDisposable + public class DebugServiceTests : IAsyncLifetime { - private readonly PsesInternalHost psesHost; - private readonly BreakpointService breakpointService; - private readonly DebugService debugService; + private PsesInternalHost psesHost; + private BreakpointService breakpointService; + private DebugService debugService; private readonly BlockingCollection debuggerStoppedQueue = new(); - private readonly WorkspaceService workspace; - private readonly ScriptFile debugScriptFile; - private readonly ScriptFile oddPathScriptFile; - private readonly ScriptFile variableScriptFile; + private WorkspaceService workspace; + private ScriptFile debugScriptFile; + private ScriptFile oddPathScriptFile; + private ScriptFile variableScriptFile; private readonly TestReadLine testReadLine = new(); - public DebugServiceTests() + public async Task InitializeAsync() { - psesHost = PsesHostFactory.Create(NullLoggerFactory.Instance); + psesHost = await PsesHostFactory.Create(NullLoggerFactory.Instance); // This is required for remote debugging, but we call it here to end up in the same // state as the usual startup path. psesHost.DebugContext.EnableDebugMode(); @@ -76,26 +76,24 @@ public DebugServiceTests() variableScriptFile = GetDebugScript("VariableTest.ps1"); } - public void Dispose() + + public async Task DisposeAsync() { debugService.Abort(); + await Task.Run(psesHost.StopAsync); debuggerStoppedQueue.Dispose(); -#pragma warning disable VSTHRD002 - psesHost.StopAsync().Wait(); -#pragma warning restore VSTHRD002 - GC.SuppressFinalize(this); } /// - /// This event handler lets us test that the debugger stopped or paused as expected. It will - /// deadlock if called in the PSES Pipeline Thread, which can easily happen in this test - /// code when methods on are called. Hence we treat this test - /// code like UI code and use 'ConfigureAwait(true)' or 'Task.Run(...)' to ensure we stay - /// OFF the pipeline thread. + /// This event handler lets us test that the debugger stopped or paused + /// as expected. It will deadlock if called in the PSES Pipeline Thread. + /// Hence we use 'Task.Run(...)' when accessing the queue to ensure we + /// stay OFF the pipeline thread. /// /// /// - private void OnDebuggerStopped(object sender, DebuggerStoppedEventArgs e) => debuggerStoppedQueue.Add(e); + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD110:Observe result of async calls", Justification = "This intentionally fires and forgets on another thread.")] + private void OnDebuggerStopped(object sender, DebuggerStoppedEventArgs e) => Task.Run(() => debuggerStoppedQueue.Add(e)); private ScriptFile GetDebugScript(string fileName) => workspace.GetFile(TestUtilities.GetSharedPath(Path.Combine("Debugging", fileName))); @@ -118,20 +116,20 @@ private Task ExecuteScriptFileAsync(string scriptFilePath, params string[] args) private Task ExecuteVariableScriptFileAsync() => ExecuteScriptFileAsync(variableScriptFile.FilePath); - private void AssertDebuggerPaused() + private async Task AssertDebuggerPaused() { using CancellationTokenSource cts = new(60000); - DebuggerStoppedEventArgs eventArgs = debuggerStoppedQueue.Take(cts.Token); + DebuggerStoppedEventArgs eventArgs = await Task.Run(() => debuggerStoppedQueue.Take(cts.Token)); Assert.Empty(eventArgs.OriginalEvent.Breakpoints); } - private void AssertDebuggerStopped( + private async Task AssertDebuggerStopped( string scriptPath = "", int lineNumber = -1, CommandBreakpointDetails commandBreakpointDetails = default) { - using CancellationTokenSource cts = new(60000); - DebuggerStoppedEventArgs eventArgs = debuggerStoppedQueue.Take(cts.Token); + using CancellationTokenSource cts = new(30000); + DebuggerStoppedEventArgs eventArgs = await Task.Run(() => debuggerStoppedQueue.Take(cts.Token)); Assert.True(psesHost.DebugContext.IsStopped); @@ -176,8 +174,8 @@ await debugService.SetCommandBreakpointsAsync( Task> executeTask = psesHost.ExecutePSCommandAsync( new PSCommand().AddScript("Get-Random -SetSeed 42 -Maximum 100"), CancellationToken.None); - AssertDebuggerStopped("", 1); - await Task.Run(debugService.Continue); + await AssertDebuggerStopped("", 1); + debugService.Continue(); Assert.Equal(17, (await executeTask)[0]); StackFrameDetails[] stackFrames = await debugService.GetStackFramesAsync(); @@ -218,7 +216,7 @@ public async Task DebuggerAcceptsScriptArgs(string[] args) Task _ = ExecuteScriptFileAsync(oddPathScriptFile.FilePath, args); - AssertDebuggerStopped(oddPathScriptFile.FilePath, 3); + await AssertDebuggerStopped(oddPathScriptFile.FilePath, 3); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -285,7 +283,7 @@ public async Task DebuggerStopsOnFunctionBreakpoints() new[] { CommandBreakpointDetails.Create("Write-Host") }); Task _ = ExecuteDebugFileAsync(); - AssertDebuggerStopped(debugScriptFile.FilePath, 6); + await AssertDebuggerStopped(debugScriptFile.FilePath, 6); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -296,8 +294,8 @@ public async Task DebuggerStopsOnFunctionBreakpoints() Assert.Equal("1", i.ValueString); // The function breakpoint should fire the next time through the loop. - await Task.Run(debugService.Continue); - AssertDebuggerStopped(debugScriptFile.FilePath, 6); + debugService.Continue(); + await AssertDebuggerStopped(debugScriptFile.FilePath, 6); variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -352,9 +350,9 @@ await debugService.SetLineBreakpointsAsync( }); Task _ = ExecuteDebugFileAsync(); - AssertDebuggerStopped(debugScriptFile.FilePath, 5); - await Task.Run(debugService.Continue); - AssertDebuggerStopped(debugScriptFile.FilePath, 7); + await AssertDebuggerStopped(debugScriptFile.FilePath, 5); + debugService.Continue(); + await AssertDebuggerStopped(debugScriptFile.FilePath, 7); } [Fact] @@ -370,7 +368,7 @@ await debugService.SetLineBreakpointsAsync( }); Task _ = ExecuteDebugFileAsync(); - AssertDebuggerStopped(debugScriptFile.FilePath, 7); + await AssertDebuggerStopped(debugScriptFile.FilePath, 7); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -382,8 +380,8 @@ await debugService.SetLineBreakpointsAsync( // The conditional breakpoint should not fire again, until the value of // i reaches breakpointValue2. - await Task.Run(debugService.Continue); - AssertDebuggerStopped(debugScriptFile.FilePath, 7); + debugService.Continue(); + await AssertDebuggerStopped(debugScriptFile.FilePath, 7); variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -406,7 +404,7 @@ await debugService.SetLineBreakpointsAsync( }); Task _ = ExecuteDebugFileAsync(); - AssertDebuggerStopped(debugScriptFile.FilePath, 6); + await AssertDebuggerStopped(debugScriptFile.FilePath, 6); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -427,7 +425,7 @@ await debugService.SetLineBreakpointsAsync( new[] { BreakpointDetails.Create(debugScriptFile.FilePath, 6, null, "$i % 2 -eq 0", $"{hitCount}") }); Task _ = ExecuteDebugFileAsync(); - AssertDebuggerStopped(debugScriptFile.FilePath, 6); + await AssertDebuggerStopped(debugScriptFile.FilePath, 6); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -495,18 +493,16 @@ public async Task DebuggerBreaksWhenRequested() IReadOnlyList confirmedBreakpoints = await GetConfirmedBreakpoints(debugScriptFile); Assert.Empty(confirmedBreakpoints); Task _ = ExecuteDebugFileAsync(); - // NOTE: This must be run on a separate thread so the async event handlers can fire. - await Task.Run(debugService.Break); - AssertDebuggerPaused(); + debugService.Break(); + await AssertDebuggerPaused(); } [Fact] public async Task DebuggerRunsCommandsWhileStopped() { Task _ = ExecuteDebugFileAsync(); - // NOTE: This must be run on a separate thread so the async event handlers can fire. - await Task.Run(debugService.Break); - AssertDebuggerPaused(); + debugService.Break(); + await AssertDebuggerPaused(); // Try running a command from outside the pipeline thread Task> executeTask = psesHost.ExecutePSCommandAsync( @@ -526,7 +522,7 @@ await debugService.SetCommandBreakpointsAsync( ScriptFile testScript = GetDebugScript("PSDebugContextTest.ps1"); Task _ = ExecuteScriptFileAsync(testScript.FilePath); - AssertDebuggerStopped(testScript.FilePath, 11); + await AssertDebuggerStopped(testScript.FilePath, 11); VariableDetails prompt = await debugService.EvaluateExpressionAsync("prompt", false, CancellationToken.None); Assert.Equal("True > ", prompt.ValueString); @@ -551,7 +547,7 @@ await debugService.SetCommandBreakpointsAsync( NullLoggerFactory.Instance, null, debugService, null, null, psesHost, workspace, null, psesHost); Task _ = configurationDoneHandler.LaunchScriptAsync(scriptPath); - AssertDebuggerStopped(scriptPath, 1); + await AssertDebuggerStopped(scriptPath, 1); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.CommandVariablesName); VariableDetailsBase myInvocation = Array.Find(variables, v => v.Name == "$MyInvocation"); @@ -629,7 +625,7 @@ await debugService.SetLineBreakpointsAsync( new[] { BreakpointDetails.Create(variableScriptFile.FilePath, 8) }); Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -647,7 +643,7 @@ await debugService.SetLineBreakpointsAsync( new[] { BreakpointDetails.Create(variableScriptFile.FilePath, 21) }); Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -697,7 +693,7 @@ await debugService.SetLineBreakpointsAsync( new[] { BreakpointDetails.Create(variableScriptFile.FilePath, 14) }); Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); VariableScope[] scopes = debugService.GetVariableScopes(0); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -723,8 +719,8 @@ await debugService.SetLineBreakpointsAsync( // The above just tests that the debug service returns the correct new value string. // Let's step the debugger and make sure the values got set to the new values. - await Task.Run(debugService.StepOver); - AssertDebuggerStopped(variableScriptFile.FilePath); + debugService.StepOver(); + await AssertDebuggerStopped(variableScriptFile.FilePath); // Test set of a local string variable (not strongly typed) variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -751,7 +747,7 @@ await debugService.SetLineBreakpointsAsync( // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); VariableScope[] scopes = debugService.GetVariableScopes(0); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -779,8 +775,8 @@ await debugService.SetLineBreakpointsAsync( // The above just tests that the debug service returns the correct new value string. // Let's step the debugger and make sure the values got set to the new values. - await Task.Run(debugService.StepOver); - AssertDebuggerStopped(variableScriptFile.FilePath); + debugService.StepOver(); + await AssertDebuggerStopped(variableScriptFile.FilePath); // Test set of a local string variable (not strongly typed but force conversion) variables = await GetVariables(VariableContainerDetails.LocalScopeName); @@ -807,7 +803,7 @@ await debugService.SetLineBreakpointsAsync( // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); StackFrameDetails[] stackFrames = await debugService.GetStackFramesAsync(); VariableDetailsBase[] variables = await debugService.GetVariables(stackFrames[0].AutoVariables.Id, CancellationToken.None); @@ -827,7 +823,7 @@ await debugService.SetLineBreakpointsAsync( // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); StackFrameDetails[] stackFrames = await debugService.GetStackFramesAsync(); VariableDetailsBase[] variables = await debugService.GetVariables(stackFrames[0].AutoVariables.Id, CancellationToken.None); @@ -860,7 +856,7 @@ await debugService.SetLineBreakpointsAsync( // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); StackFrameDetails[] stackFrames = await debugService.GetStackFramesAsync(); VariableDetailsBase[] variables = await debugService.GetVariables(stackFrames[0].AutoVariables.Id, CancellationToken.None); @@ -880,7 +876,7 @@ await debugService.SetLineBreakpointsAsync( // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); StackFrameDetails[] stackFrames = await debugService.GetStackFramesAsync(); VariableDetailsBase[] variables = await debugService.GetVariables(stackFrames[0].AutoVariables.Id, CancellationToken.None); @@ -907,7 +903,7 @@ public async Task DebuggerEnumerableShowsRawView() // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(commandBreakpointDetails: breakpoint); + await AssertDebuggerStopped(commandBreakpointDetails: breakpoint); VariableDetailsBase simpleArrayVar = Array.Find( await GetVariables(VariableContainerDetails.ScriptScopeName), @@ -964,7 +960,7 @@ public async Task DebuggerDictionaryShowsRawView() // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(commandBreakpointDetails: breakpoint); + await AssertDebuggerStopped(commandBreakpointDetails: breakpoint); VariableDetailsBase simpleDictionaryVar = Array.Find( await GetVariables(VariableContainerDetails.ScriptScopeName), @@ -1027,7 +1023,7 @@ public async Task DebuggerDerivedDictionaryPropertyInRawView() // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(commandBreakpointDetails: breakpoint); + await AssertDebuggerStopped(commandBreakpointDetails: breakpoint); VariableDetailsBase sortedDictionaryVar = Array.Find( await GetVariables(VariableContainerDetails.ScriptScopeName), @@ -1076,7 +1072,7 @@ await debugService.SetLineBreakpointsAsync( // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); StackFrameDetails[] stackFrames = await debugService.GetStackFramesAsync(); VariableDetailsBase[] variables = await debugService.GetVariables(stackFrames[0].AutoVariables.Id, CancellationToken.None); @@ -1105,7 +1101,7 @@ await debugService.SetLineBreakpointsAsync( // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(variableScriptFile.FilePath); + await AssertDebuggerStopped(variableScriptFile.FilePath); StackFrameDetails[] stackFrames = await debugService.GetStackFramesAsync(); VariableDetailsBase[] variables = await debugService.GetVariables(stackFrames[0].AutoVariables.Id, CancellationToken.None); @@ -1134,7 +1130,7 @@ await debugService.SetCommandBreakpointsAsync( ScriptFile testScript = GetDebugScript("GetChildItemTest.ps1"); Task _ = ExecuteScriptFileAsync(testScript.FilePath); - AssertDebuggerStopped(testScript.FilePath, 2); + await AssertDebuggerStopped(testScript.FilePath, 2); VariableDetailsBase[] variables = await GetVariables(VariableContainerDetails.LocalScopeName); VariableDetailsBase var = Array.Find(variables, v => v.Name == "$file"); @@ -1154,7 +1150,7 @@ public async Task DebuggerToStringShouldMarshallToPipeline() // Execute the script and wait for the breakpoint to be hit Task _ = ExecuteVariableScriptFileAsync(); - AssertDebuggerStopped(commandBreakpointDetails: breakpoint); + await AssertDebuggerStopped(commandBreakpointDetails: breakpoint); VariableDetailsBase[] vars = await GetVariables(VariableContainerDetails.ScriptScopeName); VariableDetailsBase customToStrings = Array.Find(vars, i => i.Name is "$CustomToStrings"); diff --git a/test/PowerShellEditorServices.Test/Extensions/ExtensionCommandTests.cs b/test/PowerShellEditorServices.Test/Extensions/ExtensionCommandTests.cs index 190ee5aae..70e35d3dd 100644 --- a/test/PowerShellEditorServices.Test/Extensions/ExtensionCommandTests.cs +++ b/test/PowerShellEditorServices.Test/Extensions/ExtensionCommandTests.cs @@ -20,33 +20,25 @@ namespace PowerShellEditorServices.Test.Extensions { [Trait("Category", "Extensions")] - public class ExtensionCommandTests : IDisposable + public class ExtensionCommandTests : IAsyncLifetime { - private readonly PsesInternalHost psesHost; + private PsesInternalHost psesHost; - private readonly ExtensionCommandService extensionCommandService; + private ExtensionCommandService extensionCommandService; - public ExtensionCommandTests() + public async Task InitializeAsync() { - psesHost = PsesHostFactory.Create(NullLoggerFactory.Instance); + psesHost = await PsesHostFactory.Create(NullLoggerFactory.Instance); ExtensionService extensionService = new( languageServer: null, serviceProvider: null, editorOperations: null, executionService: psesHost); -#pragma warning disable VSTHRD002 - extensionService.InitializeAsync().Wait(); -#pragma warning restore VSTHRD002 + await extensionService.InitializeAsync(); extensionCommandService = new(extensionService); } - public void Dispose() - { -#pragma warning disable VSTHRD002 - psesHost.StopAsync().Wait(); -#pragma warning restore VSTHRD002 - GC.SuppressFinalize(this); - } + public async Task DisposeAsync() => await psesHost.StopAsync(); [Fact] public async Task CanRegisterAndInvokeCommandWithCmdletName() diff --git a/test/PowerShellEditorServices.Test/Language/CompletionHandlerTests.cs b/test/PowerShellEditorServices.Test/Language/CompletionHandlerTests.cs index fae0f8104..35546cefe 100644 --- a/test/PowerShellEditorServices.Test/Language/CompletionHandlerTests.cs +++ b/test/PowerShellEditorServices.Test/Language/CompletionHandlerTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -21,26 +20,20 @@ namespace PowerShellEditorServices.Test.Language { [Trait("Category", "Completions")] - public class CompletionHandlerTests : IDisposable + public class CompletionHandlerTests : IAsyncLifetime { - private readonly PsesInternalHost psesHost; - private readonly WorkspaceService workspace; - private readonly PsesCompletionHandler completionHandler; + private PsesInternalHost psesHost; + private WorkspaceService workspace; + private PsesCompletionHandler completionHandler; - public CompletionHandlerTests() + public async Task InitializeAsync() { - psesHost = PsesHostFactory.Create(NullLoggerFactory.Instance); + psesHost = await PsesHostFactory.Create(NullLoggerFactory.Instance); workspace = new WorkspaceService(NullLoggerFactory.Instance); completionHandler = new PsesCompletionHandler(NullLoggerFactory.Instance, psesHost, psesHost, workspace); } - public void Dispose() - { -#pragma warning disable VSTHRD002 - psesHost.StopAsync().Wait(); -#pragma warning restore VSTHRD002 - GC.SuppressFinalize(this); - } + public async Task DisposeAsync() => await Task.Run(psesHost.StopAsync); private ScriptFile GetScriptFile(ScriptRegion scriptRegion) => workspace.GetFile(TestUtilities.GetSharedPath(scriptRegion.File)); diff --git a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs index f078d8d42..630c8a018 100644 --- a/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs +++ b/test/PowerShellEditorServices.Test/Language/SymbolsServiceTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections.Generic; using System.Linq; using System.Management.Automation; @@ -30,16 +29,16 @@ namespace PowerShellEditorServices.Test.Language { [Trait("Category", "Symbols")] - public class SymbolsServiceTests : IDisposable + public class SymbolsServiceTests : IAsyncLifetime { - private readonly PsesInternalHost psesHost; - private readonly WorkspaceService workspace; - private readonly SymbolsService symbolsService; + private PsesInternalHost psesHost; + private WorkspaceService workspace; + private SymbolsService symbolsService; private static readonly bool s_isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - public SymbolsServiceTests() + public async Task InitializeAsync() { - psesHost = PsesHostFactory.Create(NullLoggerFactory.Instance); + psesHost = await PsesHostFactory.Create(NullLoggerFactory.Instance); workspace = new WorkspaceService(NullLoggerFactory.Instance); workspace.WorkspaceFolders.Add(new WorkspaceFolder { @@ -53,14 +52,11 @@ public SymbolsServiceTests() new ConfigurationService()); } - public void Dispose() + public async Task DisposeAsync() { -#pragma warning disable VSTHRD002 - psesHost.StopAsync().GetAwaiter().GetResult(); -#pragma warning restore VSTHRD002 + psesHost.StopAsync(); CommandHelpers.s_cmdletToAliasCache.Clear(); CommandHelpers.s_aliasToCmdletCache.Clear(); - GC.SuppressFinalize(this); } private static void AssertIsRegion( diff --git a/test/PowerShellEditorServices.Test/PowerShellEditorServices.Test.csproj b/test/PowerShellEditorServices.Test/PowerShellEditorServices.Test.csproj index f77593613..548f36c3e 100644 --- a/test/PowerShellEditorServices.Test/PowerShellEditorServices.Test.csproj +++ b/test/PowerShellEditorServices.Test/PowerShellEditorServices.Test.csproj @@ -38,7 +38,7 @@ - + diff --git a/test/PowerShellEditorServices.Test/PsesHostFactory.cs b/test/PowerShellEditorServices.Test/PsesHostFactory.cs index 0e02b6389..9f63236d4 100644 --- a/test/PowerShellEditorServices.Test/PsesHostFactory.cs +++ b/test/PowerShellEditorServices.Test/PsesHostFactory.cs @@ -7,6 +7,7 @@ using System.Management.Automation.Host; using System.Management.Automation.Runspaces; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.PowerShell.EditorServices.Hosting; using Microsoft.PowerShell.EditorServices.Services.PowerShell.Host; @@ -28,7 +29,7 @@ internal static class PsesHostFactory public static readonly string BundledModulePath = Path.GetFullPath(TestUtilities.NormalizePath("../../../../../module")); - public static PsesInternalHost Create(ILoggerFactory loggerFactory, bool loadProfiles = false) + public static async Task Create(ILoggerFactory loggerFactory, bool loadProfiles = false) { // We intentionally use `CreateDefault2()` as it loads `Microsoft.PowerShell.Core` only, // which is a more minimal and therefore safer state. @@ -62,9 +63,7 @@ public static PsesInternalHost Create(ILoggerFactory loggerFactory, bool loadPro PsesInternalHost psesHost = new(loggerFactory, null, testHostDetails); - #pragma warning disable VSTHRD002 // Because this is used by constructors it can't use await. - if (psesHost.TryStartAsync(new HostStartOptions { LoadProfiles = loadProfiles }, CancellationToken.None).GetAwaiter().GetResult()) - #pragma warning restore VSTHRD002 + if (await psesHost.TryStartAsync(new HostStartOptions { LoadProfiles = loadProfiles }, CancellationToken.None)) { return psesHost; } diff --git a/test/PowerShellEditorServices.Test/Session/PsesInternalHostTests.cs b/test/PowerShellEditorServices.Test/Session/PsesInternalHostTests.cs index d489704f4..617b610ed 100644 --- a/test/PowerShellEditorServices.Test/Session/PsesInternalHostTests.cs +++ b/test/PowerShellEditorServices.Test/Session/PsesInternalHostTests.cs @@ -20,19 +20,13 @@ namespace PowerShellEditorServices.Test.Session using System.Management.Automation.Runspaces; [Trait("Category", "PsesInternalHost")] - public class PsesInternalHostTests : IDisposable + public class PsesInternalHostTests : IAsyncLifetime { - private readonly PsesInternalHost psesHost; + private PsesInternalHost psesHost; - public PsesInternalHostTests() => psesHost = PsesHostFactory.Create(NullLoggerFactory.Instance); + public async Task InitializeAsync() => psesHost = await PsesHostFactory.Create(NullLoggerFactory.Instance); - public void Dispose() - { -#pragma warning disable VSTHRD002 - psesHost.StopAsync().Wait(); -#pragma warning restore VSTHRD002 - GC.SuppressFinalize(this); - } + public async Task DisposeAsync() => await psesHost.StopAsync(); [Fact] public async Task CanExecutePSCommand() @@ -88,7 +82,7 @@ public async Task CanQueueParallelPSCommands() public async Task CanCancelExecutionWithToken() { using CancellationTokenSource cancellationSource = new(millisecondsDelay: 1000); - _ = await Assert.ThrowsAsync(() => + await Assert.ThrowsAsync(() => { return psesHost.ExecutePSCommandAsync( new PSCommand().AddScript("Start-Sleep 10"), @@ -104,9 +98,8 @@ public async Task CanCancelExecutionWithMethod() new PSCommand().AddScript("Start-Sleep 10"), CancellationToken.None); - // Wait until our task has started. - Thread.Sleep(2000); - psesHost.CancelCurrentTask(); + // Cancel the task after 1 second in another thread. + Task.Run(() => { Thread.Sleep(1000); psesHost.CancelCurrentTask(); }); await Assert.ThrowsAsync(() => executeTask); Assert.True(executeTask.IsCanceled); } @@ -238,19 +231,13 @@ public async Task CanHandleBadInitialWorkingDirectory(string path) } [Trait("Category", "PsesInternalHost")] - public class PsesInternalHostWithProfileTests : IDisposable + public class PsesInternalHostWithProfileTests : IAsyncLifetime { - private readonly PsesInternalHost psesHost; + private PsesInternalHost psesHost; - public PsesInternalHostWithProfileTests() => psesHost = PsesHostFactory.Create(NullLoggerFactory.Instance, loadProfiles: true); + public async Task InitializeAsync() => psesHost = await PsesHostFactory.Create(NullLoggerFactory.Instance, loadProfiles: true); - public void Dispose() - { -#pragma warning disable VSTHRD002 - psesHost.StopAsync().Wait(); -#pragma warning restore VSTHRD002 - GC.SuppressFinalize(this); - } + public async Task DisposeAsync() => await psesHost.StopAsync(); [Fact] public async Task CanResolveAndLoadProfilesForHostId() diff --git a/test/PowerShellEditorServices.Test/packages.lock.json b/test/PowerShellEditorServices.Test/packages.lock.json index 708461b71..35e73f2b9 100644 --- a/test/PowerShellEditorServices.Test/packages.lock.json +++ b/test/PowerShellEditorServices.Test/packages.lock.json @@ -28,13 +28,13 @@ }, "xunit": { "type": "Direct", - "requested": "[2.6.6, )", - "resolved": "2.6.6", - "contentHash": "MAbOOMtZIKyn2lrAmMlvhX0BhDOX/smyrTB+8WTXnSKkrmTGBS2fm8g1PZtHBPj91Dc5DJA7fY+/81TJ/yUFZw==", + "requested": "[2.7.0, )", + "resolved": "2.7.0", + "contentHash": "KcCI5zxh8zbUfQTeErc4oT7YokViVND2V0p4vDJ2VD4lhF9V5qCYMMDNixme7FdwYy3SwPHF+2xC2Dq4Z9GSlA==", "dependencies": { - "xunit.analyzers": "1.10.0", - "xunit.assert": "2.6.6", - "xunit.core": "[2.6.6]" + "xunit.analyzers": "1.11.0", + "xunit.assert": "2.7.0", + "xunit.core": "[2.7.0]" } }, "xunit.runner.visualstudio": { @@ -496,37 +496,37 @@ }, "xunit.analyzers": { "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "Lw8CiDy5NaAWcO6keqD7iZHYUTIuCOcoFrUHw5Sv84ITZ9gFeDybdkVdH0Y2maSlP9fUjtENyiykT44zwFQIHA==" + "resolved": "1.11.0", + "contentHash": "SCv+Ihxv+fCqotGeM8sVwLhw8nzAJ2aFRN5lcoKn9QtGdbVJ79JqDc+4u8/Ddnp2udxtmv+xYFWkHNlb/sk01w==" }, "xunit.assert": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "74Cm9lAZOk5TKCz2MvCBCByKsS23yryOKDIMxH3XRDHXmfGM02jKZWzRA7g4mGB41GnBnv/pcWP3vUYkrCtEcg==" + "resolved": "2.7.0", + "contentHash": "CCTs3bUhmIS4tDwK6Cn/IiabG3RhYzdf65eIkO7u9/grKoN9MrN780LzVED3E8v+vwmmj7b5TW3/GFuZHPAzWA==" }, "xunit.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "tqi7RfaNBqM7t8zx6QHryuBPzmotsZXKGaWnopQG2Ez5UV7JoWuyoNdT6gLpDIcKdGYey6YTXJdSr9IXDMKwjg==", + "resolved": "2.7.0", + "contentHash": "98tzqYAbtc/p/2Ba455XTNbD12Qoo8kPehjC4oDT46CAsLli5JOCU9hFF2MV3HHWMw/Y3yFUV2Vcukplbs6kuA==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]", - "xunit.extensibility.execution": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]", + "xunit.extensibility.execution": "[2.7.0]" } }, "xunit.extensibility.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "ty6VKByzbx4Toj4/VGJLEnlmOawqZiMv0in/tLju+ftA+lbWuAWDERM+E52Jfhj4ZYHrAYVa14KHK5T+dq0XxA==", + "resolved": "2.7.0", + "contentHash": "JLnx4PI0vn1Xr1Ust6ydrp2t/ktm2dyGPAVoDJV5gQuvBMSbd2K7WGzODa2ttiz030CeQ8nbsXl05+cvf7QNyA==", "dependencies": { "xunit.abstractions": "2.0.3" } }, "xunit.extensibility.execution": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "UDjIVGj2TepVKN3n32/qXIdb3U6STwTb9L6YEwoQO2A8OxiJS5QAVv2l1aT6tDwwv/9WBmm8Khh/LyHALipcng==", + "resolved": "2.7.0", + "contentHash": "bjY+crT1jOyxKagFjCMdEVzoenO2v66ru8+CK/0UaXvyG4U9Q3UTieJkbQXbi7/1yZIK1sGh01l5/jh2CwLJtQ==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]" } }, "Microsoft.PowerShell.EditorServices": { @@ -596,13 +596,13 @@ }, "xunit": { "type": "Direct", - "requested": "[2.6.6, )", - "resolved": "2.6.6", - "contentHash": "MAbOOMtZIKyn2lrAmMlvhX0BhDOX/smyrTB+8WTXnSKkrmTGBS2fm8g1PZtHBPj91Dc5DJA7fY+/81TJ/yUFZw==", + "requested": "[2.7.0, )", + "resolved": "2.7.0", + "contentHash": "KcCI5zxh8zbUfQTeErc4oT7YokViVND2V0p4vDJ2VD4lhF9V5qCYMMDNixme7FdwYy3SwPHF+2xC2Dq4Z9GSlA==", "dependencies": { - "xunit.analyzers": "1.10.0", - "xunit.assert": "2.6.6", - "xunit.core": "[2.6.6]" + "xunit.analyzers": "1.11.0", + "xunit.assert": "2.7.0", + "xunit.core": "[2.7.0]" } }, "xunit.runner.visualstudio": { @@ -1631,37 +1631,37 @@ }, "xunit.analyzers": { "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "Lw8CiDy5NaAWcO6keqD7iZHYUTIuCOcoFrUHw5Sv84ITZ9gFeDybdkVdH0Y2maSlP9fUjtENyiykT44zwFQIHA==" + "resolved": "1.11.0", + "contentHash": "SCv+Ihxv+fCqotGeM8sVwLhw8nzAJ2aFRN5lcoKn9QtGdbVJ79JqDc+4u8/Ddnp2udxtmv+xYFWkHNlb/sk01w==" }, "xunit.assert": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "74Cm9lAZOk5TKCz2MvCBCByKsS23yryOKDIMxH3XRDHXmfGM02jKZWzRA7g4mGB41GnBnv/pcWP3vUYkrCtEcg==" + "resolved": "2.7.0", + "contentHash": "CCTs3bUhmIS4tDwK6Cn/IiabG3RhYzdf65eIkO7u9/grKoN9MrN780LzVED3E8v+vwmmj7b5TW3/GFuZHPAzWA==" }, "xunit.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "tqi7RfaNBqM7t8zx6QHryuBPzmotsZXKGaWnopQG2Ez5UV7JoWuyoNdT6gLpDIcKdGYey6YTXJdSr9IXDMKwjg==", + "resolved": "2.7.0", + "contentHash": "98tzqYAbtc/p/2Ba455XTNbD12Qoo8kPehjC4oDT46CAsLli5JOCU9hFF2MV3HHWMw/Y3yFUV2Vcukplbs6kuA==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]", - "xunit.extensibility.execution": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]", + "xunit.extensibility.execution": "[2.7.0]" } }, "xunit.extensibility.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "ty6VKByzbx4Toj4/VGJLEnlmOawqZiMv0in/tLju+ftA+lbWuAWDERM+E52Jfhj4ZYHrAYVa14KHK5T+dq0XxA==", + "resolved": "2.7.0", + "contentHash": "JLnx4PI0vn1Xr1Ust6ydrp2t/ktm2dyGPAVoDJV5gQuvBMSbd2K7WGzODa2ttiz030CeQ8nbsXl05+cvf7QNyA==", "dependencies": { "xunit.abstractions": "2.0.3" } }, "xunit.extensibility.execution": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "UDjIVGj2TepVKN3n32/qXIdb3U6STwTb9L6YEwoQO2A8OxiJS5QAVv2l1aT6tDwwv/9WBmm8Khh/LyHALipcng==", + "resolved": "2.7.0", + "contentHash": "bjY+crT1jOyxKagFjCMdEVzoenO2v66ru8+CK/0UaXvyG4U9Q3UTieJkbQXbi7/1yZIK1sGh01l5/jh2CwLJtQ==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]" } }, "Microsoft.PowerShell.EditorServices": { @@ -1735,13 +1735,13 @@ }, "xunit": { "type": "Direct", - "requested": "[2.6.6, )", - "resolved": "2.6.6", - "contentHash": "MAbOOMtZIKyn2lrAmMlvhX0BhDOX/smyrTB+8WTXnSKkrmTGBS2fm8g1PZtHBPj91Dc5DJA7fY+/81TJ/yUFZw==", + "requested": "[2.7.0, )", + "resolved": "2.7.0", + "contentHash": "KcCI5zxh8zbUfQTeErc4oT7YokViVND2V0p4vDJ2VD4lhF9V5qCYMMDNixme7FdwYy3SwPHF+2xC2Dq4Z9GSlA==", "dependencies": { - "xunit.analyzers": "1.10.0", - "xunit.assert": "2.6.6", - "xunit.core": "[2.6.6]" + "xunit.analyzers": "1.11.0", + "xunit.assert": "2.7.0", + "xunit.core": "[2.7.0]" } }, "xunit.runner.visualstudio": { @@ -2754,37 +2754,37 @@ }, "xunit.analyzers": { "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "Lw8CiDy5NaAWcO6keqD7iZHYUTIuCOcoFrUHw5Sv84ITZ9gFeDybdkVdH0Y2maSlP9fUjtENyiykT44zwFQIHA==" + "resolved": "1.11.0", + "contentHash": "SCv+Ihxv+fCqotGeM8sVwLhw8nzAJ2aFRN5lcoKn9QtGdbVJ79JqDc+4u8/Ddnp2udxtmv+xYFWkHNlb/sk01w==" }, "xunit.assert": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "74Cm9lAZOk5TKCz2MvCBCByKsS23yryOKDIMxH3XRDHXmfGM02jKZWzRA7g4mGB41GnBnv/pcWP3vUYkrCtEcg==" + "resolved": "2.7.0", + "contentHash": "CCTs3bUhmIS4tDwK6Cn/IiabG3RhYzdf65eIkO7u9/grKoN9MrN780LzVED3E8v+vwmmj7b5TW3/GFuZHPAzWA==" }, "xunit.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "tqi7RfaNBqM7t8zx6QHryuBPzmotsZXKGaWnopQG2Ez5UV7JoWuyoNdT6gLpDIcKdGYey6YTXJdSr9IXDMKwjg==", + "resolved": "2.7.0", + "contentHash": "98tzqYAbtc/p/2Ba455XTNbD12Qoo8kPehjC4oDT46CAsLli5JOCU9hFF2MV3HHWMw/Y3yFUV2Vcukplbs6kuA==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]", - "xunit.extensibility.execution": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]", + "xunit.extensibility.execution": "[2.7.0]" } }, "xunit.extensibility.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "ty6VKByzbx4Toj4/VGJLEnlmOawqZiMv0in/tLju+ftA+lbWuAWDERM+E52Jfhj4ZYHrAYVa14KHK5T+dq0XxA==", + "resolved": "2.7.0", + "contentHash": "JLnx4PI0vn1Xr1Ust6ydrp2t/ktm2dyGPAVoDJV5gQuvBMSbd2K7WGzODa2ttiz030CeQ8nbsXl05+cvf7QNyA==", "dependencies": { "xunit.abstractions": "2.0.3" } }, "xunit.extensibility.execution": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "UDjIVGj2TepVKN3n32/qXIdb3U6STwTb9L6YEwoQO2A8OxiJS5QAVv2l1aT6tDwwv/9WBmm8Khh/LyHALipcng==", + "resolved": "2.7.0", + "contentHash": "bjY+crT1jOyxKagFjCMdEVzoenO2v66ru8+CK/0UaXvyG4U9Q3UTieJkbQXbi7/1yZIK1sGh01l5/jh2CwLJtQ==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]" } }, "Microsoft.PowerShell.EditorServices": { @@ -2854,13 +2854,13 @@ }, "xunit": { "type": "Direct", - "requested": "[2.6.6, )", - "resolved": "2.6.6", - "contentHash": "MAbOOMtZIKyn2lrAmMlvhX0BhDOX/smyrTB+8WTXnSKkrmTGBS2fm8g1PZtHBPj91Dc5DJA7fY+/81TJ/yUFZw==", + "requested": "[2.7.0, )", + "resolved": "2.7.0", + "contentHash": "KcCI5zxh8zbUfQTeErc4oT7YokViVND2V0p4vDJ2VD4lhF9V5qCYMMDNixme7FdwYy3SwPHF+2xC2Dq4Z9GSlA==", "dependencies": { - "xunit.analyzers": "1.10.0", - "xunit.assert": "2.6.6", - "xunit.core": "[2.6.6]" + "xunit.analyzers": "1.11.0", + "xunit.assert": "2.7.0", + "xunit.core": "[2.7.0]" } }, "xunit.runner.visualstudio": { @@ -3880,37 +3880,37 @@ }, "xunit.analyzers": { "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "Lw8CiDy5NaAWcO6keqD7iZHYUTIuCOcoFrUHw5Sv84ITZ9gFeDybdkVdH0Y2maSlP9fUjtENyiykT44zwFQIHA==" + "resolved": "1.11.0", + "contentHash": "SCv+Ihxv+fCqotGeM8sVwLhw8nzAJ2aFRN5lcoKn9QtGdbVJ79JqDc+4u8/Ddnp2udxtmv+xYFWkHNlb/sk01w==" }, "xunit.assert": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "74Cm9lAZOk5TKCz2MvCBCByKsS23yryOKDIMxH3XRDHXmfGM02jKZWzRA7g4mGB41GnBnv/pcWP3vUYkrCtEcg==" + "resolved": "2.7.0", + "contentHash": "CCTs3bUhmIS4tDwK6Cn/IiabG3RhYzdf65eIkO7u9/grKoN9MrN780LzVED3E8v+vwmmj7b5TW3/GFuZHPAzWA==" }, "xunit.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "tqi7RfaNBqM7t8zx6QHryuBPzmotsZXKGaWnopQG2Ez5UV7JoWuyoNdT6gLpDIcKdGYey6YTXJdSr9IXDMKwjg==", + "resolved": "2.7.0", + "contentHash": "98tzqYAbtc/p/2Ba455XTNbD12Qoo8kPehjC4oDT46CAsLli5JOCU9hFF2MV3HHWMw/Y3yFUV2Vcukplbs6kuA==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]", - "xunit.extensibility.execution": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]", + "xunit.extensibility.execution": "[2.7.0]" } }, "xunit.extensibility.core": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "ty6VKByzbx4Toj4/VGJLEnlmOawqZiMv0in/tLju+ftA+lbWuAWDERM+E52Jfhj4ZYHrAYVa14KHK5T+dq0XxA==", + "resolved": "2.7.0", + "contentHash": "JLnx4PI0vn1Xr1Ust6ydrp2t/ktm2dyGPAVoDJV5gQuvBMSbd2K7WGzODa2ttiz030CeQ8nbsXl05+cvf7QNyA==", "dependencies": { "xunit.abstractions": "2.0.3" } }, "xunit.extensibility.execution": { "type": "Transitive", - "resolved": "2.6.6", - "contentHash": "UDjIVGj2TepVKN3n32/qXIdb3U6STwTb9L6YEwoQO2A8OxiJS5QAVv2l1aT6tDwwv/9WBmm8Khh/LyHALipcng==", + "resolved": "2.7.0", + "contentHash": "bjY+crT1jOyxKagFjCMdEVzoenO2v66ru8+CK/0UaXvyG4U9Q3UTieJkbQXbi7/1yZIK1sGh01l5/jh2CwLJtQ==", "dependencies": { - "xunit.extensibility.core": "[2.6.6]" + "xunit.extensibility.core": "[2.7.0]" } }, "Microsoft.PowerShell.EditorServices": { @@ -3939,4 +3939,4 @@ } } } -} +} \ No newline at end of file