From 7c2c4943ad260b855c2e632a274b2b6599ec3ddd Mon Sep 17 00:00:00 2001 From: "Joseph L. Casale" <9957114+jcasale@users.noreply.github.com> Date: Sat, 20 Dec 2025 16:56:50 -0700 Subject: [PATCH 1/7] Updates tests to use MSTest and MTP. --- .github/workflows/main.yml | 6 +- src/PSDataProtection/PSDataProtection.csproj | 1 + src/Tests/IntegrationTests.cs | 138 ++++++++++--------- src/Tests/MSTestSettings.cs | 1 + src/Tests/ParameterTests.cs | 101 +++++++------- src/Tests/TestExtensions.cs | 2 +- src/Tests/Tests.csproj | 14 +- src/global.json | 6 + 8 files changed, 139 insertions(+), 130 deletions(-) create mode 100644 src/Tests/MSTestSettings.cs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c92dbae..7ceaf1a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -49,13 +49,15 @@ jobs: echo "informationalVersion=$informationalVersion" >> $env:GITHUB_OUTPUT - name: Run tests - run: dotnet.exe test .\src\PSDataProtection.sln --configuration Release --runtime win-x64 + run: | + cd .\src + dotnet.exe test --project .\Tests\Tests.csproj --configuration Debug --output Detailed - name: Clean solution run: dotnet.exe clean .\src\PSDataProtection.sln --configuration Release - name: Build project - run: dotnet.exe publish .\src\PSDataProtection\PSDataProtection.csproj --configuration Release --runtime win-x64 --output .\publish + run: dotnet.exe publish .\src\PSDataProtection\PSDataProtection.csproj --configuration Release --output .\publish - name: Prepare release run: Remove-Item ./publish/* -Include *.pdb,*.xml -ErrorAction Stop diff --git a/src/PSDataProtection/PSDataProtection.csproj b/src/PSDataProtection/PSDataProtection.csproj index 89451cf..b624128 100644 --- a/src/PSDataProtection/PSDataProtection.csproj +++ b/src/PSDataProtection/PSDataProtection.csproj @@ -2,6 +2,7 @@ net462 + win-x64 PSDataProtection preview preview-All diff --git a/src/Tests/IntegrationTests.cs b/src/Tests/IntegrationTests.cs index 75e7ab5..b0aaa9d 100644 --- a/src/Tests/IntegrationTests.cs +++ b/src/Tests/IntegrationTests.cs @@ -1,43 +1,29 @@ namespace Tests; -using System; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Security; using System.Security.Cryptography; + using PSDataProtection; -using Xunit; -public sealed class IntegrationTests : IDisposable +[TestClass] +public class IntegrationTests { - private readonly PowerShell powerShell; - - public IntegrationTests() - { - var initialSessionState = InitialSessionState.CreateDefault2(); - - var entry1 = new SessionStateCmdletEntry("New-DataProtectionSecret", typeof(NewDataProtectionSecretCommand), null); - initialSessionState.Commands.Add(entry1); - - var entry2 = new SessionStateCmdletEntry("Read-DataProtectionSecret", typeof(ReadDataProtectionSecretCommand), null); - initialSessionState.Commands.Add(entry2); - - this.powerShell = PowerShell.Create(initialSessionState); - } - - public static TheoryData NewDataProtectionSecretArguments() => new() - { - { Guid.NewGuid().ToString(), DataProtectionScope.CurrentUser }, - { Guid.NewGuid().ToString(), DataProtectionScope.LocalMachine } - }; - - [Theory] - [MemberData(nameof(NewDataProtectionSecretArguments))] + public static IEnumerable<(string Data, DataProtectionScope Scope)> NewDataProtectionSecretArguments() => + [ + new(Guid.NewGuid().ToString(), DataProtectionScope.CurrentUser), + new(Guid.NewGuid().ToString(), DataProtectionScope.LocalMachine) + ]; + + [TestMethod] + [DynamicData(nameof(NewDataProtectionSecretArguments))] public void ArgumentsAsObjectInPipelineShouldPass(string data, DataProtectionScope scope) { using var secureString = data.ToSecureString(); - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddCommand("Read-DataProtectionSecret") .AddParameter(nameof(ReadDataProtectionSecretCommand.Scope), scope); @@ -46,40 +32,42 @@ public void ArgumentsAsObjectInPipelineShouldPass(string data, DataProtectionSco psObject.Members.Add(new PSNoteProperty(nameof(NewDataProtectionSecretCommand.SecureString), secureString)); psObject.Members.Add(new PSNoteProperty(nameof(NewDataProtectionSecretCommand.Scope), scope)); - var results = this.powerShell.Invoke(new[] { psObject }); + var results = powerShell.Invoke(new[] { psObject }); - Assert.Single(results); + Assert.ContainsSingle(results); - Assert.Equal(data, results[0]); + Assert.AreEqual(data, results[0]); } - [Theory] - [MemberData(nameof(NewDataProtectionSecretArguments))] + [TestMethod] + [DynamicData(nameof(NewDataProtectionSecretArguments))] public void ArgumentsAsParametersShouldPass(string data, DataProtectionScope scope) { using var secureString = data.ToSecureString(); - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.SecureString), secureString) .AddParameter(nameof(NewDataProtectionSecretCommand.Scope), scope) .AddCommand("Read-DataProtectionSecret") .AddParameter(nameof(ReadDataProtectionSecretCommand.Scope), scope); - var results = this.powerShell.Invoke(); + var results = powerShell.Invoke(); - Assert.Single(results); + Assert.ContainsSingle(results); - Assert.Equal(data, results[0]); + Assert.AreEqual(data, results[0]); } - [Theory] - [MemberData(nameof(NewDataProtectionSecretArguments))] + [TestMethod] + [DynamicData(nameof(NewDataProtectionSecretArguments))] public void ResultAsSecureStringShouldPass(string data, DataProtectionScope scope) { using var secureString = data.ToSecureString(); - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.SecureString), secureString) .AddParameter(nameof(NewDataProtectionSecretCommand.Scope), scope) @@ -87,58 +75,61 @@ public void ResultAsSecureStringShouldPass(string data, DataProtectionScope scop .AddParameter(nameof(ReadDataProtectionSecretCommand.Scope), scope) .AddParameter(nameof(ReadDataProtectionSecretCommand.AsSecureString), true); - var results = this.powerShell.Invoke(); + var results = powerShell.Invoke(); - Assert.Single(results); + Assert.ContainsSingle(results); - Assert.Equal(data, results[0].ToPlainString()); + Assert.AreEqual(data, results[0].ToPlainString()); } - [Theory] - [MemberData(nameof(NewDataProtectionSecretArguments))] + [TestMethod] + [DynamicData(nameof(NewDataProtectionSecretArguments))] public void ScopeInPipelineShouldPass(string data, DataProtectionScope scope) { using var secureString = data.ToSecureString(); - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.SecureString), secureString) .AddCommand("Read-DataProtectionSecret") .AddParameter(nameof(ReadDataProtectionSecretCommand.Scope), scope); - var results = this.powerShell.Invoke(new[] { scope }); + var results = powerShell.Invoke(new[] { scope }); - Assert.Single(results); + Assert.ContainsSingle(results); - Assert.Equal(data, results[0]); + Assert.AreEqual(data, results[0]); } - [Theory] - [MemberData(nameof(NewDataProtectionSecretArguments))] + [TestMethod] + [DynamicData(nameof(NewDataProtectionSecretArguments))] public void SecureStringInPipelineShouldPass(string data, DataProtectionScope scope) { using var secureString = data.ToSecureString(); - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.Scope), scope) .AddCommand("Read-DataProtectionSecret") .AddParameter(nameof(ReadDataProtectionSecretCommand.Scope), scope); - var results = this.powerShell.Invoke(new[] { secureString }); + var results = powerShell.Invoke(new[] { secureString }); - Assert.Single(results); + Assert.ContainsSingle(results); - Assert.Equal(data, results[0]); + Assert.AreEqual(data, results[0]); } - [Theory] - [MemberData(nameof(NewDataProtectionSecretArguments))] + [TestMethod] + [DynamicData(nameof(NewDataProtectionSecretArguments))] public void ScopeAsObjectInPipelineShouldPass(string data, DataProtectionScope scope) { using var secureString = data.ToSecureString(); - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.SecureString), secureString) .AddCommand("Read-DataProtectionSecret") @@ -147,20 +138,21 @@ public void ScopeAsObjectInPipelineShouldPass(string data, DataProtectionScope s var psObject = new PSObject(); psObject.Members.Add(new PSNoteProperty(nameof(NewDataProtectionSecretCommand.Scope), scope)); - var results = this.powerShell.Invoke(new[] { psObject }); + var results = powerShell.Invoke(new[] { psObject }); - Assert.Single(results); + Assert.ContainsSingle(results); - Assert.Equal(data, results[0]); + Assert.AreEqual(data, results[0]); } - [Theory] - [MemberData(nameof(NewDataProtectionSecretArguments))] + [TestMethod] + [DynamicData(nameof(NewDataProtectionSecretArguments))] public void SecureStringAsObjectInPipelineShouldPass(string data, DataProtectionScope scope) { using var secureString = data.ToSecureString(); - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.Scope), scope) .AddCommand("Read-DataProtectionSecret") @@ -169,13 +161,23 @@ public void SecureStringAsObjectInPipelineShouldPass(string data, DataProtection var psObject = new PSObject(); psObject.Members.Add(new PSNoteProperty(nameof(NewDataProtectionSecretCommand.SecureString), secureString)); - var results = this.powerShell.Invoke(new[] { psObject }); + var results = powerShell.Invoke(new[] { psObject }); - Assert.Single(results); + Assert.ContainsSingle(results); - Assert.Equal(data, results[0]); + Assert.AreEqual(data, results[0]); } - /// - public void Dispose() => this.powerShell.Dispose(); + private static PowerShell CreateInstance() + { + var initialSessionState = InitialSessionState.CreateDefault2(); + + var entry1 = new SessionStateCmdletEntry("New-DataProtectionSecret", typeof(NewDataProtectionSecretCommand), null); + initialSessionState.Commands.Add(entry1); + + var entry2 = new SessionStateCmdletEntry("Read-DataProtectionSecret", typeof(ReadDataProtectionSecretCommand), null); + initialSessionState.Commands.Add(entry2); + + return PowerShell.Create(initialSessionState); + } } \ No newline at end of file diff --git a/src/Tests/MSTestSettings.cs b/src/Tests/MSTestSettings.cs new file mode 100644 index 0000000..6b35270 --- /dev/null +++ b/src/Tests/MSTestSettings.cs @@ -0,0 +1 @@ +[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] \ No newline at end of file diff --git a/src/Tests/ParameterTests.cs b/src/Tests/ParameterTests.cs index c660370..67b94bf 100644 --- a/src/Tests/ParameterTests.cs +++ b/src/Tests/ParameterTests.cs @@ -1,119 +1,120 @@ namespace Tests; -using System; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Security.Cryptography; + using PSDataProtection; -using Xunit; -public sealed class ParameterTests : IDisposable +[TestClass] +public class ParameterTests { - private readonly PowerShell powerShell; - - public ParameterTests() - { - var initialSessionState = InitialSessionState.CreateDefault2(); - - var entry1 = new SessionStateCmdletEntry("New-DataProtectionSecret", typeof(NewDataProtectionSecretCommand), null); - initialSessionState.Commands.Add(entry1); - - var entry2 = new SessionStateCmdletEntry("Read-DataProtectionSecret", typeof(ReadDataProtectionSecretCommand), null); - initialSessionState.Commands.Add(entry2); - - this.powerShell = PowerShell.Create(initialSessionState); - } - - [Fact] + [TestMethod] public void NewDataProtectionSecretWithEmptySecureStringShouldThrow() { using var secureString = string.Empty.ToSecureString(); - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.SecureString), secureString) .AddParameter(nameof(NewDataProtectionSecretCommand.Scope), DataProtectionScope.CurrentUser); - var exception = Record.Exception(this.powerShell.Invoke); + var exception = Assert.Throws(powerShell.Invoke); - Assert.IsType(exception); - Assert.IsType(exception.InnerException); + Assert.IsInstanceOfType(exception); + Assert.IsInstanceOfType(exception.InnerException); } - [Fact] + [TestMethod] public void NewDataProtectionSecretWithInvalidScopeShouldThrow() { using var secureString = Guid.NewGuid().ToString().ToSecureString(); - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.SecureString), secureString) .AddParameter(nameof(NewDataProtectionSecretCommand.Scope), Guid.NewGuid().ToString()); - var exception = Record.Exception(this.powerShell.Invoke); + var exception = Assert.Throws(powerShell.Invoke); - Assert.IsType(exception); - Assert.IsType(exception.InnerException); + Assert.IsInstanceOfType(exception); + Assert.IsInstanceOfType(exception.InnerException); } - [Fact] + [TestMethod] public void NewDataProtectionSecretWithInvalidSecureStringShouldThrow() { - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.SecureString), Guid.NewGuid().ToString()) .AddParameter(nameof(NewDataProtectionSecretCommand.Scope), DataProtectionScope.CurrentUser); - var exception = Record.Exception(this.powerShell.Invoke); + var exception = Assert.Throws(powerShell.Invoke); - Assert.IsType(exception); - Assert.IsType(exception.InnerException); + Assert.IsInstanceOfType(exception); + Assert.IsInstanceOfType(exception.InnerException); } - [Fact] + [TestMethod] public void ReadDataProtectionSecretWithEmptyProtectedStringShouldThrow() { - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("Read-DataProtectionSecret") .AddParameter(nameof(ReadDataProtectionSecretCommand.Protected), string.Empty) .AddParameter(nameof(ReadDataProtectionSecretCommand.Scope), DataProtectionScope.CurrentUser); - var exception = Record.Exception(this.powerShell.Invoke); + var exception = Assert.Throws(powerShell.Invoke); - Assert.IsAssignableFrom(exception); - Assert.IsType(exception.InnerException); + Assert.IsInstanceOfType(exception); + Assert.IsInstanceOfType(exception.InnerException); } - [Fact] + [TestMethod] public void ReadDataProtectionSecretWithInvalidProtectedStringShouldThrow() { - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("Read-DataProtectionSecret") .AddParameter(nameof(ReadDataProtectionSecretCommand.Protected), Guid.NewGuid()) .AddParameter(nameof(ReadDataProtectionSecretCommand.Scope), DataProtectionScope.CurrentUser); - var exception = Record.Exception(this.powerShell.Invoke); + var exception = Assert.Throws(powerShell.Invoke); - Assert.IsType(exception); - Assert.IsType(exception.InnerException); + Assert.IsInstanceOfType(exception); + Assert.IsInstanceOfType(exception.InnerException); } - [Fact] + [TestMethod] public void ReadDataProtectionSecretWithInvalidScopeShouldThrow() { - this.powerShell + using var powerShell = CreateInstance(); + powerShell .AddCommand("New-DataProtectionSecret") .AddParameter(nameof(NewDataProtectionSecretCommand.SecureString), Guid.NewGuid().ToString()) .AddParameter(nameof(NewDataProtectionSecretCommand.Scope), DataProtectionScope.CurrentUser) .AddCommand("Read-DataProtectionSecret") .AddParameter(nameof(ReadDataProtectionSecretCommand.Scope), Guid.NewGuid().ToString()); - var exception = Record.Exception(this.powerShell.Invoke); + var exception = Assert.Throws(powerShell.Invoke); - Assert.IsType(exception); - Assert.IsType(exception.InnerException); + Assert.IsInstanceOfType(exception); + Assert.IsInstanceOfType(exception.InnerException); } - /// - public void Dispose() => this.powerShell.Dispose(); + private static PowerShell CreateInstance() + { + var initialSessionState = InitialSessionState.CreateDefault2(); + + var entry1 = new SessionStateCmdletEntry("New-DataProtectionSecret", typeof(NewDataProtectionSecretCommand), null); + initialSessionState.Commands.Add(entry1); + + var entry2 = new SessionStateCmdletEntry("Read-DataProtectionSecret", typeof(ReadDataProtectionSecretCommand), null); + initialSessionState.Commands.Add(entry2); + + return PowerShell.Create(initialSessionState); + } } \ No newline at end of file diff --git a/src/Tests/TestExtensions.cs b/src/Tests/TestExtensions.cs index 3f760df..9a30a8e 100644 --- a/src/Tests/TestExtensions.cs +++ b/src/Tests/TestExtensions.cs @@ -4,7 +4,7 @@ namespace Tests; using System.Runtime.InteropServices; using System.Security; -public static class TestExtensions +internal static class TestExtensions { public static string ToPlainString(this SecureString input) { diff --git a/src/Tests/Tests.csproj b/src/Tests/Tests.csproj index 9df6bd9..dd6b2aa 100644 --- a/src/Tests/Tests.csproj +++ b/src/Tests/Tests.csproj @@ -1,22 +1,18 @@ - + net462 + win-x64 + enable preview - preview-All - + preview-all + all false - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/src/global.json b/src/global.json index c3e62a0..3b820cf 100644 --- a/src/global.json +++ b/src/global.json @@ -3,5 +3,11 @@ "version": "10.0.100", "rollForward": "latestFeature", "allowPrerelease": true + }, + "msbuild-sdks": { + "MSTest.Sdk": "4.0.2" + }, + "test": { + "runner": "Microsoft.Testing.Platform" } } \ No newline at end of file From 463bff23cc6a5496fa2870cd55c361e626d7e4b6 Mon Sep 17 00:00:00 2001 From: "Joseph L. Casale" <9957114+jcasale@users.noreply.github.com> Date: Sat, 20 Dec 2025 17:09:22 -0700 Subject: [PATCH 2/7] Migrates solution. --- .github/workflows/main.yml | 2 +- src/Directory.Packages.props | 11 ++++++ src/PSDataProtection.sln | 36 -------------------- src/PSDataProtection.slnx | 10 ++++++ src/PSDataProtection/PSDataProtection.csproj | 4 +-- src/Tests/Tests.csproj | 4 +-- 6 files changed, 26 insertions(+), 41 deletions(-) create mode 100644 src/Directory.Packages.props delete mode 100644 src/PSDataProtection.sln create mode 100644 src/PSDataProtection.slnx diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7ceaf1a..278efd9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,7 +54,7 @@ jobs: dotnet.exe test --project .\Tests\Tests.csproj --configuration Debug --output Detailed - name: Clean solution - run: dotnet.exe clean .\src\PSDataProtection.sln --configuration Release + run: dotnet.exe clean .\src\PSDataProtection.slnx --configuration Release - name: Build project run: dotnet.exe publish .\src\PSDataProtection\PSDataProtection.csproj --configuration Release --output .\publish diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props new file mode 100644 index 0000000..83d9af4 --- /dev/null +++ b/src/Directory.Packages.props @@ -0,0 +1,11 @@ + + + true + true + $(NoWarn);NU1507 + + + + + + \ No newline at end of file diff --git a/src/PSDataProtection.sln b/src/PSDataProtection.sln deleted file mode 100644 index 98be456..0000000 --- a/src/PSDataProtection.sln +++ /dev/null @@ -1,36 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PSDataProtection", "PSDataProtection\PSDataProtection.csproj", "{A3C12AE8-1389-4DF2-81BD-0E262FD78232}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{019154BA-934B-4B84-BE99-71242B2024E8}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A3D071BF-841A-4B83-9DEF-F51BB18DACBE}" - ProjectSection(SolutionItems) = preProject - ../.editorconfig = ../.editorconfig - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A3C12AE8-1389-4DF2-81BD-0E262FD78232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A3C12AE8-1389-4DF2-81BD-0E262FD78232}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A3C12AE8-1389-4DF2-81BD-0E262FD78232}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A3C12AE8-1389-4DF2-81BD-0E262FD78232}.Release|Any CPU.Build.0 = Release|Any CPU - {019154BA-934B-4B84-BE99-71242B2024E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {019154BA-934B-4B84-BE99-71242B2024E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {019154BA-934B-4B84-BE99-71242B2024E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {019154BA-934B-4B84-BE99-71242B2024E8}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {D672ED1E-3AAE-4FF8-8201-9DEAB17EB09D} - EndGlobalSection -EndGlobal \ No newline at end of file diff --git a/src/PSDataProtection.slnx b/src/PSDataProtection.slnx new file mode 100644 index 0000000..4a0d93d --- /dev/null +++ b/src/PSDataProtection.slnx @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/PSDataProtection/PSDataProtection.csproj b/src/PSDataProtection/PSDataProtection.csproj index b624128..e259268 100644 --- a/src/PSDataProtection/PSDataProtection.csproj +++ b/src/PSDataProtection/PSDataProtection.csproj @@ -10,8 +10,8 @@ - - + + diff --git a/src/Tests/Tests.csproj b/src/Tests/Tests.csproj index dd6b2aa..48202e4 100644 --- a/src/Tests/Tests.csproj +++ b/src/Tests/Tests.csproj @@ -11,8 +11,8 @@ - - + + From 223945a686da1f8db19d770c2f84625a7f15bb3e Mon Sep 17 00:00:00 2001 From: "Joseph L. Casale" <9957114+jcasale@users.noreply.github.com> Date: Sat, 20 Dec 2025 17:09:50 -0700 Subject: [PATCH 3/7] Updates dependencies. --- src/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 83d9af4..05f330b 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -6,6 +6,6 @@ - + \ No newline at end of file From 601b4009d01f4436107c078707f173c5f1208358 Mon Sep 17 00:00:00 2001 From: "Joseph L. Casale" <9957114+jcasale@users.noreply.github.com> Date: Sat, 20 Dec 2025 17:19:23 -0700 Subject: [PATCH 4/7] Updates analyzer configuration. --- .editorconfig | 477 ++++++++++++++++++----------------- src/Directory.Build.props | 11 + src/Directory.Packages.props | 2 + 3 files changed, 255 insertions(+), 235 deletions(-) diff --git a/.editorconfig b/.editorconfig index f46bf08..2a82993 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,81 +1,21 @@ root = true +# All files [*] charset = utf-8 -end_of_line = crlf -indent_size = 4 indent_style = space -tab_width = 4 -insert_final_newline = false -trim_trailing_whitespace = true -# Microsoft .NET properties -csharp_indent_braces = false -csharp_indent_switch_labels = true -csharp_new_line_before_open_brace = all -csharp_preserve_single_line_blocks = true -csharp_space_between_method_call_name_and_opening_parenthesis = false - -# ReSharper properties -resharper_align_multiline_binary_expressions_chain = false -resharper_align_multiline_statement_conditions = false -resharper_blank_lines_after_case = 1 -resharper_blank_lines_after_control_transfer_statements = 1 -resharper_blank_lines_around_accessor = 1 -resharper_blank_lines_around_block_case_section = 1 -resharper_blank_lines_around_multiline_case_section = 1 -resharper_blank_lines_before_case = 1 -resharper_blank_lines_before_control_transfer_statements = 1 -resharper_csharp_keep_blank_lines_in_code = 1 -resharper_csharp_keep_blank_lines_in_declarations = 1 -resharper_csharp_max_line_length = 999 -resharper_csharp_place_type_constraints_on_same_line = false -resharper_csharp_stick_comment = false -resharper_csharp_wrap_after_declaration_lpar = true -resharper_csharp_wrap_after_invocation_lpar = true -resharper_csharp_wrap_before_first_type_parameter_constraint = true -resharper_csharp_wrap_chained_method_calls = chop_if_long -resharper_csharp_wrap_extends_list_style = chop_if_long -resharper_csharp_wrap_lines = false -resharper_csharp_wrap_multiple_type_parameter_constraints_style = chop_always -resharper_csharp_wrap_parameters_style = chop_if_long -resharper_indent_braces_inside_statement_conditions = false -resharper_keep_existing_declaration_parens_arrangement = false -resharper_keep_existing_enum_arrangement = false -resharper_keep_existing_expr_member_arrangement = false -resharper_keep_existing_switch_expression_arrangement = false -resharper_max_attribute_length_for_same_line = 999 -resharper_max_enum_members_on_line = 1 -resharper_place_attribute_on_same_line = false -resharper_wrap_before_arrow_with_expressions = true -resharper_wrap_before_extends_colon = true -resharper_wrap_before_linq_expression = true -csharp_indent_labels = one_less_than_current -csharp_using_directive_placement = inside_namespace:suggestion -csharp_prefer_simple_using_statement = true:suggestion -csharp_prefer_braces = true:suggestion -csharp_style_namespace_declarations = file_scoped:suggestion -csharp_style_prefer_method_group_conversion = true:suggestion -csharp_style_expression_bodied_methods = true:suggestion -csharp_style_expression_bodied_constructors = true:suggestion -csharp_style_expression_bodied_operators = true:suggestion -csharp_style_expression_bodied_properties = true:suggestion -csharp_style_expression_bodied_indexers = true:suggestion -csharp_style_expression_bodied_accessors = true:suggestion -csharp_style_expression_bodied_lambdas = true:suggestion -csharp_style_expression_bodied_local_functions = true:suggestion -csharp_style_throw_expression = true:suggestion -csharp_space_around_binary_operators = before_and_after -csharp_style_prefer_top_level_statements = false:silent +# Xml files +[*.xml] +indent_size = 2 -[*.{cs,vb}] -file_header_template = +# C# files +[*.cs] #### Core EditorConfig Options #### # Indentation and spacing indent_size = 4 -indent_style = space tab_width = 4 # New line preferences @@ -83,16 +23,18 @@ end_of_line = crlf insert_final_newline = false #### .NET Coding Conventions #### +[*.{cs,vb}] # Organize usings -dotnet_separate_import_directive_groups = false +dotnet_separate_import_directive_groups = true dotnet_sort_system_directives_first = true +file_header_template = unset # this. and Me. preferences -dotnet_style_qualification_for_event = true:suggestion -dotnet_style_qualification_for_field = true:suggestion -dotnet_style_qualification_for_method = true:suggestion -dotnet_style_qualification_for_property = true:suggestion +dotnet_style_qualification_for_event = false:warning +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_property = false:warning # Language keywords vs BCL types preferences dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion @@ -105,7 +47,7 @@ dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion # Modifier preferences -dotnet_style_require_accessibility_modifiers = for_non_interface_members +dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion # Expression-level preferences dotnet_style_coalesce_expression = true:suggestion @@ -116,9 +58,11 @@ dotnet_style_null_propagation = true:suggestion dotnet_style_object_initializer = true:suggestion dotnet_style_operator_placement_when_wrapping = beginning_of_line dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion dotnet_style_prefer_compound_assignment = true:suggestion dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion -dotnet_style_prefer_conditional_expression_over_return = true:none +dotnet_style_prefer_conditional_expression_over_return = none +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed:suggestion dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion dotnet_style_prefer_inferred_tuple_names = true:suggestion dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion @@ -126,10 +70,10 @@ dotnet_style_prefer_simplified_boolean_expressions = true:suggestion dotnet_style_prefer_simplified_interpolation = true:suggestion # Field preferences -dotnet_style_readonly_field = true +dotnet_style_readonly_field = true:warning # Parameter preferences -dotnet_code_quality_unused_parameters = all +dotnet_code_quality_unused_parameters = all:suggestion # Suppression preferences dotnet_remove_unnecessary_suppression_exclusions = none @@ -138,7 +82,45 @@ dotnet_remove_unnecessary_suppression_exclusions = none dotnet_style_allow_multiple_blank_lines_experimental = false:suggestion dotnet_style_allow_statement_immediately_after_block_experimental = false:suggestion +# ReSharper inspection severities +resharper_access_to_disposed_closure_highlighting = none +resharper_arrange_object_creation_when_type_not_evident_highlighting = suggestion +resharper_convert_if_statement_to_return_statement_highlighting = none +resharper_invert_if_highlighting = none +resharper_loop_can_be_converted_to_query_highlighting = none +resharper_object_creation_when_type_not_evident = target_typed +resharper_redundant_name_qualifier_highlighting = none + +# Analyzer inspection severities +dotnet_diagnostic.IDE0001.severity = none +dotnet_diagnostic.IDE0003.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0003-ide0009 +dotnet_diagnostic.IDE0039.severity = none +dotnet_diagnostic.IDE0046.severity = none +dotnet_diagnostic.IDE0047.severity = none +dotnet_diagnostic.IDE0058.severity = none + +dotnet_diagnostic.CA1515.severity = none +dotnet_diagnostic.CA1822.severity = none + +dotnet_diagnostic.MA0003.severity = none +dotnet_diagnostic.MA0007.severity = none +dotnet_diagnostic.MA0038.severity = none +dotnet_diagnostic.MA0041.severity = none +dotnet_diagnostic.MA0051.severity = none + +dotnet_diagnostic.SA0001.severity = none +dotnet_diagnostic.SA1101.severity = none +dotnet_diagnostic.SA1118.severity = none +dotnet_diagnostic.SA1309.severity = none +dotnet_diagnostic.SA1312.severity = none +dotnet_diagnostic.SA1413.severity = none +dotnet_diagnostic.SA1518.severity = none +dotnet_diagnostic.SA1600.severity = none +dotnet_diagnostic.SA1601.severity = none +dotnet_diagnostic.SA1633.severity = none + #### C# Coding Conventions #### +[*.cs] # var preferences csharp_style_var_elsewhere = true:suggestion @@ -150,54 +132,55 @@ csharp_style_expression_bodied_accessors = true:suggestion csharp_style_expression_bodied_constructors = true:suggestion csharp_style_expression_bodied_indexers = true:suggestion csharp_style_expression_bodied_lambdas = true:suggestion -csharp_style_expression_bodied_local_functions = true:suggestion +csharp_style_expression_bodied_local_functions = false:silent csharp_style_expression_bodied_methods = true:suggestion csharp_style_expression_bodied_operators = true:suggestion csharp_style_expression_bodied_properties = true:suggestion # Pattern matching preferences -csharp_style_pattern_matching_over_as_with_null_check = true -csharp_style_pattern_matching_over_is_with_cast_check = true -csharp_style_prefer_extended_property_pattern = true -csharp_style_prefer_not_pattern = true +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion csharp_style_prefer_pattern_matching = true:suggestion -csharp_style_prefer_switch_expression = true +csharp_style_prefer_switch_expression = true:suggestion # Null-checking preferences -csharp_style_conditional_delegate_call = true -csharp_style_prefer_parameter_null_checking = true +csharp_style_conditional_delegate_call = true:suggestion # Modifier preferences -csharp_prefer_static_local_function = true -csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async +csharp_prefer_static_anonymous_function = true:suggestion +csharp_prefer_static_local_function = true:warning +csharp_preferred_modifier_order = public,private,protected,internal,file,const,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:suggestion +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion # Code-block preferences csharp_prefer_braces = true:suggestion -csharp_prefer_simple_using_statement = true +csharp_prefer_simple_using_statement = true:suggestion csharp_style_namespace_declarations = file_scoped:suggestion -csharp_style_prefer_method_group_conversion = true:suggestion +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_primary_constructors = false:silent +csharp_style_prefer_top_level_statements = true:silent # Expression-level preferences -csharp_prefer_simple_default_expression = true -csharp_style_deconstructed_variable_declaration = true -csharp_style_implicit_object_creation_when_type_is_apparent = true -csharp_style_inlined_variable_declaration = true -csharp_style_prefer_index_operator = true -csharp_style_prefer_local_over_anonymous_function = true -csharp_style_prefer_null_check_over_type_check = true -csharp_style_prefer_range_operator = true -csharp_style_prefer_tuple_swap = true -csharp_style_throw_expression = true -csharp_style_unused_value_assignment_preference = discard_variable:silent +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion csharp_style_unused_value_expression_statement_preference = discard_variable:silent # 'using' directive preferences -csharp_using_directive_placement = inside_namespace:suggestion - -# New line preferences -csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false:suggestion -csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:suggestion -csharp_style_allow_embedded_statements_on_same_line_experimental = false:suggestion +csharp_using_directive_placement = inside_namespace:warning +csharp_qualified_using_at_nested_scope = true:warning #### C# Formatting Rules #### @@ -247,182 +230,206 @@ csharp_preserve_single_line_blocks = true csharp_preserve_single_line_statements = true #### Naming styles #### +[*.{cs,vb}] # Naming rules -dotnet_naming_rule.class_should_be_pascal_case.severity = warning -dotnet_naming_rule.class_should_be_pascal_case.symbols = class -dotnet_naming_rule.class_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces +dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase -dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning -dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface -dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i +dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion +dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces +dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase -dotnet_naming_rule.struct_should_be_pascal_case.severity = warning -dotnet_naming_rule.struct_should_be_pascal_case.symbols = struct -dotnet_naming_rule.struct_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion +dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters +dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase -dotnet_naming_rule.enum_should_be_pascal_case.severity = warning -dotnet_naming_rule.enum_should_be_pascal_case.symbols = enum -dotnet_naming_rule.enum_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods +dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase -dotnet_naming_rule.types_should_be_pascal_case.severity = warning -dotnet_naming_rule.types_should_be_pascal_case.symbols = types -dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties +dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase -dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning -dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members -dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.events_should_be_pascalcase.symbols = events +dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase -dotnet_naming_rule.delegate_should_be_pascal_case.severity = warning -dotnet_naming_rule.delegate_should_be_pascal_case.symbols = delegate -dotnet_naming_rule.delegate_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion +dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables +dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase -dotnet_naming_rule.event_should_be_pascal_case.severity = warning -dotnet_naming_rule.event_should_be_pascal_case.symbols = event -dotnet_naming_rule.event_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion +dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants +dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase -dotnet_naming_rule.method_should_be_pascal_case.severity = warning -dotnet_naming_rule.method_should_be_pascal_case.symbols = method -dotnet_naming_rule.method_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion +dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters +dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase -dotnet_naming_rule.private_method_should_be_pascal_case.severity = warning -dotnet_naming_rule.private_method_should_be_pascal_case.symbols = private_method -dotnet_naming_rule.private_method_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields +dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase -dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning -dotnet_naming_rule.abstract_method_should_be_pascal_case.symbols = abstract_method -dotnet_naming_rule.abstract_method_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.private_fields_should_be__camelcase.severity = suggestion +dotnet_naming_rule.private_fields_should_be__camelcase.symbols = private_fields +dotnet_naming_rule.private_fields_should_be__camelcase.style = _camelcase -dotnet_naming_rule.static_method_should_be_pascal_case.severity = warning -dotnet_naming_rule.static_method_should_be_pascal_case.symbols = static_method -dotnet_naming_rule.static_method_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion +dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields +dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase -dotnet_naming_rule.property_should_be_pascal_case.severity = warning -dotnet_naming_rule.property_should_be_pascal_case.symbols = property -dotnet_naming_rule.property_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields +dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase -dotnet_naming_rule.property_should_be_pascal_case.severity = warning -dotnet_naming_rule.property_should_be_pascal_case.symbols = property -dotnet_naming_rule.property_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields +dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase -dotnet_naming_rule.static_field_should_be_pascal_case.severity = warning -dotnet_naming_rule.static_field_should_be_pascal_case.symbols = static_field -dotnet_naming_rule.static_field_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields +dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase -dotnet_naming_rule.private_or_internal_field_should_be_camel_case.severity = warning -dotnet_naming_rule.private_or_internal_field_should_be_camel_case.symbols = private_or_internal_field -dotnet_naming_rule.private_or_internal_field_should_be_camel_case.style = camel_case +dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields +dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase -dotnet_naming_rule.private_or_internal_static_field_should_be_camel_case.severity = warning -dotnet_naming_rule.private_or_internal_static_field_should_be_camel_case.symbols = private_or_internal_static_field -dotnet_naming_rule.private_or_internal_static_field_should_be_camel_case.style = camel_case +dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums +dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase -# Symbol specifications +dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase -dotnet_naming_symbols.class.applicable_kinds = class -dotnet_naming_symbols.class.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.class.required_modifiers = +dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase -dotnet_naming_symbols.interface.applicable_kinds = interface -dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.interface.required_modifiers = +# Symbol specifications -dotnet_naming_symbols.struct.applicable_kinds = struct -dotnet_naming_symbols.struct.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.struct.required_modifiers = +dotnet_naming_symbols.interfaces.applicable_kinds = interface +dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interfaces.required_modifiers = -dotnet_naming_symbols.enum.applicable_kinds = enum -dotnet_naming_symbols.enum.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.enum.required_modifiers = +dotnet_naming_symbols.enums.applicable_kinds = enum +dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.enums.required_modifiers = -dotnet_naming_symbols.delegate.applicable_kinds = delegate -dotnet_naming_symbols.delegate.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.delegate.required_modifiers = +dotnet_naming_symbols.events.applicable_kinds = event +dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.events.required_modifiers = -dotnet_naming_symbols.event.applicable_kinds = event -dotnet_naming_symbols.event.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.event.required_modifiers = +dotnet_naming_symbols.methods.applicable_kinds = method +dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.methods.required_modifiers = -dotnet_naming_symbols.method.applicable_kinds = method -dotnet_naming_symbols.method.applicable_accessibilities = public -dotnet_naming_symbols.method.required_modifiers = +dotnet_naming_symbols.properties.applicable_kinds = property +dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.properties.required_modifiers = -dotnet_naming_symbols.private_method.applicable_kinds = method -dotnet_naming_symbols.private_method.applicable_accessibilities = private -dotnet_naming_symbols.private_method.required_modifiers = +dotnet_naming_symbols.public_fields.applicable_kinds = field +dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal +dotnet_naming_symbols.public_fields.required_modifiers = -dotnet_naming_symbols.abstract_method.applicable_kinds = method -dotnet_naming_symbols.abstract_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.abstract_method.required_modifiers = abstract +dotnet_naming_symbols.private_fields.applicable_kinds = field +dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_fields.required_modifiers = -dotnet_naming_symbols.static_method.applicable_kinds = method -dotnet_naming_symbols.static_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.static_method.required_modifiers = static +dotnet_naming_symbols.private_static_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_static_fields.required_modifiers = static -dotnet_naming_symbols.property.applicable_kinds = property -dotnet_naming_symbols.property.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.property.required_modifiers = +dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum +dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types_and_namespaces.required_modifiers = -dotnet_naming_symbols.static_field.applicable_kinds = field -dotnet_naming_symbols.static_field.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.static_field.required_modifiers = static +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = -dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field -dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected -dotnet_naming_symbols.private_or_internal_field.required_modifiers = +dotnet_naming_symbols.type_parameters.applicable_kinds = namespace +dotnet_naming_symbols.type_parameters.applicable_accessibilities = * +dotnet_naming_symbols.type_parameters.required_modifiers = -dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds = field -dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities = internal, private, private_protected -dotnet_naming_symbols.private_or_internal_static_field.required_modifiers = static +dotnet_naming_symbols.private_constant_fields.applicable_kinds = field +dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_constant_fields.required_modifiers = const -dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum -dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.types.required_modifiers = +dotnet_naming_symbols.local_variables.applicable_kinds = local +dotnet_naming_symbols.local_variables.applicable_accessibilities = local +dotnet_naming_symbols.local_variables.required_modifiers = -dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method -dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.non_field_members.required_modifiers = +dotnet_naming_symbols.local_constants.applicable_kinds = local +dotnet_naming_symbols.local_constants.applicable_accessibilities = local +dotnet_naming_symbols.local_constants.required_modifiers = const -# Naming styles +dotnet_naming_symbols.parameters.applicable_kinds = parameter +dotnet_naming_symbols.parameters.applicable_accessibilities = * +dotnet_naming_symbols.parameters.required_modifiers = -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_naming_symbols.public_constant_fields.applicable_kinds = field +dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal +dotnet_naming_symbols.public_constant_fields.required_modifiers = const -dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.required_suffix = -dotnet_naming_style.begins_with_i.word_separator = -dotnet_naming_style.begins_with_i.capitalization = pascal_case +dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal +dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static -dotnet_naming_style.camel_case.required_prefix = -dotnet_naming_style.camel_case.required_suffix = -dotnet_naming_style.camel_case.word_separator = -dotnet_naming_style.camel_case.capitalization = camel_case +dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected +dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static -# ReSharper inspection severities -resharper_class_with_virtual_members_never_inherited_global_highlighting = none -resharper_convert_to_local_function_highlighting = none -resharper_inconsistent_naming_highlighting = none -resharper_member_can_be_private_global_highlighting = none -resharper_out_parameter_value_is_always_discarded_global_highlighting = none -resharper_out_parameter_value_is_always_discarded_local_highlighting = none -resharper_unused_auto_property_accessor_global_highlighting = none -resharper_unused_type_global_highlighting = none -resharper_redundant_name_qualifier_highlighting = none +dotnet_naming_symbols.local_functions.applicable_kinds = local_function +dotnet_naming_symbols.local_functions.applicable_accessibilities = * +dotnet_naming_symbols.local_functions.required_modifiers = -# MA0051: Method is too long -dotnet_diagnostic.MA0051.severity = none +# Naming styles -[*.csproj] +dotnet_naming_style.pascalcase.required_prefix = +dotnet_naming_style.pascalcase.required_suffix = +dotnet_naming_style.pascalcase.word_separator = +dotnet_naming_style.pascalcase.capitalization = pascal_case + +dotnet_naming_style.ipascalcase.required_prefix = I +dotnet_naming_style.ipascalcase.required_suffix = +dotnet_naming_style.ipascalcase.word_separator = +dotnet_naming_style.ipascalcase.capitalization = pascal_case + +dotnet_naming_style.tpascalcase.required_prefix = T +dotnet_naming_style.tpascalcase.required_suffix = +dotnet_naming_style.tpascalcase.word_separator = +dotnet_naming_style.tpascalcase.capitalization = pascal_case + +dotnet_naming_style._camelcase.required_prefix = _ +dotnet_naming_style._camelcase.required_suffix = +dotnet_naming_style._camelcase.word_separator = +dotnet_naming_style._camelcase.capitalization = camel_case + +dotnet_naming_style.camelcase.required_prefix = +dotnet_naming_style.camelcase.required_suffix = +dotnet_naming_style.camelcase.word_separator = +dotnet_naming_style.camelcase.capitalization = camel_case + +dotnet_naming_style.s_camelcase.required_prefix = s_ +dotnet_naming_style.s_camelcase.required_suffix = +dotnet_naming_style.s_camelcase.word_separator = +dotnet_naming_style.s_camelcase.capitalization = camel_case + +[**.json] indent_size = 2 +tab_width = 2 -[*.ruleset] +# XML project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] indent_size = 2 +tab_width = 2 -[*.json] +# XML config files +[*.{props,targets,ruleset,config,nuspec,resx,transform,vsixmanifest,vsct}] indent_size = 2 - -[*.yml] -indent_size = 2 \ No newline at end of file +tab_width = 2 diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b50b54b..c15c72b 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -7,4 +7,15 @@ Copyright (c) Joseph L. Casale. All rights reserved. + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 05f330b..97c330e 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -5,7 +5,9 @@ $(NoWarn);NU1507 + + \ No newline at end of file From 44fa980666888c9ce579a7af703b43f928c8a35a Mon Sep 17 00:00:00 2001 From: "Joseph L. Casale" <9957114+jcasale@users.noreply.github.com> Date: Sat, 20 Dec 2025 17:22:03 -0700 Subject: [PATCH 5/7] Updates access modifiers. --- src/PSDataProtection/ReadDataProtectionSecretCommand.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PSDataProtection/ReadDataProtectionSecretCommand.cs b/src/PSDataProtection/ReadDataProtectionSecretCommand.cs index a69bc67..944d514 100644 --- a/src/PSDataProtection/ReadDataProtectionSecretCommand.cs +++ b/src/PSDataProtection/ReadDataProtectionSecretCommand.cs @@ -10,11 +10,11 @@ namespace PSDataProtection; [OutputType(typeof(SecureString), ParameterSetName = [SecureStringParameterSetName])] public class ReadDataProtectionSecretCommand : PSCmdlet { - private readonly System.Text.UTF8Encoding encoding = new(); - public const string StringParameterSetName = "StringOutput"; public const string SecureStringParameterSetName = "SecureStringOutput"; + private readonly System.Text.UTF8Encoding encoding = new(); + [Parameter( Position = 0, Mandatory = true, From 14f32f456cd9cfc8c288de65c85d75f22df1f702 Mon Sep 17 00:00:00 2001 From: "Joseph L. Casale" <9957114+jcasale@users.noreply.github.com> Date: Sat, 20 Dec 2025 17:24:21 -0700 Subject: [PATCH 6/7] Fixes IDE1006: Naming rule violation. --- .../NewDataProtectionSecretCommand.cs | 22 ++++++++--------- .../ReadDataProtectionSecretCommand.cs | 24 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/PSDataProtection/NewDataProtectionSecretCommand.cs b/src/PSDataProtection/NewDataProtectionSecretCommand.cs index fc86548..6ccf8ca 100644 --- a/src/PSDataProtection/NewDataProtectionSecretCommand.cs +++ b/src/PSDataProtection/NewDataProtectionSecretCommand.cs @@ -10,7 +10,7 @@ namespace PSDataProtection; [OutputType(typeof(string))] public class NewDataProtectionSecretCommand : PSCmdlet { - private readonly System.Text.UTF8Encoding encoding = new(); + private readonly System.Text.UTF8Encoding _encoding = new(); [Parameter( Position = 0, @@ -35,11 +35,11 @@ protected override void ProcessRecord() IntPtr bString; try { - bString = Marshal.SecureStringToBSTR(this.SecureString); + bString = Marshal.SecureStringToBSTR(SecureString); } catch (Exception e) { - this.ThrowTerminatingError(new ErrorRecord( + ThrowTerminatingError(new ErrorRecord( e, "SecureStringToBinaryStringError", ErrorCategory.InvalidData, @@ -55,7 +55,7 @@ protected override void ProcessRecord() } catch (Exception e) { - this.ThrowTerminatingError(new ErrorRecord( + ThrowTerminatingError(new ErrorRecord( e, "BinaryStringToManagedStringError", ErrorCategory.InvalidData, @@ -70,7 +70,7 @@ protected override void ProcessRecord() if (string.IsNullOrWhiteSpace(insecurePassword)) { - this.ThrowTerminatingError(new ErrorRecord( + ThrowTerminatingError(new ErrorRecord( new InvalidOperationException("The secure string was empty."), "EmptyPassword", ErrorCategory.InvalidData, @@ -82,11 +82,11 @@ protected override void ProcessRecord() byte[] bytes; try { - bytes = this.encoding.GetBytes(insecurePassword); + bytes = _encoding.GetBytes(insecurePassword); } catch (Exception e) { - this.ThrowTerminatingError(new ErrorRecord( + ThrowTerminatingError(new ErrorRecord( e, "BinaryEncodingError", ErrorCategory.InvalidData, @@ -98,11 +98,11 @@ protected override void ProcessRecord() byte[] secret; try { - secret = ProtectedData.Protect(bytes, null, this.Scope!.Value); + secret = ProtectedData.Protect(bytes, null, Scope!.Value); } catch (Exception e) { - this.ThrowTerminatingError(new ErrorRecord( + ThrowTerminatingError(new ErrorRecord( e, "ProtectionError", ErrorCategory.NotSpecified, @@ -118,7 +118,7 @@ protected override void ProcessRecord() } catch (Exception e) { - this.ThrowTerminatingError(new ErrorRecord( + ThrowTerminatingError(new ErrorRecord( e, "Base64EncodingError", ErrorCategory.NotSpecified, @@ -127,6 +127,6 @@ protected override void ProcessRecord() return; } - this.WriteObject(encoded); + WriteObject(encoded); } } \ No newline at end of file diff --git a/src/PSDataProtection/ReadDataProtectionSecretCommand.cs b/src/PSDataProtection/ReadDataProtectionSecretCommand.cs index 944d514..67d8f68 100644 --- a/src/PSDataProtection/ReadDataProtectionSecretCommand.cs +++ b/src/PSDataProtection/ReadDataProtectionSecretCommand.cs @@ -10,10 +10,10 @@ namespace PSDataProtection; [OutputType(typeof(SecureString), ParameterSetName = [SecureStringParameterSetName])] public class ReadDataProtectionSecretCommand : PSCmdlet { - public const string StringParameterSetName = "StringOutput"; - public const string SecureStringParameterSetName = "SecureStringOutput"; + private const string StringParameterSetName = "StringOutput"; + private const string SecureStringParameterSetName = "SecureStringOutput"; - private readonly System.Text.UTF8Encoding encoding = new(); + private readonly System.Text.UTF8Encoding _encoding = new(); [Parameter( Position = 0, @@ -43,11 +43,11 @@ protected override void ProcessRecord() byte[] bytes; try { - bytes = Convert.FromBase64String(this.Protected); + bytes = Convert.FromBase64String(Protected); } catch (Exception e) { - this.ThrowTerminatingError(new ErrorRecord( + ThrowTerminatingError(new ErrorRecord( e, "Base64DecodingError", ErrorCategory.InvalidData, @@ -59,11 +59,11 @@ protected override void ProcessRecord() byte[] secret; try { - secret = ProtectedData.Unprotect(bytes, null, this.Scope!.Value); + secret = ProtectedData.Unprotect(bytes, null, Scope!.Value); } catch (Exception e) { - this.ThrowTerminatingError(new ErrorRecord( + ThrowTerminatingError(new ErrorRecord( e, "DecryptionError", ErrorCategory.NotSpecified, @@ -75,11 +75,11 @@ protected override void ProcessRecord() string decoded; try { - decoded = this.encoding.GetString(secret); + decoded = _encoding.GetString(secret); } catch (Exception e) { - this.ThrowTerminatingError(new ErrorRecord( + ThrowTerminatingError(new ErrorRecord( e, "DecodingError", ErrorCategory.NotSpecified, @@ -90,7 +90,7 @@ protected override void ProcessRecord() object result; - switch (this.ParameterSetName) + switch (ParameterSetName) { case StringParameterSetName: @@ -118,9 +118,9 @@ protected override void ProcessRecord() default: - throw new InvalidOperationException($"Unknown parameter set name: \"{this.ParameterSetName}\"."); + throw new InvalidOperationException($"Unknown parameter set name: \"{ParameterSetName}\"."); } - this.WriteObject(result); + WriteObject(result); } } \ No newline at end of file From 44fb10d03073c9844cc81c674058a62e59eb3473 Mon Sep 17 00:00:00 2001 From: "Joseph L. Casale" <9957114+jcasale@users.noreply.github.com> Date: Sat, 20 Dec 2025 17:35:38 -0700 Subject: [PATCH 7/7] Fixes formatting. --- .../NewDataProtectionSecretCommand.cs | 66 ++++++++++--------- .../ReadDataProtectionSecretCommand.cs | 33 +++++----- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/src/PSDataProtection/NewDataProtectionSecretCommand.cs b/src/PSDataProtection/NewDataProtectionSecretCommand.cs index 6ccf8ca..e154543 100644 --- a/src/PSDataProtection/NewDataProtectionSecretCommand.cs +++ b/src/PSDataProtection/NewDataProtectionSecretCommand.cs @@ -39,11 +39,12 @@ protected override void ProcessRecord() } catch (Exception e) { - ThrowTerminatingError(new ErrorRecord( - e, - "SecureStringToBinaryStringError", - ErrorCategory.InvalidData, - null)); + ThrowTerminatingError( + new( + e, + "SecureStringToBinaryStringError", + ErrorCategory.InvalidData, + null)); return; } @@ -55,11 +56,12 @@ protected override void ProcessRecord() } catch (Exception e) { - ThrowTerminatingError(new ErrorRecord( - e, - "BinaryStringToManagedStringError", - ErrorCategory.InvalidData, - null)); + ThrowTerminatingError( + new( + e, + "BinaryStringToManagedStringError", + ErrorCategory.InvalidData, + null)); return; } @@ -70,11 +72,12 @@ protected override void ProcessRecord() if (string.IsNullOrWhiteSpace(insecurePassword)) { - ThrowTerminatingError(new ErrorRecord( - new InvalidOperationException("The secure string was empty."), - "EmptyPassword", - ErrorCategory.InvalidData, - null)); + ThrowTerminatingError( + new( + new InvalidOperationException("The secure string was empty."), + "EmptyPassword", + ErrorCategory.InvalidData, + null)); return; } @@ -86,11 +89,12 @@ protected override void ProcessRecord() } catch (Exception e) { - ThrowTerminatingError(new ErrorRecord( - e, - "BinaryEncodingError", - ErrorCategory.InvalidData, - null)); + ThrowTerminatingError( + new( + e, + "BinaryEncodingError", + ErrorCategory.InvalidData, + null)); return; } @@ -102,11 +106,12 @@ protected override void ProcessRecord() } catch (Exception e) { - ThrowTerminatingError(new ErrorRecord( - e, - "ProtectionError", - ErrorCategory.NotSpecified, - null)); + ThrowTerminatingError( + new( + e, + "ProtectionError", + ErrorCategory.NotSpecified, + null)); return; } @@ -118,11 +123,12 @@ protected override void ProcessRecord() } catch (Exception e) { - ThrowTerminatingError(new ErrorRecord( - e, - "Base64EncodingError", - ErrorCategory.NotSpecified, - null)); + ThrowTerminatingError( + new( + e, + "Base64EncodingError", + ErrorCategory.NotSpecified, + null)); return; } diff --git a/src/PSDataProtection/ReadDataProtectionSecretCommand.cs b/src/PSDataProtection/ReadDataProtectionSecretCommand.cs index 67d8f68..0d4cfcd 100644 --- a/src/PSDataProtection/ReadDataProtectionSecretCommand.cs +++ b/src/PSDataProtection/ReadDataProtectionSecretCommand.cs @@ -47,11 +47,12 @@ protected override void ProcessRecord() } catch (Exception e) { - ThrowTerminatingError(new ErrorRecord( - e, - "Base64DecodingError", - ErrorCategory.InvalidData, - null)); + ThrowTerminatingError( + new( + e, + "Base64DecodingError", + ErrorCategory.InvalidData, + null)); return; } @@ -63,11 +64,12 @@ protected override void ProcessRecord() } catch (Exception e) { - ThrowTerminatingError(new ErrorRecord( - e, - "DecryptionError", - ErrorCategory.NotSpecified, - null)); + ThrowTerminatingError( + new( + e, + "DecryptionError", + ErrorCategory.NotSpecified, + null)); return; } @@ -79,11 +81,12 @@ protected override void ProcessRecord() } catch (Exception e) { - ThrowTerminatingError(new ErrorRecord( - e, - "DecodingError", - ErrorCategory.NotSpecified, - null)); + ThrowTerminatingError( + new( + e, + "DecodingError", + ErrorCategory.NotSpecified, + null)); return; }