From 509898724e1e84c1ecb6a14389e932c7ce46c60b Mon Sep 17 00:00:00 2001 From: Stuart Turner Date: Sat, 12 Oct 2024 11:44:36 -0500 Subject: [PATCH 1/2] Support attributes on input parameters --- .../ImmediateHandlersGenerator.Models.cs | 1 + ...diateHandlersGenerator.TransformHandler.cs | 42 +++++ .../Templates/Handler.sbntxt | 2 +- ...=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs | 73 +++++++++ ....ServiceCollectionExtensions.g.verified.cs | 25 +++ ...=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs | 73 +++++++++ ....ServiceCollectionExtensions.g.verified.cs | 25 +++ ...=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs | 73 +++++++++ ....ServiceCollectionExtensions.g.verified.cs | 25 +++ .../GeneratorTests/HandlerTests.cs | 154 +++++++++++++++++- 10 files changed, 489 insertions(+), 4 deletions(-) create mode 100644 tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.ComplexParameterAttribute_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs create mode 100644 tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.ComplexParameterAttribute_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs create mode 100644 tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs create mode 100644 tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs create mode 100644 tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.SimpleParameterAttribute_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs create mode 100644 tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.SimpleParameterAttribute_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs diff --git a/src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.Models.cs b/src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.Models.cs index dc03363a..fd23146e 100644 --- a/src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.Models.cs +++ b/src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.Models.cs @@ -19,6 +19,7 @@ private sealed record Behavior [ExcludeFromCodeCoverage] private sealed record Parameter { + public required string? Attributes { get; init; } public required string Type { get; init; } public required string Name { get; init; } } diff --git a/src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.TransformHandler.cs b/src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.TransformHandler.cs index 07167ad7..c346725a 100644 --- a/src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.TransformHandler.cs +++ b/src/Immediate.Handlers.Generators/ImmediateHandlersGenerator.TransformHandler.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; namespace Immediate.Handlers.Generators.ImmediateHandlers; @@ -61,6 +62,7 @@ CancellationToken cancellationToken .Take(handleMethod.Parameters.Length - (useToken ? 2 : 1)) .Select(p => new Parameter { + Attributes = p.GetAttributesString(), Type = p.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), Name = p.Name, }) @@ -136,4 +138,44 @@ file static class Extensions symbol .GetAttributes() .FirstOrDefault(a => a.AttributeClass.IsBehaviorsAttribute()); + + public static string? GetAttributesString(this IParameterSymbol parameter) + { + var attributes = parameter.GetAttributes(); + if (attributes.Length == 0) + return null; + + return $"[{string.Join(", ", attributes.Select(GetAttributeString))}] "; + } + + private static string GetAttributeString(AttributeData attributeData) + { + var @class = attributeData.AttributeClass!.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + + var parameters = new List(); + + foreach (var tc in attributeData.ConstructorArguments) + { + if (tc.GetTypedConstantString() is { } str) + parameters.Add(str); + } + + foreach (var na in attributeData.NamedArguments) + { + if (na.Value.GetTypedConstantString() is { } str) + parameters.Add($"{na.Key} = {str}"); + } + + return parameters.Count == 0 + ? @class + : $"{@class}({string.Join(", ", parameters)})"; + } + + [SuppressMessage("Style", "IDE0072:Add missing cases")] + private static string? GetTypedConstantString(this TypedConstant tc) => + tc.Kind switch + { + TypedConstantKind.Array => $"[{string.Join(", ", tc.Values.Select(GetTypedConstantString))}]", + _ => tc.ToCSharpString(), + }; } diff --git a/src/Immediate.Handlers.Generators/Templates/Handler.sbntxt b/src/Immediate.Handlers.Generators/Templates/Handler.sbntxt index 9da95c0d..2690b1bf 100644 --- a/src/Immediate.Handlers.Generators/Templates/Handler.sbntxt +++ b/src/Immediate.Handlers.Generators/Templates/Handler.sbntxt @@ -68,7 +68,7 @@ partial class {{ class_name }} public HandleBehavior( {{~ for parameter in handler_parameters ~}} - {{ parameter.type }} {{ parameter.name }}{{ if !for.last }},{{ end }} + {{ parameter.attributes }}{{ parameter.type }} {{ parameter.name }}{{ if !for.last }},{{ end }} {{~ end ~}} ) { diff --git a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.ComplexParameterAttribute_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.ComplexParameterAttribute_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs new file mode 100644 index 00000000..888bd5db --- /dev/null +++ b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.ComplexParameterAttribute_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs @@ -0,0 +1,73 @@ +//HintName: IH.Dummy.GetUsersQuery.g.cs +using Microsoft.Extensions.DependencyInjection; + +#pragma warning disable CS1591 + +namespace Dummy; + +partial class GetUsersQuery +{ + public sealed partial class Handler : global::Immediate.Handlers.Shared.IHandler + { + private readonly global::Dummy.GetUsersQuery.HandleBehavior _handleBehavior; + + public Handler( + global::Dummy.GetUsersQuery.HandleBehavior handleBehavior + ) + { + var handlerType = typeof(GetUsersQuery); + + _handleBehavior = handleBehavior; + + } + + public async global::System.Threading.Tasks.ValueTask HandleAsync( + global::Dummy.GetUsersQuery.Query request, + global::System.Threading.CancellationToken cancellationToken = default + ) + { + return await _handleBehavior + .HandleAsync(request, cancellationToken) + .ConfigureAwait(false); + } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior + { + private readonly global::Dummy.Service _service; + + public HandleBehavior( + [global::Dummy.TestAttribute(["Dummy1", "Dummy2"], ["Dummy1", "Dummy2"], ["Dummy3", "Dummy4"])] global::Dummy.Service service + ) + { + _service = service; + } + + public override async global::System.Threading.Tasks.ValueTask HandleAsync( + global::Dummy.GetUsersQuery.Query request, + global::System.Threading.CancellationToken cancellationToken + ) + { + return await global::Dummy.GetUsersQuery + .HandleAsync( + request + , _service + , cancellationToken + ) + .ConfigureAwait(false); + } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public static IServiceCollection AddHandlers( + IServiceCollection services, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + { + services.Add(new(typeof(global::Dummy.GetUsersQuery.Handler), typeof(global::Dummy.GetUsersQuery.Handler), lifetime)); + services.Add(new(typeof(global::Immediate.Handlers.Shared.IHandler), typeof(global::Dummy.GetUsersQuery.Handler), lifetime)); + services.Add(new(typeof(global::Dummy.GetUsersQuery.HandleBehavior), typeof(global::Dummy.GetUsersQuery.HandleBehavior), lifetime)); + return services; + } +} diff --git a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.ComplexParameterAttribute_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.ComplexParameterAttribute_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs new file mode 100644 index 00000000..7caa9424 --- /dev/null +++ b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.ComplexParameterAttribute_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs @@ -0,0 +1,25 @@ +//HintName: IH.ServiceCollectionExtensions.g.cs +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +#pragma warning disable CS1591 + +public static class HandlerServiceCollectionExtensions +{ + public static IServiceCollection AddBehaviors( + this IServiceCollection services) + { + + return services; + } + + public static IServiceCollection AddHandlers( + this IServiceCollection services, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + { + global::Dummy.GetUsersQuery.AddHandlers(services, lifetime); + + return services; + } +} diff --git a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs new file mode 100644 index 00000000..7da15aad --- /dev/null +++ b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs @@ -0,0 +1,73 @@ +//HintName: IH.Dummy.GetUsersQuery.g.cs +using Microsoft.Extensions.DependencyInjection; + +#pragma warning disable CS1591 + +namespace Dummy; + +partial class GetUsersQuery +{ + public sealed partial class Handler : global::Immediate.Handlers.Shared.IHandler + { + private readonly global::Dummy.GetUsersQuery.HandleBehavior _handleBehavior; + + public Handler( + global::Dummy.GetUsersQuery.HandleBehavior handleBehavior + ) + { + var handlerType = typeof(GetUsersQuery); + + _handleBehavior = handleBehavior; + + } + + public async global::System.Threading.Tasks.ValueTask HandleAsync( + global::Dummy.GetUsersQuery.Query request, + global::System.Threading.CancellationToken cancellationToken = default + ) + { + return await _handleBehavior + .HandleAsync(request, cancellationToken) + .ConfigureAwait(false); + } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior + { + private readonly global::Dummy.SomeKeyedService _service; + + public HandleBehavior( + [global::Microsoft.Extensions.DependencyInjection.FromKeyedServicesAttribute("SomeServiceKey"), global::Dummy.TestAttribute(Message = "Test")] global::Dummy.SomeKeyedService service + ) + { + _service = service; + } + + public override async global::System.Threading.Tasks.ValueTask HandleAsync( + global::Dummy.GetUsersQuery.Query request, + global::System.Threading.CancellationToken cancellationToken + ) + { + return await global::Dummy.GetUsersQuery + .HandleAsync( + request + , _service + , cancellationToken + ) + .ConfigureAwait(false); + } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public static IServiceCollection AddHandlers( + IServiceCollection services, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + { + services.Add(new(typeof(global::Dummy.GetUsersQuery.Handler), typeof(global::Dummy.GetUsersQuery.Handler), lifetime)); + services.Add(new(typeof(global::Immediate.Handlers.Shared.IHandler), typeof(global::Dummy.GetUsersQuery.Handler), lifetime)); + services.Add(new(typeof(global::Dummy.GetUsersQuery.HandleBehavior), typeof(global::Dummy.GetUsersQuery.HandleBehavior), lifetime)); + return services; + } +} diff --git a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs new file mode 100644 index 00000000..7caa9424 --- /dev/null +++ b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs @@ -0,0 +1,25 @@ +//HintName: IH.ServiceCollectionExtensions.g.cs +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +#pragma warning disable CS1591 + +public static class HandlerServiceCollectionExtensions +{ + public static IServiceCollection AddBehaviors( + this IServiceCollection services) + { + + return services; + } + + public static IServiceCollection AddHandlers( + this IServiceCollection services, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + { + global::Dummy.GetUsersQuery.AddHandlers(services, lifetime); + + return services; + } +} diff --git a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.SimpleParameterAttribute_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.SimpleParameterAttribute_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs new file mode 100644 index 00000000..c90fe4c1 --- /dev/null +++ b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.SimpleParameterAttribute_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs @@ -0,0 +1,73 @@ +//HintName: IH.Dummy.GetUsersQuery.g.cs +using Microsoft.Extensions.DependencyInjection; + +#pragma warning disable CS1591 + +namespace Dummy; + +partial class GetUsersQuery +{ + public sealed partial class Handler : global::Immediate.Handlers.Shared.IHandler + { + private readonly global::Dummy.GetUsersQuery.HandleBehavior _handleBehavior; + + public Handler( + global::Dummy.GetUsersQuery.HandleBehavior handleBehavior + ) + { + var handlerType = typeof(GetUsersQuery); + + _handleBehavior = handleBehavior; + + } + + public async global::System.Threading.Tasks.ValueTask HandleAsync( + global::Dummy.GetUsersQuery.Query request, + global::System.Threading.CancellationToken cancellationToken = default + ) + { + return await _handleBehavior + .HandleAsync(request, cancellationToken) + .ConfigureAwait(false); + } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior + { + private readonly global::Dummy.SomeKeyedService _service; + + public HandleBehavior( + [global::Microsoft.Extensions.DependencyInjection.FromKeyedServicesAttribute("SomeServiceKey")] global::Dummy.SomeKeyedService service + ) + { + _service = service; + } + + public override async global::System.Threading.Tasks.ValueTask HandleAsync( + global::Dummy.GetUsersQuery.Query request, + global::System.Threading.CancellationToken cancellationToken + ) + { + return await global::Dummy.GetUsersQuery + .HandleAsync( + request + , _service + , cancellationToken + ) + .ConfigureAwait(false); + } + } + + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + public static IServiceCollection AddHandlers( + IServiceCollection services, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + { + services.Add(new(typeof(global::Dummy.GetUsersQuery.Handler), typeof(global::Dummy.GetUsersQuery.Handler), lifetime)); + services.Add(new(typeof(global::Immediate.Handlers.Shared.IHandler), typeof(global::Dummy.GetUsersQuery.Handler), lifetime)); + services.Add(new(typeof(global::Dummy.GetUsersQuery.HandleBehavior), typeof(global::Dummy.GetUsersQuery.HandleBehavior), lifetime)); + return services; + } +} diff --git a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.SimpleParameterAttribute_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.SimpleParameterAttribute_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs new file mode 100644 index 00000000..7caa9424 --- /dev/null +++ b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.SimpleParameterAttribute_assemblies=Msdi#IH.ServiceCollectionExtensions.g.verified.cs @@ -0,0 +1,25 @@ +//HintName: IH.ServiceCollectionExtensions.g.cs +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +#pragma warning disable CS1591 + +public static class HandlerServiceCollectionExtensions +{ + public static IServiceCollection AddBehaviors( + this IServiceCollection services) + { + + return services; + } + + public static IServiceCollection AddHandlers( + this IServiceCollection services, + ServiceLifetime lifetime = ServiceLifetime.Scoped + ) + { + global::Dummy.GetUsersQuery.AddHandlers(services, lifetime); + + return services; + } +} diff --git a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.cs b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.cs index 33ba9dbb..33ed0f4c 100644 --- a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.cs +++ b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.cs @@ -34,7 +34,7 @@ private static ValueTask HandleAsync( Assert.Equal( [ - @"Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.Dummy.GetUsersQuery.g.cs", + "Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.Dummy.GetUsersQuery.g.cs", ], result.GeneratedTrees.Select(t => t.FilePath.Replace("\\", "/", StringComparison.Ordinal)) ); @@ -73,7 +73,7 @@ private static ValueTask HandleAsync( Assert.Equal( [ - @"Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.Dummy.GetUsersQuery.g.cs", + "Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.Dummy.GetUsersQuery.g.cs", ], result.GeneratedTrees.Select(t => t.FilePath.Replace("\\", "/", StringComparison.Ordinal)) ); @@ -112,7 +112,155 @@ Query _ Assert.Equal( [ - @"Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.Dummy.GetUsersQuery.g.cs", + "Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.Dummy.GetUsersQuery.g.cs", + ], + result.GeneratedTrees.Select(t => t.FilePath.Replace("\\", "/", StringComparison.Ordinal)) + ); + + _ = await Verify(result) + .UseParameters(string.Join("_", assemblies)); + } + + [Theory] + [InlineData(DriverReferenceAssemblies.Msdi)] + public async Task SimpleParameterAttribute(DriverReferenceAssemblies assemblies) + { + var result = GeneratorTestHelper.RunGenerator( + """ + using System.Threading; + using System.Threading.Tasks; + using Immediate.Handlers.Shared; + using Microsoft.Extensions.DependencyInjection; + + namespace Dummy; + + public sealed class SomeKeyedService; + + [Handler] + public static partial class GetUsersQuery + { + public record Query; + + private static ValueTask HandleAsync( + Query _, + [FromKeyedServices("SomeServiceKey")] SomeKeyedService service, + CancellationToken token) + { + return ValueTask.FromResult(0); + } + } + """, + assemblies + ); + + Assert.Equal( + [ + "Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.Dummy.GetUsersQuery.g.cs", + "Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.ServiceCollectionExtensions.g.cs", + ], + result.GeneratedTrees.Select(t => t.FilePath.Replace("\\", "/", StringComparison.Ordinal)) + ); + + _ = await Verify(result) + .UseParameters(string.Join("_", assemblies)); + } + + [Theory] + [InlineData(DriverReferenceAssemblies.Msdi)] + public async Task MultipleParameterAttributes(DriverReferenceAssemblies assemblies) + { + var result = GeneratorTestHelper.RunGenerator( + """ + using System; + using System.Threading; + using System.Threading.Tasks; + using Immediate.Handlers.Shared; + using Microsoft.Extensions.DependencyInjection; + + namespace Dummy; + + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class TestAttribute : Attribute + { + public required string Message { get; init; } + } + + public sealed class SomeKeyedService; + + [Handler] + public static partial class GetUsersQuery + { + public record Query; + + private static ValueTask HandleAsync( + Query _, + [FromKeyedServices("SomeServiceKey")] [Test(Message = "Test")] SomeKeyedService service, + CancellationToken token) + { + return ValueTask.FromResult(0); + } + } + """, + assemblies + ); + + Assert.Equal( + [ + "Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.Dummy.GetUsersQuery.g.cs", + "Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.ServiceCollectionExtensions.g.cs", + ], + result.GeneratedTrees.Select(t => t.FilePath.Replace("\\", "/", StringComparison.Ordinal)) + ); + + _ = await Verify(result) + .UseParameters(string.Join("_", assemblies)); + } + + [Theory] + [InlineData(DriverReferenceAssemblies.Msdi)] + public async Task ComplexParameterAttribute(DriverReferenceAssemblies assemblies) + { + var result = GeneratorTestHelper.RunGenerator( + """ + using System; + using System.Threading; + using System.Threading.Tasks; + using Immediate.Handlers.Shared; + using Microsoft.Extensions.DependencyInjection; + + namespace Dummy; + + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class TestAttribute(string[] param1, string[] param2, params string[] param3) : Attribute + { + public string[] Param1 => param1; + public string[] Param2 => param2; + public string[] Param3 => param3; + } + + public sealed class Service; + + [Handler] + public static partial class GetUsersQuery + { + public record Query; + + private static ValueTask HandleAsync( + Query _, + [Test(["Dummy1", "Dummy2"], param2: ["Dummy1", "Dummy2"], "Dummy3", "Dummy4")] Service service, + CancellationToken token) + { + return ValueTask.FromResult(0); + } + } + """, + assemblies + ); + + Assert.Equal( + [ + "Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.Dummy.GetUsersQuery.g.cs", + "Immediate.Handlers.Generators/Immediate.Handlers.Generators.ImmediateHandlers.ImmediateHandlersGenerator/IH.ServiceCollectionExtensions.g.cs", ], result.GeneratedTrees.Select(t => t.FilePath.Replace("\\", "/", StringComparison.Ordinal)) ); From eb9658ffe88d0dc71b441af7a768c493f10f6b16 Mon Sep 17 00:00:00 2001 From: Stuart Turner Date: Sat, 12 Oct 2024 11:51:33 -0500 Subject: [PATCH 2/2] Improve coverage --- ...es_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs | 2 +- .../GeneratorTests/HandlerTests.cs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs index 7da15aad..76e36510 100644 --- a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs +++ b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.MultipleParameterAttributes_assemblies=Msdi#IH.Dummy.GetUsersQuery.g.verified.cs @@ -38,7 +38,7 @@ public sealed class HandleBehavior : global::Immediate.Handlers.Shared.Behavior< private readonly global::Dummy.SomeKeyedService _service; public HandleBehavior( - [global::Microsoft.Extensions.DependencyInjection.FromKeyedServicesAttribute("SomeServiceKey"), global::Dummy.TestAttribute(Message = "Test")] global::Dummy.SomeKeyedService service + [global::Microsoft.Extensions.DependencyInjection.FromKeyedServicesAttribute("SomeServiceKey"), global::Dummy.TestAttribute(Message = "Test"), global::Dummy.Test2Attribute] global::Dummy.SomeKeyedService service ) { _service = service; diff --git a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.cs b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.cs index 33ed0f4c..3c39019d 100644 --- a/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.cs +++ b/tests/Immediate.Handlers.Tests/GeneratorTests/HandlerTests.cs @@ -184,7 +184,10 @@ public sealed class TestAttribute : Attribute { public required string Message { get; init; } } - + + [AttributeUsage(AttributeTargets.Parameter)] + public sealed class Test2Attribute : Attribute; + public sealed class SomeKeyedService; [Handler] @@ -194,7 +197,7 @@ public record Query; private static ValueTask HandleAsync( Query _, - [FromKeyedServices("SomeServiceKey")] [Test(Message = "Test")] SomeKeyedService service, + [FromKeyedServices("SomeServiceKey")] [Test(Message = "Test"), Test2] SomeKeyedService service, CancellationToken token) { return ValueTask.FromResult(0);