From 0f8a4d6309f78ae23d259fddf45c5cba536b71bc Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 13 Apr 2022 16:07:54 -0700 Subject: [PATCH 1/3] Upgrade severity of warnings (and some suggestions) to errors --- .editorconfig | 120 +++++++++--------- .../Commands/StartEditorServicesCommand.cs | 3 +- .../Internal/NamedPipeUtils.cs | 3 +- .../Handlers/ConfigurationHandler.cs | 6 +- 4 files changed, 65 insertions(+), 67 deletions(-) diff --git a/.editorconfig b/.editorconfig index b9414dbf0..b98f7baef 100644 --- a/.editorconfig +++ b/.editorconfig @@ -56,26 +56,26 @@ dotnet_diagnostic.CA2016.severity = error # CS0618: A class member was marked with the Obsolete attribute dotnet_diagnostic.CS0618.severity = suggestion # CS0649: Uninitialized private or internal field declaration that is never assigned a value -dotnet_diagnostic.CS0649.severity = warning +dotnet_diagnostic.CS0649.severity = error # CS1998: This async method lacks 'await' operators and will run synchronously dotnet_diagnostic.CS1998.severity = suggestion # CS4014: Consider applying the await operator to the result of the call dotnet_diagnostic.CS4014.severity = suggestion # RCS1102: Make class static -dotnet_diagnostic.RCS1102.severity = warning +dotnet_diagnostic.RCS1102.severity = error # RCS1139: Add summary element to documentation comment dotnet_diagnostic.RCS1139.severity = silent # RCS1194: Implement exception constructors dotnet_diagnostic.RCS1194.severity = suggestion # RCS1210: Return completed task instead of returning null -dotnet_diagnostic.RCS1210.severity = suggestion +dotnet_diagnostic.RCS1210.severity = error # RCS1036: Remove unnecessary blank line -dotnet_diagnostic.RCS1036.severity = warning +dotnet_diagnostic.RCS1036.severity = error # RCS1075: Avoid empty catch clause that catches System.Exception dotnet_diagnostic.RCS1075.severity = suggestion # RCS1170: Use read-only auto-implemented property -dotnet_diagnostic.RCS1170.severity = warning +dotnet_diagnostic.RCS1170.severity = error # VSTHRD002: Avoid problematic synchronous waits dotnet_diagnostic.VSTHRD002.severity = suggestion @@ -90,123 +90,123 @@ dotnet_diagnostic.VSTHRD103.severity = suggestion # VSTHRD110: Observe result of async calls dotnet_diagnostic.VSTHRD110.severity = suggestion # VSTHRD114: Avoid returning a null Task -dotnet_diagnostic.VSTHRD114.severity = suggestion +dotnet_diagnostic.VSTHRD114.severity = error # VSTHRD200: Use "Async" suffix for awaitable methods dotnet_diagnostic.VSTHRD200.severity = silent # xUnit2013: Do not use equality check to check for collection size -dotnet_diagnostic.xUnit2013.severity = warning +dotnet_diagnostic.xUnit2013.severity = error # xUnit1004: Test methods should not be skipped dotnet_diagnostic.xUnit1004.severity = suggestion # IDE0001: Simplify name -dotnet_diagnostic.IDE0001.severity = warning +dotnet_diagnostic.IDE0001.severity = error # IDE0002: Simplify member access -dotnet_diagnostic.IDE0001.severity = warning +dotnet_diagnostic.IDE0001.severity = error # IDE0003: Remove this or Me qualification -dotnet_diagnostic.IDE0003.severity = warning +dotnet_diagnostic.IDE0003.severity = error # IDE0004: Remove unnecessary cast -dotnet_diagnostic.IDE0004.severity = warning +dotnet_diagnostic.IDE0004.severity = error # IDE0005: Remove unnecessary import -dotnet_diagnostic.IDE0005.severity = suggestion +dotnet_diagnostic.IDE0005.severity = error # IDE0008: Use explicit type instead of var -dotnet_diagnostic.IDE0008.severity = warning +dotnet_diagnostic.IDE0008.severity = error # IDE0011: Add braces -dotnet_diagnostic.IDE0011.severity = warning +dotnet_diagnostic.IDE0011.severity = error # IDE0016: Use throw expression -dotnet_diagnostic.IDE0016.severity = warning +dotnet_diagnostic.IDE0016.severity = error # IDE0017: Use object initializers -dotnet_diagnostic.IDE0017.severity = warning +dotnet_diagnostic.IDE0017.severity = error # IDE0018: Inline variable declaration -dotnet_diagnostic.IDE0018.severity = warning +dotnet_diagnostic.IDE0018.severity = error # IDE0019: Use pattern matching to avoid 'as' followed by a 'null' check -dotnet_diagnostic.IDE0019.severity = warning +dotnet_diagnostic.IDE0019.severity = error # IDE0020: Use pattern matching to avoid 'is' check followed by a cast (with variable) -dotnet_diagnostic.IDE0020.severity = warning +dotnet_diagnostic.IDE0020.severity = error # IDE0021: Use expression body for constructors -dotnet_diagnostic.IDE0021.severity = warning +dotnet_diagnostic.IDE0021.severity = error # IDE0022: Use expression body for methods -dotnet_diagnostic.IDE0022.severity = warning +dotnet_diagnostic.IDE0022.severity = error # IDE0023: Use expression body for conversion operators -dotnet_diagnostic.IDE0023.severity = warning +dotnet_diagnostic.IDE0023.severity = error # IDE0024: Use expression body for operators -dotnet_diagnostic.IDE0024.severity = warning +dotnet_diagnostic.IDE0024.severity = error # IDE0025: Use expression body for properties -dotnet_diagnostic.IDE0025.severity = warning +dotnet_diagnostic.IDE0025.severity = error # IDE0026: Use expression body for indexers -dotnet_diagnostic.IDE0026.severity = warning +dotnet_diagnostic.IDE0026.severity = error # IDE0027: Use expression body for accessors -dotnet_diagnostic.IDE0027.severity = warning +dotnet_diagnostic.IDE0027.severity = error # IDE0028: Use collection initializers -dotnet_diagnostic.IDE0028.severity = warning +dotnet_diagnostic.IDE0028.severity = error # IDE0029: Use coalesce expression (non-nullable types) -dotnet_diagnostic.IDE0029.severity = warning +dotnet_diagnostic.IDE0029.severity = error # IDE0030: Use coalesce expression (nullable types) -dotnet_diagnostic.IDE0030.severity = warning +dotnet_diagnostic.IDE0030.severity = error # IDE0031: Use null propagation -dotnet_diagnostic.IDE0031.severity = warning +dotnet_diagnostic.IDE0031.severity = error # IDE0032: Use auto property -dotnet_diagnostic.IDE0032.severity = warning +dotnet_diagnostic.IDE0032.severity = error # IDE0033: Use explicitly provided tuple name -dotnet_diagnostic.IDE0033.severity = warning +dotnet_diagnostic.IDE0033.severity = error # IDE0034: Simplify 'default' expression -dotnet_diagnostic.IDE0034.severity = warning +dotnet_diagnostic.IDE0034.severity = error # IDE0035: Remove unreachable code -dotnet_diagnostic.IDE0035.severity = warning +dotnet_diagnostic.IDE0035.severity = error # IDE0036: Order modifiers -dotnet_diagnostic.IDE0036.severity = warning +dotnet_diagnostic.IDE0036.severity = error # IDE0037: Use inferred member name -dotnet_diagnostic.IDE0037.severity = warning +dotnet_diagnostic.IDE0037.severity = error # IDE0038: Use pattern matching to avoid is check followed by a cast (without variable) -dotnet_diagnostic.IDE0038.severity = suggestion +dotnet_diagnostic.IDE0038.severity = error # IDE0040: Add accessibility modifiers -dotnet_diagnostic.IDE0040.severity = warning +dotnet_diagnostic.IDE0040.severity = error # IDE0041: Use is null check -dotnet_diagnostic.IDE0041.severity = warning +dotnet_diagnostic.IDE0041.severity = error # IDE0042: Deconstruct variable declaration -dotnet_diagnostic.IDE0042.severity = warning +dotnet_diagnostic.IDE0042.severity = error # IDE0044: Add readonly modifier -dotnet_diagnostic.IDE0044.severity = warning +dotnet_diagnostic.IDE0044.severity = error # IDE0045: Use conditional expression for assignment -dotnet_diagnostic.IDE0045.severity = warning +dotnet_diagnostic.IDE0045.severity = error # IDE0046: Use conditional expression for return dotnet_diagnostic.IDE0046.severity = silent # IDE0047: Remove unnecessary parentheses -dotnet_diagnostic.IDE0047.severity = warning +dotnet_diagnostic.IDE0047.severity = error # IDE0049: Use language keywords instead of framework type names for type references -dotnet_diagnostic.IDE0049.severity = warning +dotnet_diagnostic.IDE0049.severity = error # IDE0051: Remove unused private member -dotnet_diagnostic.IDE0051.severity = warning +dotnet_diagnostic.IDE0051.severity = error # IDE0052: Remove unread private member -dotnet_diagnostic.IDE0052.severity = suggestion +dotnet_diagnostic.IDE0052.severity = error # IDE0053: Use expression body for lambdas -dotnet_diagnostic.IDE0053.severity = warning +dotnet_diagnostic.IDE0053.severity = error # IDE0054: Use compound assignment -dotnet_diagnostic.IDE0054.severity = warning +dotnet_diagnostic.IDE0054.severity = error # IDE0063: Use simple 'using' statement -dotnet_diagnostic.IDE0063.severity = warning +dotnet_diagnostic.IDE0063.severity = error # IDE0066: Use switch expression -dotnet_diagnostic.IDE0066.severity = warning +dotnet_diagnostic.IDE0066.severity = error # IDE0071: Simplify interpolation -dotnet_diagnostic.IDE0071.severity = warning +dotnet_diagnostic.IDE0071.severity = error # IDE0073: Require file header -dotnet_diagnostic.IDE0073.severity = warning +dotnet_diagnostic.IDE0073.severity = error # IDE0075: Simplify conditional expression -dotnet_diagnostic.IDE0075.severity = warning +dotnet_diagnostic.IDE0075.severity = error # IDE0078: Use pattern matching -dotnet_diagnostic.IDE0078.severity = warning +dotnet_diagnostic.IDE0078.severity = error # IDE0082: Convert typeof to nameof -dotnet_diagnostic.IDE0082.severity = warning +dotnet_diagnostic.IDE0082.severity = error # IDE0083: Use pattern matching (not operator) -dotnet_diagnostic.IDE0083.severity = warning +dotnet_diagnostic.IDE0083.severity = error # IDE0090: Simplify new expression -dotnet_diagnostic.IDE0090.severity = warning +dotnet_diagnostic.IDE0090.severity = error # IDE0100: Remove unnecessary equality operator -dotnet_diagnostic.IDE0100.severity = warning +dotnet_diagnostic.IDE0100.severity = error # IDE0110: Remove unnecessary discard -dotnet_diagnostic.IDE0110.severity = warning +dotnet_diagnostic.IDE0110.severity = error # IDE1005: Use conditional delegate call -dotnet_diagnostic.IDE1005.severity = warning +dotnet_diagnostic.IDE1005.severity = error [*.{json}] indent_size = 2 diff --git a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs index 5501ac2ce..3d31ede06 100644 --- a/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs +++ b/src/PowerShellEditorServices.Hosting/Commands/StartEditorServicesCommand.cs @@ -191,6 +191,7 @@ public StartEditorServicesCommand() [Parameter] public string StartupBanner { get; set; } +#pragma warning disable IDE0022 protected override void BeginProcessing() { #if DEBUG @@ -203,10 +204,10 @@ protected override void BeginProcessing() } } #endif - // Set up logging now for use throughout startup StartLogging(); } +#pragma warning restore IDE0022 [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Uses ThrowTerminatingError() instead")] protected override void EndProcessing() diff --git a/src/PowerShellEditorServices.Hosting/Internal/NamedPipeUtils.cs b/src/PowerShellEditorServices.Hosting/Internal/NamedPipeUtils.cs index 31f8d8414..79084427c 100644 --- a/src/PowerShellEditorServices.Hosting/Internal/NamedPipeUtils.cs +++ b/src/PowerShellEditorServices.Hosting/Internal/NamedPipeUtils.cs @@ -4,11 +4,12 @@ using System.Collections.Generic; using System.IO; using System.IO.Pipes; -using System.Runtime.InteropServices; #if !CoreCLR using System.Security.Principal; using System.Security.AccessControl; +#else +using System.Runtime.InteropServices; #endif namespace Microsoft.PowerShell.EditorServices.Hosting diff --git a/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs b/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs index d6974db2c..7e1b3487b 100644 --- a/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs +++ b/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs @@ -30,7 +30,6 @@ internal class PsesConfigurationHandler : DidChangeConfigurationHandlerBase private readonly PsesInternalHost _psesHost; private readonly ILanguageServerFacade _languageServer; private bool _profilesLoaded; - private readonly bool _extensionServiceInitialized; private bool _cwdSet; public PsesConfigurationHandler( @@ -127,10 +126,7 @@ await _psesHost.SetInitialWorkingDirectoryAsync( _cwdSet = true; } - if (!_extensionServiceInitialized) - { - await _extensionService.InitializeAsync().ConfigureAwait(false); - } + await _extensionService.InitializeAsync().ConfigureAwait(false); // Run any events subscribed to configuration updates _logger.LogTrace("Running configuration update event handlers"); From 416b58aeee4be9478d9cb747b2a7bc19ba1e174a Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 13 Apr 2022 16:32:34 -0700 Subject: [PATCH 2/3] Enable maintainability rules (and sort rule list) --- .editorconfig | 40 +++++++++++-------- .../Services/Analysis/AnalysisService.cs | 2 +- .../Handlers/DisconnectHandler.cs | 3 +- .../Handlers/LaunchAndAttachHandler.cs | 3 +- .../Handlers/ConfigurationHandler.cs | 10 ++--- .../Workspace/LanguageServerSettings.cs | 2 +- 6 files changed, 31 insertions(+), 29 deletions(-) diff --git a/.editorconfig b/.editorconfig index b98f7baef..e1fc3f2b9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -22,6 +22,8 @@ csharp_style_expression_bodied_indexers = true csharp_style_expression_bodied_accessors = true csharp_style_expression_bodied_lambdas = when_on_single_line +# TODO: Fix silenced and suggested rules! + # CS0168: The variable 'var' is declared but never used dotnet_diagnostic.CS0168.severity = error # CS0169: The private field 'class member' is never used @@ -30,10 +32,31 @@ dotnet_diagnostic.CS0169.severity = error dotnet_diagnostic.CS0219.severity = error # CS0414: The private field 'field' is assigned but its value is never used dotnet_diagnostic.CS0414.severity = error +# CS0618: A class member was marked with the Obsolete attribute +dotnet_diagnostic.CS0618.severity = suggestion +# CS0649: Uninitialized private or internal field declaration that is never assigned a value +dotnet_diagnostic.CS0649.severity = error +# CS1998: This async method lacks 'await' operators and will run synchronously +dotnet_diagnostic.CS1998.severity = suggestion +# CS4014: Consider applying the await operator to the result of the call +dotnet_diagnostic.CS4014.severity = suggestion + # CA1067: Should override Equals because it implements IEquatable dotnet_diagnostic.CA1067.severity = silent # CA1068: CancellationToken parameters must come last dotnet_diagnostic.CA1068.severity = error +# CA1501: Avoid excessive inheritance +dotnet_diagnostic.CA1501.severity = error +# CA1502: Avoid excessive complexity +dotnet_diagnostic.CA1502.severity = warning +# CA1505: Avoid unmaintainable code +dotnet_diagnostic.CA1505.severity = error +# CA1506: Avoid excessive class coupling +dotnet_diagnostic.CA1506.severity = warning +# CA1507: Use nameof in place of string +dotnet_diagnostic.CA1507.severity = error +# CA1508: Avoid dead conditional code +dotnet_diagnostic.CA1508.severity = error # CA1822: Mark members as static dotnet_diagnostic.CA1822.severity = error # CA1823: Avoid unused private fields @@ -45,23 +68,6 @@ dotnet_diagnostic.CA2016.severity = error # CA2254: The logging message template should not vary between calls to 'LoggerExtensions.*' dotnet_diagnostic.CA2254.severity = silent -# TODO: Enable all maintainability issues (dead code etc.) and enforce -# See: https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/maintainability-warnings -dotnet_analyzer_diagnostic.category-Maintainability.severity = error - -# TODO: Fix all of these issues and explicitly ignore the intentional ones! - -# CA2016: Forward the CancellationToken parameter to methods that take one -dotnet_diagnostic.CA2016.severity = error -# CS0618: A class member was marked with the Obsolete attribute -dotnet_diagnostic.CS0618.severity = suggestion -# CS0649: Uninitialized private or internal field declaration that is never assigned a value -dotnet_diagnostic.CS0649.severity = error -# CS1998: This async method lacks 'await' operators and will run synchronously -dotnet_diagnostic.CS1998.severity = suggestion -# CS4014: Consider applying the await operator to the result of the call -dotnet_diagnostic.CS4014.severity = suggestion - # RCS1102: Make class static dotnet_diagnostic.RCS1102.severity = error # RCS1139: Add summary element to documentation comment diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index e29063f19..2fa6cb636 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -249,7 +249,7 @@ public async Task>> Ge /// The new language server settings. public void OnConfigurationUpdated(object _, LanguageServerSettings settings) { - if (settings.ScriptAnalysis.Enable ?? true) + if (settings.ScriptAnalysis.Enable) { InitializeAnalysisEngineToCurrentSettings(); } diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DisconnectHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DisconnectHandler.cs index 704312d48..fef2b107c 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DisconnectHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/DisconnectHandler.cs @@ -67,8 +67,7 @@ await _executionService.ExecutePSCommandAsync( new PSCommand().AddCommand("Exit-PSHostProcess"), CancellationToken.None).ConfigureAwait(false); - if (_debugStateService.IsRemoteAttach && - _runspaceContext.CurrentRunspace.RunspaceOrigin == RunspaceOrigin.EnteredProcess) + if (_debugStateService.IsRemoteAttach) { await _executionService.ExecutePSCommandAsync( new PSCommand().AddCommand("Exit-PSSession"), diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs index b45edd25d..6c3db9dab 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs @@ -420,8 +420,7 @@ private async Task OnExecutionCompletedAsync(Task executeTask) { await _executionService.ExecutePSCommandAsync(new PSCommand().AddCommand("Exit-PSHostProcess"), CancellationToken.None).ConfigureAwait(false); - if (_debugStateService.IsRemoteAttach && - _runspaceContext.CurrentRunspace.RunspaceOrigin != RunspaceOrigin.Local) + if (_debugStateService.IsRemoteAttach) { await _executionService.ExecutePSCommandAsync(new PSCommand().AddCommand("Exit-PSSession"), CancellationToken.None).ConfigureAwait(false); } diff --git a/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs b/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs index 7e1b3487b..43a341191 100644 --- a/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs +++ b/src/PowerShellEditorServices/Services/Workspace/Handlers/ConfigurationHandler.cs @@ -64,10 +64,8 @@ public override async Task Handle(DidChangeConfigurationParams request, Ca SendFeatureChangesTelemetry(incomingSettings); bool profileLoadingPreviouslyEnabled = _configurationService.CurrentSettings.EnableProfileLoading; - bool oldScriptAnalysisEnabled = - _configurationService.CurrentSettings.ScriptAnalysis.Enable ?? false; - string oldScriptAnalysisSettingsPath = - _configurationService.CurrentSettings.ScriptAnalysis?.SettingsPath; + bool oldScriptAnalysisEnabled = _configurationService.CurrentSettings.ScriptAnalysis.Enable; + string oldScriptAnalysisSettingsPath = _configurationService.CurrentSettings.ScriptAnalysis?.SettingsPath; _configurationService.CurrentSettings.Update( incomingSettings.Powershell, @@ -186,10 +184,10 @@ private void SendFeatureChangesTelemetry(LanguageServerSettingsWrapper incomingS Dictionary configChanges = new(); // Send telemetry if the user opted-out of ScriptAnalysis - if (incomingSettings.Powershell.ScriptAnalysis.Enable == false && + if (!incomingSettings.Powershell.ScriptAnalysis.Enable && _configurationService.CurrentSettings.ScriptAnalysis.Enable != incomingSettings.Powershell.ScriptAnalysis.Enable) { - configChanges["ScriptAnalysis"] = incomingSettings.Powershell.ScriptAnalysis.Enable ?? false; + configChanges["ScriptAnalysis"] = incomingSettings.Powershell.ScriptAnalysis.Enable; } // Send telemetry if the user opted-out of CodeFolding diff --git a/src/PowerShellEditorServices/Services/Workspace/LanguageServerSettings.cs b/src/PowerShellEditorServices/Services/Workspace/LanguageServerSettings.cs index 9b30391fa..51f76f5ac 100644 --- a/src/PowerShellEditorServices/Services/Workspace/LanguageServerSettings.cs +++ b/src/PowerShellEditorServices/Services/Workspace/LanguageServerSettings.cs @@ -54,7 +54,7 @@ public void Update( internal class ScriptAnalysisSettings { private readonly object updateLock = new(); - public bool? Enable { get; set; } + public bool Enable { get; set; } public string SettingsPath { get; set; } public ScriptAnalysisSettings() => Enable = true; From 468f3baf8e9fbe916f3d1e8f77c3a8266d0c95cb Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 13 Apr 2022 19:38:17 -0700 Subject: [PATCH 3/3] Selectively enable and fix a few more rules --- .editorconfig | 10 ++++++++++ PowerShellEditorServices.Common.props | 1 + .../Configuration/EditorServicesConfig.cs | 8 ++++---- .../Configuration/TransportConfig.cs | 2 +- .../Hosting/EditorServicesServerFactory.cs | 3 ++- .../Server/PsesDebugServer.cs | 1 + .../Services/Analysis/AnalysisService.cs | 4 ++-- .../Services/Analysis/PssaCmdletAnalysisEngine.cs | 2 +- .../PowerShell/Utility/ErrorRecordExtensions.cs | 2 +- .../Services/TextDocument/FoldingReference.cs | 4 ++-- .../Services/TextDocument/TokenOperations.cs | 8 +++----- .../Services/Workspace/LanguageServerSettings.cs | 2 +- .../Processes/StdioServerProcess.cs | 13 ++++++++----- .../Completion/CompleteCommandFromModule.cs | 2 +- .../TestUtilities/TestUtilities.cs | 2 +- .../Debugging/DebugServiceTests.cs | 3 ++- .../Session/PathEscapingTests.cs | 4 ++-- .../Session/ScriptFileTests.cs | 4 ++-- 18 files changed, 45 insertions(+), 30 deletions(-) diff --git a/.editorconfig b/.editorconfig index e1fc3f2b9..2953ae8d9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -57,6 +57,12 @@ dotnet_diagnostic.CA1506.severity = warning dotnet_diagnostic.CA1507.severity = error # CA1508: Avoid dead conditional code dotnet_diagnostic.CA1508.severity = error +# CA1802: Use Literals Where Appropriate +dotnet_diagnostic.CA1802.severity = error +# CA1805: Do not initialize unnecessarily. +dotnet_diagnostic.CA1805.severity = error +# CA1820: Test for empty strings using string length +dotnet_diagnostic.CA1820.severity = error # CA1822: Mark members as static dotnet_diagnostic.CA1822.severity = error # CA1823: Avoid unused private fields @@ -65,9 +71,13 @@ dotnet_diagnostic.CA1823.severity = error dotnet_diagnostic.CA2007.severity = error # CA2016: Forward the CancellationToken parameter to methods that take one dotnet_diagnostic.CA2016.severity = error +# CA2213: Disposable fields should be disposed +dotnet_diagnostic.CA2213.severity = error # CA2254: The logging message template should not vary between calls to 'LoggerExtensions.*' dotnet_diagnostic.CA2254.severity = silent +# RCS1049: Simplify boolean comparison +dotnet_diagnostic.RCS1049.severity = error # RCS1102: Make class static dotnet_diagnostic.RCS1102.severity = error # RCS1139: Add summary element to documentation comment diff --git a/PowerShellEditorServices.Common.props b/PowerShellEditorServices.Common.props index d5546caef..4f7ab8e70 100644 --- a/PowerShellEditorServices.Common.props +++ b/PowerShellEditorServices.Common.props @@ -14,6 +14,7 @@ true true + true diff --git a/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs b/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs index 2347ac4a1..f8b6ef30f 100644 --- a/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs +++ b/src/PowerShellEditorServices.Hosting/Configuration/EditorServicesConfig.cs @@ -76,12 +76,12 @@ public EditorServicesConfig( /// /// Names of or paths to any additional modules to load on startup. /// - public IReadOnlyList AdditionalModules { get; set; } = null; + public IReadOnlyList AdditionalModules { get; set; } /// /// Flags of features to enable on startup. /// - public IReadOnlyList FeatureFlags { get; set; } = null; + public IReadOnlyList FeatureFlags { get; set; } /// /// The console REPL experience to use in the integrated console @@ -97,12 +97,12 @@ public EditorServicesConfig( /// /// Configuration for the language server protocol transport to use. /// - public ITransportConfig LanguageServiceTransport { get; set; } = null; + public ITransportConfig LanguageServiceTransport { get; set; } /// /// Configuration for the debug adapter protocol transport to use. /// - public ITransportConfig DebugServiceTransport { get; set; } = null; + public ITransportConfig DebugServiceTransport { get; set; } /// /// PowerShell profile locations for Editor Services to use for its profiles. diff --git a/src/PowerShellEditorServices.Hosting/Configuration/TransportConfig.cs b/src/PowerShellEditorServices.Hosting/Configuration/TransportConfig.cs index f3a703341..be763737c 100644 --- a/src/PowerShellEditorServices.Hosting/Configuration/TransportConfig.cs +++ b/src/PowerShellEditorServices.Hosting/Configuration/TransportConfig.cs @@ -49,7 +49,7 @@ public sealed class StdioTransportConfig : ITransportConfig public string SessionFileTransportName => "Stdio"; - public IReadOnlyDictionary SessionFileEntries { get; } = null; + public IReadOnlyDictionary SessionFileEntries { get; } public Task<(Stream inStream, Stream outStream)> ConnectStreamsAsync() { diff --git a/src/PowerShellEditorServices/Hosting/EditorServicesServerFactory.cs b/src/PowerShellEditorServices/Hosting/EditorServicesServerFactory.cs index d764d2155..72109788c 100644 --- a/src/PowerShellEditorServices/Hosting/EditorServicesServerFactory.cs +++ b/src/PowerShellEditorServices/Hosting/EditorServicesServerFactory.cs @@ -58,7 +58,8 @@ public static EditorServicesServerFactory Create(string logPath, int minimumLogL SelfLog.Enable(msg => Debug.WriteLine(msg)); #endif - ILoggerFactory loggerFactory = new LoggerFactory().AddSerilog(); + LoggerFactory loggerFactory = new(); + loggerFactory.AddSerilog(); // Hook up logging from the host so that its recorded in the log file hostLogger.Subscribe(new HostLoggerAdapter(loggerFactory)); diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs index 8d7ebf22c..c058f9460 100644 --- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs +++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs @@ -124,6 +124,7 @@ public void Dispose() _debugAdapterServer.Dispose(); _inputStream.Dispose(); _outputStream.Dispose(); + _loggerFactory.Dispose(); _serverStopped.SetResult(true); // TODO: If the debugger has stopped, should we clear the breakpoints? } diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index 2fa6cb636..9f511c37a 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -136,7 +136,7 @@ public AnalysisService( public void StartScriptDiagnostics( ScriptFile[] filesToAnalyze) { - if (_configurationService.CurrentSettings.ScriptAnalysis.Enable == false) + if (!_configurationService.CurrentSettings.ScriptAnalysis.Enable) { return; } @@ -468,7 +468,7 @@ private static Hashtable GetCommentHelpRuleSettings(string helpLocation, bool fo } #region IDisposable Support - private bool disposedValue = false; // To detect redundant calls + private bool disposedValue; // To detect redundant calls protected virtual void Dispose(bool disposing) { diff --git a/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs b/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs index b6d5ed7d4..9af1bff60 100644 --- a/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs +++ b/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs @@ -258,7 +258,7 @@ public Task AnalyzeScriptAsync(string scriptContent, Hashtab public PssaCmdletAnalysisEngine RecreateWithRules(string[] rules) => new(_logger, _analysisRunspacePool, _pssaModuleInfo, rules); #region IDisposable Support - private bool disposedValue = false; // To detect redundant calls + private bool disposedValue; // To detect redundant calls protected virtual void Dispose(bool disposing) { diff --git a/src/PowerShellEditorServices/Services/PowerShell/Utility/ErrorRecordExtensions.cs b/src/PowerShellEditorServices/Services/PowerShell/Utility/ErrorRecordExtensions.cs index e52675061..1cd5e4093 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Utility/ErrorRecordExtensions.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Utility/ErrorRecordExtensions.cs @@ -12,7 +12,7 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShell.Utility { internal static class ErrorRecordExtensions { - private static readonly Action s_setWriteStreamProperty = null; + private static readonly Action s_setWriteStreamProperty; [SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline", Justification = "cctor needed for version specific initialization")] static ErrorRecordExtensions() diff --git a/src/PowerShellEditorServices/Services/TextDocument/FoldingReference.cs b/src/PowerShellEditorServices/Services/TextDocument/FoldingReference.cs index 9b5be96f5..909a1a2ba 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/FoldingReference.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/FoldingReference.cs @@ -20,7 +20,7 @@ internal class FoldingReference : IComparable, IEquatable /// The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line. /// - public int StartCharacter { get; set; } = 0; + public int StartCharacter { get; set; } /// /// The zero-based line number where the folded range ends. @@ -30,7 +30,7 @@ internal class FoldingReference : IComparable, IEquatable /// The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line. /// - public int EndCharacter { get; set; } = 0; + public int EndCharacter { get; set; } /// /// Describes the kind of the folding range such as `comment' or 'region'. diff --git a/src/PowerShellEditorServices/Services/TextDocument/TokenOperations.cs b/src/PowerShellEditorServices/Services/TextDocument/TokenOperations.cs index 112cac163..67853388a 100644 --- a/src/PowerShellEditorServices/Services/TextDocument/TokenOperations.cs +++ b/src/PowerShellEditorServices/Services/TextDocument/TokenOperations.cs @@ -13,8 +13,6 @@ namespace Microsoft.PowerShell.EditorServices.Services.TextDocument /// internal static class TokenOperations { - private static readonly FoldingRangeKind? RegionKindNone = null; - // These regular expressions are used to match lines which mark the start and end of region comment in a PowerShell // script. They are based on the defaults in the VS Code Language Configuration at; // https://github.com/Microsoft/vscode/blob/64186b0a26/extensions/powershell/language-configuration.json#L26-L31 @@ -48,7 +46,7 @@ internal static FoldingReferenceList FoldableReferences( case TokenKind.RCurly: if (tokenCurlyStack.Count > 0) { - refList.SafeAdd(CreateFoldingReference(tokenCurlyStack.Pop(), token, RegionKindNone)); + refList.SafeAdd(CreateFoldingReference(tokenCurlyStack.Pop(), token, default)); } break; @@ -64,7 +62,7 @@ internal static FoldingReferenceList FoldableReferences( case TokenKind.RParen: if (tokenParenStack.Count > 0) { - refList.SafeAdd(CreateFoldingReference(tokenParenStack.Pop(), token, RegionKindNone)); + refList.SafeAdd(CreateFoldingReference(tokenParenStack.Pop(), token, default)); } break; @@ -76,7 +74,7 @@ internal static FoldingReferenceList FoldableReferences( case TokenKind.HereStringExpandable: if (token.Extent.StartLineNumber != token.Extent.EndLineNumber) { - refList.SafeAdd(CreateFoldingReference(token, token, RegionKindNone)); + refList.SafeAdd(CreateFoldingReference(token, token, default)); } break; } diff --git a/src/PowerShellEditorServices/Services/Workspace/LanguageServerSettings.cs b/src/PowerShellEditorServices/Services/Workspace/LanguageServerSettings.cs index 51f76f5ac..2a87ed97c 100644 --- a/src/PowerShellEditorServices/Services/Workspace/LanguageServerSettings.cs +++ b/src/PowerShellEditorServices/Services/Workspace/LanguageServerSettings.cs @@ -383,7 +383,7 @@ public class PesterSettings /// /// Whether integration features specific to Pester v5 are enabled /// - public bool UseLegacyCodeLens { get; set; } = false; + public bool UseLegacyCodeLens { get; set; } /// /// Update these settings from another settings object diff --git a/test/PowerShellEditorServices.Test.E2E/Processes/StdioServerProcess.cs b/test/PowerShellEditorServices.Test.E2E/Processes/StdioServerProcess.cs index be13c3203..0cfc516ec 100644 --- a/test/PowerShellEditorServices.Test.E2E/Processes/StdioServerProcess.cs +++ b/test/PowerShellEditorServices.Test.E2E/Processes/StdioServerProcess.cs @@ -23,7 +23,9 @@ public class StdioServerProcess : ServerProcess /// /// The current server process (if any). /// +#pragma warning disable CA2213 private Process _serverProcess; +#pragma warning restore CA2213 /// /// Create a new . @@ -55,7 +57,7 @@ protected override void Dispose(bool disposing) if (disposing) { Process serverProcess = Interlocked.Exchange(ref _serverProcess, null); - if (serverProcess != null) + if (serverProcess is not null) { if (!serverProcess.HasExited) { @@ -65,6 +67,7 @@ protected override void Dispose(bool disposing) serverProcess.Dispose(); } } + base.Dispose(disposing); } /// @@ -126,7 +129,7 @@ public override Task Stop() return ServerExitCompletion.Task; } - public event EventHandler ProcessExited; + public event EventHandler ProcessExited; /// /// Called when the server process has exited. @@ -147,7 +150,7 @@ private void ServerProcess_Exit(object sender, EventArgs args) string errorMsg = serverProcess.StandardError.ReadToEnd(); OnExited(); - ProcessExited?.Invoke(this, new ProcessExitedArgs(exitCode, errorMsg)); + ProcessExited?.Invoke(this, new ProcessExitedEventArgs(exitCode, errorMsg)); if (exitCode != 0) { ServerExitCompletion.TrySetException(new ProcessExitedException("Stdio server process exited unexpectedly", exitCode, errorMsg)); @@ -174,9 +177,9 @@ public ProcessExitedException(string message, int exitCode, string errorMessage) public string ErrorMessage { get; init; } } - public class ProcessExitedArgs : EventArgs + public class ProcessExitedEventArgs : EventArgs { - public ProcessExitedArgs(int exitCode, string errorMessage) + public ProcessExitedEventArgs(int exitCode, string errorMessage) { ExitCode = exitCode; ErrorMessage = errorMessage; diff --git a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandFromModule.cs b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandFromModule.cs index 7b4249228..709d66563 100644 --- a/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandFromModule.cs +++ b/test/PowerShellEditorServices.Test.Shared/Completion/CompleteCommandFromModule.cs @@ -8,7 +8,7 @@ namespace Microsoft.PowerShell.EditorServices.Test.Shared.Completion { internal static class CompleteCommandFromModule { - public static readonly string GetRandomDetail = + public const string GetRandomDetail = "Get-Random [[-Maximum] ] [-SetSeed ] [-Minimum ]"; public static readonly ScriptRegion SourceDetails = new( diff --git a/test/PowerShellEditorServices.Test.Shared/TestUtilities/TestUtilities.cs b/test/PowerShellEditorServices.Test.Shared/TestUtilities/TestUtilities.cs index 94513f666..555b51529 100644 --- a/test/PowerShellEditorServices.Test.Shared/TestUtilities/TestUtilities.cs +++ b/test/PowerShellEditorServices.Test.Shared/TestUtilities/TestUtilities.cs @@ -81,7 +81,7 @@ public static string NormalizeNewlines(string unixString) /// /// Not for use in production -- convenience code for debugging tests. /// - public static void AWAIT_DEBUGGER_HERE( + public static void AwaitDebuggerHere( [CallerMemberName] string callerName = null, [CallerFilePath] string callerPath = null, [CallerLineNumber] int callerLine = -1) diff --git a/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs b/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs index cf11f3cdc..b7b55ad61 100644 --- a/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs +++ b/test/PowerShellEditorServices.Test/Debugging/DebugServiceTests.cs @@ -62,6 +62,7 @@ public DebugServiceTests() public void Dispose() { debugService.Abort(); + debuggerStoppedQueue.Dispose(); psesHost.StopAsync().Wait(); GC.SuppressFinalize(this); } @@ -113,7 +114,7 @@ private void AssertDebuggerStopped( Assert.True(psesHost.DebugContext.IsStopped); - if (scriptPath != "") + if (!string.IsNullOrEmpty(scriptPath)) { // TODO: The drive letter becomes lower cased on Windows for some reason. Assert.Equal(scriptPath, eventArgs.ScriptPath, ignoreCase: true); diff --git a/test/PowerShellEditorServices.Test/Session/PathEscapingTests.cs b/test/PowerShellEditorServices.Test/Session/PathEscapingTests.cs index abc1605de..ef4a7a935 100644 --- a/test/PowerShellEditorServices.Test/Session/PathEscapingTests.cs +++ b/test/PowerShellEditorServices.Test/Session/PathEscapingTests.cs @@ -23,7 +23,7 @@ public class PathEscapingTests [InlineData("/CJK.chars/脚本/[hello].ps1", "/CJK.chars/脚本/`[hello`].ps1")] [InlineData("C:\\Animals\\утка\\quack.ps1", "C:\\Animals\\утка\\quack.ps1")] [InlineData("C:\\&nimals\\утка\\qu*ck?.ps1", "C:\\&nimals\\утка\\qu`*ck`?.ps1")] - public void CorrectlyWildcardEscapesPaths_NoSpaces(string unescapedPath, string escapedPath) + public void CorrectlyWildcardEscapesPathsNoSpaces(string unescapedPath, string escapedPath) { string extensionEscapedPath = PathUtils.WildcardEscapePath(unescapedPath); Assert.Equal(escapedPath, extensionEscapedPath); @@ -44,7 +44,7 @@ public void CorrectlyWildcardEscapesPaths_NoSpaces(string unescapedPath, string [InlineData("/CJK chars/脚本/[hello].ps1", "/CJK` chars/脚本/`[hello`].ps1")] [InlineData("C:\\Animal s\\утка\\quack.ps1", "C:\\Animal` s\\утка\\quack.ps1")] [InlineData("C:\\&nimals\\утка\\qu*ck?.ps1", "C:\\&nimals\\утка\\qu`*ck`?.ps1")] - public void CorrectlyWildcardEscapesPaths_Spaces(string unescapedPath, string escapedPath) + public void CorrectlyWildcardEscapesPathsSpaces(string unescapedPath, string escapedPath) { string extensionEscapedPath = PathUtils.WildcardEscapePath(unescapedPath, escapeSpaces: true); Assert.Equal(escapedPath, extensionEscapedPath); diff --git a/test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs b/test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs index 2543e69fc..140b2c37f 100644 --- a/test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs +++ b/test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs @@ -377,11 +377,11 @@ public void CanGetRangeAtLineBoundaries() [Trait("Category", "ScriptFile")] [Fact] - public void CanSplitLines_NoTrailingNewline() => Assert.Equal(s_testStringLines_noTrailingNewline, _scriptFile_noTrailingNewline.FileLines); + public void CanSplitLinesNoTrailingNewline() => Assert.Equal(s_testStringLines_noTrailingNewline, _scriptFile_noTrailingNewline.FileLines); [Trait("Category", "ScriptFile")] [Fact] - public void CanSplitLines_TrailingNewline() => Assert.Equal(s_testStringLines_trailingNewline, _scriptFile_trailingNewline.FileLines); + public void CanSplitLinesTrailingNewline() => Assert.Equal(s_testStringLines_trailingNewline, _scriptFile_trailingNewline.FileLines); [Trait("Category", "ScriptFile")] [Fact]