diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 38dafb06..da0d4187 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,14 +33,30 @@ jobs: dotnet-version: | 11.0.x + - name: Restore tools + run: dotnet tool restore + - name: Restore dependencies run: dotnet restore - name: Build run: dotnet build -c Release --no-restore - name: Test - run: dotnet test -c Release --no-build -- --coverage --coverage-output-format cobertura --coverage-output coverage.cobertura.xml + run: dotnet test -c Release --no-build -- --coverage --coverage-output-format cobertura --coverage-output coverage.cobertura.xml --coverage-settings ./coverage-settings.xml + + - name: Package + run: dotnet pack -c Release --no-build --property:PackageOutputPath=../../nupkgs + - name: Validate Package + run: dotnet tool run dotnet-validate -- package local ./nupkgs/*.nupkg - - name: Upload coverage reports to Codecov with GitHub Action - uses: codecov/codecov-action@v6 + - name: Coveralls + uses: coverallsapp/github-action@v2 with: - token: ${{ secrets.CODECOV_TOKEN }} + files: > + tests/Immediate.Handlers.FunctionalTests/bin/Release/net8.0/TestResults/coverage.cobertura.xml + tests/Immediate.Handlers.FunctionalTests/bin/Release/net9.0/TestResults/coverage.cobertura.xml + tests/Immediate.Handlers.FunctionalTests/bin/Release/net10.0/TestResults/coverage.cobertura.xml + tests/Immediate.Handlers.FunctionalTests/bin/Release/net11.0/TestResults/coverage.cobertura.xml + tests/Immediate.Handlers.Tests/bin/Release/net8.0/TestResults/coverage.cobertura.xml + tests/Immediate.Handlers.Tests/bin/Release/net9.0/TestResults/coverage.cobertura.xml + tests/Immediate.Handlers.Tests/bin/Release/net10.0/TestResults/coverage.cobertura.xml + tests/Immediate.Handlers.Tests/bin/Release/net11.0/TestResults/coverage.cobertura.xml diff --git a/Directory.Build.props b/Directory.Build.props index 16144d67..8033da1a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,6 @@ + net8.0;net9.0;net10.0;net11.0 latest enable @@ -23,12 +24,12 @@ $(Polyfill)|T:System.Index $(Polyfill)|T:System.Range + $(Polyfill)|T:System.Diagnostics.CodeAnalysis $(Polyfill)|T:System.Runtime.CompilerServices.CallerArgumentExpressionAttribute $(Polyfill)|T:System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute $(Polyfill)|T:System.Runtime.CompilerServices.IsExternalInit $(Polyfill)|T:System.Runtime.CompilerServices.RequiredMemberAttribute $(Polyfill)|T:System.Runtime.CompilerServices.SkipLocalsInitAttribute - $(Polyfill)|T:System.Diagnostics.CodeAnalysis $(Polyfill) diff --git a/Directory.Packages.props b/Directory.Packages.props index c1ec4df3..a03eff88 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,9 +15,9 @@ - - - + + + @@ -59,8 +59,8 @@ - - - + + + diff --git a/Immediate.Handlers.slnx b/Immediate.Handlers.slnx index 696b672a..06481439 100644 --- a/Immediate.Handlers.slnx +++ b/Immediate.Handlers.slnx @@ -3,8 +3,10 @@ + + diff --git a/coverage-settings.xml b/coverage-settings.xml new file mode 100644 index 00000000..36bb3fbb --- /dev/null +++ b/coverage-settings.xml @@ -0,0 +1,20 @@ + + + + + + + + + ^System\.Diagnostics\.DebuggerHiddenAttribute$ + ^System\.Diagnostics\.DebuggerNonUserCodeAttribute$ + ^System\.CodeDom\.Compiler\.GeneratedCodeAttribute$ + ^System\.Diagnostics\.CodeAnalysis\.ExcludeFromCodeCoverageAttribute$ + + + + True + True + + + diff --git a/dotnet-tools.json b/dotnet-tools.json new file mode 100644 index 00000000..02aeded6 --- /dev/null +++ b/dotnet-tools.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-validate": { + "version": "0.0.1-preview.582", + "commands": [ + "dotnet-validate" + ], + "rollForward": true + } + } +} diff --git a/readme.md b/readme.md index 20dda482..8bc762bd 100644 --- a/readme.md +++ b/readme.md @@ -6,6 +6,7 @@ [![GitHub issues](https://img.shields.io/github/issues/ImmediatePlatform/Immediate.Handlers.svg)](https://GitHub.com/ImmediatePlatform/Immediate.Handlers/issues/) [![GitHub issues-closed](https://img.shields.io/github/issues-closed/ImmediatePlatform/Immediate.Handlers.svg)](https://GitHub.com/ImmediatePlatform/Immediate.Handlers/issues?q=is%3Aissue+is%3Aclosed) [![GitHub Actions](https://github.com/ImmediatePlatform/Immediate.Handlers/actions/workflows/build.yml/badge.svg)](https://github.com/ImmediatePlatform/Immediate.Handlers/actions) +[![Coverage Status](https://coveralls.io/repos/github/ImmediatePlatform/Immediate.Handlers/badge.svg)](https://coveralls.io/github/ImmediatePlatform/Immediate.Handlers) --- Immediate.Handlers is an implementation of the mediator pattern in .NET using source-generation. All pipeline behaviors @@ -17,16 +18,8 @@ safety checks. Behaviors and dependencies are obtained via DI at runtime based o ## Installing Immediate.Handlers -You can install [Immediate.Handlers with NuGet](https://www.nuget.org/packages/Immediate.Handlers): - - Install-Package Immediate.Handlers - -Or via the .NET Core command line interface: - dotnet add package Immediate.Handlers -Either commands, from Package Manager Console or .NET Core CLI, will download and install Immediate.Handlers. - ## Using Immediate.Handlers ### Creating Handlers diff --git a/src/Immediate.Handlers.Analyzers/Immediate.Handlers.Analyzers.csproj b/src/Immediate.Handlers.Analyzers/Immediate.Handlers.Analyzers.csproj index 11875335..24b6dbf3 100644 --- a/src/Immediate.Handlers.Analyzers/Immediate.Handlers.Analyzers.csproj +++ b/src/Immediate.Handlers.Analyzers/Immediate.Handlers.Analyzers.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0 true true @@ -14,7 +14,6 @@ - diff --git a/src/Immediate.Handlers.CodeFixes/Immediate.Handlers.CodeFixes.csproj b/src/Immediate.Handlers.CodeFixes/Immediate.Handlers.CodeFixes.csproj index d0699767..f3aa426e 100644 --- a/src/Immediate.Handlers.CodeFixes/Immediate.Handlers.CodeFixes.csproj +++ b/src/Immediate.Handlers.CodeFixes/Immediate.Handlers.CodeFixes.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0 true true @@ -19,7 +19,6 @@ - diff --git a/src/Immediate.Handlers.Generators/Immediate.Handlers.Generators.csproj b/src/Immediate.Handlers.Generators/Immediate.Handlers.Generators.csproj index 9debc555..552dd1e7 100644 --- a/src/Immediate.Handlers.Generators/Immediate.Handlers.Generators.csproj +++ b/src/Immediate.Handlers.Generators/Immediate.Handlers.Generators.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0 true true $(NoWarn);CA1716 @@ -21,7 +21,6 @@ - diff --git a/src/Immediate.Handlers/Immediate.Handlers.csproj b/src/Immediate.Handlers/Immediate.Handlers.csproj index 5a674234..d0a2bbad 100644 --- a/src/Immediate.Handlers/Immediate.Handlers.csproj +++ b/src/Immediate.Handlers/Immediate.Handlers.csproj @@ -1,7 +1,6 @@ - net8.0;net9.0;net10.0;net11.0 true false @@ -11,7 +10,7 @@ An implementation of the mediator pattern in .NET using source-generation. Immediate.Handlers Developers - © 2024-2025 Immediate.Handlers Developers + © 2024-2026 Immediate.Handlers Developers MIT readme.md @@ -26,14 +25,14 @@ --> - - - + + + - diff --git a/tests/Immediate.Handlers.FunctionalTests/Immediate.Handlers.FunctionalTests.csproj b/tests/Immediate.Handlers.FunctionalTests/Immediate.Handlers.FunctionalTests.csproj index 3b308e97..48d73b27 100644 --- a/tests/Immediate.Handlers.FunctionalTests/Immediate.Handlers.FunctionalTests.csproj +++ b/tests/Immediate.Handlers.FunctionalTests/Immediate.Handlers.FunctionalTests.csproj @@ -1,6 +1,6 @@  + - net8.0;net9.0;net10.0;net11.0 Exe diff --git a/tests/Immediate.Handlers.Tests/AnalyzerTests/AnalyzerTestHelpers.cs b/tests/Immediate.Handlers.Tests/AnalyzerTests/AnalyzerTestHelpers.cs index 747e07df..980450d3 100644 --- a/tests/Immediate.Handlers.Tests/AnalyzerTests/AnalyzerTestHelpers.cs +++ b/tests/Immediate.Handlers.Tests/AnalyzerTests/AnalyzerTestHelpers.cs @@ -1,8 +1,5 @@ -using System.Collections.Immutable; -using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using Immediate.Handlers.Generators; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Testing; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; @@ -38,118 +35,4 @@ private sealed class ImmediateHandlersGeneratorAnalyzerTest : CSharpA protected override IEnumerable GetSourceGenerators() => [typeof(ImmediateHandlersGenerator)]; } - - public sealed class CSharpSuppressorTest : CSharpAnalyzerTest - where TSuppressor : DiagnosticSuppressor, new() - where TVerifier : IVerifier, new() - { - private readonly List _analyzers = []; - - protected override IEnumerable GetDiagnosticAnalyzers() => - base.GetDiagnosticAnalyzers().Concat(_analyzers); - - public CSharpSuppressorTest WithAnalyzer(bool enableDiagnostics = false) - where TAnalyzer : DiagnosticAnalyzer, new() - { - var analyzer = new TAnalyzer(); - _analyzers.Add(analyzer); - - if (enableDiagnostics) - { - var diagnosticOptions = analyzer.SupportedDiagnostics - .ToImmutableDictionary( - descriptor => descriptor.Id, - descriptor => descriptor.DefaultSeverity.ToReportDiagnostic() - ); - - SolutionTransforms.Clear(); - SolutionTransforms.Add(EnableDiagnostics(diagnosticOptions)); - } - - return this; - } - - public CSharpSuppressorTest WithSpecificDiagnostics( - params DiagnosticResult[] diagnostics - ) - { - var diagnosticOptions = diagnostics - .ToImmutableDictionary( - descriptor => descriptor.Id, - descriptor => descriptor.Severity.ToReportDiagnostic() - ); - - SolutionTransforms.Clear(); - SolutionTransforms.Add(EnableDiagnostics(diagnosticOptions)); - return this; - } - - private static Func EnableDiagnostics( - ImmutableDictionary diagnostics - ) => - (solution, id) => - { - var options = solution.GetProject(id)?.CompilationOptions - ?? throw new InvalidOperationException("Compilation options missing."); - - return solution - .WithProjectCompilationOptions( - id, - options - .WithSpecificDiagnosticOptions(diagnostics) - ); - }; - - public CSharpSuppressorTest WithExpectedDiagnosticsResults( - params DiagnosticResult[] diagnostics - ) - { - ExpectedDiagnostics.AddRange(diagnostics); - return this; - } - - public CSharpSuppressorTest WithEditorConfig( - string content - ) - { - TestState.AnalyzerConfigFiles.Add(("/.editorconfig", content)); - return this; - } - } - - public static CSharpSuppressorTest CreateSuppressorTest( - [StringSyntax("c#-test")] string inputSource - ) - where TSuppressor : DiagnosticSuppressor, new() - { - var test = new CSharpSuppressorTest - { - TestCode = inputSource, - ReferenceAssemblies = Utility.ReferenceAssemblies, - CompilerDiagnostics = CompilerDiagnostics.Warnings, - DisabledDiagnostics = - { - "CS1591", - "CS8767", - }, - }; - - test.TestState.AdditionalReferences - .AddRange(Utility.GetAdditionalReferences()); - - return test; - } -} - -file static class DiagnosticSeverityExtensions -{ - public static ReportDiagnostic ToReportDiagnostic(this DiagnosticSeverity severity) - => severity switch - { - DiagnosticSeverity.Hidden => ReportDiagnostic.Hidden, - DiagnosticSeverity.Info => ReportDiagnostic.Info, - DiagnosticSeverity.Warning => ReportDiagnostic.Warn, - DiagnosticSeverity.Error => ReportDiagnostic.Error, - _ => throw new InvalidEnumArgumentException(nameof(severity), (int)severity, typeof(DiagnosticSeverity)), - }; } diff --git a/tests/Immediate.Handlers.Tests/Immediate.Handlers.Tests.csproj b/tests/Immediate.Handlers.Tests/Immediate.Handlers.Tests.csproj index 459e293b..00764cb0 100644 --- a/tests/Immediate.Handlers.Tests/Immediate.Handlers.Tests.csproj +++ b/tests/Immediate.Handlers.Tests/Immediate.Handlers.Tests.csproj @@ -1,7 +1,6 @@  - net8.0;net9.0;net10.0;net11.0 Exe <_SkipUpgradeNetAnalyzersNuGetWarning>true diff --git a/tests/Immediate.Handlers.Tests/AnalyzerTests/MarkHandleMethodAsStaticSuppressorTests.cs b/tests/Immediate.Handlers.Tests/SuppressorTests/MarkHandleMethodAsStaticSuppressorTests.cs similarity index 94% rename from tests/Immediate.Handlers.Tests/AnalyzerTests/MarkHandleMethodAsStaticSuppressorTests.cs rename to tests/Immediate.Handlers.Tests/SuppressorTests/MarkHandleMethodAsStaticSuppressorTests.cs index cc9e2884..19e3059d 100644 --- a/tests/Immediate.Handlers.Tests/AnalyzerTests/MarkHandleMethodAsStaticSuppressorTests.cs +++ b/tests/Immediate.Handlers.Tests/SuppressorTests/MarkHandleMethodAsStaticSuppressorTests.cs @@ -3,7 +3,7 @@ using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeQuality.Analyzers.QualityGuidelines; -namespace Immediate.Handlers.Tests.AnalyzerTests; +namespace Immediate.Handlers.Tests.SuppressorTests; public sealed class MarkHandleMethodAsStaticSuppressorTests { @@ -11,7 +11,7 @@ public sealed class MarkHandleMethodAsStaticSuppressorTests [Fact] public async Task HandlerMethodCA1822IsNotSuppressedNormally() => - await AnalyzerTestHelpers + await SuppressorTestHelper .CreateSuppressorTest( """ using System.Threading; @@ -44,7 +44,7 @@ CancellationToken token [Fact] public async Task HandlerMethodCA1822IsSuppressedWithEditorConfigOption() => - await AnalyzerTestHelpers + await SuppressorTestHelper .CreateSuppressorTest( """ using System.Threading; diff --git a/tests/Immediate.Handlers.Tests/SuppressorTests/SuppressorTestHelper.cs b/tests/Immediate.Handlers.Tests/SuppressorTests/SuppressorTestHelper.cs new file mode 100644 index 00000000..525ba187 --- /dev/null +++ b/tests/Immediate.Handlers.Tests/SuppressorTests/SuppressorTestHelper.cs @@ -0,0 +1,126 @@ +using System.Collections.Immutable; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; + +namespace Immediate.Handlers.Tests.SuppressorTests; + +internal static class SuppressorTestHelper +{ + public sealed class CSharpSuppressorTest : CSharpAnalyzerTest + where TSuppressor : DiagnosticSuppressor, new() + where TVerifier : IVerifier, new() + { + private readonly List _analyzers = []; + + protected override IEnumerable GetDiagnosticAnalyzers() => + base.GetDiagnosticAnalyzers().Concat(_analyzers); + + public CSharpSuppressorTest WithAnalyzer(bool enableDiagnostics = false) + where TAnalyzer : DiagnosticAnalyzer, new() + { + var analyzer = new TAnalyzer(); + _analyzers.Add(analyzer); + + if (enableDiagnostics) + { + var diagnosticOptions = analyzer.SupportedDiagnostics + .ToImmutableDictionary( + descriptor => descriptor.Id, + descriptor => descriptor.DefaultSeverity.ToReportDiagnostic() + ); + + SolutionTransforms.Clear(); + SolutionTransforms.Add(EnableDiagnostics(diagnosticOptions)); + } + + return this; + } + + public CSharpSuppressorTest WithSpecificDiagnostics( + params DiagnosticResult[] diagnostics + ) + { + var diagnosticOptions = diagnostics + .ToImmutableDictionary( + descriptor => descriptor.Id, + descriptor => descriptor.Severity.ToReportDiagnostic() + ); + + SolutionTransforms.Clear(); + SolutionTransforms.Add(EnableDiagnostics(diagnosticOptions)); + return this; + } + + private static Func EnableDiagnostics( + ImmutableDictionary diagnostics + ) => + (solution, id) => + { + var options = solution.GetProject(id)?.CompilationOptions + ?? throw new InvalidOperationException("Compilation options missing."); + + return solution + .WithProjectCompilationOptions( + id, + options + .WithSpecificDiagnosticOptions(diagnostics) + ); + }; + + public CSharpSuppressorTest WithExpectedDiagnosticsResults( + params DiagnosticResult[] diagnostics + ) + { + ExpectedDiagnostics.AddRange(diagnostics); + return this; + } + + public CSharpSuppressorTest WithEditorConfig( + string content + ) + { + TestState.AnalyzerConfigFiles.Add(("/.editorconfig", content)); + return this; + } + } + + public static CSharpSuppressorTest CreateSuppressorTest( + [StringSyntax("c#-test")] string inputSource + ) + where TSuppressor : DiagnosticSuppressor, new() + { + var test = new CSharpSuppressorTest + { + TestCode = inputSource, + ReferenceAssemblies = Utility.ReferenceAssemblies, + CompilerDiagnostics = CompilerDiagnostics.Warnings, + DisabledDiagnostics = + { + "CS1591", + "CS8767", + }, + }; + + test.TestState.AdditionalReferences + .AddRange(Utility.GetAdditionalReferences()); + + return test; + } +} + +file static class DiagnosticSeverityExtensions +{ + public static ReportDiagnostic ToReportDiagnostic(this DiagnosticSeverity severity) + => severity switch + { + DiagnosticSeverity.Hidden => ReportDiagnostic.Hidden, + DiagnosticSeverity.Info => ReportDiagnostic.Info, + DiagnosticSeverity.Warning => ReportDiagnostic.Warn, + DiagnosticSeverity.Error => ReportDiagnostic.Error, + _ => throw new InvalidEnumArgumentException(nameof(severity), (int)severity, typeof(DiagnosticSeverity)), + }; +}