From cc41af2ecfa72d16ba1baf31c577a404c9526923 Mon Sep 17 00:00:00 2001 From: JerrettDavis Date: Wed, 27 May 2026 19:49:53 -0500 Subject: [PATCH] style: establish dotnet format baseline --- .editorconfig | 1 + .../Behavioral/Chain/ActionChain.cs | 2 +- .../Behavioral/Chain/ResultChain.cs | 2 +- .../Behavioral/Command/Command.cs | 2 +- .../Behavioral/Iterator/ReplayableSequence.cs | 2 +- .../Behavioral/Mediator/Mediator.cs | 2 +- .../Behavioral/Memento/Memento.cs | 2 +- .../Behavioral/Observer/AsyncObserver.cs | 570 +++++++++--------- .../Behavioral/Strategy/ActionStrategy.cs | 2 +- .../Behavioral/Strategy/AsyncStrategy.cs | 2 +- .../Behavioral/Strategy/Strategy.Try.cs | 2 +- .../Behavioral/Strategy/Strategy.cs | 2 +- .../Behavioral/Template/AsyncTemplate.cs | 2 +- .../Template/AsyncTemplateMethod.cs | 2 +- .../Behavioral/Template/TemplateMethod.cs | 2 +- src/PatternKit.Core/Common/Functional.cs | 2 +- src/PatternKit.Core/Common/Throw.cs | 2 +- .../Creational/Builder/BranchBuilder.cs | 2 +- .../Creational/Builder/ChainBuilder.cs | 2 +- .../Creational/Builder/Composer.cs | 2 +- .../Creational/Builder/MutableBuilder.cs | 2 +- .../Creational/Factory/Factory.cs | 2 +- .../Creational/Prototype/Prototype.cs | 2 +- .../Creational/Singleton/Singleton.cs | 2 +- .../Shims/DoesNotReturnAttribute.cs | 2 +- .../Structural/Adapter/Adapter.cs | 2 +- .../Structural/Bridge/Bridge.cs | 2 +- .../Structural/Facade/TypedFacade.cs | 2 +- src/PatternKit.Examples/ApiGateway/Demo.cs | 2 +- .../Chain/AuthLoggingDemo.cs | 2 +- .../ConfigDriven/TransactionPipelineDemo.cs | 2 +- .../Chain/MediatedTransactionPipelineDemo.cs | 2 +- ...rnKitExampleServiceCollectionExtensions.cs | 30 +- .../BackgroundJobsModule.cs | 2 +- .../CorporateAppState.cs | 2 +- .../IAppModule.cs | 2 +- .../IBackgroundJobScheduler.cs | 2 +- .../INotificationPublisher.cs | 2 +- .../InMemoryJobScheduler.cs | 2 +- .../MessagingModule.cs | 2 +- .../NotificationOptions.cs | 2 +- .../ObservabilityModule.cs | 2 +- .../QueueNotificationPublisher.cs | 2 +- .../Generators/State/OrderFlowDemo.cs | 34 +- .../Generators/Strategies/StrategySpecs.cs | 2 +- .../ComprehensiveDemo.cs | 4 +- .../MediatorDemo/Abstractions.cs | 2 +- src/PatternKit.Examples/MediatorDemo/Demo.cs | 2 +- .../MediatorDemo/MediatorScanning.cs | 4 +- .../MementoDemo/MementoDemo.cs | 2 +- .../Messaging/DispatcherExample.cs | 2 +- .../Messaging/ErpChannelAdapterExample.cs | 2 +- .../Messaging/MailboxExample.cs | 2 +- .../Messaging/MessageEnvelopeExample.cs | 2 +- .../Messaging/MessageRoutingExample.cs | 2 +- .../OrderEventDrivenConsumerExample.cs | 2 +- .../Messaging/ReliabilityExample.cs | 2 +- .../ObserverDemo/ReactivePrimitives.cs | 238 ++++---- .../ObserverDemo/ReactiveTransaction.cs | 428 ++++++------- .../ObserverDemo/SimpleEventHub.cs | 106 ++-- .../NotificationSystem.cs | 16 +- .../TemperatureMonitor.cs | 2 +- src/PatternKit.Examples/Pricing/Pipeline.cs | 2 +- .../Properties/AssemblyCoverage.cs | 2 +- .../Interceptors/TimingInterceptor.cs | 2 +- .../SingletonGeneratorDemo/ServiceRegistry.cs | 2 +- .../TemplateDemo/TemplateAsyncDemo.cs | 2 +- .../TemplateDemo/TemplateDemo.cs | 2 +- .../TemplateDemo/TemplateFluentDemo.cs | 2 +- .../Interpreter/InterpreterAttributes.cs | 2 +- .../ActivityTrackerGenerator.cs | 4 +- .../Adapter/AdapterGenerator.cs | 6 +- .../Ambassador/AmbassadorGenerator.cs | 4 +- .../AntiCorruptionLayerGenerator.cs | 6 +- .../AuditLog/AuditLogGenerator.cs | 4 +- .../BackendsForFrontendsGenerator.cs | 4 +- .../Bridge/BridgeGenerator.cs | 2 +- .../Bulkhead/BulkheadPolicyGenerator.cs | 4 +- .../CacheAside/CacheAsidePolicyGenerator.cs | 4 +- .../CanonicalDataModelGenerator.cs | 4 +- .../Chain/ChainGenerator.cs | 2 +- .../CircuitBreakerPolicyGenerator.cs | 4 +- .../ExternalConfigurationStoreGenerator.cs | 6 +- .../Command/CommandGenerator.cs | 2 +- .../ComposerGenerator.cs | 2 +- .../Composite/CompositeGenerator.cs | 2 +- .../DataMapping/DataMapperGenerator.cs | 4 +- .../DecoratorGenerator.cs | 2 +- .../DomainEventDispatcherGenerator.cs | 6 +- .../EventCarriedStateTransferGenerator.cs | 4 +- .../EventNotificationGenerator.cs | 4 +- .../EventSourcing/EventStoreGenerator.cs | 4 +- src/PatternKit.Generators/FacadeGenerator.cs | 6 +- .../Factories/AbstractFactoryGenerator.cs | 6 +- .../FeatureToggleSetGenerator.cs | 6 +- .../Flyweight/FlyweightGenerator.cs | 2 +- .../GatewayAggregationGenerator.cs | 4 +- .../GatewayRouting/GatewayRoutingGenerator.cs | 4 +- .../HealthEndpointMonitoringGenerator.cs | 4 +- .../IdentityMap/IdentityMapGenerator.cs | 4 +- .../Interpreter/InterpreterGenerator.cs | 6 +- .../Iterator/IteratorGenerator.cs | 2 +- .../LeaderElection/LeaderElectionGenerator.cs | 4 +- .../MaterializedViewGenerator.cs | 6 +- src/PatternKit.Generators/MementoGenerator.cs | 2 +- .../Messaging/BackplaneTopologyGenerator.cs | 6 +- .../Messaging/ChannelAdapterGenerator.cs | 4 +- .../Messaging/ChannelPurgerGenerator.cs | 4 +- .../Messaging/ClaimCheckGenerator.cs | 4 +- .../CompetingConsumerGroupGenerator.cs | 268 ++++---- .../Messaging/ContentEnricherGenerator.cs | 6 +- .../Messaging/ContentRouterGenerator.cs | 6 +- .../Messaging/ControlBusGenerator.cs | 6 +- .../CorrelationIdentifierGenerator.cs | 4 +- .../Messaging/DeadLetterChannelGenerator.cs | 4 +- .../Messaging/DispatcherGenerator.cs | 4 +- .../Messaging/DurableSubscriberGenerator.cs | 4 +- .../Messaging/DynamicRouterGenerator.cs | 6 +- .../Messaging/EventDrivenConsumerGenerator.cs | 4 +- .../Messaging/GuaranteedDeliveryGenerator.cs | 4 +- .../InvalidMessageChannelGenerator.cs | 4 +- .../Messaging/MailboxGenerator.cs | 6 +- .../Messaging/MessageBusGenerator.cs | 6 +- .../Messaging/MessageChannelGenerator.cs | 4 +- .../Messaging/MessageEnvelopeGenerator.cs | 8 +- .../Messaging/MessageExpirationGenerator.cs | 4 +- .../Messaging/MessageFilterGenerator.cs | 6 +- .../Messaging/MessageHistoryGenerator.cs | 4 +- .../Messaging/MessageStoreGenerator.cs | 4 +- .../Messaging/MessageTranslatorGenerator.cs | 6 +- .../Messaging/MessagingBridgeGenerator.cs | 4 +- .../Messaging/MessagingGatewayGenerator.cs | 4 +- .../PipesAndFiltersPipelineGenerator.cs | 4 +- .../Messaging/PollingConsumerGenerator.cs | 4 +- .../Messaging/RecipientListGenerator.cs | 6 +- .../Messaging/ReliabilityPipelineGenerator.cs | 6 +- .../Messaging/ResequencerGenerator.cs | 4 +- .../Messaging/RoutingSlipGenerator.cs | 6 +- .../Messaging/SagaGenerator.cs | 6 +- .../Messaging/ScatterGatherGenerator.cs | 6 +- .../Messaging/ServiceActivatorGenerator.cs | 4 +- .../Messaging/SplitterAggregatorGenerator.cs | 6 +- .../Messaging/WireTapGenerator.cs | 6 +- .../Observer/ObserverGenerator.cs | 18 +- .../PriorityQueue/PriorityQueueGenerator.cs | 4 +- .../Properties/AssemblyCoverage.cs | 2 +- .../PrototypeGenerator.cs | 6 +- src/PatternKit.Generators/ProxyGenerator.cs | 2 +- .../QueueLoadLevelingPolicyGenerator.cs | 4 +- .../RateLimiting/RateLimitPolicyGenerator.cs | 4 +- .../Repository/RepositoryGenerator.cs | 4 +- .../Retry/RetryPolicyGenerator.cs | 4 +- .../SchedulerAgentSupervisorGenerator.cs | 4 +- .../ServiceLayerOperationGenerator.cs | 6 +- .../Shims/NetStandard20.cs | 2 +- .../Sidecar/SidecarGenerator.cs | 4 +- .../Singleton/SingletonGenerator.cs | 2 +- .../Specification/SpecificationGenerator.cs | 6 +- .../StateMachineGenerator.cs | 36 +- .../StranglerFig/StranglerFigGenerator.cs | 4 +- .../StrategyGenerator.cs | 2 +- .../TableDataGatewayGenerator.cs | 4 +- .../TemplateGenerator.cs | 4 +- .../TransactionScriptGenerator.cs | 4 +- .../UnitOfWork/UnitOfWorkGenerator.cs | 6 +- src/PatternKit.Generators/VisitorGenerator.cs | 4 +- .../AbstractFactoryDemoTests.cs | 2 +- .../ApiGateway/ApiGatewayTests.cs | 2 +- .../BridgeDemo/BridgeDemoTests.cs | 2 +- .../BulkheadDemo/ShippingBulkheadDemoTests.cs | 8 +- .../ProductCatalogCacheAsideDemoTests.cs | 8 +- .../Chain/AuthLoggingDemoTests.cs | 2 +- .../MediatedTransactionPipelineDemoTests.cs | 2 +- .../Chain/NickelRoundingTests.cs | 2 +- .../FulfillmentCircuitBreakerDemoTests.cs | 8 +- .../CompositeDemo/CompositeDemoTests.cs | 2 +- ...tternKitExampleDependencyInjectionTests.cs | 4 +- .../EnterpriseOrderDemoTests.cs | 2 +- .../FacadeDemo/FacadeDemoTests.cs | 2 +- .../CorporateApplicationBuilderDemoTests.cs | 8 +- .../VisitorGeneratorExamplesTests.cs | 16 +- .../OrderIdentityMapDemoTests.cs | 8 +- .../InterpreterDemo/InterpreterDemoTests.cs | 2 +- .../IteratorDemo/IteratorDemoTests.cs | 2 +- .../OrderMaterializedViewDemoTests.cs | 2 +- .../MediatorDemo/MediatorDemoTests.cs | 2 +- .../MementoDemo/MementoDemoTests.cs | 2 +- .../PatternKitBenchmarkCoverageTests.cs | 24 +- .../PatternKitExampleCatalogTests.cs | 8 +- .../PatternKitPatternCatalogTests.cs | 8 +- .../Properties/AssemblyCoverage.cs | 2 +- .../PrototypeDemo/PrototypeDemoTests.cs | 2 +- .../ProxyDemo/ConsoleOutputCollection.cs | 12 +- .../ProxyDemo/ProxyDemoParameterlessTests.cs | 228 +++---- .../ProxyGeneratorDemoTests.cs | 14 +- .../RetryDemo/InventoryRetryDemoTests.cs | 8 +- .../ComposedStrategiesTests.Extended.cs | 2 +- .../Composed/ComposedStrategiesTests.cs | 2 +- .../AbstractionsAttributeCoverageTests.cs | 20 +- .../CompetingConsumerGroupGeneratorTests.cs | 158 ++--- .../InterpreterGeneratorTests.cs | 2 +- .../ObserverGeneratorTests.cs | 14 +- .../Properties/AssemblyCoverage.cs | 2 +- .../ProxyGeneratorTests.cs | 2 +- .../RoslynTestHelpers.cs | 2 +- .../StateMachineGeneratorTests.cs | 8 +- .../StrategyGeneratorTests.cs | 2 +- .../UnitOfWorkGeneratorTests.cs | 188 +++--- .../Application/UnitOfWork/UnitOfWorkTests.cs | 154 ++--- .../Behavioral/AsyncTemplateFluentTests.cs | 2 +- .../Behavioral/AsyncTemplateMethodTests.cs | 2 +- .../Behavioral/Chain/ActionChainTests.cs | 2 +- .../Behavioral/Chain/ResultChainTests.cs | 2 +- .../Behavioral/Command/CommandTests.cs | 2 +- .../Iterator/ReplayableSequenceTests.cs | 2 +- .../Behavioral/Memento/MementoTests.cs | 2 +- .../Strategy/ActionStrategyTests.cs | 2 +- .../Strategy/CoercerTryStrategyTests.cs | 2 +- .../Strategy/SelectorStrategyTests.cs | 2 +- .../Behavioral/TemplateFluentTests.cs | 2 +- .../Behavioral/TemplateMethodTests.cs | 2 +- .../Creational/Builder/ComposerTests.cs | 2 +- .../Messaging/ControlBus/ControlBusTests.cs | 204 +++---- .../Messaging/Routing/ResequencerTests.cs | 2 +- .../Messaging/Routing/ScatterGatherTests.cs | 4 +- .../Transformation/KeyedNormalizerTests.cs | 14 +- .../Properties/AssemblyCoverage.cs | 2 +- .../Structural/Facade/FacadeTests.cs | 2 +- .../Structural/Facade/TypedFacadeTests.cs | 14 +- .../Structural/Flyweight/FlyweightTests.cs | 2 +- 230 files changed, 1750 insertions(+), 1749 deletions(-) diff --git a/.editorconfig b/.editorconfig index daa5776c..94c5eae8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,6 +2,7 @@ root = true [*] charset = utf-8 +end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true diff --git a/src/PatternKit.Core/Behavioral/Chain/ActionChain.cs b/src/PatternKit.Core/Behavioral/Chain/ActionChain.cs index 4a336e57..2fcac46c 100644 --- a/src/PatternKit.Core/Behavioral/Chain/ActionChain.cs +++ b/src/PatternKit.Core/Behavioral/Chain/ActionChain.cs @@ -263,4 +263,4 @@ public Builder ThenContinue(Action action) /// /// public static Builder Create() => new(); -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Chain/ResultChain.cs b/src/PatternKit.Core/Behavioral/Chain/ResultChain.cs index d38b4f36..fb371448 100644 --- a/src/PatternKit.Core/Behavioral/Chain/ResultChain.cs +++ b/src/PatternKit.Core/Behavioral/Chain/ResultChain.cs @@ -246,4 +246,4 @@ public Builder Then(Func produce) /// ]]> /// public static Builder Create() => new(); -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Command/Command.cs b/src/PatternKit.Core/Behavioral/Command/Command.cs index a757de08..8efe1609 100644 --- a/src/PatternKit.Core/Behavioral/Command/Command.cs +++ b/src/PatternKit.Core/Behavioral/Command/Command.cs @@ -275,4 +275,4 @@ static async ValueTask AwaitUndo(int startIndex, ValueTask pending, TCtx localCt return new Command(Do, Undo); } } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Iterator/ReplayableSequence.cs b/src/PatternKit.Core/Behavioral/Iterator/ReplayableSequence.cs index 4b7da0c1..84907fad 100644 --- a/src/PatternKit.Core/Behavioral/Iterator/ReplayableSequence.cs +++ b/src/PatternKit.Core/Behavioral/Iterator/ReplayableSequence.cs @@ -207,4 +207,4 @@ public static IEnumerable> Batch(this ReplayableSequence. if (batch.Count > 0) yield return batch.ToArray(); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Mediator/Mediator.cs b/src/PatternKit.Core/Behavioral/Mediator/Mediator.cs index 4c63329a..354c3426 100644 --- a/src/PatternKit.Core/Behavioral/Mediator/Mediator.cs +++ b/src/PatternKit.Core/Behavioral/Mediator/Mediator.cs @@ -410,4 +410,4 @@ internal static class MediatorHelpers return r; } } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Memento/Memento.cs b/src/PatternKit.Core/Behavioral/Memento/Memento.cs index a66bdc5e..ddd692c2 100644 --- a/src/PatternKit.Core/Behavioral/Memento/Memento.cs +++ b/src/PatternKit.Core/Behavioral/Memento/Memento.cs @@ -271,4 +271,4 @@ public Builder Capacity(int capacity) /// Build the immutable history engine. public Memento Build() => new(_cloner, _applier, _equality, _capacity); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Observer/AsyncObserver.cs b/src/PatternKit.Core/Behavioral/Observer/AsyncObserver.cs index 646532cd..997c5f52 100644 --- a/src/PatternKit.Core/Behavioral/Observer/AsyncObserver.cs +++ b/src/PatternKit.Core/Behavioral/Observer/AsyncObserver.cs @@ -1,285 +1,285 @@ -using System.Runtime.CompilerServices; - -namespace PatternKit.Behavioral.Observer; - -/// -/// Async Observer (typed, fluent, thread-safe) -/// Asynchronously notifies multiple observers about events of type . -/// -/// -/// -/// This implementation mirrors but for asynchronous handlers. It uses a copy-on-write array -/// for subscriptions, providing lock-free add/remove and snapshot-based iteration during publish. Handlers can optionally be -/// gated by a predicate that is awaited. Error handling behavior is configured via the fluent . -/// -/// After and , the observer instance is immutable and thread-safe. -/// -/// The event payload type to broadcast. -public sealed class AsyncObserver -{ - /// - /// Asynchronous predicate to filter whether a handler should receive the event. - /// - /// The event. - /// - /// A whose result is to invoke the handler; otherwise . - /// - public delegate ValueTask Predicate(TEvent evt); - - /// - /// Asynchronous handler invoked when a published event passes an optional predicate. - /// - /// The event payload. - /// A that completes when handling finishes. - public delegate ValueTask Handler(TEvent evt); - - /// - /// Asynchronous error sink invoked when a handler throws; never throws back into the publisher. - /// - /// The exception from a handler. - /// The event being processed. - /// A representing sink completion. - public delegate ValueTask ErrorSink(Exception ex, TEvent evt); - - private enum ErrorPolicy - { - Swallow, - ThrowFirst, - ThrowAggregate - } - - private readonly ErrorPolicy _errorPolicy; - private readonly ErrorSink? _errorSink; - - private Entry[] _entries = []; // copy-on-write storage - private int _nextId; - - private struct Entry - { - public int Id; - public Predicate? Pred; - public Handler Callback; - } - - private AsyncObserver(ErrorPolicy policy, ErrorSink? sink) - => (_errorPolicy, _errorSink) = (policy, sink); - - /// - /// Current number of active subscriptions (approximate during concurrent updates). - /// - public int SubscriberCount => Volatile.Read(ref _entries).Length; - - /// - /// Publish an event to all matching subscribers asynchronously. Exceptions are handled according to the configured policy. - /// - /// The event value. - /// A token to cancel the publish operation. - /// When policy is ThrowAggregate and one or more handlers threw. - /// When policy is ThrowFirst and a handler threw; the first exception is rethrown. - /// If is canceled. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public async ValueTask PublishAsync(TEvent evt, CancellationToken cancellationToken = default) - { - cancellationToken.ThrowIfCancellationRequested(); - var snapshot = Volatile.Read(ref _entries); - List? errors = null; - - foreach (var t in snapshot) - { - cancellationToken.ThrowIfCancellationRequested(); - var e = t; // copy to avoid ref across await - var run = e.Pred is null || await e.Pred(evt).ConfigureAwait(false); - if (!run) continue; - - try - { - await e.Callback(evt).ConfigureAwait(false); - } - catch (Exception ex) - { - var sink = _errorSink; - if (sink is not null) - { - try - { - await sink(ex, evt).ConfigureAwait(false); - } - catch - { - /* swallow */ - } - } - - switch (_errorPolicy) - { - case ErrorPolicy.Swallow: - break; - case ErrorPolicy.ThrowFirst: - throw; - case ErrorPolicy.ThrowAggregate: - (errors ??= []).Add(ex); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - - if (errors is { Count: > 0 }) throw new AggregateException(errors); - } - - // Subscriptions - /// - /// Subscribe an asynchronous handler to receive all events. - /// - /// The handler to invoke. - /// An that removes the subscription when disposed. - public IDisposable Subscribe(Handler handler) => Subscribe(null, handler); - - /// - /// Subscribe an asynchronous handler with an optional asynchronous predicate filter. - /// - /// The filter to decide whether to deliver the event to the handler (optional). - /// The handler to invoke. - /// An that removes the subscription when disposed. - public IDisposable Subscribe(Predicate? predicate, Handler handler) - { - var id = Interlocked.Increment(ref _nextId); - while (true) - { - var curr = Volatile.Read(ref _entries); - var next = new Entry[curr.Length + 1]; - Array.Copy(curr, next, curr.Length); - next[curr.Length] = new Entry { Id = id, Pred = predicate, Callback = handler }; - if (Interlocked.CompareExchange(ref _entries, next, curr) == curr) - break; - } - - return new Subscription(this, id); - } - - // Convenience adapters for sync delegates - /// - /// Convenience adapter: subscribe a synchronous to the async observer. - /// - /// The synchronous handler to adapt. - /// An that removes the subscription when disposed. - public IDisposable Subscribe(Observer.Handler handler) - => Subscribe(null, e => - { - handler(in e); - return default; - }); - - /// - /// Convenience adapter: subscribe a synchronous predicate and handler to the async observer. - /// - /// The synchronous predicate to filter events. - /// The synchronous handler to adapt. - /// An that removes the subscription when disposed. - public IDisposable Subscribe(Observer.Predicate predicate, Observer.Handler handler) - => Subscribe((Predicate)(e => new ValueTask(predicate(in e))), - e => - { - handler(in e); - return default; - }); - - private void Unsubscribe(int id) - { - while (true) - { - var curr = Volatile.Read(ref _entries); - var idx = -1; - for (var i = 0; i < curr.Length; i++) - if (curr[i].Id == id) - { - idx = i; - break; - } - - if (idx < 0) return; - - var next = new Entry[curr.Length - 1]; - if (idx > 0) Array.Copy(curr, 0, next, 0, idx); - if (idx < curr.Length - 1) Array.Copy(curr, idx + 1, next, idx, curr.Length - idx - 1); - if (Interlocked.CompareExchange(ref _entries, next, curr) == curr) - return; - } - } - - private sealed class Subscription : IDisposable - { - private AsyncObserver? _owner; - private readonly int _id; - internal Subscription(AsyncObserver owner, int id) => (_owner, _id) = (owner, id); - - public void Dispose() - { - var o = Interlocked.Exchange(ref _owner, null); - o?.Unsubscribe(_id); - } - } - - /// Create a new fluent builder for . - public static Builder Create() => new(); - - /// Fluent builder for configuring error policy and sinks. - public sealed class Builder - { - private ErrorPolicy _policy = ErrorPolicy.ThrowAggregate; - private ErrorSink? _sink; - - /// Send handler exceptions to the provided asynchronous sink (never throws back). - /// The asynchronous error sink. - /// The current builder. - public Builder OnError(ErrorSink sink) - { - _sink = sink; - return this; - } - - /// - /// Convenience overload for synchronous error sinks. - /// - /// The synchronous error sink. - /// The current builder. - public Builder OnError(Observer.ErrorSink sink) - { - _sink = (ex, e) => - { - sink(ex, in e); - return default; - }; - return this; - } - - /// Swallow handler exceptions (after sending to sink if configured). - /// The current builder. - public Builder SwallowErrors() - { - _policy = ErrorPolicy.Swallow; - return this; - } - - /// Throw the first handler exception immediately. - /// The current builder. - public Builder ThrowFirstError() - { - _policy = ErrorPolicy.ThrowFirst; - return this; - } - - /// Aggregate all handler exceptions and throw at the end of publish (default). - /// The current builder. - public Builder ThrowAggregate() - { - _policy = ErrorPolicy.ThrowAggregate; - return this; - } - - /// Build the immutable, thread-safe async observer. - /// A configured . - public AsyncObserver Build() => new(_policy, _sink); - } -} \ No newline at end of file +using System.Runtime.CompilerServices; + +namespace PatternKit.Behavioral.Observer; + +/// +/// Async Observer (typed, fluent, thread-safe) +/// Asynchronously notifies multiple observers about events of type . +/// +/// +/// +/// This implementation mirrors but for asynchronous handlers. It uses a copy-on-write array +/// for subscriptions, providing lock-free add/remove and snapshot-based iteration during publish. Handlers can optionally be +/// gated by a predicate that is awaited. Error handling behavior is configured via the fluent . +/// +/// After and , the observer instance is immutable and thread-safe. +/// +/// The event payload type to broadcast. +public sealed class AsyncObserver +{ + /// + /// Asynchronous predicate to filter whether a handler should receive the event. + /// + /// The event. + /// + /// A whose result is to invoke the handler; otherwise . + /// + public delegate ValueTask Predicate(TEvent evt); + + /// + /// Asynchronous handler invoked when a published event passes an optional predicate. + /// + /// The event payload. + /// A that completes when handling finishes. + public delegate ValueTask Handler(TEvent evt); + + /// + /// Asynchronous error sink invoked when a handler throws; never throws back into the publisher. + /// + /// The exception from a handler. + /// The event being processed. + /// A representing sink completion. + public delegate ValueTask ErrorSink(Exception ex, TEvent evt); + + private enum ErrorPolicy + { + Swallow, + ThrowFirst, + ThrowAggregate + } + + private readonly ErrorPolicy _errorPolicy; + private readonly ErrorSink? _errorSink; + + private Entry[] _entries = []; // copy-on-write storage + private int _nextId; + + private struct Entry + { + public int Id; + public Predicate? Pred; + public Handler Callback; + } + + private AsyncObserver(ErrorPolicy policy, ErrorSink? sink) + => (_errorPolicy, _errorSink) = (policy, sink); + + /// + /// Current number of active subscriptions (approximate during concurrent updates). + /// + public int SubscriberCount => Volatile.Read(ref _entries).Length; + + /// + /// Publish an event to all matching subscribers asynchronously. Exceptions are handled according to the configured policy. + /// + /// The event value. + /// A token to cancel the publish operation. + /// When policy is ThrowAggregate and one or more handlers threw. + /// When policy is ThrowFirst and a handler threw; the first exception is rethrown. + /// If is canceled. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public async ValueTask PublishAsync(TEvent evt, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var snapshot = Volatile.Read(ref _entries); + List? errors = null; + + foreach (var t in snapshot) + { + cancellationToken.ThrowIfCancellationRequested(); + var e = t; // copy to avoid ref across await + var run = e.Pred is null || await e.Pred(evt).ConfigureAwait(false); + if (!run) continue; + + try + { + await e.Callback(evt).ConfigureAwait(false); + } + catch (Exception ex) + { + var sink = _errorSink; + if (sink is not null) + { + try + { + await sink(ex, evt).ConfigureAwait(false); + } + catch + { + /* swallow */ + } + } + + switch (_errorPolicy) + { + case ErrorPolicy.Swallow: + break; + case ErrorPolicy.ThrowFirst: + throw; + case ErrorPolicy.ThrowAggregate: + (errors ??= []).Add(ex); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + + if (errors is { Count: > 0 }) throw new AggregateException(errors); + } + + // Subscriptions + /// + /// Subscribe an asynchronous handler to receive all events. + /// + /// The handler to invoke. + /// An that removes the subscription when disposed. + public IDisposable Subscribe(Handler handler) => Subscribe(null, handler); + + /// + /// Subscribe an asynchronous handler with an optional asynchronous predicate filter. + /// + /// The filter to decide whether to deliver the event to the handler (optional). + /// The handler to invoke. + /// An that removes the subscription when disposed. + public IDisposable Subscribe(Predicate? predicate, Handler handler) + { + var id = Interlocked.Increment(ref _nextId); + while (true) + { + var curr = Volatile.Read(ref _entries); + var next = new Entry[curr.Length + 1]; + Array.Copy(curr, next, curr.Length); + next[curr.Length] = new Entry { Id = id, Pred = predicate, Callback = handler }; + if (Interlocked.CompareExchange(ref _entries, next, curr) == curr) + break; + } + + return new Subscription(this, id); + } + + // Convenience adapters for sync delegates + /// + /// Convenience adapter: subscribe a synchronous to the async observer. + /// + /// The synchronous handler to adapt. + /// An that removes the subscription when disposed. + public IDisposable Subscribe(Observer.Handler handler) + => Subscribe(null, e => + { + handler(in e); + return default; + }); + + /// + /// Convenience adapter: subscribe a synchronous predicate and handler to the async observer. + /// + /// The synchronous predicate to filter events. + /// The synchronous handler to adapt. + /// An that removes the subscription when disposed. + public IDisposable Subscribe(Observer.Predicate predicate, Observer.Handler handler) + => Subscribe((Predicate)(e => new ValueTask(predicate(in e))), + e => + { + handler(in e); + return default; + }); + + private void Unsubscribe(int id) + { + while (true) + { + var curr = Volatile.Read(ref _entries); + var idx = -1; + for (var i = 0; i < curr.Length; i++) + if (curr[i].Id == id) + { + idx = i; + break; + } + + if (idx < 0) return; + + var next = new Entry[curr.Length - 1]; + if (idx > 0) Array.Copy(curr, 0, next, 0, idx); + if (idx < curr.Length - 1) Array.Copy(curr, idx + 1, next, idx, curr.Length - idx - 1); + if (Interlocked.CompareExchange(ref _entries, next, curr) == curr) + return; + } + } + + private sealed class Subscription : IDisposable + { + private AsyncObserver? _owner; + private readonly int _id; + internal Subscription(AsyncObserver owner, int id) => (_owner, _id) = (owner, id); + + public void Dispose() + { + var o = Interlocked.Exchange(ref _owner, null); + o?.Unsubscribe(_id); + } + } + + /// Create a new fluent builder for . + public static Builder Create() => new(); + + /// Fluent builder for configuring error policy and sinks. + public sealed class Builder + { + private ErrorPolicy _policy = ErrorPolicy.ThrowAggregate; + private ErrorSink? _sink; + + /// Send handler exceptions to the provided asynchronous sink (never throws back). + /// The asynchronous error sink. + /// The current builder. + public Builder OnError(ErrorSink sink) + { + _sink = sink; + return this; + } + + /// + /// Convenience overload for synchronous error sinks. + /// + /// The synchronous error sink. + /// The current builder. + public Builder OnError(Observer.ErrorSink sink) + { + _sink = (ex, e) => + { + sink(ex, in e); + return default; + }; + return this; + } + + /// Swallow handler exceptions (after sending to sink if configured). + /// The current builder. + public Builder SwallowErrors() + { + _policy = ErrorPolicy.Swallow; + return this; + } + + /// Throw the first handler exception immediately. + /// The current builder. + public Builder ThrowFirstError() + { + _policy = ErrorPolicy.ThrowFirst; + return this; + } + + /// Aggregate all handler exceptions and throw at the end of publish (default). + /// The current builder. + public Builder ThrowAggregate() + { + _policy = ErrorPolicy.ThrowAggregate; + return this; + } + + /// Build the immutable, thread-safe async observer. + /// A configured . + public AsyncObserver Build() => new(_policy, _sink); + } +} diff --git a/src/PatternKit.Core/Behavioral/Strategy/ActionStrategy.cs b/src/PatternKit.Core/Behavioral/Strategy/ActionStrategy.cs index d4e57f76..3eda4e0e 100644 --- a/src/PatternKit.Core/Behavioral/Strategy/ActionStrategy.cs +++ b/src/PatternKit.Core/Behavioral/Strategy/ActionStrategy.cs @@ -183,4 +183,4 @@ public Builder Then(ActionHandler action) /// /// public static Builder Create() => new(); -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Strategy/AsyncStrategy.cs b/src/PatternKit.Core/Behavioral/Strategy/AsyncStrategy.cs index 54fb3171..99eebe1f 100644 --- a/src/PatternKit.Core/Behavioral/Strategy/AsyncStrategy.cs +++ b/src/PatternKit.Core/Behavioral/Strategy/AsyncStrategy.cs @@ -214,4 +214,4 @@ public Builder Default(Func syncHandler) /// /// A new instance. public static Builder Create() => new(); -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Strategy/Strategy.Try.cs b/src/PatternKit.Core/Behavioral/Strategy/Strategy.Try.cs index 2297ede7..3b1dd97a 100644 --- a/src/PatternKit.Core/Behavioral/Strategy/Strategy.Try.cs +++ b/src/PatternKit.Core/Behavioral/Strategy/Strategy.Try.cs @@ -149,4 +149,4 @@ public WhenBuilder Add(TryHandler handler) /// /// public static Builder Create() => new(); -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Strategy/Strategy.cs b/src/PatternKit.Core/Behavioral/Strategy/Strategy.cs index 6bd285a2..4d6d587e 100644 --- a/src/PatternKit.Core/Behavioral/Strategy/Strategy.cs +++ b/src/PatternKit.Core/Behavioral/Strategy/Strategy.cs @@ -150,4 +150,4 @@ public Builder Then(Handler handler) /// /// public static Builder Create() => new(); -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Template/AsyncTemplate.cs b/src/PatternKit.Core/Behavioral/Template/AsyncTemplate.cs index cb9fcc0d..09ed420e 100644 --- a/src/PatternKit.Core/Behavioral/Template/AsyncTemplate.cs +++ b/src/PatternKit.Core/Behavioral/Template/AsyncTemplate.cs @@ -177,4 +177,4 @@ public Builder Synchronized(bool synchronized = true) public AsyncTemplate Build() => new(_before, _step, _after, _onError, _synchronized); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Template/AsyncTemplateMethod.cs b/src/PatternKit.Core/Behavioral/Template/AsyncTemplateMethod.cs index b4b52e34..1b42d967 100644 --- a/src/PatternKit.Core/Behavioral/Template/AsyncTemplateMethod.cs +++ b/src/PatternKit.Core/Behavioral/Template/AsyncTemplateMethod.cs @@ -58,4 +58,4 @@ public async Task ExecuteAsync(TContext context, CancellationToken canc /// Optional async hook after the main step. /// protected virtual ValueTask OnAfterAsync(TContext context, TResult result, CancellationToken cancellationToken) => default; -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Behavioral/Template/TemplateMethod.cs b/src/PatternKit.Core/Behavioral/Template/TemplateMethod.cs index 21f4179b..2088dd9f 100644 --- a/src/PatternKit.Core/Behavioral/Template/TemplateMethod.cs +++ b/src/PatternKit.Core/Behavioral/Template/TemplateMethod.cs @@ -53,4 +53,4 @@ protected virtual void OnBefore(TContext context) { } /// Optional hook after the main step. /// protected virtual void OnAfter(TContext context, TResult result) { } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Common/Functional.cs b/src/PatternKit.Core/Common/Functional.cs index fff42268..11e001ea 100644 --- a/src/PatternKit.Core/Common/Functional.cs +++ b/src/PatternKit.Core/Common/Functional.cs @@ -137,4 +137,4 @@ public static Option FirstMatch( return Option.Some(r); return Option.None(); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Common/Throw.cs b/src/PatternKit.Core/Common/Throw.cs index 9eb13b23..332d2ad2 100644 --- a/src/PatternKit.Core/Common/Throw.cs +++ b/src/PatternKit.Core/Common/Throw.cs @@ -107,4 +107,4 @@ public static void ArgumentNullWhenNull([CallerMemberName] object? arg = null) { if (arg is null) throw new ArgumentNullException(nameof(arg)); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Creational/Builder/BranchBuilder.cs b/src/PatternKit.Core/Creational/Builder/BranchBuilder.cs index 5dfe6f57..99ea4ee2 100644 --- a/src/PatternKit.Core/Creational/Builder/BranchBuilder.cs +++ b/src/PatternKit.Core/Creational/Builder/BranchBuilder.cs @@ -52,4 +52,4 @@ public TProduct Build( var def = _default ?? fallbackDefault; return projector(predicates, handlers, hasDefault, def); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Creational/Builder/ChainBuilder.cs b/src/PatternKit.Core/Creational/Builder/ChainBuilder.cs index bbe8a072..383839ee 100644 --- a/src/PatternKit.Core/Creational/Builder/ChainBuilder.cs +++ b/src/PatternKit.Core/Creational/Builder/ChainBuilder.cs @@ -70,4 +70,4 @@ public ChainBuilder AddIf(bool condition, T item) /// public TProduct Build(Func projector) => projector(_items.ToArray()); -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Creational/Builder/Composer.cs b/src/PatternKit.Core/Creational/Builder/Composer.cs index b0498ff1..f7b095fa 100644 --- a/src/PatternKit.Core/Creational/Builder/Composer.cs +++ b/src/PatternKit.Core/Creational/Builder/Composer.cs @@ -96,4 +96,4 @@ public TOut Build(Func project) ? throw new InvalidOperationException(error) : project(state); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Creational/Builder/MutableBuilder.cs b/src/PatternKit.Core/Creational/Builder/MutableBuilder.cs index 506ed67b..d7d84063 100644 --- a/src/PatternKit.Core/Creational/Builder/MutableBuilder.cs +++ b/src/PatternKit.Core/Creational/Builder/MutableBuilder.cs @@ -232,4 +232,4 @@ public static MutableBuilder RequireRange( ? $"{s.paramName} must be within [{s.minInclusive}, {s.maxInclusive}] but was {v}." : null; }); -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Creational/Factory/Factory.cs b/src/PatternKit.Core/Creational/Factory/Factory.cs index 9f029718..91c8f511 100644 --- a/src/PatternKit.Core/Creational/Factory/Factory.cs +++ b/src/PatternKit.Core/Creational/Factory/Factory.cs @@ -181,4 +181,4 @@ public Factory Build() static TOut ThrowBeforeDefault() => throw new InvalidOperationException("No Default() configured."); } } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Creational/Prototype/Prototype.cs b/src/PatternKit.Core/Creational/Prototype/Prototype.cs index bddb4317..70cbbe84 100644 --- a/src/PatternKit.Core/Creational/Prototype/Prototype.cs +++ b/src/PatternKit.Core/Creational/Prototype/Prototype.cs @@ -206,4 +206,4 @@ public Prototype Build() static T ThrowBeforeDefault() => throw new InvalidOperationException("No Default() configured."); } } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Creational/Singleton/Singleton.cs b/src/PatternKit.Core/Creational/Singleton/Singleton.cs index 53af51ed..365659f4 100644 --- a/src/PatternKit.Core/Creational/Singleton/Singleton.cs +++ b/src/PatternKit.Core/Creational/Singleton/Singleton.cs @@ -81,4 +81,4 @@ public Builder Eager() /// Build an immutable, thread-safe singleton wrapper. public Singleton Build() => new(_factory, _init, _eager); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Shims/DoesNotReturnAttribute.cs b/src/PatternKit.Core/Shims/DoesNotReturnAttribute.cs index ab07cab4..122c3983 100644 --- a/src/PatternKit.Core/Shims/DoesNotReturnAttribute.cs +++ b/src/PatternKit.Core/Shims/DoesNotReturnAttribute.cs @@ -2,4 +2,4 @@ namespace System.Diagnostics.CodeAnalysis; public class DoesNotReturnAttribute : Attribute { } -#endif \ No newline at end of file +#endif diff --git a/src/PatternKit.Core/Structural/Adapter/Adapter.cs b/src/PatternKit.Core/Structural/Adapter/Adapter.cs index d2426230..4fbed611 100644 --- a/src/PatternKit.Core/Structural/Adapter/Adapter.cs +++ b/src/PatternKit.Core/Structural/Adapter/Adapter.cs @@ -123,4 +123,4 @@ public Builder Require(Validator validator) public Adapter Build() => new(_seed, _seedFrom, _maps.ToArray(), _validators.ToArray()); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Structural/Bridge/Bridge.cs b/src/PatternKit.Core/Structural/Bridge/Bridge.cs index fccc26d6..8b0f5f6d 100644 --- a/src/PatternKit.Core/Structural/Bridge/Bridge.cs +++ b/src/PatternKit.Core/Structural/Bridge/Bridge.cs @@ -201,4 +201,4 @@ public Bridge Build() _pres.ToArray(), _posts.ToArray(), _validators.ToArray(), _resultValidators.ToArray()); } } -} \ No newline at end of file +} diff --git a/src/PatternKit.Core/Structural/Facade/TypedFacade.cs b/src/PatternKit.Core/Structural/Facade/TypedFacade.cs index 94f32b53..50d7c893 100644 --- a/src/PatternKit.Core/Structural/Facade/TypedFacade.cs +++ b/src/PatternKit.Core/Structural/Facade/TypedFacade.cs @@ -293,4 +293,4 @@ internal void Initialize(Dictionary handlers) } } } -#endif \ No newline at end of file +#endif diff --git a/src/PatternKit.Examples/ApiGateway/Demo.cs b/src/PatternKit.Examples/ApiGateway/Demo.cs index 8c386135..bfc43951 100644 --- a/src/PatternKit.Examples/ApiGateway/Demo.cs +++ b/src/PatternKit.Examples/ApiGateway/Demo.cs @@ -62,4 +62,4 @@ public static void Run(TextWriter writer) static void Print(Response res, TextWriter w) => w.WriteLine($"{res.StatusCode} {res.ContentType}\n{res.Body}\n"); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Chain/AuthLoggingDemo.cs b/src/PatternKit.Examples/Chain/AuthLoggingDemo.cs index 8c1ea3a1..30a4fe9e 100644 --- a/src/PatternKit.Examples/Chain/AuthLoggingDemo.cs +++ b/src/PatternKit.Examples/Chain/AuthLoggingDemo.cs @@ -122,4 +122,4 @@ public static List Run() return log; // ["GET /health", "deny: missing auth"] } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Chain/ConfigDriven/TransactionPipelineDemo.cs b/src/PatternKit.Examples/Chain/ConfigDriven/TransactionPipelineDemo.cs index d731d593..85395df4 100644 --- a/src/PatternKit.Examples/Chain/ConfigDriven/TransactionPipelineDemo.cs +++ b/src/PatternKit.Examples/Chain/ConfigDriven/TransactionPipelineDemo.cs @@ -363,4 +363,4 @@ public sealed class PaymentPipeline(TransactionPipeline pipeline) public (TxResult Result, TransactionContext Ctx) Run(TransactionContext ctx) => pipeline.Run(ctx); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Chain/MediatedTransactionPipelineDemo.cs b/src/PatternKit.Examples/Chain/MediatedTransactionPipelineDemo.cs index 97872e4e..bfaff7da 100644 --- a/src/PatternKit.Examples/Chain/MediatedTransactionPipelineDemo.cs +++ b/src/PatternKit.Examples/Chain/MediatedTransactionPipelineDemo.cs @@ -941,4 +941,4 @@ public static (TxResult Result, TransactionContext Ctx) Run(TransactionContext c return pipeline.Run(ctx); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/DependencyInjection/PatternKitExampleServiceCollectionExtensions.cs b/src/PatternKit.Examples/DependencyInjection/PatternKitExampleServiceCollectionExtensions.cs index 21af9b45..3f7b4637 100644 --- a/src/PatternKit.Examples/DependencyInjection/PatternKitExampleServiceCollectionExtensions.cs +++ b/src/PatternKit.Examples/DependencyInjection/PatternKitExampleServiceCollectionExtensions.cs @@ -1,8 +1,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using PatternKit.Application.AntiCorruption; using PatternKit.Application.ActivityTracking; +using PatternKit.Application.AntiCorruption; using PatternKit.Application.Specification; using PatternKit.Behavioral.Chain; using PatternKit.Behavioral.Interpreter; @@ -13,16 +13,16 @@ using PatternKit.Cloud.CircuitBreaker; using PatternKit.Cloud.HealthEndpointMonitoring; using PatternKit.Cloud.PriorityQueue; -using PatternKit.Cloud.RateLimiting; using PatternKit.Cloud.QueueLoadLeveling; +using PatternKit.Cloud.RateLimiting; using PatternKit.Cloud.Retry; using PatternKit.Creational.AbstractFactory; using PatternKit.Creational.Prototype; using PatternKit.Creational.Singleton; -using PatternKit.Examples.ApiGateway; +using PatternKit.Examples.ActivityTrackingDemo; using PatternKit.Examples.AmbassadorDemo; using PatternKit.Examples.AntiCorruptionDemo; -using PatternKit.Examples.ActivityTrackingDemo; +using PatternKit.Examples.ApiGateway; using PatternKit.Examples.AsyncStateDemo; using PatternKit.Examples.AuditLogDemo; using PatternKit.Examples.BackendsForFrontendsDemo; @@ -35,9 +35,9 @@ using PatternKit.Examples.DataMapperDemo; using PatternKit.Examples.DomainEventDemo; using PatternKit.Examples.EnterpriseFeatureSlices; -using PatternKit.Examples.EventSourcingDemo; using PatternKit.Examples.EventCarriedStateTransferDemo; using PatternKit.Examples.EventNotificationDemo; +using PatternKit.Examples.EventSourcingDemo; using PatternKit.Examples.ExternalConfigurationStoreDemo; using PatternKit.Examples.FeatureToggleDemo; using PatternKit.Examples.FlyweightDemo; @@ -55,8 +55,8 @@ using PatternKit.Examples.PatternShowcase; using PatternKit.Examples.PointOfSale; using PatternKit.Examples.Pricing; -using PatternKit.Examples.ProductionReadiness; using PatternKit.Examples.PriorityQueueDemo; +using PatternKit.Examples.ProductionReadiness; using PatternKit.Examples.PrototypeDemo; using PatternKit.Examples.ProxyDemo; using PatternKit.Examples.QueueLoadLevelingDemo; @@ -76,36 +76,36 @@ using PatternKit.Examples.TransactionScriptDemo; using PatternKit.Examples.UnitOfWorkDemo; using PatternKit.Examples.VisitorDemo; +using PatternKit.Messaging.Activation; +using PatternKit.Messaging.Adapters; +using PatternKit.Messaging.Bridges; using PatternKit.Messaging.Channels; +using PatternKit.Messaging.CompetingConsumers; using PatternKit.Messaging.Consumers; +using PatternKit.Messaging.ControlBus; using PatternKit.Messaging.Correlation; using PatternKit.Messaging.Diagnostics; -using PatternKit.Messaging.Adapters; -using PatternKit.Messaging.Activation; -using PatternKit.Messaging.Bridges; using PatternKit.Messaging.Gateways; -using PatternKit.Messaging.Routing; +using PatternKit.Messaging.PipesAndFilters; using PatternKit.Messaging.Reliability; +using PatternKit.Messaging.Routing; using PatternKit.Messaging.Storage; -using PatternKit.Messaging.ControlBus; -using PatternKit.Messaging.CompetingConsumers; -using PatternKit.Messaging.PipesAndFilters; using PatternKit.Messaging.Transformation; using PatternKit.Structural.Decorator; using PatternKit.Structural.Proxy; using CheckoutRequest = PatternKit.Examples.Messaging.CheckoutRequest; -using ConfigTenderHandler = PatternKit.Examples.Chain.ConfigDriven.ITenderHandler; using ConfigPaymentPipeline = PatternKit.Examples.Chain.ConfigDriven.ConfigDrivenPipelineDemo.PaymentPipeline; +using ConfigTenderHandler = PatternKit.Examples.Chain.ConfigDriven.ITenderHandler; using DocumentValidationResult = PatternKit.Examples.Generators.Visitors.DocumentProcessingDemo.ValidationResult; using EnterpriseCheckout = PatternKit.Examples.EnterpriseFeatureSlices.EnterpriseFeatureSlicesDemo.IEnterpriseCheckout; using EnterpriseCheckoutRequest = PatternKit.Examples.EnterpriseFeatureSlices.EnterpriseFeatureSlicesDemo.CheckoutRequest; using EnterpriseCheckoutResult = PatternKit.Examples.EnterpriseFeatureSlices.EnterpriseFeatureSlicesDemo.CheckoutResult; +using InterpreterRulesDemo = PatternKit.Examples.InterpreterDemo.InterpreterDemo; using PosPaymentKind = PatternKit.Examples.ObserverDemo.PaymentKind; using ShowcaseFacade = PatternKit.Examples.PatternShowcase.PatternShowcase.IOrderProcessingFacade; using TransactionPipeline = PatternKit.Examples.Chain.TransactionPipeline; using VisitorTender = PatternKit.Examples.VisitorDemo.Tender; using WidgetDemo = PatternKit.Examples.AbstractFactoryDemo.AbstractFactoryDemo; -using InterpreterRulesDemo = PatternKit.Examples.InterpreterDemo.InterpreterDemo; namespace PatternKit.Examples.DependencyInjection; diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/BackgroundJobsModule.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/BackgroundJobsModule.cs index 831d63b2..31cc1828 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/BackgroundJobsModule.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/BackgroundJobsModule.cs @@ -10,4 +10,4 @@ public void Configure(IHostApplicationBuilder builder, IList log) builder.Services.AddSingleton(); log.Add("module:jobs"); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/CorporateAppState.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/CorporateAppState.cs index 3e2d1fea..bea9de8a 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/CorporateAppState.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/CorporateAppState.cs @@ -7,4 +7,4 @@ public readonly record struct CorporateAppState( List Modules, List> Customizations, List> StartupTasks, - List Log); \ No newline at end of file + List Log); diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/IAppModule.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/IAppModule.cs index 17c43f08..b8e2951a 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/IAppModule.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/IAppModule.cs @@ -5,4 +5,4 @@ namespace PatternKit.Examples.Generators.Builders.CorporateApplicationBuilderDem public interface IAppModule { void Configure(IHostApplicationBuilder builder, IList log); -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/IBackgroundJobScheduler.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/IBackgroundJobScheduler.cs index dbf6a83f..dcc09e87 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/IBackgroundJobScheduler.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/IBackgroundJobScheduler.cs @@ -3,4 +3,4 @@ namespace PatternKit.Examples.Generators.Builders.CorporateApplicationBuilderDem public interface IBackgroundJobScheduler { Task ScheduleAsync(string jobName, TimeSpan cadence, CancellationToken cancellationToken = default); -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/INotificationPublisher.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/INotificationPublisher.cs index 5fa8669c..6eed5e82 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/INotificationPublisher.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/INotificationPublisher.cs @@ -3,4 +3,4 @@ namespace PatternKit.Examples.Generators.Builders.CorporateApplicationBuilderDem public interface INotificationPublisher { Task PublishAsync(string topic, string message, CancellationToken cancellationToken = default); -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/InMemoryJobScheduler.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/InMemoryJobScheduler.cs index b6fa7e8e..1850e320 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/InMemoryJobScheduler.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/InMemoryJobScheduler.cs @@ -9,4 +9,4 @@ public Task ScheduleAsync(string jobName, TimeSpan cadence, CancellationToken ca logger.LogInformation("Scheduled {Job} every {Cadence}", jobName, cadence); return Task.CompletedTask; } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/MessagingModule.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/MessagingModule.cs index ff874785..624a1885 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/MessagingModule.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/MessagingModule.cs @@ -11,4 +11,4 @@ public void Configure(IHostApplicationBuilder builder, IList log) builder.Services.AddOptions(); log.Add("module:messaging"); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/NotificationOptions.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/NotificationOptions.cs index a85adcca..73128c23 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/NotificationOptions.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/NotificationOptions.cs @@ -4,4 +4,4 @@ public sealed class NotificationOptions { public bool Enabled { get; set; } = true; public string Provider { get; set; } = "queue"; -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/ObservabilityModule.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/ObservabilityModule.cs index aca1a21f..66aeba2d 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/ObservabilityModule.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/ObservabilityModule.cs @@ -17,4 +17,4 @@ public void Configure(IHostApplicationBuilder builder, IList log) }); log.Add("module:observability"); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/QueueNotificationPublisher.cs b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/QueueNotificationPublisher.cs index 079b3c30..c041dc2f 100644 --- a/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/QueueNotificationPublisher.cs +++ b/src/PatternKit.Examples/Generators/Builders/CorporateApplicationBuilderDemo/QueueNotificationPublisher.cs @@ -9,4 +9,4 @@ public Task PublishAsync(string topic, string message, CancellationToken cancell logger.LogInformation("Published {Topic}: {Message}", topic, message); return Task.CompletedTask; } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Generators/State/OrderFlowDemo.cs b/src/PatternKit.Examples/Generators/State/OrderFlowDemo.cs index b748058a..b065289f 100644 --- a/src/PatternKit.Examples/Generators/State/OrderFlowDemo.cs +++ b/src/PatternKit.Examples/Generators/State/OrderFlowDemo.cs @@ -28,7 +28,7 @@ public static void Run() // Create an order flow instance var order = new OrderFlow("ORD-001", 299.99m); - + Console.WriteLine($"Order: {order.Id}, Amount: ${order.Amount:F2}"); Console.WriteLine($"Initial State: {order.State}\n"); @@ -72,7 +72,7 @@ public static void CancellationDemo() Console.WriteLine("=== Cancellation Example ===\n"); var order = new OrderFlow("ORD-002", 599.99m); - + Console.WriteLine($"Order: {order.Id}, Amount: ${order.Amount:F2}"); Console.WriteLine($"Initial State: {order.State}\n"); @@ -96,7 +96,7 @@ public static void GuardFailureDemo() Console.WriteLine("=== Guard Failure Example ===\n"); var order = new OrderFlow("ORD-003", -50m); // Invalid amount - + Console.WriteLine($"Order: {order.Id}, Amount: ${order.Amount:F2}"); Console.WriteLine($"Initial State: {order.State}\n"); @@ -163,7 +163,7 @@ void ShowAvailableActions(OrderFlow o) { Console.WriteLine($"Current state: {o.State}"); Console.WriteLine("Available actions:"); - + foreach (OrderTrigger trigger in Enum.GetValues(typeof(OrderTrigger))) { if (o.CanFire(trigger)) @@ -221,16 +221,16 @@ public enum OrderState { /// Initial state - order is being prepared Draft, - + /// Order has been submitted for processing Submitted, - + /// Payment has been successfully processed Paid, - + /// Order has been shipped to the customer Shipped, - + /// Order was cancelled and will not be processed Cancelled } @@ -242,13 +242,13 @@ public enum OrderTrigger { /// Submit the order for processing Submit, - + /// Process payment for the order Pay, - + /// Ship the order to the customer Ship, - + /// Cancel the order Cancel } @@ -268,12 +268,12 @@ public partial class OrderFlow /// Gets the unique identifier for this order. /// public string Id { get; } - + /// /// Gets the order amount. /// public decimal Amount { get; } - + /// /// Initializes a new instance of the OrderFlow state machine. /// @@ -317,15 +317,15 @@ private bool CanPay() private async ValueTask OnPayAsync(CancellationToken ct) { Console.WriteLine($" >> Transition: Processing payment for {Id}..."); - + // Simulate payment processing await Task.Delay(500, ct); - + // In a real system: // - Call payment gateway // - Update payment records // - Generate receipt - + Console.WriteLine($" >> Payment of ${Amount:F2} processed"); } @@ -466,7 +466,7 @@ public partial class DocumentWorkflow public string DocumentId { get; } public string Author { get; } public List ReviewComments { get; } = new(); - + public DocumentWorkflow(string documentId, string author) { DocumentId = documentId; diff --git a/src/PatternKit.Examples/Generators/Strategies/StrategySpecs.cs b/src/PatternKit.Examples/Generators/Strategies/StrategySpecs.cs index 078e0b29..bac07d72 100644 --- a/src/PatternKit.Examples/Generators/Strategies/StrategySpecs.cs +++ b/src/PatternKit.Examples/Generators/Strategies/StrategySpecs.cs @@ -15,4 +15,4 @@ public partial class ScoreLabeler [GenerateStrategy(nameof(IntParser), typeof(string), typeof(int), StrategyKind.Try)] public partial class IntParser { -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/MediatorComprehensiveDemo/ComprehensiveDemo.cs b/src/PatternKit.Examples/MediatorComprehensiveDemo/ComprehensiveDemo.cs index 15b57758..e02dba19 100644 --- a/src/PatternKit.Examples/MediatorComprehensiveDemo/ComprehensiveDemo.cs +++ b/src/PatternKit.Examples/MediatorComprehensiveDemo/ComprehensiveDemo.cs @@ -1,11 +1,11 @@ -using Microsoft.Extensions.DependencyInjection; -using PatternKit.Generators.Messaging; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using PatternKit.Generators.Messaging; // Generate the dispatcher for the comprehensive demo - use different name to avoid conflict with ExampleDispatcher [assembly: GenerateDispatcher( diff --git a/src/PatternKit.Examples/MediatorDemo/Abstractions.cs b/src/PatternKit.Examples/MediatorDemo/Abstractions.cs index 408e303d..f1fe3c77 100644 --- a/src/PatternKit.Examples/MediatorDemo/Abstractions.cs +++ b/src/PatternKit.Examples/MediatorDemo/Abstractions.cs @@ -422,4 +422,4 @@ static async ValueTask Await(ValueTask v) return o is null ? default! : (T)o; } } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/MediatorDemo/Demo.cs b/src/PatternKit.Examples/MediatorDemo/Demo.cs index ae4cef0b..329803e6 100644 --- a/src/PatternKit.Examples/MediatorDemo/Demo.cs +++ b/src/PatternKit.Examples/MediatorDemo/Demo.cs @@ -163,4 +163,4 @@ public async ValueTask Handle(SumCmd request, CancellationToken ct, Func assemblies, IServiceCo Behaviors = behaviors }; } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/MementoDemo/MementoDemo.cs b/src/PatternKit.Examples/MementoDemo/MementoDemo.cs index 6d60d94c..78fe6fbd 100644 --- a/src/PatternKit.Examples/MementoDemo/MementoDemo.cs +++ b/src/PatternKit.Examples/MementoDemo/MementoDemo.cs @@ -277,4 +277,4 @@ void Capture(string action) log.Add($"FINAL:'{editor.State.Text}' version={editor.Version} history={editor.History.Count}"); return log; } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Messaging/DispatcherExample.cs b/src/PatternKit.Examples/Messaging/DispatcherExample.cs index 1a61ecd8..e1ca8429 100644 --- a/src/PatternKit.Examples/Messaging/DispatcherExample.cs +++ b/src/PatternKit.Examples/Messaging/DispatcherExample.cs @@ -1,8 +1,8 @@ -using PatternKit.Generators.Messaging; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; +using PatternKit.Generators.Messaging; // NOTE: The comprehensive production demo in MediatorComprehensiveDemo/ComprehensiveDemo.cs // generates the dispatcher for this assembly. This file contains simple usage examples only. diff --git a/src/PatternKit.Examples/Messaging/ErpChannelAdapterExample.cs b/src/PatternKit.Examples/Messaging/ErpChannelAdapterExample.cs index 3a32817f..74a1bb04 100644 --- a/src/PatternKit.Examples/Messaging/ErpChannelAdapterExample.cs +++ b/src/PatternKit.Examples/Messaging/ErpChannelAdapterExample.cs @@ -1,9 +1,9 @@ +using System.Globalization; using Microsoft.Extensions.DependencyInjection; using PatternKit.Generators.Messaging; using PatternKit.Messaging; using PatternKit.Messaging.Adapters; using PatternKit.Messaging.Channels; -using System.Globalization; namespace PatternKit.Examples.Messaging; diff --git a/src/PatternKit.Examples/Messaging/MailboxExample.cs b/src/PatternKit.Examples/Messaging/MailboxExample.cs index 6fa82421..51de715b 100644 --- a/src/PatternKit.Examples/Messaging/MailboxExample.cs +++ b/src/PatternKit.Examples/Messaging/MailboxExample.cs @@ -1,6 +1,6 @@ +using PatternKit.Generators.Messaging; using PatternKit.Messaging; using PatternKit.Messaging.Mailboxes; -using PatternKit.Generators.Messaging; namespace PatternKit.Examples.Messaging; diff --git a/src/PatternKit.Examples/Messaging/MessageEnvelopeExample.cs b/src/PatternKit.Examples/Messaging/MessageEnvelopeExample.cs index 54e9a86e..c628a7ee 100644 --- a/src/PatternKit.Examples/Messaging/MessageEnvelopeExample.cs +++ b/src/PatternKit.Examples/Messaging/MessageEnvelopeExample.cs @@ -1,6 +1,6 @@ -using PatternKit.Messaging; using Microsoft.Extensions.DependencyInjection; using PatternKit.Generators.Messaging; +using PatternKit.Messaging; namespace PatternKit.Examples.Messaging; diff --git a/src/PatternKit.Examples/Messaging/MessageRoutingExample.cs b/src/PatternKit.Examples/Messaging/MessageRoutingExample.cs index 44b82dcf..b336cb54 100644 --- a/src/PatternKit.Examples/Messaging/MessageRoutingExample.cs +++ b/src/PatternKit.Examples/Messaging/MessageRoutingExample.cs @@ -1,6 +1,6 @@ +using PatternKit.Generators.Messaging; using PatternKit.Messaging; using PatternKit.Messaging.Routing; -using PatternKit.Generators.Messaging; namespace PatternKit.Examples.Messaging; diff --git a/src/PatternKit.Examples/Messaging/OrderEventDrivenConsumerExample.cs b/src/PatternKit.Examples/Messaging/OrderEventDrivenConsumerExample.cs index 1205e65a..fd38272b 100644 --- a/src/PatternKit.Examples/Messaging/OrderEventDrivenConsumerExample.cs +++ b/src/PatternKit.Examples/Messaging/OrderEventDrivenConsumerExample.cs @@ -1,8 +1,8 @@ +using System.Globalization; using Microsoft.Extensions.DependencyInjection; using PatternKit.Generators.Messaging; using PatternKit.Messaging; using PatternKit.Messaging.Consumers; -using System.Globalization; namespace PatternKit.Examples.Messaging; diff --git a/src/PatternKit.Examples/Messaging/ReliabilityExample.cs b/src/PatternKit.Examples/Messaging/ReliabilityExample.cs index 58ce8e18..c7716e70 100644 --- a/src/PatternKit.Examples/Messaging/ReliabilityExample.cs +++ b/src/PatternKit.Examples/Messaging/ReliabilityExample.cs @@ -1,7 +1,7 @@ +using PatternKit.Generators.Messaging; using PatternKit.Messaging; using PatternKit.Messaging.Mailboxes; using PatternKit.Messaging.Reliability; -using PatternKit.Generators.Messaging; namespace PatternKit.Examples.Messaging; diff --git a/src/PatternKit.Examples/ObserverDemo/ReactivePrimitives.cs b/src/PatternKit.Examples/ObserverDemo/ReactivePrimitives.cs index 58ee8baa..f1a72c77 100644 --- a/src/PatternKit.Examples/ObserverDemo/ReactivePrimitives.cs +++ b/src/PatternKit.Examples/ObserverDemo/ReactivePrimitives.cs @@ -1,119 +1,119 @@ -using PatternKit.Behavioral.Observer; -using System.Collections; - -namespace PatternKit.Examples.ObserverDemo; - -/// -/// Lightweight property change hub (INotifyPropertyChanged-like) built on of . -/// Publishes property names to subscribers. -/// -public sealed class PropertyChangedHub -{ - private readonly Observer _obs = Observer.Create().Build(); - - /// - /// Subscribe to property name change notifications. - /// - /// Callback that receives the property name. - /// An that removes the subscription when disposed. - public IDisposable Subscribe(Action onProperty) => _obs.Subscribe((in p) => onProperty(p)); - - /// - /// Raise a property change notification. - /// - /// The property name to publish. - public void Raise(string propertyName) => _obs.Publish(in propertyName); -} - -/// -/// A tiny observable variable that publishes change notifications when its value changes. -/// -/// The value type. -/// Optional initial value. -public sealed class ObservableVar(T initial = default!) -{ - private readonly Observer<(T Old, T New)> _obs = Observer<(T Old, T New)>.Create().Build(); - private T _value = initial; - - /// - /// The current value. Setting this will publish a change event if the value actually changes. - /// - public T Value - { - get => _value; - set - { - var old = _value; - if (EqualityComparer.Default.Equals(old, value)) return; - _value = value; - var ev = (Old: old, New: value); - _obs.Publish(in ev); - } - } - - /// - /// Subscribe to change notifications. The callback receives the old and new value. - /// - /// Callback invoked when changes. - /// An that removes the subscription when disposed. - public IDisposable Subscribe(Action onChange) - => _obs.Subscribe((in e) => onChange(e.Old, e.New)); -} - -/// -/// Observable list wrapper that publishes simple add/remove events. -/// -/// The element type. -public sealed class ObservableList : IEnumerable -{ - private readonly List _items = []; - private readonly Observer<(string Action, T Item)> _obs = Observer<(string Action, T Item)>.Create().Build(); - - /// The current number of items. - public int Count => _items.Count; - - /// - /// Return a shallow snapshot copy of the list's current items. - /// - public IReadOnlyList Snapshot() => _items.ToArray(); - - /// - /// Add an item and publish an "add" event. - /// - /// The item to add. - public void Add(T item) - { - _items.Add(item); - var ev = (Action: "add", Item: item); - _obs.Publish(in ev); - } - - /// - /// Remove an item and publish a "remove" event if the item existed. - /// - /// The item to remove. - /// if the item was removed; otherwise . - public bool Remove(T item) - { - var ok = _items.Remove(item); - if (!ok) - return ok; - var ev = (Action: "remove", Item: item); - _obs.Publish(in ev); - return ok; - } - - /// - /// Subscribe to add/remove change notifications. - /// - /// Callback receiving the action ("add" or "remove") and the item. - /// An that removes the subscription when disposed. - public IDisposable Subscribe(Action onChange) - => _obs.Subscribe((in e) => onChange(e.Action, e.Item)); - - /// - public IEnumerator GetEnumerator() => _items.GetEnumerator(); - - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); -} +using System.Collections; +using PatternKit.Behavioral.Observer; + +namespace PatternKit.Examples.ObserverDemo; + +/// +/// Lightweight property change hub (INotifyPropertyChanged-like) built on of . +/// Publishes property names to subscribers. +/// +public sealed class PropertyChangedHub +{ + private readonly Observer _obs = Observer.Create().Build(); + + /// + /// Subscribe to property name change notifications. + /// + /// Callback that receives the property name. + /// An that removes the subscription when disposed. + public IDisposable Subscribe(Action onProperty) => _obs.Subscribe((in p) => onProperty(p)); + + /// + /// Raise a property change notification. + /// + /// The property name to publish. + public void Raise(string propertyName) => _obs.Publish(in propertyName); +} + +/// +/// A tiny observable variable that publishes change notifications when its value changes. +/// +/// The value type. +/// Optional initial value. +public sealed class ObservableVar(T initial = default!) +{ + private readonly Observer<(T Old, T New)> _obs = Observer<(T Old, T New)>.Create().Build(); + private T _value = initial; + + /// + /// The current value. Setting this will publish a change event if the value actually changes. + /// + public T Value + { + get => _value; + set + { + var old = _value; + if (EqualityComparer.Default.Equals(old, value)) return; + _value = value; + var ev = (Old: old, New: value); + _obs.Publish(in ev); + } + } + + /// + /// Subscribe to change notifications. The callback receives the old and new value. + /// + /// Callback invoked when changes. + /// An that removes the subscription when disposed. + public IDisposable Subscribe(Action onChange) + => _obs.Subscribe((in e) => onChange(e.Old, e.New)); +} + +/// +/// Observable list wrapper that publishes simple add/remove events. +/// +/// The element type. +public sealed class ObservableList : IEnumerable +{ + private readonly List _items = []; + private readonly Observer<(string Action, T Item)> _obs = Observer<(string Action, T Item)>.Create().Build(); + + /// The current number of items. + public int Count => _items.Count; + + /// + /// Return a shallow snapshot copy of the list's current items. + /// + public IReadOnlyList Snapshot() => _items.ToArray(); + + /// + /// Add an item and publish an "add" event. + /// + /// The item to add. + public void Add(T item) + { + _items.Add(item); + var ev = (Action: "add", Item: item); + _obs.Publish(in ev); + } + + /// + /// Remove an item and publish a "remove" event if the item existed. + /// + /// The item to remove. + /// if the item was removed; otherwise . + public bool Remove(T item) + { + var ok = _items.Remove(item); + if (!ok) + return ok; + var ev = (Action: "remove", Item: item); + _obs.Publish(in ev); + return ok; + } + + /// + /// Subscribe to add/remove change notifications. + /// + /// Callback receiving the action ("add" or "remove") and the item. + /// An that removes the subscription when disposed. + public IDisposable Subscribe(Action onChange) + => _obs.Subscribe((in e) => onChange(e.Action, e.Item)); + + /// + public IEnumerator GetEnumerator() => _items.GetEnumerator(); + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} diff --git a/src/PatternKit.Examples/ObserverDemo/ReactiveTransaction.cs b/src/PatternKit.Examples/ObserverDemo/ReactiveTransaction.cs index 285d755a..d1fe0149 100644 --- a/src/PatternKit.Examples/ObserverDemo/ReactiveTransaction.cs +++ b/src/PatternKit.Examples/ObserverDemo/ReactiveTransaction.cs @@ -1,214 +1,214 @@ -using PatternKit.Behavioral.Observer; - -namespace PatternKit.Examples.ObserverDemo; - -/// Customer loyalty tiers used for discount calculation. -public enum LoyaltyTier { None, Silver, Gold, Platinum } - -/// Payment methods that may influence discounts or eligibility. -public enum PaymentKind { None, CreditCard, StoreCard, Cash } - -/// -/// Represents a line item in a transaction. -/// -/// The product SKU. -/// The quantity ordered. -/// The unit price. -/// Optional per-line discount percentage (0..1). -/// Whether the line is taxable. -public readonly record struct LineItem(string Sku, int Qty, decimal UnitPrice, decimal? DiscountPct = null, bool Taxable = true) -{ - /// Total raw amount before discounts. - public decimal Raw => Qty * UnitPrice; - - /// Discount amount for this line based on . - public decimal LineDiscount => DiscountPct is { } p ? Raw * p : 0m; - - /// Net amount after line discount. - public decimal Net => Raw - LineDiscount; -} - -/// -/// Reactive transaction shows dependent, computed properties updated via Observer-based subscriptions. -/// It recomputes totals and UI-like flags whenever any input changes. -/// -public sealed class ReactiveTransaction -{ - // Inputs (reactive) - /// Collection of items in the transaction. Publishes add/remove events. - public ObservableList Items { get; } = []; - - /// Current customer loyalty tier. - public ObservableVar Tier { get; } = new(); - - /// Selected payment method. - public ObservableVar Payment { get; } = new(); - - /// Applicable tax rate for taxable items. - public ObservableVar TaxRate { get; } = new(0.07m); - - // Outputs (reactive vars so consumers can subscribe to precise changes) - /// Subtotal before discounts and tax. - public ObservableVar Subtotal { get; } = new(); - - /// Total of all per-line discounts. - public ObservableVar LineItemDiscounts { get; } = new(); - - /// Discount based on loyalty tier. - public ObservableVar LoyaltyDiscount { get; } = new(); - - /// Discount based on payment method. - public ObservableVar PaymentDiscount { get; } = new(); - - /// Calculated tax on taxable net amount. - public ObservableVar Tax { get; } = new(); - - /// Final total after all discounts and tax. - public ObservableVar Total { get; } = new(); - - // UI-ish dependent properties - /// Whether the transaction meets basic checkout requirements. - public ObservableVar CanCheckout { get; } = new(); - - /// Optional badge text indicating savings. - public ObservableVar DiscountBadge { get; } = new(); - - // Fine-grained change notifications for property names, if needed - /// Name-based change hub for UI bindings listening by property name. - public PropertyChangedHub PropertyChanged { get; } = new(); - - private readonly Observer.Handler _notify; - - /// - /// Create the transaction and wire reactive inputs so that any change triggers recomputation of outputs. - /// - public ReactiveTransaction() - { - _notify = (in p) => PropertyChanged.Raise(p); - - // Recompute on any input change - Items.Subscribe((_, _) => Recompute()); - Tier.Subscribe((_, _) => Recompute()); - Payment.Subscribe((_, _) => Recompute()); - TaxRate.Subscribe((_, _) => Recompute()); - - // Recompute once on construction - Recompute(); - } - - private void Recompute() - { - var list = Items.Snapshot(); - decimal raw = 0m, lineDisc = 0m, taxableNet = 0m; - - foreach (var it in list) - { - raw += it.Raw; - lineDisc += it.LineDiscount; - if (it.Taxable) taxableNet += it.Net; - } - - var tierDiscPct = Tier.Value switch - { - LoyaltyTier.Platinum => 0.10m, - LoyaltyTier.Gold => 0.07m, - LoyaltyTier.Silver => 0.04m, - _ => 0m - }; - - var paymentDiscPct = Payment.Value switch - { - PaymentKind.StoreCard => 0.05m, // in-house card promo - _ => 0m - }; - - var loyaltyDisc = Math.Round((raw - lineDisc) * tierDiscPct, 2, MidpointRounding.AwayFromZero); - var payDisc = Math.Round((raw - lineDisc - loyaltyDisc) * paymentDiscPct, 2, MidpointRounding.AwayFromZero); - var preTax = raw - lineDisc - loyaltyDisc - payDisc; - var tax = Math.Round(taxableNet * TaxRate.Value, 2, MidpointRounding.AwayFromZero); - var total = Math.Round(preTax + tax, 2, MidpointRounding.AwayFromZero); - - // Publish to reactive outputs (triggers subscribers if changed) - Subtotal.Value = raw; - LineItemDiscounts.Value = lineDisc; - LoyaltyDiscount.Value = loyaltyDisc; - PaymentDiscount.Value = payDisc; - Tax.Value = tax; - Total.Value = total; - - // UI-ish dependents - CanCheckout.Value = total > 0 && Payment.Value != PaymentKind.None; - DiscountBadge.Value = (loyaltyDisc + payDisc) > 0 ? $"You saved {(loyaltyDisc + payDisc):C}" : null; - - // Optional name-based notifications for UIs that listen by name - var p1 = nameof(Subtotal); _notify(in p1); - var p2 = nameof(LineItemDiscounts); _notify(in p2); - var p3 = nameof(LoyaltyDiscount); _notify(in p3); - var p4 = nameof(PaymentDiscount); _notify(in p4); - var p5 = nameof(Tax); _notify(in p5); - var p6 = nameof(Total); _notify(in p6); - var p7 = nameof(CanCheckout); _notify(in p7); - var p8 = nameof(DiscountBadge); _notify(in p8); - } - - // Convenience API - /// Add a line item. - public void AddItem(LineItem item) => Items.Add(item); - - /// Remove a line item. - /// if removed; otherwise . - public bool RemoveItem(LineItem item) => Items.Remove(item); - - /// Set the loyalty tier. - public void SetTier(LoyaltyTier tier) => Tier.Value = tier; - - /// Set the payment method. - public void SetPayment(PaymentKind kind) => Payment.Value = kind; - - /// Set the tax rate. - public void SetTaxRate(decimal rate) => TaxRate.Value = rate; -} - -/// -/// Minimal reactive ViewModel sample to demonstrate dependent properties and control enablement. -/// -public sealed class ProfileViewModel -{ - /// First name input. - public ObservableVar FirstName { get; } = new(); - - /// Last name input. - public ObservableVar LastName { get; } = new(); - - /// Computed full name. - public ObservableVar FullName { get; } = new(string.Empty); - - /// Whether saving is currently allowed. - public ObservableVar CanSave { get; } = new(); - - /// Name-based change hub for UI bindings listening by property name. - public PropertyChangedHub PropertyChanged { get; } = new(); - - private readonly Observer.Handler _notify; - - /// Create the view model and wire reactive recompute behavior. - public ProfileViewModel() - { - _notify = (in p) => PropertyChanged.Raise(p); - - FirstName.Subscribe((_, _) => Recompute()); - LastName.Subscribe((_, _) => Recompute()); - Recompute(); - } - - private void Recompute() - { - var fn = FirstName.Value?.Trim(); - var ln = LastName.Value?.Trim(); - var full = string.Join(' ', new[] { fn, ln }.Where(s => !string.IsNullOrWhiteSpace(s))); - FullName.Value = full; - CanSave.Value = !string.IsNullOrWhiteSpace(fn) && !string.IsNullOrWhiteSpace(ln); - var pFull = nameof(FullName); _notify(in pFull); - var pSave = nameof(CanSave); _notify(in pSave); - } -} +using PatternKit.Behavioral.Observer; + +namespace PatternKit.Examples.ObserverDemo; + +/// Customer loyalty tiers used for discount calculation. +public enum LoyaltyTier { None, Silver, Gold, Platinum } + +/// Payment methods that may influence discounts or eligibility. +public enum PaymentKind { None, CreditCard, StoreCard, Cash } + +/// +/// Represents a line item in a transaction. +/// +/// The product SKU. +/// The quantity ordered. +/// The unit price. +/// Optional per-line discount percentage (0..1). +/// Whether the line is taxable. +public readonly record struct LineItem(string Sku, int Qty, decimal UnitPrice, decimal? DiscountPct = null, bool Taxable = true) +{ + /// Total raw amount before discounts. + public decimal Raw => Qty * UnitPrice; + + /// Discount amount for this line based on . + public decimal LineDiscount => DiscountPct is { } p ? Raw * p : 0m; + + /// Net amount after line discount. + public decimal Net => Raw - LineDiscount; +} + +/// +/// Reactive transaction shows dependent, computed properties updated via Observer-based subscriptions. +/// It recomputes totals and UI-like flags whenever any input changes. +/// +public sealed class ReactiveTransaction +{ + // Inputs (reactive) + /// Collection of items in the transaction. Publishes add/remove events. + public ObservableList Items { get; } = []; + + /// Current customer loyalty tier. + public ObservableVar Tier { get; } = new(); + + /// Selected payment method. + public ObservableVar Payment { get; } = new(); + + /// Applicable tax rate for taxable items. + public ObservableVar TaxRate { get; } = new(0.07m); + + // Outputs (reactive vars so consumers can subscribe to precise changes) + /// Subtotal before discounts and tax. + public ObservableVar Subtotal { get; } = new(); + + /// Total of all per-line discounts. + public ObservableVar LineItemDiscounts { get; } = new(); + + /// Discount based on loyalty tier. + public ObservableVar LoyaltyDiscount { get; } = new(); + + /// Discount based on payment method. + public ObservableVar PaymentDiscount { get; } = new(); + + /// Calculated tax on taxable net amount. + public ObservableVar Tax { get; } = new(); + + /// Final total after all discounts and tax. + public ObservableVar Total { get; } = new(); + + // UI-ish dependent properties + /// Whether the transaction meets basic checkout requirements. + public ObservableVar CanCheckout { get; } = new(); + + /// Optional badge text indicating savings. + public ObservableVar DiscountBadge { get; } = new(); + + // Fine-grained change notifications for property names, if needed + /// Name-based change hub for UI bindings listening by property name. + public PropertyChangedHub PropertyChanged { get; } = new(); + + private readonly Observer.Handler _notify; + + /// + /// Create the transaction and wire reactive inputs so that any change triggers recomputation of outputs. + /// + public ReactiveTransaction() + { + _notify = (in p) => PropertyChanged.Raise(p); + + // Recompute on any input change + Items.Subscribe((_, _) => Recompute()); + Tier.Subscribe((_, _) => Recompute()); + Payment.Subscribe((_, _) => Recompute()); + TaxRate.Subscribe((_, _) => Recompute()); + + // Recompute once on construction + Recompute(); + } + + private void Recompute() + { + var list = Items.Snapshot(); + decimal raw = 0m, lineDisc = 0m, taxableNet = 0m; + + foreach (var it in list) + { + raw += it.Raw; + lineDisc += it.LineDiscount; + if (it.Taxable) taxableNet += it.Net; + } + + var tierDiscPct = Tier.Value switch + { + LoyaltyTier.Platinum => 0.10m, + LoyaltyTier.Gold => 0.07m, + LoyaltyTier.Silver => 0.04m, + _ => 0m + }; + + var paymentDiscPct = Payment.Value switch + { + PaymentKind.StoreCard => 0.05m, // in-house card promo + _ => 0m + }; + + var loyaltyDisc = Math.Round((raw - lineDisc) * tierDiscPct, 2, MidpointRounding.AwayFromZero); + var payDisc = Math.Round((raw - lineDisc - loyaltyDisc) * paymentDiscPct, 2, MidpointRounding.AwayFromZero); + var preTax = raw - lineDisc - loyaltyDisc - payDisc; + var tax = Math.Round(taxableNet * TaxRate.Value, 2, MidpointRounding.AwayFromZero); + var total = Math.Round(preTax + tax, 2, MidpointRounding.AwayFromZero); + + // Publish to reactive outputs (triggers subscribers if changed) + Subtotal.Value = raw; + LineItemDiscounts.Value = lineDisc; + LoyaltyDiscount.Value = loyaltyDisc; + PaymentDiscount.Value = payDisc; + Tax.Value = tax; + Total.Value = total; + + // UI-ish dependents + CanCheckout.Value = total > 0 && Payment.Value != PaymentKind.None; + DiscountBadge.Value = (loyaltyDisc + payDisc) > 0 ? $"You saved {(loyaltyDisc + payDisc):C}" : null; + + // Optional name-based notifications for UIs that listen by name + var p1 = nameof(Subtotal); _notify(in p1); + var p2 = nameof(LineItemDiscounts); _notify(in p2); + var p3 = nameof(LoyaltyDiscount); _notify(in p3); + var p4 = nameof(PaymentDiscount); _notify(in p4); + var p5 = nameof(Tax); _notify(in p5); + var p6 = nameof(Total); _notify(in p6); + var p7 = nameof(CanCheckout); _notify(in p7); + var p8 = nameof(DiscountBadge); _notify(in p8); + } + + // Convenience API + /// Add a line item. + public void AddItem(LineItem item) => Items.Add(item); + + /// Remove a line item. + /// if removed; otherwise . + public bool RemoveItem(LineItem item) => Items.Remove(item); + + /// Set the loyalty tier. + public void SetTier(LoyaltyTier tier) => Tier.Value = tier; + + /// Set the payment method. + public void SetPayment(PaymentKind kind) => Payment.Value = kind; + + /// Set the tax rate. + public void SetTaxRate(decimal rate) => TaxRate.Value = rate; +} + +/// +/// Minimal reactive ViewModel sample to demonstrate dependent properties and control enablement. +/// +public sealed class ProfileViewModel +{ + /// First name input. + public ObservableVar FirstName { get; } = new(); + + /// Last name input. + public ObservableVar LastName { get; } = new(); + + /// Computed full name. + public ObservableVar FullName { get; } = new(string.Empty); + + /// Whether saving is currently allowed. + public ObservableVar CanSave { get; } = new(); + + /// Name-based change hub for UI bindings listening by property name. + public PropertyChangedHub PropertyChanged { get; } = new(); + + private readonly Observer.Handler _notify; + + /// Create the view model and wire reactive recompute behavior. + public ProfileViewModel() + { + _notify = (in p) => PropertyChanged.Raise(p); + + FirstName.Subscribe((_, _) => Recompute()); + LastName.Subscribe((_, _) => Recompute()); + Recompute(); + } + + private void Recompute() + { + var fn = FirstName.Value?.Trim(); + var ln = LastName.Value?.Trim(); + var full = string.Join(' ', new[] { fn, ln }.Where(s => !string.IsNullOrWhiteSpace(s))); + FullName.Value = full; + CanSave.Value = !string.IsNullOrWhiteSpace(fn) && !string.IsNullOrWhiteSpace(ln); + var pFull = nameof(FullName); _notify(in pFull); + var pSave = nameof(CanSave); _notify(in pSave); + } +} diff --git a/src/PatternKit.Examples/ObserverDemo/SimpleEventHub.cs b/src/PatternKit.Examples/ObserverDemo/SimpleEventHub.cs index e6693b80..4cfb9b4a 100644 --- a/src/PatternKit.Examples/ObserverDemo/SimpleEventHub.cs +++ b/src/PatternKit.Examples/ObserverDemo/SimpleEventHub.cs @@ -1,53 +1,53 @@ -namespace PatternKit.Examples.ObserverDemo; - -using Behavioral.Observer; - -/// -/// A tiny demo event hub built on top of for examples and docs. -/// -/// The event payload type to broadcast. -public sealed class EventHub -{ - private readonly Observer _observer; - - /// - /// Create an event hub that wraps the provided . - /// - /// The underlying observer to delegate to. - public EventHub(Observer observer) => _observer = observer; - - /// - /// Create a default event hub using with default error handling (aggregate). - /// - /// A new . - public static EventHub CreateDefault() - => new(Observer.Create().Build()); - - /// - /// Subscribe a handler to receive all events. - /// - /// The handler to invoke. - /// An that removes the subscription when disposed. - public IDisposable On(Observer.Handler handler) - => _observer.Subscribe(handler); - - /// - /// Subscribe a handler with an optional predicate filter. - /// - /// The filter to decide whether to deliver the event to the handler. - /// The handler to invoke. - /// An that removes the subscription when disposed. - public IDisposable On(Observer.Predicate predicate, Observer.Handler handler) - => _observer.Subscribe(predicate, handler); - - /// - /// Publish an event to all matching subscribers. - /// - /// The event value. - public void Publish(in TEvent evt) => _observer.Publish(in evt); -} - -/// Sample event used in docs and tests for the observer demo. -/// The unique user identifier. -/// The action performed by the user. -public readonly record struct UserEvent(int Id, string Action); +namespace PatternKit.Examples.ObserverDemo; + +using Behavioral.Observer; + +/// +/// A tiny demo event hub built on top of for examples and docs. +/// +/// The event payload type to broadcast. +public sealed class EventHub +{ + private readonly Observer _observer; + + /// + /// Create an event hub that wraps the provided . + /// + /// The underlying observer to delegate to. + public EventHub(Observer observer) => _observer = observer; + + /// + /// Create a default event hub using with default error handling (aggregate). + /// + /// A new . + public static EventHub CreateDefault() + => new(Observer.Create().Build()); + + /// + /// Subscribe a handler to receive all events. + /// + /// The handler to invoke. + /// An that removes the subscription when disposed. + public IDisposable On(Observer.Handler handler) + => _observer.Subscribe(handler); + + /// + /// Subscribe a handler with an optional predicate filter. + /// + /// The filter to decide whether to deliver the event to the handler. + /// The handler to invoke. + /// An that removes the subscription when disposed. + public IDisposable On(Observer.Predicate predicate, Observer.Handler handler) + => _observer.Subscribe(predicate, handler); + + /// + /// Publish an event to all matching subscribers. + /// + /// The event value. + public void Publish(in TEvent evt) => _observer.Publish(in evt); +} + +/// Sample event used in docs and tests for the observer demo. +/// The unique user identifier. +/// The action performed by the user. +public readonly record struct UserEvent(int Id, string Action); diff --git a/src/PatternKit.Examples/ObserverGeneratorDemo/NotificationSystem.cs b/src/PatternKit.Examples/ObserverGeneratorDemo/NotificationSystem.cs index 45bfbe8d..78932d8b 100644 --- a/src/PatternKit.Examples/ObserverGeneratorDemo/NotificationSystem.cs +++ b/src/PatternKit.Examples/ObserverGeneratorDemo/NotificationSystem.cs @@ -22,7 +22,7 @@ public record NotificationResult(bool Success, string Channel, string? Error = n /// Observable event for notifications with async support. /// Demonstrates async handlers and PublishAsync. /// -[Observer(typeof(Notification), +[Observer(typeof(Notification), Threading = ObserverThreadingPolicy.Locking, Exceptions = ObserverExceptionPolicy.Continue, GenerateAsync = true)] @@ -95,7 +95,7 @@ public void ReportSent(NotificationResult result) public async Task SendEmailAsync(Notification notification) { await Task.Delay(100); // Simulate network delay - + // Simulate random failures (20% chance) if (_random.NextDouble() < 0.2) { @@ -112,7 +112,7 @@ public async Task SendEmailAsync(Notification notification) public async Task SendSmsAsync(Notification notification) { await Task.Delay(80); // Simulate network delay - + // High priority only if (notification.Priority < 2) { @@ -222,9 +222,9 @@ public static void Run() private static void DemoContinuePolicy() { var notification = new NotificationPublished(); - + // Handler 1: Works fine - notification.Subscribe(n => + notification.Subscribe(n => Console.WriteLine(" ✅ Handler 1: Success")); // Handler 2: Throws exception @@ -308,13 +308,13 @@ public static async Task RunAsync() Console.WriteLine("Publishing with Publish (sync):"); notification.Publish(new Notification("user", "Hello World", 1)); - + // Note: async handlers run fire-and-forget with Publish await Task.Delay(100); // Wait for async handlers - + Console.WriteLine("\nPublishing with PublishAsync (awaits async handlers):"); await notification.PublishAsync(new Notification("user", "Goodbye World", 2)); - + Console.WriteLine("\nNote: PublishAsync waits for all async handlers to complete."); } } diff --git a/src/PatternKit.Examples/ObserverGeneratorDemo/TemperatureMonitor.cs b/src/PatternKit.Examples/ObserverGeneratorDemo/TemperatureMonitor.cs index f4a3a1a1..f3f050bc 100644 --- a/src/PatternKit.Examples/ObserverGeneratorDemo/TemperatureMonitor.cs +++ b/src/PatternKit.Examples/ObserverGeneratorDemo/TemperatureMonitor.cs @@ -38,7 +38,7 @@ partial void OnSubscriberError(Exception ex) /// Observable event for temperature alerts with custom configuration. /// Uses Stop exception policy to ensure critical alerts aren't missed. /// -[Observer(typeof(TemperatureAlert), +[Observer(typeof(TemperatureAlert), Threading = ObserverThreadingPolicy.Locking, Exceptions = ObserverExceptionPolicy.Stop, Order = ObserverOrderPolicy.RegistrationOrder)] diff --git a/src/PatternKit.Examples/Pricing/Pipeline.cs b/src/PatternKit.Examples/Pricing/Pipeline.cs index 6687b6f9..77c5dd17 100644 --- a/src/PatternKit.Examples/Pricing/Pipeline.cs +++ b/src/PatternKit.Examples/Pricing/Pipeline.cs @@ -273,4 +273,4 @@ public decimal ComputeDelta(PricingContext ctx, decimal total) } public LineItem? ChooseTargetLine(PricingContext ctx) => ctx.Items.FirstOrDefault(li => li.Sku.HasTag("round:nickel")); -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/Properties/AssemblyCoverage.cs b/src/PatternKit.Examples/Properties/AssemblyCoverage.cs index 598a1a76..29178265 100644 --- a/src/PatternKit.Examples/Properties/AssemblyCoverage.cs +++ b/src/PatternKit.Examples/Properties/AssemblyCoverage.cs @@ -1,4 +1,4 @@ #if NETSTANDARD2_1 // Exclude the entire assembly from coverage when built for netstandard2.1 [assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] -#endif \ No newline at end of file +#endif diff --git a/src/PatternKit.Examples/ProxyGeneratorDemo/Interceptors/TimingInterceptor.cs b/src/PatternKit.Examples/ProxyGeneratorDemo/Interceptors/TimingInterceptor.cs index 8772e31b..72b21df3 100644 --- a/src/PatternKit.Examples/ProxyGeneratorDemo/Interceptors/TimingInterceptor.cs +++ b/src/PatternKit.Examples/ProxyGeneratorDemo/Interceptors/TimingInterceptor.cs @@ -1,5 +1,5 @@ -using System.Diagnostics; using System.Collections.Concurrent; +using System.Diagnostics; namespace PatternKit.Examples.ProxyGeneratorDemo.Interceptors; diff --git a/src/PatternKit.Examples/SingletonGeneratorDemo/ServiceRegistry.cs b/src/PatternKit.Examples/SingletonGeneratorDemo/ServiceRegistry.cs index bd504c08..86236b99 100644 --- a/src/PatternKit.Examples/SingletonGeneratorDemo/ServiceRegistry.cs +++ b/src/PatternKit.Examples/SingletonGeneratorDemo/ServiceRegistry.cs @@ -1,5 +1,5 @@ -using PatternKit.Generators.Singleton; using System.Collections.Concurrent; +using PatternKit.Generators.Singleton; namespace PatternKit.Examples.SingletonGeneratorDemo; diff --git a/src/PatternKit.Examples/TemplateDemo/TemplateAsyncDemo.cs b/src/PatternKit.Examples/TemplateDemo/TemplateAsyncDemo.cs index 6ee991a3..cb529476 100644 --- a/src/PatternKit.Examples/TemplateDemo/TemplateAsyncDemo.cs +++ b/src/PatternKit.Examples/TemplateDemo/TemplateAsyncDemo.cs @@ -72,4 +72,4 @@ public static async Task RunAsync(CancellationToken cancellationToken = default) var (ok2, res2, err2) = await tpl.TryExecuteAsync(-1, cancellationToken); Console.WriteLine(ok2 ? $"OK: {res2}" : $"ERR: {err2}"); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/TemplateDemo/TemplateDemo.cs b/src/PatternKit.Examples/TemplateDemo/TemplateDemo.cs index fb8c6ec1..c058842c 100644 --- a/src/PatternKit.Examples/TemplateDemo/TemplateDemo.cs +++ b/src/PatternKit.Examples/TemplateDemo/TemplateDemo.cs @@ -31,4 +31,4 @@ public static void Run() int result = processor.Execute("The quick brown fox jumps over the lazy dog"); Console.WriteLine($"Word count: {result}"); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Examples/TemplateDemo/TemplateFluentDemo.cs b/src/PatternKit.Examples/TemplateDemo/TemplateFluentDemo.cs index eddc0da0..69f5bc04 100644 --- a/src/PatternKit.Examples/TemplateDemo/TemplateFluentDemo.cs +++ b/src/PatternKit.Examples/TemplateDemo/TemplateFluentDemo.cs @@ -18,4 +18,4 @@ public static void Run() var ok = tpl.TryExecute("The quick brown fox", out var result, out var error); Console.WriteLine(ok ? $"Word count: {result}" : $"Failed: {error}"); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Generators.Abstractions/Interpreter/InterpreterAttributes.cs b/src/PatternKit.Generators.Abstractions/Interpreter/InterpreterAttributes.cs index 32c5fe2e..2fe3ce64 100644 --- a/src/PatternKit.Generators.Abstractions/Interpreter/InterpreterAttributes.cs +++ b/src/PatternKit.Generators.Abstractions/Interpreter/InterpreterAttributes.cs @@ -1,4 +1,4 @@ -namespace PatternKit.Generators.Interpreter; +namespace PatternKit.Generators.Interpreter; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)] public sealed class GenerateInterpreterAttribute(Type contextType, Type resultType) : Attribute diff --git a/src/PatternKit.Generators/ActivityTracking/ActivityTrackerGenerator.cs b/src/PatternKit.Generators/ActivityTracking/ActivityTrackerGenerator.cs index 6ef9938a..90f79683 100644 --- a/src/PatternKit.Generators/ActivityTracking/ActivityTrackerGenerator.cs +++ b/src/PatternKit.Generators/ActivityTracking/ActivityTrackerGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.ActivityTracking; diff --git a/src/PatternKit.Generators/Adapter/AdapterGenerator.cs b/src/PatternKit.Generators/Adapter/AdapterGenerator.cs index ebab8f9c..03dd5b47 100644 --- a/src/PatternKit.Generators/Adapter/AdapterGenerator.cs +++ b/src/PatternKit.Generators/Adapter/AdapterGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators.Adapter; @@ -749,7 +749,7 @@ private static List GetTargetMembers(INamedTypeSymbol targetType) // (interfaces: exclude default implementations added in C# 8.0+) if (isAbstractClass || type.TypeKind == TypeKind.Interface) return m.IsAbstract; - + return true; }); @@ -973,7 +973,7 @@ private static void GenerateMappedMember(StringBuilder sb, ISymbol member, IMeth var methodName = targetMethod.Name; var parameters = string.Join(", ", targetMethod.Parameters.Select(p => $"{GetParameterModifiers(p)}{p.Type.ToDisplayString(FullyQualifiedFormat)} {p.Name}{GetDefaultValue(p)}")); - var parameterNames = string.Join(", ", targetMethod.Parameters.Select(p => + var parameterNames = string.Join(", ", targetMethod.Parameters.Select(p => $"{GetArgumentModifier(p)}{p.Name}")); var isVoid = targetMethod.ReturnsVoid; diff --git a/src/PatternKit.Generators/Ambassador/AmbassadorGenerator.cs b/src/PatternKit.Generators/Ambassador/AmbassadorGenerator.cs index 9e271353..ac11bab7 100644 --- a/src/PatternKit.Generators/Ambassador/AmbassadorGenerator.cs +++ b/src/PatternKit.Generators/Ambassador/AmbassadorGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Ambassador; diff --git a/src/PatternKit.Generators/AntiCorruption/AntiCorruptionLayerGenerator.cs b/src/PatternKit.Generators/AntiCorruption/AntiCorruptionLayerGenerator.cs index 99773b3d..786e3838 100644 --- a/src/PatternKit.Generators/AntiCorruption/AntiCorruptionLayerGenerator.cs +++ b/src/PatternKit.Generators/AntiCorruption/AntiCorruptionLayerGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.AntiCorruption; diff --git a/src/PatternKit.Generators/AuditLog/AuditLogGenerator.cs b/src/PatternKit.Generators/AuditLog/AuditLogGenerator.cs index 9de810b2..eaa59d9a 100644 --- a/src/PatternKit.Generators/AuditLog/AuditLogGenerator.cs +++ b/src/PatternKit.Generators/AuditLog/AuditLogGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.AuditLog; diff --git a/src/PatternKit.Generators/BackendsForFrontends/BackendsForFrontendsGenerator.cs b/src/PatternKit.Generators/BackendsForFrontends/BackendsForFrontendsGenerator.cs index d45cffdb..a9f8b00e 100644 --- a/src/PatternKit.Generators/BackendsForFrontends/BackendsForFrontendsGenerator.cs +++ b/src/PatternKit.Generators/BackendsForFrontends/BackendsForFrontendsGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.BackendsForFrontends; diff --git a/src/PatternKit.Generators/Bridge/BridgeGenerator.cs b/src/PatternKit.Generators/Bridge/BridgeGenerator.cs index 600c02b8..8717a0fe 100644 --- a/src/PatternKit.Generators/Bridge/BridgeGenerator.cs +++ b/src/PatternKit.Generators/Bridge/BridgeGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators.Bridge; diff --git a/src/PatternKit.Generators/Bulkhead/BulkheadPolicyGenerator.cs b/src/PatternKit.Generators/Bulkhead/BulkheadPolicyGenerator.cs index f1ac3d98..a74f1c6a 100644 --- a/src/PatternKit.Generators/Bulkhead/BulkheadPolicyGenerator.cs +++ b/src/PatternKit.Generators/Bulkhead/BulkheadPolicyGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Bulkhead; diff --git a/src/PatternKit.Generators/CacheAside/CacheAsidePolicyGenerator.cs b/src/PatternKit.Generators/CacheAside/CacheAsidePolicyGenerator.cs index 63c85094..f299e0fb 100644 --- a/src/PatternKit.Generators/CacheAside/CacheAsidePolicyGenerator.cs +++ b/src/PatternKit.Generators/CacheAside/CacheAsidePolicyGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.CacheAside; diff --git a/src/PatternKit.Generators/CanonicalDataModel/CanonicalDataModelGenerator.cs b/src/PatternKit.Generators/CanonicalDataModel/CanonicalDataModelGenerator.cs index bb7f1a0f..97f03abe 100644 --- a/src/PatternKit.Generators/CanonicalDataModel/CanonicalDataModelGenerator.cs +++ b/src/PatternKit.Generators/CanonicalDataModel/CanonicalDataModelGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.CanonicalDataModel; diff --git a/src/PatternKit.Generators/Chain/ChainGenerator.cs b/src/PatternKit.Generators/Chain/ChainGenerator.cs index 58f3f1a4..9374f907 100644 --- a/src/PatternKit.Generators/Chain/ChainGenerator.cs +++ b/src/PatternKit.Generators/Chain/ChainGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators.Chain; diff --git a/src/PatternKit.Generators/CircuitBreaker/CircuitBreakerPolicyGenerator.cs b/src/PatternKit.Generators/CircuitBreaker/CircuitBreakerPolicyGenerator.cs index 5532ecfe..bd1ef098 100644 --- a/src/PatternKit.Generators/CircuitBreaker/CircuitBreakerPolicyGenerator.cs +++ b/src/PatternKit.Generators/CircuitBreaker/CircuitBreakerPolicyGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.CircuitBreaker; diff --git a/src/PatternKit.Generators/Cloud/ExternalConfigurationStoreGenerator.cs b/src/PatternKit.Generators/Cloud/ExternalConfigurationStoreGenerator.cs index 8eeaf7c1..3940a813 100644 --- a/src/PatternKit.Generators/Cloud/ExternalConfigurationStoreGenerator.cs +++ b/src/PatternKit.Generators/Cloud/ExternalConfigurationStoreGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Cloud; diff --git a/src/PatternKit.Generators/Command/CommandGenerator.cs b/src/PatternKit.Generators/Command/CommandGenerator.cs index 23db7519..bd25199e 100644 --- a/src/PatternKit.Generators/Command/CommandGenerator.cs +++ b/src/PatternKit.Generators/Command/CommandGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators.Command; diff --git a/src/PatternKit.Generators/ComposerGenerator.cs b/src/PatternKit.Generators/ComposerGenerator.cs index 88d65aff..9520b9a9 100644 --- a/src/PatternKit.Generators/ComposerGenerator.cs +++ b/src/PatternKit.Generators/ComposerGenerator.cs @@ -1,8 +1,8 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using PatternKit.Generators.Composer; -using System.Text; namespace PatternKit.Generators; diff --git a/src/PatternKit.Generators/Composite/CompositeGenerator.cs b/src/PatternKit.Generators/Composite/CompositeGenerator.cs index 41e8282b..a9f68c68 100644 --- a/src/PatternKit.Generators/Composite/CompositeGenerator.cs +++ b/src/PatternKit.Generators/Composite/CompositeGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators.Composite; diff --git a/src/PatternKit.Generators/DataMapping/DataMapperGenerator.cs b/src/PatternKit.Generators/DataMapping/DataMapperGenerator.cs index 43fcc88c..e4138b8f 100644 --- a/src/PatternKit.Generators/DataMapping/DataMapperGenerator.cs +++ b/src/PatternKit.Generators/DataMapping/DataMapperGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.DataMapping; diff --git a/src/PatternKit.Generators/DecoratorGenerator.cs b/src/PatternKit.Generators/DecoratorGenerator.cs index 662c7abf..ceba9a22 100644 --- a/src/PatternKit.Generators/DecoratorGenerator.cs +++ b/src/PatternKit.Generators/DecoratorGenerator.cs @@ -1,8 +1,8 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using PatternKit.Generators.Decorator; -using System.Text; namespace PatternKit.Generators; diff --git a/src/PatternKit.Generators/DomainEvents/DomainEventDispatcherGenerator.cs b/src/PatternKit.Generators/DomainEvents/DomainEventDispatcherGenerator.cs index db1112e6..37433d8c 100644 --- a/src/PatternKit.Generators/DomainEvents/DomainEventDispatcherGenerator.cs +++ b/src/PatternKit.Generators/DomainEvents/DomainEventDispatcherGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.DomainEvents; diff --git a/src/PatternKit.Generators/EventCarriedStateTransfer/EventCarriedStateTransferGenerator.cs b/src/PatternKit.Generators/EventCarriedStateTransfer/EventCarriedStateTransferGenerator.cs index ab9a1611..e3c9d5f7 100644 --- a/src/PatternKit.Generators/EventCarriedStateTransfer/EventCarriedStateTransferGenerator.cs +++ b/src/PatternKit.Generators/EventCarriedStateTransfer/EventCarriedStateTransferGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.EventCarriedStateTransfer; diff --git a/src/PatternKit.Generators/EventNotification/EventNotificationGenerator.cs b/src/PatternKit.Generators/EventNotification/EventNotificationGenerator.cs index ec870328..2a74cc6a 100644 --- a/src/PatternKit.Generators/EventNotification/EventNotificationGenerator.cs +++ b/src/PatternKit.Generators/EventNotification/EventNotificationGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.EventNotification; diff --git a/src/PatternKit.Generators/EventSourcing/EventStoreGenerator.cs b/src/PatternKit.Generators/EventSourcing/EventStoreGenerator.cs index f46a1e4d..701a6c5c 100644 --- a/src/PatternKit.Generators/EventSourcing/EventStoreGenerator.cs +++ b/src/PatternKit.Generators/EventSourcing/EventStoreGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.EventSourcing; diff --git a/src/PatternKit.Generators/FacadeGenerator.cs b/src/PatternKit.Generators/FacadeGenerator.cs index b3da7432..76ec8bc8 100644 --- a/src/PatternKit.Generators/FacadeGenerator.cs +++ b/src/PatternKit.Generators/FacadeGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; namespace PatternKit.Generators; diff --git a/src/PatternKit.Generators/Factories/AbstractFactoryGenerator.cs b/src/PatternKit.Generators/Factories/AbstractFactoryGenerator.cs index 2b5a13d1..37df796f 100644 --- a/src/PatternKit.Generators/Factories/AbstractFactoryGenerator.cs +++ b/src/PatternKit.Generators/Factories/AbstractFactoryGenerator.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Globalization; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Factories; diff --git a/src/PatternKit.Generators/FeatureToggles/FeatureToggleSetGenerator.cs b/src/PatternKit.Generators/FeatureToggles/FeatureToggleSetGenerator.cs index fb056022..cbe55d11 100644 --- a/src/PatternKit.Generators/FeatureToggles/FeatureToggleSetGenerator.cs +++ b/src/PatternKit.Generators/FeatureToggles/FeatureToggleSetGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.FeatureToggles; diff --git a/src/PatternKit.Generators/Flyweight/FlyweightGenerator.cs b/src/PatternKit.Generators/Flyweight/FlyweightGenerator.cs index b24deabc..96b885ee 100644 --- a/src/PatternKit.Generators/Flyweight/FlyweightGenerator.cs +++ b/src/PatternKit.Generators/Flyweight/FlyweightGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators.Flyweight; diff --git a/src/PatternKit.Generators/GatewayAggregation/GatewayAggregationGenerator.cs b/src/PatternKit.Generators/GatewayAggregation/GatewayAggregationGenerator.cs index 22b134b7..ac66c6b7 100644 --- a/src/PatternKit.Generators/GatewayAggregation/GatewayAggregationGenerator.cs +++ b/src/PatternKit.Generators/GatewayAggregation/GatewayAggregationGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.GatewayAggregation; diff --git a/src/PatternKit.Generators/GatewayRouting/GatewayRoutingGenerator.cs b/src/PatternKit.Generators/GatewayRouting/GatewayRoutingGenerator.cs index 76709f51..7239e426 100644 --- a/src/PatternKit.Generators/GatewayRouting/GatewayRoutingGenerator.cs +++ b/src/PatternKit.Generators/GatewayRouting/GatewayRoutingGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.GatewayRouting; diff --git a/src/PatternKit.Generators/HealthEndpointMonitoring/HealthEndpointMonitoringGenerator.cs b/src/PatternKit.Generators/HealthEndpointMonitoring/HealthEndpointMonitoringGenerator.cs index a2ac1bef..0f859daf 100644 --- a/src/PatternKit.Generators/HealthEndpointMonitoring/HealthEndpointMonitoringGenerator.cs +++ b/src/PatternKit.Generators/HealthEndpointMonitoring/HealthEndpointMonitoringGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.HealthEndpointMonitoring; diff --git a/src/PatternKit.Generators/IdentityMap/IdentityMapGenerator.cs b/src/PatternKit.Generators/IdentityMap/IdentityMapGenerator.cs index 5b1a4d26..1b522bd8 100644 --- a/src/PatternKit.Generators/IdentityMap/IdentityMapGenerator.cs +++ b/src/PatternKit.Generators/IdentityMap/IdentityMapGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.IdentityMap; diff --git a/src/PatternKit.Generators/Interpreter/InterpreterGenerator.cs b/src/PatternKit.Generators/Interpreter/InterpreterGenerator.cs index 626bde7e..20fd6ffc 100644 --- a/src/PatternKit.Generators/Interpreter/InterpreterGenerator.cs +++ b/src/PatternKit.Generators/Interpreter/InterpreterGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Interpreter; diff --git a/src/PatternKit.Generators/Iterator/IteratorGenerator.cs b/src/PatternKit.Generators/Iterator/IteratorGenerator.cs index f5750d58..7b523264 100644 --- a/src/PatternKit.Generators/Iterator/IteratorGenerator.cs +++ b/src/PatternKit.Generators/Iterator/IteratorGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators.Iterator; diff --git a/src/PatternKit.Generators/LeaderElection/LeaderElectionGenerator.cs b/src/PatternKit.Generators/LeaderElection/LeaderElectionGenerator.cs index c70b8bc2..0d1cf3de 100644 --- a/src/PatternKit.Generators/LeaderElection/LeaderElectionGenerator.cs +++ b/src/PatternKit.Generators/LeaderElection/LeaderElectionGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.LeaderElection; diff --git a/src/PatternKit.Generators/MaterializedViews/MaterializedViewGenerator.cs b/src/PatternKit.Generators/MaterializedViews/MaterializedViewGenerator.cs index 29509306..76920bfb 100644 --- a/src/PatternKit.Generators/MaterializedViews/MaterializedViewGenerator.cs +++ b/src/PatternKit.Generators/MaterializedViews/MaterializedViewGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.MaterializedViews; diff --git a/src/PatternKit.Generators/MementoGenerator.cs b/src/PatternKit.Generators/MementoGenerator.cs index 95c5216e..f8db7105 100644 --- a/src/PatternKit.Generators/MementoGenerator.cs +++ b/src/PatternKit.Generators/MementoGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators; diff --git a/src/PatternKit.Generators/Messaging/BackplaneTopologyGenerator.cs b/src/PatternKit.Generators/Messaging/BackplaneTopologyGenerator.cs index acc0f4ad..a8c089f5 100644 --- a/src/PatternKit.Generators/Messaging/BackplaneTopologyGenerator.cs +++ b/src/PatternKit.Generators/Messaging/BackplaneTopologyGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/ChannelAdapterGenerator.cs b/src/PatternKit.Generators/Messaging/ChannelAdapterGenerator.cs index f0cd818a..8caee1f5 100644 --- a/src/PatternKit.Generators/Messaging/ChannelAdapterGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ChannelAdapterGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/ChannelPurgerGenerator.cs b/src/PatternKit.Generators/Messaging/ChannelPurgerGenerator.cs index fef8e797..c46bbfc7 100644 --- a/src/PatternKit.Generators/Messaging/ChannelPurgerGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ChannelPurgerGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/ClaimCheckGenerator.cs b/src/PatternKit.Generators/Messaging/ClaimCheckGenerator.cs index 1cec8114..2ce7091d 100644 --- a/src/PatternKit.Generators/Messaging/ClaimCheckGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ClaimCheckGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/CompetingConsumerGroupGenerator.cs b/src/PatternKit.Generators/Messaging/CompetingConsumerGroupGenerator.cs index c94bd8e6..03bb8793 100644 --- a/src/PatternKit.Generators/Messaging/CompetingConsumerGroupGenerator.cs +++ b/src/PatternKit.Generators/Messaging/CompetingConsumerGroupGenerator.cs @@ -1,134 +1,134 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; - -namespace PatternKit.Generators.Messaging; - -[Generator] -public sealed class CompetingConsumerGroupGenerator : IIncrementalGenerator -{ - private const string AttributeName = "PatternKit.Generators.Messaging.GenerateCompetingConsumerGroupAttribute"; - - private static readonly SymbolDisplayFormat TypeFormat = new( - globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Included, - typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, - genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, - miscellaneousOptions: SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier | SymbolDisplayMiscellaneousOptions.UseSpecialTypes); - - private static readonly DiagnosticDescriptor MustBePartial = new( - "PKCNS001", "Competing Consumers host must be partial", - "Type '{0}' is marked with [GenerateCompetingConsumerGroup] but is not declared as partial", - "PatternKit.Generators.Messaging", DiagnosticSeverity.Error, true); - - private static readonly DiagnosticDescriptor InvalidConfiguration = new( - "PKCNS002", "Competing Consumers configuration is invalid", - "Competing Consumers group '{0}' must have MaxConcurrentDeliveries >= 1", - "PatternKit.Generators.Messaging", DiagnosticSeverity.Error, true); - - public void Initialize(IncrementalGeneratorInitializationContext context) - { - var candidates = context.SyntaxProvider.ForAttributeWithMetadataName( - AttributeName, - static (node, _) => node is TypeDeclarationSyntax, - static (ctx, _) => (Type: (INamedTypeSymbol)ctx.TargetSymbol, Node: (TypeDeclarationSyntax)ctx.TargetNode, Attributes: ctx.Attributes)); - - context.RegisterSourceOutput(candidates, static (spc, candidate) => - { - var attr = candidate.Attributes.FirstOrDefault(static a => a.AttributeClass?.ToDisplayString() == AttributeName); - if (attr is not null) - Generate(spc, candidate.Type, candidate.Node, attr); - }); - } - - private static void Generate(SourceProductionContext context, INamedTypeSymbol type, TypeDeclarationSyntax node, AttributeData attribute) - { - if (!node.Modifiers.Any(static modifier => modifier.Text == "partial")) - { - context.ReportDiagnostic(Diagnostic.Create(MustBePartial, node.Identifier.GetLocation(), type.Name)); - return; - } - - var messageType = attribute.ConstructorArguments.Length >= 1 ? attribute.ConstructorArguments[0].Value as INamedTypeSymbol : null; - var resultType = attribute.ConstructorArguments.Length >= 2 ? attribute.ConstructorArguments[1].Value as INamedTypeSymbol : null; - if (messageType is null || resultType is null) - return; - - var maxConcurrentDeliveries = GetNamedInt(attribute, "MaxConcurrentDeliveries") ?? 1; - if (maxConcurrentDeliveries < 1) - { - context.ReportDiagnostic(Diagnostic.Create(InvalidConfiguration, node.Identifier.GetLocation(), type.Name)); - return; - } - - context.AddSource($"{type.Name}.CompetingConsumerGroup.g.cs", SourceText.From( - GenerateSource( - type, - messageType, - resultType, - GetNamedString(attribute, "FactoryMethodName") ?? "Create", - GetNamedString(attribute, "GroupName") ?? "competing-consumers", - maxConcurrentDeliveries), - Encoding.UTF8)); - } - - private static string GenerateSource( - INamedTypeSymbol type, - INamedTypeSymbol messageType, - INamedTypeSymbol resultType, - string factoryMethodName, - string groupName, - int maxConcurrentDeliveries) - { - var ns = type.ContainingNamespace.IsGlobalNamespace ? null : type.ContainingNamespace.ToDisplayString(); - var messageTypeName = messageType.ToDisplayString(TypeFormat); - var resultTypeName = resultType.ToDisplayString(TypeFormat); - var sb = new StringBuilder(); - sb.AppendLine("// "); - sb.AppendLine("#nullable enable"); - sb.AppendLine(); - if (ns is not null) - { - sb.Append("namespace ").Append(ns).AppendLine(";"); - sb.AppendLine(); - } - - sb.Append(GetAccessibility(type.DeclaredAccessibility)).Append(' '); - if (type.IsStatic) - sb.Append("static "); - else if (type.IsAbstract && type.TypeKind == TypeKind.Class) - sb.Append("abstract "); - else if (type.IsSealed && type.TypeKind == TypeKind.Class) - sb.Append("sealed "); - sb.Append("partial ").Append(type.TypeKind == TypeKind.Struct ? "struct" : "class").Append(' ').Append(type.Name).AppendLine(); - sb.AppendLine("{"); - sb.Append(" public static global::PatternKit.Messaging.CompetingConsumers.CompetingConsumerGroup<").Append(messageTypeName).Append(", ").Append(resultTypeName).Append(">.Builder ").Append(factoryMethodName).AppendLine("()"); - sb.AppendLine(" {"); - sb.Append(" return global::PatternKit.Messaging.CompetingConsumers.CompetingConsumerGroup<").Append(messageTypeName).Append(", ").Append(resultTypeName).Append(">.Create(\"").Append(Escape(groupName)).AppendLine("\")"); - sb.Append(" .WithMaxConcurrentDeliveries(").Append(maxConcurrentDeliveries).AppendLine(");"); - sb.AppendLine(" }"); - sb.AppendLine("}"); - return sb.ToString(); - } - - private static string Escape(string value) => value.Replace("\\", "\\\\").Replace("\"", "\\\""); - - private static string? GetNamedString(AttributeData attribute, string name) - => attribute.NamedArguments.FirstOrDefault(kv => kv.Key == name).Value.Value as string; - - private static int? GetNamedInt(AttributeData attribute, string name) - => attribute.NamedArguments.FirstOrDefault(kv => kv.Key == name).Value.Value as int?; - - private static string GetAccessibility(Accessibility accessibility) - => accessibility switch - { - Accessibility.Public => "public", - Accessibility.Internal => "internal", - Accessibility.Private => "private", - Accessibility.Protected => "protected", - Accessibility.ProtectedAndInternal => "private protected", - Accessibility.ProtectedOrInternal => "protected internal", - _ => "internal" - }; -} +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; + +namespace PatternKit.Generators.Messaging; + +[Generator] +public sealed class CompetingConsumerGroupGenerator : IIncrementalGenerator +{ + private const string AttributeName = "PatternKit.Generators.Messaging.GenerateCompetingConsumerGroupAttribute"; + + private static readonly SymbolDisplayFormat TypeFormat = new( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Included, + typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, + genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, + miscellaneousOptions: SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier | SymbolDisplayMiscellaneousOptions.UseSpecialTypes); + + private static readonly DiagnosticDescriptor MustBePartial = new( + "PKCNS001", "Competing Consumers host must be partial", + "Type '{0}' is marked with [GenerateCompetingConsumerGroup] but is not declared as partial", + "PatternKit.Generators.Messaging", DiagnosticSeverity.Error, true); + + private static readonly DiagnosticDescriptor InvalidConfiguration = new( + "PKCNS002", "Competing Consumers configuration is invalid", + "Competing Consumers group '{0}' must have MaxConcurrentDeliveries >= 1", + "PatternKit.Generators.Messaging", DiagnosticSeverity.Error, true); + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var candidates = context.SyntaxProvider.ForAttributeWithMetadataName( + AttributeName, + static (node, _) => node is TypeDeclarationSyntax, + static (ctx, _) => (Type: (INamedTypeSymbol)ctx.TargetSymbol, Node: (TypeDeclarationSyntax)ctx.TargetNode, Attributes: ctx.Attributes)); + + context.RegisterSourceOutput(candidates, static (spc, candidate) => + { + var attr = candidate.Attributes.FirstOrDefault(static a => a.AttributeClass?.ToDisplayString() == AttributeName); + if (attr is not null) + Generate(spc, candidate.Type, candidate.Node, attr); + }); + } + + private static void Generate(SourceProductionContext context, INamedTypeSymbol type, TypeDeclarationSyntax node, AttributeData attribute) + { + if (!node.Modifiers.Any(static modifier => modifier.Text == "partial")) + { + context.ReportDiagnostic(Diagnostic.Create(MustBePartial, node.Identifier.GetLocation(), type.Name)); + return; + } + + var messageType = attribute.ConstructorArguments.Length >= 1 ? attribute.ConstructorArguments[0].Value as INamedTypeSymbol : null; + var resultType = attribute.ConstructorArguments.Length >= 2 ? attribute.ConstructorArguments[1].Value as INamedTypeSymbol : null; + if (messageType is null || resultType is null) + return; + + var maxConcurrentDeliveries = GetNamedInt(attribute, "MaxConcurrentDeliveries") ?? 1; + if (maxConcurrentDeliveries < 1) + { + context.ReportDiagnostic(Diagnostic.Create(InvalidConfiguration, node.Identifier.GetLocation(), type.Name)); + return; + } + + context.AddSource($"{type.Name}.CompetingConsumerGroup.g.cs", SourceText.From( + GenerateSource( + type, + messageType, + resultType, + GetNamedString(attribute, "FactoryMethodName") ?? "Create", + GetNamedString(attribute, "GroupName") ?? "competing-consumers", + maxConcurrentDeliveries), + Encoding.UTF8)); + } + + private static string GenerateSource( + INamedTypeSymbol type, + INamedTypeSymbol messageType, + INamedTypeSymbol resultType, + string factoryMethodName, + string groupName, + int maxConcurrentDeliveries) + { + var ns = type.ContainingNamespace.IsGlobalNamespace ? null : type.ContainingNamespace.ToDisplayString(); + var messageTypeName = messageType.ToDisplayString(TypeFormat); + var resultTypeName = resultType.ToDisplayString(TypeFormat); + var sb = new StringBuilder(); + sb.AppendLine("// "); + sb.AppendLine("#nullable enable"); + sb.AppendLine(); + if (ns is not null) + { + sb.Append("namespace ").Append(ns).AppendLine(";"); + sb.AppendLine(); + } + + sb.Append(GetAccessibility(type.DeclaredAccessibility)).Append(' '); + if (type.IsStatic) + sb.Append("static "); + else if (type.IsAbstract && type.TypeKind == TypeKind.Class) + sb.Append("abstract "); + else if (type.IsSealed && type.TypeKind == TypeKind.Class) + sb.Append("sealed "); + sb.Append("partial ").Append(type.TypeKind == TypeKind.Struct ? "struct" : "class").Append(' ').Append(type.Name).AppendLine(); + sb.AppendLine("{"); + sb.Append(" public static global::PatternKit.Messaging.CompetingConsumers.CompetingConsumerGroup<").Append(messageTypeName).Append(", ").Append(resultTypeName).Append(">.Builder ").Append(factoryMethodName).AppendLine("()"); + sb.AppendLine(" {"); + sb.Append(" return global::PatternKit.Messaging.CompetingConsumers.CompetingConsumerGroup<").Append(messageTypeName).Append(", ").Append(resultTypeName).Append(">.Create(\"").Append(Escape(groupName)).AppendLine("\")"); + sb.Append(" .WithMaxConcurrentDeliveries(").Append(maxConcurrentDeliveries).AppendLine(");"); + sb.AppendLine(" }"); + sb.AppendLine("}"); + return sb.ToString(); + } + + private static string Escape(string value) => value.Replace("\\", "\\\\").Replace("\"", "\\\""); + + private static string? GetNamedString(AttributeData attribute, string name) + => attribute.NamedArguments.FirstOrDefault(kv => kv.Key == name).Value.Value as string; + + private static int? GetNamedInt(AttributeData attribute, string name) + => attribute.NamedArguments.FirstOrDefault(kv => kv.Key == name).Value.Value as int?; + + private static string GetAccessibility(Accessibility accessibility) + => accessibility switch + { + Accessibility.Public => "public", + Accessibility.Internal => "internal", + Accessibility.Private => "private", + Accessibility.Protected => "protected", + Accessibility.ProtectedAndInternal => "private protected", + Accessibility.ProtectedOrInternal => "protected internal", + _ => "internal" + }; +} diff --git a/src/PatternKit.Generators/Messaging/ContentEnricherGenerator.cs b/src/PatternKit.Generators/Messaging/ContentEnricherGenerator.cs index 27c25aef..95560eeb 100644 --- a/src/PatternKit.Generators/Messaging/ContentEnricherGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ContentEnricherGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/ContentRouterGenerator.cs b/src/PatternKit.Generators/Messaging/ContentRouterGenerator.cs index 210b4d11..25fa2aa5 100644 --- a/src/PatternKit.Generators/Messaging/ContentRouterGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ContentRouterGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/ControlBusGenerator.cs b/src/PatternKit.Generators/Messaging/ControlBusGenerator.cs index 008458cb..95856d6c 100644 --- a/src/PatternKit.Generators/Messaging/ControlBusGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ControlBusGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/CorrelationIdentifierGenerator.cs b/src/PatternKit.Generators/Messaging/CorrelationIdentifierGenerator.cs index 2228f763..5972b1a5 100644 --- a/src/PatternKit.Generators/Messaging/CorrelationIdentifierGenerator.cs +++ b/src/PatternKit.Generators/Messaging/CorrelationIdentifierGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/DeadLetterChannelGenerator.cs b/src/PatternKit.Generators/Messaging/DeadLetterChannelGenerator.cs index efa97cb7..8be98803 100644 --- a/src/PatternKit.Generators/Messaging/DeadLetterChannelGenerator.cs +++ b/src/PatternKit.Generators/Messaging/DeadLetterChannelGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/DispatcherGenerator.cs b/src/PatternKit.Generators/Messaging/DispatcherGenerator.cs index 7f00863d..cd8536d5 100644 --- a/src/PatternKit.Generators/Messaging/DispatcherGenerator.cs +++ b/src/PatternKit.Generators/Messaging/DispatcherGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/DurableSubscriberGenerator.cs b/src/PatternKit.Generators/Messaging/DurableSubscriberGenerator.cs index 09ae3206..e55b28a2 100644 --- a/src/PatternKit.Generators/Messaging/DurableSubscriberGenerator.cs +++ b/src/PatternKit.Generators/Messaging/DurableSubscriberGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/DynamicRouterGenerator.cs b/src/PatternKit.Generators/Messaging/DynamicRouterGenerator.cs index 2b80c64c..17883ddb 100644 --- a/src/PatternKit.Generators/Messaging/DynamicRouterGenerator.cs +++ b/src/PatternKit.Generators/Messaging/DynamicRouterGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/EventDrivenConsumerGenerator.cs b/src/PatternKit.Generators/Messaging/EventDrivenConsumerGenerator.cs index fdd806ea..75013e23 100644 --- a/src/PatternKit.Generators/Messaging/EventDrivenConsumerGenerator.cs +++ b/src/PatternKit.Generators/Messaging/EventDrivenConsumerGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/GuaranteedDeliveryGenerator.cs b/src/PatternKit.Generators/Messaging/GuaranteedDeliveryGenerator.cs index 4b4e8b5b..c646f5ae 100644 --- a/src/PatternKit.Generators/Messaging/GuaranteedDeliveryGenerator.cs +++ b/src/PatternKit.Generators/Messaging/GuaranteedDeliveryGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/InvalidMessageChannelGenerator.cs b/src/PatternKit.Generators/Messaging/InvalidMessageChannelGenerator.cs index 154ae078..081bb94c 100644 --- a/src/PatternKit.Generators/Messaging/InvalidMessageChannelGenerator.cs +++ b/src/PatternKit.Generators/Messaging/InvalidMessageChannelGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MailboxGenerator.cs b/src/PatternKit.Generators/Messaging/MailboxGenerator.cs index 55300bd6..25187182 100644 --- a/src/PatternKit.Generators/Messaging/MailboxGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MailboxGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessageBusGenerator.cs b/src/PatternKit.Generators/Messaging/MessageBusGenerator.cs index 05dacf50..881e1477 100644 --- a/src/PatternKit.Generators/Messaging/MessageBusGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessageBusGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessageChannelGenerator.cs b/src/PatternKit.Generators/Messaging/MessageChannelGenerator.cs index 9d0e30af..9f1f60e6 100644 --- a/src/PatternKit.Generators/Messaging/MessageChannelGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessageChannelGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessageEnvelopeGenerator.cs b/src/PatternKit.Generators/Messaging/MessageEnvelopeGenerator.cs index 585bddac..dba231f2 100644 --- a/src/PatternKit.Generators/Messaging/MessageEnvelopeGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessageEnvelopeGenerator.cs @@ -1,11 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessageExpirationGenerator.cs b/src/PatternKit.Generators/Messaging/MessageExpirationGenerator.cs index f3b411a9..c0ef2a23 100644 --- a/src/PatternKit.Generators/Messaging/MessageExpirationGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessageExpirationGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessageFilterGenerator.cs b/src/PatternKit.Generators/Messaging/MessageFilterGenerator.cs index 24e9d2c3..f6f3656c 100644 --- a/src/PatternKit.Generators/Messaging/MessageFilterGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessageFilterGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessageHistoryGenerator.cs b/src/PatternKit.Generators/Messaging/MessageHistoryGenerator.cs index 7f3f155d..9ab3b26c 100644 --- a/src/PatternKit.Generators/Messaging/MessageHistoryGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessageHistoryGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessageStoreGenerator.cs b/src/PatternKit.Generators/Messaging/MessageStoreGenerator.cs index a0c2ab4a..38ba8095 100644 --- a/src/PatternKit.Generators/Messaging/MessageStoreGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessageStoreGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessageTranslatorGenerator.cs b/src/PatternKit.Generators/Messaging/MessageTranslatorGenerator.cs index d00fbab1..021bc3c2 100644 --- a/src/PatternKit.Generators/Messaging/MessageTranslatorGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessageTranslatorGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessagingBridgeGenerator.cs b/src/PatternKit.Generators/Messaging/MessagingBridgeGenerator.cs index 87e7f055..9e019594 100644 --- a/src/PatternKit.Generators/Messaging/MessagingBridgeGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessagingBridgeGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/MessagingGatewayGenerator.cs b/src/PatternKit.Generators/Messaging/MessagingGatewayGenerator.cs index e73850c4..88cc02f7 100644 --- a/src/PatternKit.Generators/Messaging/MessagingGatewayGenerator.cs +++ b/src/PatternKit.Generators/Messaging/MessagingGatewayGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/PipesAndFiltersPipelineGenerator.cs b/src/PatternKit.Generators/Messaging/PipesAndFiltersPipelineGenerator.cs index 7d8c17b1..c632b774 100644 --- a/src/PatternKit.Generators/Messaging/PipesAndFiltersPipelineGenerator.cs +++ b/src/PatternKit.Generators/Messaging/PipesAndFiltersPipelineGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/PollingConsumerGenerator.cs b/src/PatternKit.Generators/Messaging/PollingConsumerGenerator.cs index 224e2d5a..205b99ea 100644 --- a/src/PatternKit.Generators/Messaging/PollingConsumerGenerator.cs +++ b/src/PatternKit.Generators/Messaging/PollingConsumerGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/RecipientListGenerator.cs b/src/PatternKit.Generators/Messaging/RecipientListGenerator.cs index 67080157..9d7577ea 100644 --- a/src/PatternKit.Generators/Messaging/RecipientListGenerator.cs +++ b/src/PatternKit.Generators/Messaging/RecipientListGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/ReliabilityPipelineGenerator.cs b/src/PatternKit.Generators/Messaging/ReliabilityPipelineGenerator.cs index 2c0574f8..cc2a2159 100644 --- a/src/PatternKit.Generators/Messaging/ReliabilityPipelineGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ReliabilityPipelineGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/ResequencerGenerator.cs b/src/PatternKit.Generators/Messaging/ResequencerGenerator.cs index 933eed58..c62d85e5 100644 --- a/src/PatternKit.Generators/Messaging/ResequencerGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ResequencerGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/RoutingSlipGenerator.cs b/src/PatternKit.Generators/Messaging/RoutingSlipGenerator.cs index d5e32454..3d9615d9 100644 --- a/src/PatternKit.Generators/Messaging/RoutingSlipGenerator.cs +++ b/src/PatternKit.Generators/Messaging/RoutingSlipGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/SagaGenerator.cs b/src/PatternKit.Generators/Messaging/SagaGenerator.cs index 0f14294c..ef5dcb01 100644 --- a/src/PatternKit.Generators/Messaging/SagaGenerator.cs +++ b/src/PatternKit.Generators/Messaging/SagaGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/ScatterGatherGenerator.cs b/src/PatternKit.Generators/Messaging/ScatterGatherGenerator.cs index c87d6ef9..0be71007 100644 --- a/src/PatternKit.Generators/Messaging/ScatterGatherGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ScatterGatherGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/ServiceActivatorGenerator.cs b/src/PatternKit.Generators/Messaging/ServiceActivatorGenerator.cs index 29a9fdba..1bd5f403 100644 --- a/src/PatternKit.Generators/Messaging/ServiceActivatorGenerator.cs +++ b/src/PatternKit.Generators/Messaging/ServiceActivatorGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/SplitterAggregatorGenerator.cs b/src/PatternKit.Generators/Messaging/SplitterAggregatorGenerator.cs index f82b4d23..ef6b9f80 100644 --- a/src/PatternKit.Generators/Messaging/SplitterAggregatorGenerator.cs +++ b/src/PatternKit.Generators/Messaging/SplitterAggregatorGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Messaging/WireTapGenerator.cs b/src/PatternKit.Generators/Messaging/WireTapGenerator.cs index 73038657..bde8fc81 100644 --- a/src/PatternKit.Generators/Messaging/WireTapGenerator.cs +++ b/src/PatternKit.Generators/Messaging/WireTapGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Messaging; diff --git a/src/PatternKit.Generators/Observer/ObserverGenerator.cs b/src/PatternKit.Generators/Observer/ObserverGenerator.cs index 74972e66..663ed670 100644 --- a/src/PatternKit.Generators/Observer/ObserverGenerator.cs +++ b/src/PatternKit.Generators/Observer/ObserverGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators.Observer; @@ -148,13 +148,13 @@ private static ObserverConfig ExtractConfig(AttributeData attr) break; } } - + // If ForceAsync is true but GenerateAsync is false, enable GenerateAsync if (config.ForceAsync && !config.GenerateAsync) { config.GenerateAsync = true; } - + return config; } @@ -187,7 +187,7 @@ private static string GenerateSource(INamedTypeSymbol typeSymbol, string typeNam sb.AppendLine("#nullable enable"); sb.AppendLine("// "); sb.AppendLine(); - + // Add using System.Linq for ToArray() extension method on ImmutableList if (config.Threading == 2 && config.Order == 0) // Concurrent + RegistrationOrder uses ImmutableList { @@ -220,7 +220,7 @@ private static void GenerateFields(StringBuilder sb, ObserverConfig config) // Generate a shared state object to avoid any issues with subscriptions sb.AppendLine(" private sealed class ObserverState"); sb.AppendLine(" {"); - + switch (config.Threading) { case 0: // SingleThreadedFast @@ -247,7 +247,7 @@ private static void GenerateFields(StringBuilder sb, ObserverConfig config) } break; } - + sb.AppendLine(" }"); sb.AppendLine(); sb.AppendLine(" private readonly ObserverState _state = new();"); @@ -255,7 +255,7 @@ private static void GenerateFields(StringBuilder sb, ObserverConfig config) } private static void GenerateSubscribeMethods(StringBuilder sb, string payloadType, ObserverConfig config) - { + { if (!config.ForceAsync) { sb.AppendLine($" public System.IDisposable Subscribe(System.Action<{payloadType}> handler)"); @@ -326,7 +326,7 @@ private static void GeneratePublishMethods(StringBuilder sb, string payloadType, sb.AppendLine(" foreach (var sub in snapshot)"); sb.AppendLine(" {"); - + // Handle async subscriptions in fire-and-forget mode sb.AppendLine(" if (sub.IsAsync)"); sb.AppendLine(" {"); @@ -425,7 +425,7 @@ private static void GeneratePublishMethods(StringBuilder sb, string payloadType, } private static void GenerateSnapshot(StringBuilder sb, ObserverConfig config, string indent) - { + { switch (config.Threading) { case 0: // SingleThreadedFast diff --git a/src/PatternKit.Generators/PriorityQueue/PriorityQueueGenerator.cs b/src/PatternKit.Generators/PriorityQueue/PriorityQueueGenerator.cs index 2dcc806a..08cc7ff6 100644 --- a/src/PatternKit.Generators/PriorityQueue/PriorityQueueGenerator.cs +++ b/src/PatternKit.Generators/PriorityQueue/PriorityQueueGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.PriorityQueue; diff --git a/src/PatternKit.Generators/Properties/AssemblyCoverage.cs b/src/PatternKit.Generators/Properties/AssemblyCoverage.cs index 598a1a76..29178265 100644 --- a/src/PatternKit.Generators/Properties/AssemblyCoverage.cs +++ b/src/PatternKit.Generators/Properties/AssemblyCoverage.cs @@ -1,4 +1,4 @@ #if NETSTANDARD2_1 // Exclude the entire assembly from coverage when built for netstandard2.1 [assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] -#endif \ No newline at end of file +#endif diff --git a/src/PatternKit.Generators/PrototypeGenerator.cs b/src/PatternKit.Generators/PrototypeGenerator.cs index 860a9853..819ed9bb 100644 --- a/src/PatternKit.Generators/PrototypeGenerator.cs +++ b/src/PatternKit.Generators/PrototypeGenerator.cs @@ -1,9 +1,9 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; -using System.Linq; -using System.Collections.Generic; namespace PatternKit.Generators; diff --git a/src/PatternKit.Generators/ProxyGenerator.cs b/src/PatternKit.Generators/ProxyGenerator.cs index c9216703..04e1befa 100644 --- a/src/PatternKit.Generators/ProxyGenerator.cs +++ b/src/PatternKit.Generators/ProxyGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators; diff --git a/src/PatternKit.Generators/QueueLoadLeveling/QueueLoadLevelingPolicyGenerator.cs b/src/PatternKit.Generators/QueueLoadLeveling/QueueLoadLevelingPolicyGenerator.cs index f018febb..c5db34ff 100644 --- a/src/PatternKit.Generators/QueueLoadLeveling/QueueLoadLevelingPolicyGenerator.cs +++ b/src/PatternKit.Generators/QueueLoadLeveling/QueueLoadLevelingPolicyGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.QueueLoadLeveling; diff --git a/src/PatternKit.Generators/RateLimiting/RateLimitPolicyGenerator.cs b/src/PatternKit.Generators/RateLimiting/RateLimitPolicyGenerator.cs index 9c2a9425..4d0c1bac 100644 --- a/src/PatternKit.Generators/RateLimiting/RateLimitPolicyGenerator.cs +++ b/src/PatternKit.Generators/RateLimiting/RateLimitPolicyGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.RateLimiting; diff --git a/src/PatternKit.Generators/Repository/RepositoryGenerator.cs b/src/PatternKit.Generators/Repository/RepositoryGenerator.cs index a4b6a01c..3388f96d 100644 --- a/src/PatternKit.Generators/Repository/RepositoryGenerator.cs +++ b/src/PatternKit.Generators/Repository/RepositoryGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Repository; diff --git a/src/PatternKit.Generators/Retry/RetryPolicyGenerator.cs b/src/PatternKit.Generators/Retry/RetryPolicyGenerator.cs index f71c2c3f..97dfcf9d 100644 --- a/src/PatternKit.Generators/Retry/RetryPolicyGenerator.cs +++ b/src/PatternKit.Generators/Retry/RetryPolicyGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Retry; diff --git a/src/PatternKit.Generators/SchedulerAgentSupervisor/SchedulerAgentSupervisorGenerator.cs b/src/PatternKit.Generators/SchedulerAgentSupervisor/SchedulerAgentSupervisorGenerator.cs index 1350042b..ddfe7191 100644 --- a/src/PatternKit.Generators/SchedulerAgentSupervisor/SchedulerAgentSupervisorGenerator.cs +++ b/src/PatternKit.Generators/SchedulerAgentSupervisor/SchedulerAgentSupervisorGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.SchedulerAgentSupervisor; diff --git a/src/PatternKit.Generators/ServiceLayer/ServiceLayerOperationGenerator.cs b/src/PatternKit.Generators/ServiceLayer/ServiceLayerOperationGenerator.cs index bf8f94ae..59d73e3a 100644 --- a/src/PatternKit.Generators/ServiceLayer/ServiceLayerOperationGenerator.cs +++ b/src/PatternKit.Generators/ServiceLayer/ServiceLayerOperationGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.ServiceLayer; diff --git a/src/PatternKit.Generators/Shims/NetStandard20.cs b/src/PatternKit.Generators/Shims/NetStandard20.cs index 254d2b93..fc1417c0 100644 --- a/src/PatternKit.Generators/Shims/NetStandard20.cs +++ b/src/PatternKit.Generators/Shims/NetStandard20.cs @@ -1,4 +1,4 @@ -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 namespace System.Runtime.CompilerServices { internal class IsExternalInit { } diff --git a/src/PatternKit.Generators/Sidecar/SidecarGenerator.cs b/src/PatternKit.Generators/Sidecar/SidecarGenerator.cs index 614ab10b..89ba63e4 100644 --- a/src/PatternKit.Generators/Sidecar/SidecarGenerator.cs +++ b/src/PatternKit.Generators/Sidecar/SidecarGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.Sidecar; diff --git a/src/PatternKit.Generators/Singleton/SingletonGenerator.cs b/src/PatternKit.Generators/Singleton/SingletonGenerator.cs index 411688c3..35a3c6f4 100644 --- a/src/PatternKit.Generators/Singleton/SingletonGenerator.cs +++ b/src/PatternKit.Generators/Singleton/SingletonGenerator.cs @@ -1,7 +1,7 @@ +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Text; namespace PatternKit.Generators.Singleton; diff --git a/src/PatternKit.Generators/Specification/SpecificationGenerator.cs b/src/PatternKit.Generators/Specification/SpecificationGenerator.cs index b84b514b..3c0af081 100644 --- a/src/PatternKit.Generators/Specification/SpecificationGenerator.cs +++ b/src/PatternKit.Generators/Specification/SpecificationGenerator.cs @@ -1,10 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.Specification; diff --git a/src/PatternKit.Generators/StateMachineGenerator.cs b/src/PatternKit.Generators/StateMachineGenerator.cs index 20b0769b..b048ef83 100644 --- a/src/PatternKit.Generators/StateMachineGenerator.cs +++ b/src/PatternKit.Generators/StateMachineGenerator.cs @@ -1,8 +1,8 @@ +using System.Collections.Immutable; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Collections.Immutable; -using System.Text; namespace PatternKit.Generators; @@ -209,10 +209,10 @@ private void GenerateStateMachineForType( bool needsAsync; // Check if GenerateAsync was explicitly set to false and async members exist - var explicitlyDisabled = config.GenerateAsyncExplicitlySet && - config.GenerateAsync.HasValue && + var explicitlyDisabled = config.GenerateAsyncExplicitlySet && + config.GenerateAsync.HasValue && !config.GenerateAsync.Value; - + if (explicitlyDisabled && hasAsyncMembers && !config.ForceAsync) { // Async members are present but async generation was explicitly disabled. @@ -234,7 +234,7 @@ private void GenerateStateMachineForType( } // Generate the state machine implementation - var source = GenerateStateMachine(typeSymbol, config, stateType, triggerType, + var source = GenerateStateMachine(typeSymbol, config, stateType, triggerType, transitions, guards, entryHooks, exitHooks, needsAsync); var fileName = $"{typeSymbol.Name}.StateMachine.g.cs"; context.AddSource(fileName, source); @@ -820,25 +820,25 @@ private void GenerateCanFireMethod( foreach (var group in transitionGroups) { var (fromState, trigger) = group.Key; - + // Check if there's a guard for this transition var guard = guards.FirstOrDefault(g => g.FromState == fromState && g.Trigger == trigger); - + if (guard is not null) { var guardHasCt = guard.Method.Parameters.Length > 0 && IsCancellationToken(guard.Method.Parameters[0].Type); - + // If guard is async, evaluate it synchronously using GetAwaiter().GetResult() if (IsGenericValueTaskOfBool(guard.Method.ReturnType)) { - var guardCall = guardHasCt + var guardCall = guardHasCt ? $"{guard.Method.Name}(global::System.Threading.CancellationToken.None).GetAwaiter().GetResult()" : $"{guard.Method.Name}().GetAwaiter().GetResult()"; sb.AppendLine($" ({config.StateTypeName}.{fromState}, {config.TriggerTypeName}.{trigger}) => {guardCall},"); } else { - var guardCall = guardHasCt + var guardCall = guardHasCt ? $"{guard.Method.Name}(global::System.Threading.CancellationToken.None)" : $"{guard.Method.Name}()"; sb.AppendLine($" ({config.StateTypeName}.{fromState}, {config.TriggerTypeName}.{trigger}) => {guardCall},"); @@ -935,16 +935,16 @@ private void GenerateFireMethod( { var guardHasCt = guard.Method.Parameters.Length > 0 && IsCancellationToken(guard.Method.Parameters[0].Type); var guardCall = IsGenericValueTaskOfBool(guard.Method.ReturnType) - ? (isAsync + ? (isAsync ? (guardHasCt ? $"await {guard.Method.Name}(cancellationToken){configureAwait}" : $"await {guard.Method.Name}(){configureAwait}") : (guardHasCt ? $"{guard.Method.Name}(global::System.Threading.CancellationToken.None).GetAwaiter().GetResult()" : $"{guard.Method.Name}().GetAwaiter().GetResult()")) - : (guardHasCt + : (guardHasCt ? (isAsync ? $"{guard.Method.Name}(cancellationToken)" : $"{guard.Method.Name}(global::System.Threading.CancellationToken.None)") : $"{guard.Method.Name}()"); sb.AppendLine($" if (!{guardCall})"); sb.AppendLine($" {{"); - + if (config.GuardFailurePolicy == 0) // Throw { sb.AppendLine($" throw new global::System.InvalidOperationException($\"Guard failed for transition from {fromState} on trigger {trigger}.\");"); @@ -953,7 +953,7 @@ private void GenerateFireMethod( { sb.AppendLine($" return;"); } - + sb.AppendLine($" }}"); } @@ -963,7 +963,7 @@ private void GenerateFireMethod( { var hookHasCt = exitHook.Method.Parameters.Length > 0 && IsCancellationToken(exitHook.Method.Parameters[0].Type); var hookCall = IsNonGenericValueTask(exitHook.Method.ReturnType) - ? (isAsync + ? (isAsync ? (hookHasCt ? $"await {exitHook.Method.Name}(cancellationToken){configureAwait};" : $"await {exitHook.Method.Name}(){configureAwait};") : (hookHasCt ? $"{exitHook.Method.Name}(global::System.Threading.CancellationToken.None).GetAwaiter().GetResult();" : $"{exitHook.Method.Name}().GetAwaiter().GetResult();")) : (hookHasCt @@ -976,7 +976,7 @@ private void GenerateFireMethod( var transitionHasCt = transition.Method.Parameters.Length > 0 && IsCancellationToken(transition.Method.Parameters[0].Type); if (IsNonGenericValueTask(transition.Method.ReturnType)) { - var transitionCall = isAsync + var transitionCall = isAsync ? (transitionHasCt ? $"await {transition.Method.Name}(cancellationToken){configureAwait};" : $"await {transition.Method.Name}(){configureAwait};") : (transitionHasCt ? $"{transition.Method.Name}(global::System.Threading.CancellationToken.None).GetAwaiter().GetResult();" : $"{transition.Method.Name}().GetAwaiter().GetResult();"); sb.AppendLine($" {transitionCall}"); @@ -998,7 +998,7 @@ private void GenerateFireMethod( { var entryHasCt = entryHook.Method.Parameters.Length > 0 && IsCancellationToken(entryHook.Method.Parameters[0].Type); var hookCall = IsNonGenericValueTask(entryHook.Method.ReturnType) - ? (isAsync + ? (isAsync ? (entryHasCt ? $"await {entryHook.Method.Name}(cancellationToken){configureAwait};" : $"await {entryHook.Method.Name}(){configureAwait};") : (entryHasCt ? $"{entryHook.Method.Name}(global::System.Threading.CancellationToken.None).GetAwaiter().GetResult();" : $"{entryHook.Method.Name}().GetAwaiter().GetResult();")) : (entryHasCt diff --git a/src/PatternKit.Generators/StranglerFig/StranglerFigGenerator.cs b/src/PatternKit.Generators/StranglerFig/StranglerFigGenerator.cs index 43901f99..6c4839f6 100644 --- a/src/PatternKit.Generators/StranglerFig/StranglerFigGenerator.cs +++ b/src/PatternKit.Generators/StranglerFig/StranglerFigGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.StranglerFig; diff --git a/src/PatternKit.Generators/StrategyGenerator.cs b/src/PatternKit.Generators/StrategyGenerator.cs index a8ec8a85..3b7a29e8 100644 --- a/src/PatternKit.Generators/StrategyGenerator.cs +++ b/src/PatternKit.Generators/StrategyGenerator.cs @@ -296,4 +296,4 @@ private static void Report(SourceProductionContext spc, string id, string messag spc.ReportDiagnostic(Diagnostic.Create(descriptor, loc)); } -} \ No newline at end of file +} diff --git a/src/PatternKit.Generators/TableDataGateway/TableDataGatewayGenerator.cs b/src/PatternKit.Generators/TableDataGateway/TableDataGatewayGenerator.cs index 30629416..e77362d7 100644 --- a/src/PatternKit.Generators/TableDataGateway/TableDataGatewayGenerator.cs +++ b/src/PatternKit.Generators/TableDataGateway/TableDataGatewayGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.TableDataGateway; diff --git a/src/PatternKit.Generators/TemplateGenerator.cs b/src/PatternKit.Generators/TemplateGenerator.cs index 454379f1..1b82bb50 100644 --- a/src/PatternKit.Generators/TemplateGenerator.cs +++ b/src/PatternKit.Generators/TemplateGenerator.cs @@ -1,8 +1,8 @@ +using System.Collections.Immutable; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Collections.Immutable; -using System.Text; namespace PatternKit.Generators; diff --git a/src/PatternKit.Generators/TransactionScript/TransactionScriptGenerator.cs b/src/PatternKit.Generators/TransactionScript/TransactionScriptGenerator.cs index f39022a0..5f8f39b9 100644 --- a/src/PatternKit.Generators/TransactionScript/TransactionScriptGenerator.cs +++ b/src/PatternKit.Generators/TransactionScript/TransactionScriptGenerator.cs @@ -1,8 +1,8 @@ +using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; -using System.Linq; -using System.Text; namespace PatternKit.Generators.TransactionScript; diff --git a/src/PatternKit.Generators/UnitOfWork/UnitOfWorkGenerator.cs b/src/PatternKit.Generators/UnitOfWork/UnitOfWorkGenerator.cs index fc249482..d331e7ff 100644 --- a/src/PatternKit.Generators/UnitOfWork/UnitOfWorkGenerator.cs +++ b/src/PatternKit.Generators/UnitOfWork/UnitOfWorkGenerator.cs @@ -1,9 +1,9 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Text; using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace PatternKit.Generators.UnitOfWork; diff --git a/src/PatternKit.Generators/VisitorGenerator.cs b/src/PatternKit.Generators/VisitorGenerator.cs index 17f871da..efa21c20 100644 --- a/src/PatternKit.Generators/VisitorGenerator.cs +++ b/src/PatternKit.Generators/VisitorGenerator.cs @@ -1,8 +1,8 @@ +using System.Collections.Immutable; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using System.Collections.Immutable; -using System.Text; namespace PatternKit.Generators; diff --git a/test/PatternKit.Examples.Tests/AbstractFactoryDemo/AbstractFactoryDemoTests.cs b/test/PatternKit.Examples.Tests/AbstractFactoryDemo/AbstractFactoryDemoTests.cs index ef15d28b..31d01add 100644 --- a/test/PatternKit.Examples.Tests/AbstractFactoryDemo/AbstractFactoryDemoTests.cs +++ b/test/PatternKit.Examples.Tests/AbstractFactoryDemo/AbstractFactoryDemoTests.cs @@ -1,7 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using PatternKit.Examples.AbstractFactoryDemo; -using static PatternKit.Examples.AbstractFactoryDemo.AbstractFactoryDemo; using TinyBDD; +using static PatternKit.Examples.AbstractFactoryDemo.AbstractFactoryDemo; namespace PatternKit.Examples.Tests.AbstractFactoryDemoTests; diff --git a/test/PatternKit.Examples.Tests/ApiGateway/ApiGatewayTests.cs b/test/PatternKit.Examples.Tests/ApiGateway/ApiGatewayTests.cs index 078be7fd..fec4616b 100644 --- a/test/PatternKit.Examples.Tests/ApiGateway/ApiGatewayTests.cs +++ b/test/PatternKit.Examples.Tests/ApiGateway/ApiGatewayTests.cs @@ -165,4 +165,4 @@ await Given("a router with two matching middleware branches", Build) .And("the first middleware ran", _ => hits[0] == "A") .AssertPassed(); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Examples.Tests/BridgeDemo/BridgeDemoTests.cs b/test/PatternKit.Examples.Tests/BridgeDemo/BridgeDemoTests.cs index 96c74a50..c1fbdff5 100644 --- a/test/PatternKit.Examples.Tests/BridgeDemo/BridgeDemoTests.cs +++ b/test/PatternKit.Examples.Tests/BridgeDemo/BridgeDemoTests.cs @@ -1,6 +1,6 @@ using PatternKit.Examples.BridgeDemo; -using static PatternKit.Examples.BridgeDemo.BridgeDemo; using TinyBDD; +using static PatternKit.Examples.BridgeDemo.BridgeDemo; namespace PatternKit.Examples.Tests.BridgeDemoTests; diff --git a/test/PatternKit.Examples.Tests/BulkheadDemo/ShippingBulkheadDemoTests.cs b/test/PatternKit.Examples.Tests/BulkheadDemo/ShippingBulkheadDemoTests.cs index 538ecb2d..5fe60d21 100644 --- a/test/PatternKit.Examples.Tests/BulkheadDemo/ShippingBulkheadDemoTests.cs +++ b/test/PatternKit.Examples.Tests/BulkheadDemo/ShippingBulkheadDemoTests.cs @@ -14,10 +14,10 @@ public sealed class ShippingBulkheadDemoTests(ITestOutputHelper output) : TinyBd [Fact] public Task Fluent_And_Generated_Bulkhead_Policies_Reserve_Shipping_Allocations() => Given("shipping allocators imported by an application", static () => new - { - FluentAllocator = new ScriptedShippingAllocator(new ShippingAllocation("ORDER-100", "ground", true)), - GeneratedAllocator = new ScriptedShippingAllocator(new ShippingAllocation("ORDER-100", "ground", true)) - }) + { + FluentAllocator = new ScriptedShippingAllocator(new ShippingAllocation("ORDER-100", "ground", true)), + GeneratedAllocator = new ScriptedShippingAllocator(new ShippingAllocation("ORDER-100", "ground", true)) + }) .When("reserving through both policy paths", ctx => new { Fluent = new ShippingBulkheadService(ctx.FluentAllocator, ShippingBulkheadPolicies.CreateFluentPolicy()) diff --git a/test/PatternKit.Examples.Tests/CacheAsideDemo/ProductCatalogCacheAsideDemoTests.cs b/test/PatternKit.Examples.Tests/CacheAsideDemo/ProductCatalogCacheAsideDemoTests.cs index b257b437..bf8083d6 100644 --- a/test/PatternKit.Examples.Tests/CacheAsideDemo/ProductCatalogCacheAsideDemoTests.cs +++ b/test/PatternKit.Examples.Tests/CacheAsideDemo/ProductCatalogCacheAsideDemoTests.cs @@ -13,10 +13,10 @@ public sealed class ProductCatalogCacheAsideDemoTests(ITestOutputHelper output) [Fact] public Task Fluent_And_Generated_CacheAside_Policies_Reuse_Product_Catalog_Reads() => Given("product catalog repositories imported by an application", static () => new - { - FluentRepository = new ScriptedProductCatalogRepository(new ProductReadModel("SKU-42", "Trail Jacket", 129m, true)), - GeneratedRepository = new ScriptedProductCatalogRepository(new ProductReadModel("SKU-42", "Trail Jacket", 129m, true)) - }) + { + FluentRepository = new ScriptedProductCatalogRepository(new ProductReadModel("SKU-42", "Trail Jacket", 129m, true)), + GeneratedRepository = new ScriptedProductCatalogRepository(new ProductReadModel("SKU-42", "Trail Jacket", 129m, true)) + }) .When("looking up the same product twice through both policy paths", ctx => { var fluent = new ProductCatalogCacheAsideService(ctx.FluentRepository, ProductCatalogCacheAsidePolicies.CreateFluentPolicy()); diff --git a/test/PatternKit.Examples.Tests/Chain/AuthLoggingDemoTests.cs b/test/PatternKit.Examples.Tests/Chain/AuthLoggingDemoTests.cs index 70f076b5..1ca4dd2e 100644 --- a/test/PatternKit.Examples.Tests/Chain/AuthLoggingDemoTests.cs +++ b/test/PatternKit.Examples.Tests/Chain/AuthLoggingDemoTests.cs @@ -115,4 +115,4 @@ public Task RequestId_Then_Deny() .And("deny next", log => log.ElementAtOrDefault(1) == "deny: missing auth") .And("stops after deny (no method/path)", log => log.Count == 2 && !log.Any(s => s.StartsWith("GET "))) .AssertPassed(); -} \ No newline at end of file +} diff --git a/test/PatternKit.Examples.Tests/Chain/MediatedTransactionPipelineDemoTests.cs b/test/PatternKit.Examples.Tests/Chain/MediatedTransactionPipelineDemoTests.cs index 3c37db7b..e091edf9 100644 --- a/test/PatternKit.Examples.Tests/Chain/MediatedTransactionPipelineDemoTests.cs +++ b/test/PatternKit.Examples.Tests/Chain/MediatedTransactionPipelineDemoTests.cs @@ -323,4 +323,4 @@ await Given("a cash customer buying 2 age-restricted items with loyalty", Arrang .And("pipeline logs completion", r => r.Ctx.Log.Contains("done.")) .AssertPassed(); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Examples.Tests/Chain/NickelRoundingTests.cs b/test/PatternKit.Examples.Tests/Chain/NickelRoundingTests.cs index f183ab7e..1407d49b 100644 --- a/test/PatternKit.Examples.Tests/Chain/NickelRoundingTests.cs +++ b/test/PatternKit.Examples.Tests/Chain/NickelRoundingTests.cs @@ -91,4 +91,4 @@ await Given("a 22.97 subtotal basket with ROUND:NICKEL and cash-only tender", () .And("transaction succeeds", c => c.Result?.Ok == true) .AssertPassed(); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Examples.Tests/CircuitBreakerDemo/FulfillmentCircuitBreakerDemoTests.cs b/test/PatternKit.Examples.Tests/CircuitBreakerDemo/FulfillmentCircuitBreakerDemoTests.cs index ec820324..5ef6563e 100644 --- a/test/PatternKit.Examples.Tests/CircuitBreakerDemo/FulfillmentCircuitBreakerDemoTests.cs +++ b/test/PatternKit.Examples.Tests/CircuitBreakerDemo/FulfillmentCircuitBreakerDemoTests.cs @@ -14,16 +14,16 @@ public sealed class FulfillmentCircuitBreakerDemoTests(ITestOutputHelper output) [Fact] public Task Fluent_And_Generated_Circuit_Breaker_Policies_Isolate_Fulfillment_Outages() => Given("an unstable fulfillment gateway", static () => new - { - FluentGateway = new ScriptedFulfillmentGateway( + { + FluentGateway = new ScriptedFulfillmentGateway( new FulfillmentResponse("ORDER-42", 503, "down"), new FulfillmentResponse("ORDER-42", 503, "down"), new FulfillmentResponse("ORDER-42", 202, "accepted")), - GeneratedGateway = new ScriptedFulfillmentGateway( + GeneratedGateway = new ScriptedFulfillmentGateway( new FulfillmentResponse("ORDER-42", 503, "down"), new FulfillmentResponse("ORDER-42", 503, "down"), new FulfillmentResponse("ORDER-42", 202, "accepted")) - }) + }) .When("submitting orders through both policy paths", ctx => { var fluent = new FulfillmentCircuitBreakerService(ctx.FluentGateway, FulfillmentCircuitBreakerPolicies.CreateFluentPolicy()); diff --git a/test/PatternKit.Examples.Tests/CompositeDemo/CompositeDemoTests.cs b/test/PatternKit.Examples.Tests/CompositeDemo/CompositeDemoTests.cs index 77abaf5f..aca726ef 100644 --- a/test/PatternKit.Examples.Tests/CompositeDemo/CompositeDemoTests.cs +++ b/test/PatternKit.Examples.Tests/CompositeDemo/CompositeDemoTests.cs @@ -1,7 +1,7 @@ using PatternKit.Examples.CompositeDemo; +using TinyBDD; using static PatternKit.Examples.CompositeDemo.CompositeDemo; using FileInfo = PatternKit.Examples.CompositeDemo.CompositeDemo.FileInfo; -using TinyBDD; namespace PatternKit.Examples.Tests.CompositeDemoTests; diff --git a/test/PatternKit.Examples.Tests/DependencyInjection/PatternKitExampleDependencyInjectionTests.cs b/test/PatternKit.Examples.Tests/DependencyInjection/PatternKitExampleDependencyInjectionTests.cs index fe3e270a..2d115a03 100644 --- a/test/PatternKit.Examples.Tests/DependencyInjection/PatternKitExampleDependencyInjectionTests.cs +++ b/test/PatternKit.Examples.Tests/DependencyInjection/PatternKitExampleDependencyInjectionTests.cs @@ -22,11 +22,11 @@ using PatternKit.Examples.TableDataGatewayDemo; using PatternKit.Examples.TransactionScriptDemo; using PatternKit.Examples.UnitOfWorkDemo; -using Showcase = PatternKit.Examples.PatternShowcase.PatternShowcase; -using WidgetDemo = PatternKit.Examples.AbstractFactoryDemo.AbstractFactoryDemo; using TinyBDD; using TinyBDD.Xunit; using Xunit.Abstractions; +using Showcase = PatternKit.Examples.PatternShowcase.PatternShowcase; +using WidgetDemo = PatternKit.Examples.AbstractFactoryDemo.AbstractFactoryDemo; namespace PatternKit.Examples.Tests.DependencyInjection; diff --git a/test/PatternKit.Examples.Tests/EnterpriseDemo/EnterpriseOrderDemoTests.cs b/test/PatternKit.Examples.Tests/EnterpriseDemo/EnterpriseOrderDemoTests.cs index 14e7d6a4..8d8c91c5 100644 --- a/test/PatternKit.Examples.Tests/EnterpriseDemo/EnterpriseOrderDemoTests.cs +++ b/test/PatternKit.Examples.Tests/EnterpriseDemo/EnterpriseOrderDemoTests.cs @@ -1,6 +1,6 @@ using PatternKit.Examples.EnterpriseDemo; -using static PatternKit.Examples.EnterpriseDemo.EnterpriseOrderDemo; using TinyBDD; +using static PatternKit.Examples.EnterpriseDemo.EnterpriseOrderDemo; namespace PatternKit.Examples.Tests.EnterpriseDemoTests; diff --git a/test/PatternKit.Examples.Tests/FacadeDemo/FacadeDemoTests.cs b/test/PatternKit.Examples.Tests/FacadeDemo/FacadeDemoTests.cs index 1e1c2edd..a7c6a3ba 100644 --- a/test/PatternKit.Examples.Tests/FacadeDemo/FacadeDemoTests.cs +++ b/test/PatternKit.Examples.Tests/FacadeDemo/FacadeDemoTests.cs @@ -383,4 +383,4 @@ public void NotificationService_SendRefundNotice_DoesNotThrow() { NotificationService.SendRefundNotice("test@test.com", 50.00m); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Examples.Tests/Generators/CorporateApplicationBuilderDemoTests.cs b/test/PatternKit.Examples.Tests/Generators/CorporateApplicationBuilderDemoTests.cs index 7ce47250..c32b8707 100644 --- a/test/PatternKit.Examples.Tests/Generators/CorporateApplicationBuilderDemoTests.cs +++ b/test/PatternKit.Examples.Tests/Generators/CorporateApplicationBuilderDemoTests.cs @@ -75,10 +75,10 @@ await Given("the public production build recipe", () => (Func Given("default and configured notification options", () => new - { - Defaults = new NotificationOptions(), - Configured = new NotificationOptions { Enabled = false, Provider = "rabbitmq" } - }) + { + Defaults = new NotificationOptions(), + Configured = new NotificationOptions { Enabled = false, Provider = "rabbitmq" } + }) .When("reading options", options => ( DefaultEnabled: options.Defaults.Enabled, DefaultProvider: options.Defaults.Provider, diff --git a/test/PatternKit.Examples.Tests/Generators/VisitorGeneratorExamplesTests.cs b/test/PatternKit.Examples.Tests/Generators/VisitorGeneratorExamplesTests.cs index 3e45453b..7408fbc8 100644 --- a/test/PatternKit.Examples.Tests/Generators/VisitorGeneratorExamplesTests.cs +++ b/test/PatternKit.Examples.Tests/Generators/VisitorGeneratorExamplesTests.cs @@ -189,14 +189,14 @@ await Given("documents and async visitors", () => public async Task DocumentProcessingDemo_PrivateAsyncHelpers_CoverConcreteBranches() { await Given("documents that exercise every helper branch", () => new - { - Pdf = new PdfDocument { Id = "PDF-1", FileName = "secure.pdf", PageCount = 4, IsEncrypted = true }, - Word = new WordDocument { Id = "WORD-1", FileName = "macro.docx", WordCount = 12, HasMacros = true }, - SheetWithFormulas = new SpreadsheetDocument { Id = "SHEET-1", FileName = "calc.xlsx", SheetCount = 3, HasFormulas = true }, - SheetWithoutFormulas = new SpreadsheetDocument { Id = "SHEET-2", FileName = "plain.xlsx", SheetCount = 1, HasFormulas = false }, - MarkdownWithCode = new MarkdownDocument { Id = "MD-1", FileName = "code.md", LineCount = 10, HasCodeBlocks = true }, - MarkdownWithoutCode = new MarkdownDocument { Id = "MD-2", FileName = "plain.md", LineCount = 5, HasCodeBlocks = false } - }) + { + Pdf = new PdfDocument { Id = "PDF-1", FileName = "secure.pdf", PageCount = 4, IsEncrypted = true }, + Word = new WordDocument { Id = "WORD-1", FileName = "macro.docx", WordCount = 12, HasMacros = true }, + SheetWithFormulas = new SpreadsheetDocument { Id = "SHEET-1", FileName = "calc.xlsx", SheetCount = 3, HasFormulas = true }, + SheetWithoutFormulas = new SpreadsheetDocument { Id = "SHEET-2", FileName = "plain.xlsx", SheetCount = 1, HasFormulas = false }, + MarkdownWithCode = new MarkdownDocument { Id = "MD-1", FileName = "code.md", LineCount = 10, HasCodeBlocks = true }, + MarkdownWithoutCode = new MarkdownDocument { Id = "MD-2", FileName = "plain.md", LineCount = 5, HasCodeBlocks = false } + }) .When("invoking the indexing and scanning helpers", async Task<(string[] Keys, List Scans)> (docs) => { var keys = new[] diff --git a/test/PatternKit.Examples.Tests/IdentityMapDemo/OrderIdentityMapDemoTests.cs b/test/PatternKit.Examples.Tests/IdentityMapDemo/OrderIdentityMapDemoTests.cs index 213d9336..6ba70b1e 100644 --- a/test/PatternKit.Examples.Tests/IdentityMapDemo/OrderIdentityMapDemoTests.cs +++ b/test/PatternKit.Examples.Tests/IdentityMapDemo/OrderIdentityMapDemoTests.cs @@ -13,10 +13,10 @@ public sealed partial class OrderIdentityMapDemoTests(ITestOutputHelper output) [Fact] public Task Fluent_And_Generated_Identity_Maps_Reuse_Loaded_Orders() => Given("fluent and generated identity maps", () => new - { - Fluent = OrderIdentityMapDemo.RunFluent(), - Generated = OrderIdentityMapDemo.RunGenerated() - }) + { + Fluent = OrderIdentityMapDemo.RunFluent(), + Generated = OrderIdentityMapDemo.RunGenerated() + }) .Then("both paths reuse object identity and reject duplicates", runs => { ScenarioExpect.True(runs.Fluent.ReusedInstance); diff --git a/test/PatternKit.Examples.Tests/InterpreterDemo/InterpreterDemoTests.cs b/test/PatternKit.Examples.Tests/InterpreterDemo/InterpreterDemoTests.cs index b242b4d8..17f18a94 100644 --- a/test/PatternKit.Examples.Tests/InterpreterDemo/InterpreterDemoTests.cs +++ b/test/PatternKit.Examples.Tests/InterpreterDemo/InterpreterDemoTests.cs @@ -1,7 +1,7 @@ using PatternKit.Examples.InterpreterDemo; +using TinyBDD; using static PatternKit.Examples.InterpreterDemo.InterpreterDemo; using Expr = PatternKit.Behavioral.Interpreter.ExpressionExtensions; -using TinyBDD; namespace PatternKit.Examples.Tests.InterpreterDemoTests; diff --git a/test/PatternKit.Examples.Tests/IteratorDemo/IteratorDemoTests.cs b/test/PatternKit.Examples.Tests/IteratorDemo/IteratorDemoTests.cs index 5986d41a..1cb999f9 100644 --- a/test/PatternKit.Examples.Tests/IteratorDemo/IteratorDemoTests.cs +++ b/test/PatternKit.Examples.Tests/IteratorDemo/IteratorDemoTests.cs @@ -1,6 +1,6 @@ using PatternKit.Examples.IteratorDemo; -using static PatternKit.Examples.IteratorDemo.IteratorDemo; using TinyBDD; +using static PatternKit.Examples.IteratorDemo.IteratorDemo; namespace PatternKit.Examples.Tests.IteratorDemoTests; diff --git a/test/PatternKit.Examples.Tests/MaterializedViewDemo/OrderMaterializedViewDemoTests.cs b/test/PatternKit.Examples.Tests/MaterializedViewDemo/OrderMaterializedViewDemoTests.cs index 6f68f41a..d7618a22 100644 --- a/test/PatternKit.Examples.Tests/MaterializedViewDemo/OrderMaterializedViewDemoTests.cs +++ b/test/PatternKit.Examples.Tests/MaterializedViewDemo/OrderMaterializedViewDemoTests.cs @@ -1,5 +1,5 @@ -using PatternKit.Examples.MaterializedViewDemo; using Microsoft.Extensions.DependencyInjection; +using PatternKit.Examples.MaterializedViewDemo; using TinyBDD; using TinyBDD.Xunit; using Xunit.Abstractions; diff --git a/test/PatternKit.Examples.Tests/MediatorDemo/MediatorDemoTests.cs b/test/PatternKit.Examples.Tests/MediatorDemo/MediatorDemoTests.cs index 026f3d4c..6487d87e 100644 --- a/test/PatternKit.Examples.Tests/MediatorDemo/MediatorDemoTests.cs +++ b/test/PatternKit.Examples.Tests/MediatorDemo/MediatorDemoTests.cs @@ -297,4 +297,4 @@ public Task MultipleBehaviors_Compose_In_Order() .Then("log shows correct order", log => string.Join("|", log) == "pre|whole1:before|whole2:before|whole2:after|whole1:after|post") .AssertPassed(); -} \ No newline at end of file +} diff --git a/test/PatternKit.Examples.Tests/MementoDemo/MementoDemoTests.cs b/test/PatternKit.Examples.Tests/MementoDemo/MementoDemoTests.cs index a8bec42a..f3ef6fb3 100644 --- a/test/PatternKit.Examples.Tests/MementoDemo/MementoDemoTests.cs +++ b/test/PatternKit.Examples.Tests/MementoDemo/MementoDemoTests.cs @@ -1,8 +1,8 @@ using TinyBDD; using TinyBDD.Xunit; using Xunit.Abstractions; -using Editor = PatternKit.Examples.MementoDemo.MementoDemo.TextEditor; using Demo = PatternKit.Examples.MementoDemo.MementoDemo; +using Editor = PatternKit.Examples.MementoDemo.MementoDemo.TextEditor; namespace PatternKit.Examples.Tests.MementoDemo; diff --git a/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitBenchmarkCoverageTests.cs b/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitBenchmarkCoverageTests.cs index aec83d1b..3c37d868 100644 --- a/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitBenchmarkCoverageTests.cs +++ b/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitBenchmarkCoverageTests.cs @@ -47,10 +47,10 @@ public Task Every_Catalog_Pattern_Has_Fluent_And_Generated_Benchmark_Routes() [Fact] public Task Every_Generator_Source_Is_Represented_In_The_Benchmark_Matrix() => Given("the repository root and generator benchmark routes", () => new - { - RepositoryRoot = FindRepoRoot(), - BenchmarkRoutes = GeneratorBenchmarkCoverage.Routes - }) + { + RepositoryRoot = FindRepoRoot(), + BenchmarkRoutes = GeneratorBenchmarkCoverage.Routes + }) .When("reading generator source files", ctx => new { SourceFiles = Directory @@ -72,10 +72,10 @@ public Task Every_Generator_Source_Is_Represented_In_The_Benchmark_Matrix() [Fact] public Task Published_Benchmark_Results_Include_Every_Catalog_Pattern() => Given("the benchmark results guide and production pattern catalog", () => new - { - ResultsGuide = File.ReadAllText(Path.Combine(FindRepoRoot(), "docs", "guides", "benchmark-results.md")), - Catalog = new PatternKitPatternCatalog() - }) + { + ResultsGuide = File.ReadAllText(Path.Combine(FindRepoRoot(), "docs", "guides", "benchmark-results.md")), + Catalog = new PatternKitPatternCatalog() + }) .When("checking catalog names against the published results", ctx => new { ctx.ResultsGuide, @@ -95,10 +95,10 @@ public Task Published_Benchmark_Results_Include_Every_Catalog_Pattern() [Fact] public Task Published_Benchmark_Results_Include_Every_Generator_Source() => Given("the benchmark results guide and generator benchmark routes", () => new - { - ResultsGuide = File.ReadAllText(Path.Combine(FindRepoRoot(), "docs", "guides", "benchmark-results.md")), - BenchmarkRoutes = GeneratorBenchmarkCoverage.Routes - }) + { + ResultsGuide = File.ReadAllText(Path.Combine(FindRepoRoot(), "docs", "guides", "benchmark-results.md")), + BenchmarkRoutes = GeneratorBenchmarkCoverage.Routes + }) .When("checking generator names against the published results", ctx => new { ctx.ResultsGuide, diff --git a/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitExampleCatalogTests.cs b/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitExampleCatalogTests.cs index 90b73e5c..2a94292c 100644 --- a/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitExampleCatalogTests.cs +++ b/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitExampleCatalogTests.cs @@ -16,10 +16,10 @@ public sealed class PatternKitExampleCatalogTests(ITestOutputHelper output) : Ti [Fact] public Task Catalog_Entries_Map_Documented_Examples_To_Source_Tests_And_Production_Checks() => Given("an examples catalog and the repository root", () => new - { - Catalog = new PatternKitExampleCatalog(), - RepositoryRoot = FindRepoRoot() - }) + { + Catalog = new PatternKitExampleCatalog(), + RepositoryRoot = FindRepoRoot() + }) .When("validating the catalog against repository files", ctx => new { ctx.Catalog.Entries, diff --git a/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitPatternCatalogTests.cs b/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitPatternCatalogTests.cs index 253312fa..7ca3c339 100644 --- a/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitPatternCatalogTests.cs +++ b/test/PatternKit.Examples.Tests/ProductionReadiness/PatternKitPatternCatalogTests.cs @@ -166,10 +166,10 @@ public Task Catalog_Includes_Enterprise_Integration_And_Architecture_Patterns() [Fact] public Task Each_Pattern_Has_Fluent_Generated_Documented_And_Example_Paths() => Given("the PatternKit pattern catalog and repository root", () => new - { - Catalog = new PatternKitPatternCatalog(), - RepositoryRoot = FindRepoRoot() - }) + { + Catalog = new PatternKitPatternCatalog(), + RepositoryRoot = FindRepoRoot() + }) .When("validating implementation paths", ctx => ctx.Catalog.Patterns .SelectMany(pattern => ValidatePattern(ctx.RepositoryRoot, pattern)) .ToArray()) diff --git a/test/PatternKit.Examples.Tests/Properties/AssemblyCoverage.cs b/test/PatternKit.Examples.Tests/Properties/AssemblyCoverage.cs index 598a1a76..29178265 100644 --- a/test/PatternKit.Examples.Tests/Properties/AssemblyCoverage.cs +++ b/test/PatternKit.Examples.Tests/Properties/AssemblyCoverage.cs @@ -1,4 +1,4 @@ #if NETSTANDARD2_1 // Exclude the entire assembly from coverage when built for netstandard2.1 [assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] -#endif \ No newline at end of file +#endif diff --git a/test/PatternKit.Examples.Tests/PrototypeDemo/PrototypeDemoTests.cs b/test/PatternKit.Examples.Tests/PrototypeDemo/PrototypeDemoTests.cs index f5522223..625ee986 100644 --- a/test/PatternKit.Examples.Tests/PrototypeDemo/PrototypeDemoTests.cs +++ b/test/PatternKit.Examples.Tests/PrototypeDemo/PrototypeDemoTests.cs @@ -1,6 +1,6 @@ using PatternKit.Examples.PrototypeDemo; -using static PatternKit.Examples.PrototypeDemo.PrototypeDemo; using TinyBDD; +using static PatternKit.Examples.PrototypeDemo.PrototypeDemo; namespace PatternKit.Examples.Tests.PrototypeDemoTests; diff --git a/test/PatternKit.Examples.Tests/ProxyDemo/ConsoleOutputCollection.cs b/test/PatternKit.Examples.Tests/ProxyDemo/ConsoleOutputCollection.cs index 281f54ea..ef0a6e9d 100644 --- a/test/PatternKit.Examples.Tests/ProxyDemo/ConsoleOutputCollection.cs +++ b/test/PatternKit.Examples.Tests/ProxyDemo/ConsoleOutputCollection.cs @@ -1,6 +1,6 @@ -namespace PatternKit.Examples.Tests.ProxyDemo; - -// Collection to ensure tests that redirect Console output do not run in parallel. -[CollectionDefinition("ConsoleOutput", DisableParallelization = true)] -public sealed class ConsoleOutputCollection { } - +namespace PatternKit.Examples.Tests.ProxyDemo; + +// Collection to ensure tests that redirect Console output do not run in parallel. +[CollectionDefinition("ConsoleOutput", DisableParallelization = true)] +public sealed class ConsoleOutputCollection { } + diff --git a/test/PatternKit.Examples.Tests/ProxyDemo/ProxyDemoParameterlessTests.cs b/test/PatternKit.Examples.Tests/ProxyDemo/ProxyDemoParameterlessTests.cs index 6283f629..afb78b95 100644 --- a/test/PatternKit.Examples.Tests/ProxyDemo/ProxyDemoParameterlessTests.cs +++ b/test/PatternKit.Examples.Tests/ProxyDemo/ProxyDemoParameterlessTests.cs @@ -1,114 +1,114 @@ -using TinyBDD; -using TinyBDD.Xunit; -using Xunit.Abstractions; - -namespace PatternKit.Examples.Tests.ProxyDemo; - -[Feature("Examples - Proxy Pattern Demonstrations (Parameterless Methods)")] -[Collection("ConsoleOutput")] // prevent parallel Console.Out redirection conflicts -public sealed class ProxyDemoParameterlessTests(ITestOutputHelper output) : TinyBddXunitBase(output) -{ - private (bool success, string output) CaptureConsole(Action action) - { - var original = Console.Out; - using var sw = new StringWriter(); - try - { - Console.SetOut(sw); - action(); - Console.Out.Flush(); - return (true, sw.ToString()); - } - catch - { - return (false, sw.ToString()); - } - finally - { - Console.SetOut(original); - } - } - - [Scenario("Parameterless DemonstrateVirtualProxy executes and writes header")] - [Fact] - public Task DemonstrateVirtualProxy_NoWriter_Executes() - => Given("parameterless virtual proxy demo", () => true) - .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateVirtualProxy())) - .Then("executes successfully", r => r.success) - .And("writes virtual proxy header", r => r.output.Contains("Virtual Proxy - Lazy Initialization")) - .AssertPassed(); - - [Scenario("Parameterless DemonstrateProtectionProxy executes and writes header")] - [Fact] - public Task DemonstrateProtectionProxy_NoWriter_Executes() - => Given("parameterless protection proxy demo", () => true) - .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateProtectionProxy())) - .Then("executes successfully", r => r.success) - .And("writes protection proxy header", r => r.output.Contains("Protection Proxy - Access Control")) - .AssertPassed(); - - [Scenario("Parameterless DemonstrateCachingProxy executes and writes header")] - [Fact] - public Task DemonstrateCachingProxy_NoWriter_Executes() - => Given("parameterless caching proxy demo", () => true) - .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateCachingProxy())) - .Then("executes successfully", r => r.success) - .And("writes caching proxy header", r => r.output.Contains("Caching Proxy - Result Memoization")) - .AssertPassed(); - - [Scenario("Parameterless DemonstrateLoggingProxy executes and writes header")] - [Fact] - public Task DemonstrateLoggingProxy_NoWriter_Executes() - => Given("parameterless logging proxy demo", () => true) - .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateLoggingProxy())) - .Then("executes successfully", r => r.success) - .And("writes logging proxy header", r => r.output.Contains("Logging Proxy - Invocation Tracking")) - .AssertPassed(); - - [Scenario("Parameterless DemonstrateCustomInterception executes and writes header")] - [Fact] - public Task DemonstrateCustomInterception_NoWriter_Executes() - => Given("parameterless custom interception demo", () => true) - .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateCustomInterception())) - .Then("executes successfully", r => r.success) - .And("writes custom interception header", r => r.output.Contains("Custom Interception - Retry Logic")) - .AssertPassed(); - - [Scenario("Parameterless DemonstrateMockFramework executes and writes header")] - [Fact] - public Task DemonstrateMockFramework_NoWriter_Executes() - => Given("parameterless mock framework demo", () => true) - .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateMockFramework())) - .Then("executes successfully", r => r.success) - .And("writes mock framework header", r => r.output.Contains("Mock Framework - Test Doubles")) - .AssertPassed(); - - [Scenario("Parameterless DemonstrateRemoteProxy executes and writes header")] - [Fact] - public Task DemonstrateRemoteProxy_NoWriter_Executes() - => Given("parameterless remote proxy demo", () => true) - .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateRemoteProxy())) - .Then("executes successfully", r => r.success) - .And("writes remote proxy header", r => r.output.Contains("Remote Proxy - Network Call Optimization")) - .AssertPassed(); - - [Scenario("Parameterless RunAllDemos executes all demos and writes all headers")] - [Fact] - public Task RunAllDemos_NoWriter_Executes_All() - => Given("parameterless run all demos", () => true) - .When("executing all demos", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.RunAllDemos())) - .Then("executes successfully", r => r.success) - .And("includes all demo headers", r => - new[] - { - "Virtual Proxy - Lazy Initialization", - "Protection Proxy - Access Control", - "Caching Proxy - Result Memoization", - "Logging Proxy - Invocation Tracking", - "Custom Interception - Retry Logic", - "Mock Framework - Test Doubles", - "Remote Proxy - Network Call Optimization" - }.All(h => r.output.Contains(h))) - .AssertPassed(); -} - +using TinyBDD; +using TinyBDD.Xunit; +using Xunit.Abstractions; + +namespace PatternKit.Examples.Tests.ProxyDemo; + +[Feature("Examples - Proxy Pattern Demonstrations (Parameterless Methods)")] +[Collection("ConsoleOutput")] // prevent parallel Console.Out redirection conflicts +public sealed class ProxyDemoParameterlessTests(ITestOutputHelper output) : TinyBddXunitBase(output) +{ + private (bool success, string output) CaptureConsole(Action action) + { + var original = Console.Out; + using var sw = new StringWriter(); + try + { + Console.SetOut(sw); + action(); + Console.Out.Flush(); + return (true, sw.ToString()); + } + catch + { + return (false, sw.ToString()); + } + finally + { + Console.SetOut(original); + } + } + + [Scenario("Parameterless DemonstrateVirtualProxy executes and writes header")] + [Fact] + public Task DemonstrateVirtualProxy_NoWriter_Executes() + => Given("parameterless virtual proxy demo", () => true) + .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateVirtualProxy())) + .Then("executes successfully", r => r.success) + .And("writes virtual proxy header", r => r.output.Contains("Virtual Proxy - Lazy Initialization")) + .AssertPassed(); + + [Scenario("Parameterless DemonstrateProtectionProxy executes and writes header")] + [Fact] + public Task DemonstrateProtectionProxy_NoWriter_Executes() + => Given("parameterless protection proxy demo", () => true) + .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateProtectionProxy())) + .Then("executes successfully", r => r.success) + .And("writes protection proxy header", r => r.output.Contains("Protection Proxy - Access Control")) + .AssertPassed(); + + [Scenario("Parameterless DemonstrateCachingProxy executes and writes header")] + [Fact] + public Task DemonstrateCachingProxy_NoWriter_Executes() + => Given("parameterless caching proxy demo", () => true) + .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateCachingProxy())) + .Then("executes successfully", r => r.success) + .And("writes caching proxy header", r => r.output.Contains("Caching Proxy - Result Memoization")) + .AssertPassed(); + + [Scenario("Parameterless DemonstrateLoggingProxy executes and writes header")] + [Fact] + public Task DemonstrateLoggingProxy_NoWriter_Executes() + => Given("parameterless logging proxy demo", () => true) + .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateLoggingProxy())) + .Then("executes successfully", r => r.success) + .And("writes logging proxy header", r => r.output.Contains("Logging Proxy - Invocation Tracking")) + .AssertPassed(); + + [Scenario("Parameterless DemonstrateCustomInterception executes and writes header")] + [Fact] + public Task DemonstrateCustomInterception_NoWriter_Executes() + => Given("parameterless custom interception demo", () => true) + .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateCustomInterception())) + .Then("executes successfully", r => r.success) + .And("writes custom interception header", r => r.output.Contains("Custom Interception - Retry Logic")) + .AssertPassed(); + + [Scenario("Parameterless DemonstrateMockFramework executes and writes header")] + [Fact] + public Task DemonstrateMockFramework_NoWriter_Executes() + => Given("parameterless mock framework demo", () => true) + .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateMockFramework())) + .Then("executes successfully", r => r.success) + .And("writes mock framework header", r => r.output.Contains("Mock Framework - Test Doubles")) + .AssertPassed(); + + [Scenario("Parameterless DemonstrateRemoteProxy executes and writes header")] + [Fact] + public Task DemonstrateRemoteProxy_NoWriter_Executes() + => Given("parameterless remote proxy demo", () => true) + .When("executing demo", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.DemonstrateRemoteProxy())) + .Then("executes successfully", r => r.success) + .And("writes remote proxy header", r => r.output.Contains("Remote Proxy - Network Call Optimization")) + .AssertPassed(); + + [Scenario("Parameterless RunAllDemos executes all demos and writes all headers")] + [Fact] + public Task RunAllDemos_NoWriter_Executes_All() + => Given("parameterless run all demos", () => true) + .When("executing all demos", _ => CaptureConsole(() => PatternKit.Examples.ProxyDemo.ProxyDemo.RunAllDemos())) + .Then("executes successfully", r => r.success) + .And("includes all demo headers", r => + new[] + { + "Virtual Proxy - Lazy Initialization", + "Protection Proxy - Access Control", + "Caching Proxy - Result Memoization", + "Logging Proxy - Invocation Tracking", + "Custom Interception - Retry Logic", + "Mock Framework - Test Doubles", + "Remote Proxy - Network Call Optimization" + }.All(h => r.output.Contains(h))) + .AssertPassed(); +} + diff --git a/test/PatternKit.Examples.Tests/ProxyGeneratorDemo/ProxyGeneratorDemoTests.cs b/test/PatternKit.Examples.Tests/ProxyGeneratorDemo/ProxyGeneratorDemoTests.cs index 59588bc4..299a6523 100644 --- a/test/PatternKit.Examples.Tests/ProxyGeneratorDemo/ProxyGeneratorDemoTests.cs +++ b/test/PatternKit.Examples.Tests/ProxyGeneratorDemo/ProxyGeneratorDemoTests.cs @@ -243,12 +243,12 @@ await Given("throwing sync and async payment proxies", () => public async Task ProxyInterceptors_CoverAsyncNoOpAndNonRetriableBranches() { await Given("standalone interceptors and method contexts", () => new - { - Retry = new RetryInterceptor(maxRetries: 1), - Cache = new CachingInterceptor(), - Auth = new AuthenticationInterceptor(), - Context = new GetTransactionHistoryMethodContext("cust-standalone"), - MissingToken = new ProcessPaymentAsyncMethodContext( + { + Retry = new RetryInterceptor(maxRetries: 1), + Cache = new CachingInterceptor(), + Auth = new AuthenticationInterceptor(), + Context = new GetTransactionHistoryMethodContext("cust-standalone"), + MissingToken = new ProcessPaymentAsyncMethodContext( new PaymentRequest { CustomerId = "cust-standalone", @@ -258,7 +258,7 @@ public async Task ProxyInterceptors_CoverAsyncNoOpAndNonRetriableBranches() AuthToken = null }, CancellationToken.None) - }) + }) .When("invoking direct async interceptor paths", async Task (harness) => { await harness.Retry.BeforeAsync(harness.Context); diff --git a/test/PatternKit.Examples.Tests/RetryDemo/InventoryRetryDemoTests.cs b/test/PatternKit.Examples.Tests/RetryDemo/InventoryRetryDemoTests.cs index 91c0b3d6..39080c80 100644 --- a/test/PatternKit.Examples.Tests/RetryDemo/InventoryRetryDemoTests.cs +++ b/test/PatternKit.Examples.Tests/RetryDemo/InventoryRetryDemoTests.cs @@ -13,14 +13,14 @@ public sealed class InventoryRetryDemoTests(ITestOutputHelper output) : TinyBddX [Fact] public Task Fluent_And_Generated_Retry_Policies_Recover_Inventory_Lookups() => Given("a transient inventory outage", static () => new - { - FluentClient = new ScriptedInventoryClient( + { + FluentClient = new ScriptedInventoryClient( new InventoryResponse("SKU-42", 0, 503), new InventoryResponse("SKU-42", 8, 200)), - GeneratedClient = new ScriptedInventoryClient( + GeneratedClient = new ScriptedInventoryClient( new InventoryResponse("SKU-42", 0, 503), new InventoryResponse("SKU-42", 8, 200)) - }) + }) .When("checking availability through both policy paths", ctx => new { Fluent = new InventoryLookupService(ctx.FluentClient, InventoryRetryPolicies.CreateFluentPolicy()) diff --git a/test/PatternKit.Examples.Tests/Strategies/Composed/ComposedStrategiesTests.Extended.cs b/test/PatternKit.Examples.Tests/Strategies/Composed/ComposedStrategiesTests.Extended.cs index 9e9aa199..7c8f7d88 100644 --- a/test/PatternKit.Examples.Tests/Strategies/Composed/ComposedStrategiesTests.Extended.cs +++ b/test/PatternKit.Examples.Tests/Strategies/Composed/ComposedStrategiesTests.Extended.cs @@ -247,4 +247,4 @@ public async Task Preference_Order_Ties_BreakByOrder_NotCapability() .And("others not called", x => x.t.push.Calls == 0 && x.t.email.Calls == 0 && x.t.im.Calls == 0) .AssertPassed(); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Examples.Tests/Strategies/Composed/ComposedStrategiesTests.cs b/test/PatternKit.Examples.Tests/Strategies/Composed/ComposedStrategiesTests.cs index 9618f646..455e0f09 100644 --- a/test/PatternKit.Examples.Tests/Strategies/Composed/ComposedStrategiesTests.cs +++ b/test/PatternKit.Examples.Tests/Strategies/Composed/ComposedStrategiesTests.cs @@ -408,4 +408,4 @@ public async Task DefaultEmailFallback_IgnoresEmailGate_ByDesign() .And("email called once", x => x.H.Email.Calls == 1) .AssertPassed(); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Generators.Tests/AbstractionsAttributeCoverageTests.cs b/test/PatternKit.Generators.Tests/AbstractionsAttributeCoverageTests.cs index bd0d0ad3..a95f791a 100644 --- a/test/PatternKit.Generators.Tests/AbstractionsAttributeCoverageTests.cs +++ b/test/PatternKit.Generators.Tests/AbstractionsAttributeCoverageTests.cs @@ -1,4 +1,10 @@ +using PatternKit.Generators; +using PatternKit.Generators.ActivityTracking; using PatternKit.Generators.Adapter; +using PatternKit.Generators.Ambassador; +using PatternKit.Generators.AntiCorruption; +using PatternKit.Generators.AuditLog; +using PatternKit.Generators.BackendsForFrontends; using PatternKit.Generators.Bridge; using PatternKit.Generators.Bulkhead; using PatternKit.Generators.CacheAside; @@ -7,8 +13,8 @@ using PatternKit.Generators.CircuitBreaker; using PatternKit.Generators.Cloud; using PatternKit.Generators.Command; -using PatternKit.Generators.Composite; using PatternKit.Generators.Composer; +using PatternKit.Generators.Composite; using PatternKit.Generators.DataMapping; using PatternKit.Generators.Decorator; using PatternKit.Generators.DomainEvents; @@ -16,22 +22,22 @@ using PatternKit.Generators.EventNotification; using PatternKit.Generators.EventSourcing; using PatternKit.Generators.Facade; +using PatternKit.Generators.Factories; using PatternKit.Generators.FeatureToggles; using PatternKit.Generators.Flyweight; -using PatternKit.Generators.Factories; using PatternKit.Generators.GatewayAggregation; using PatternKit.Generators.GatewayRouting; +using PatternKit.Generators.HealthEndpointMonitoring; using PatternKit.Generators.IdentityMap; using PatternKit.Generators.Interpreter; using PatternKit.Generators.Iterator; -using PatternKit.Generators.HealthEndpointMonitoring; using PatternKit.Generators.LeaderElection; using PatternKit.Generators.MaterializedViews; using PatternKit.Generators.Messaging; using PatternKit.Generators.Observer; +using PatternKit.Generators.PriorityQueue; using PatternKit.Generators.Prototype; using PatternKit.Generators.Proxy; -using PatternKit.Generators.PriorityQueue; using PatternKit.Generators.QueueLoadLeveling; using PatternKit.Generators.RateLimiting; using PatternKit.Generators.Repository; @@ -48,12 +54,6 @@ using PatternKit.Generators.TransactionScript; using PatternKit.Generators.UnitOfWork; using PatternKit.Generators.Visitors; -using PatternKit.Generators; -using PatternKit.Generators.AntiCorruption; -using PatternKit.Generators.ActivityTracking; -using PatternKit.Generators.AuditLog; -using PatternKit.Generators.Ambassador; -using PatternKit.Generators.BackendsForFrontends; using TinyBDD; namespace PatternKit.Generators.Tests; diff --git a/test/PatternKit.Generators.Tests/CompetingConsumerGroupGeneratorTests.cs b/test/PatternKit.Generators.Tests/CompetingConsumerGroupGeneratorTests.cs index 28106918..ff644b29 100644 --- a/test/PatternKit.Generators.Tests/CompetingConsumerGroupGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/CompetingConsumerGroupGeneratorTests.cs @@ -1,79 +1,79 @@ -using Microsoft.CodeAnalysis; -using PatternKit.Generators.Messaging; -using PatternKit.Messaging.CompetingConsumers; -using TinyBDD; -using TinyBDD.Xunit; -using Xunit.Abstractions; - -namespace PatternKit.Generators.Tests; - -[Feature("Competing Consumers generator")] -public sealed partial class CompetingConsumerGroupGeneratorTests(ITestOutputHelper output) : TinyBddXunitBase(output) -{ - [Scenario("Generates competing consumer group builder factory")] - [Fact] - public Task Generates_Competing_Consumer_Group_Builder_Factory() - => Given("a competing consumer group declaration", () => Compile(""" - using PatternKit.Generators.Messaging; - namespace Demo; - public sealed record FulfillmentWork(string OrderId); - public sealed record FulfillmentResult(string OrderId, string Consumer); - [GenerateCompetingConsumerGroup(typeof(FulfillmentWork), typeof(FulfillmentResult), FactoryMethodName = "Build", GroupName = "fulfillment-consumers", MaxConcurrentDeliveries = 4)] - public static partial class FulfillmentConsumers; - """)) - .Then("the generated source creates the configured builder", result => - { - ScenarioExpect.Empty(result.Diagnostics); - var source = ScenarioExpect.Single(result.GeneratedSources); - ScenarioExpect.Contains("Build()", source); - ScenarioExpect.Contains("CompetingConsumerGroup.Create(\"fulfillment-consumers\")", source); - ScenarioExpect.Contains(".WithMaxConcurrentDeliveries(4)", source); - ScenarioExpect.True(result.EmitSuccess, string.Join(Environment.NewLine, result.EmitDiagnostics)); - }) - .AssertPassed(); - - [Scenario("Reports diagnostics for invalid competing consumer declarations")] - [Fact] - public Task Reports_Diagnostics_For_Invalid_Competing_Consumer_Declarations() - => Given("invalid competing consumer declarations", () => new[] - { - Compile(""" - using PatternKit.Generators.Messaging; - [GenerateCompetingConsumerGroup(typeof(string), typeof(int))] - public static class ConsumerHost; - """), - Compile(""" - using PatternKit.Generators.Messaging; - [GenerateCompetingConsumerGroup(typeof(string), typeof(int), MaxConcurrentDeliveries = 0)] - public static partial class ConsumerHost; - """) - }) - .Then("diagnostics identify the invalid declarations", results => - { - ScenarioExpect.Contains(results[0].Diagnostics, diagnostic => diagnostic.Id == "PKCNS001"); - ScenarioExpect.Contains(results[1].Diagnostics, diagnostic => diagnostic.Id == "PKCNS002"); - }) - .AssertPassed(); - - private static GeneratorResult Compile(string source) - { - var compilation = RoslynTestHelpers.CreateCompilation( - source, - "CompetingConsumerGroupGeneratorTests", - extra: MetadataReference.CreateFromFile(typeof(CompetingConsumerGroup<,>).Assembly.Location)); - _ = RoslynTestHelpers.Run(compilation, new CompetingConsumerGroupGenerator(), out var run, out var updated); - var result = run.Results.Single(); - var emit = updated.Emit(Stream.Null); - return new GeneratorResult( - result.Diagnostics.ToArray(), - result.GeneratedSources.Select(static source => source.SourceText.ToString()).ToArray(), - emit.Success, - emit.Diagnostics.Select(static diagnostic => diagnostic.ToString()).ToArray()); - } - - private sealed record GeneratorResult( - IReadOnlyList Diagnostics, - IReadOnlyList GeneratedSources, - bool EmitSuccess, - IReadOnlyList EmitDiagnostics); -} +using Microsoft.CodeAnalysis; +using PatternKit.Generators.Messaging; +using PatternKit.Messaging.CompetingConsumers; +using TinyBDD; +using TinyBDD.Xunit; +using Xunit.Abstractions; + +namespace PatternKit.Generators.Tests; + +[Feature("Competing Consumers generator")] +public sealed partial class CompetingConsumerGroupGeneratorTests(ITestOutputHelper output) : TinyBddXunitBase(output) +{ + [Scenario("Generates competing consumer group builder factory")] + [Fact] + public Task Generates_Competing_Consumer_Group_Builder_Factory() + => Given("a competing consumer group declaration", () => Compile(""" + using PatternKit.Generators.Messaging; + namespace Demo; + public sealed record FulfillmentWork(string OrderId); + public sealed record FulfillmentResult(string OrderId, string Consumer); + [GenerateCompetingConsumerGroup(typeof(FulfillmentWork), typeof(FulfillmentResult), FactoryMethodName = "Build", GroupName = "fulfillment-consumers", MaxConcurrentDeliveries = 4)] + public static partial class FulfillmentConsumers; + """)) + .Then("the generated source creates the configured builder", result => + { + ScenarioExpect.Empty(result.Diagnostics); + var source = ScenarioExpect.Single(result.GeneratedSources); + ScenarioExpect.Contains("Build()", source); + ScenarioExpect.Contains("CompetingConsumerGroup.Create(\"fulfillment-consumers\")", source); + ScenarioExpect.Contains(".WithMaxConcurrentDeliveries(4)", source); + ScenarioExpect.True(result.EmitSuccess, string.Join(Environment.NewLine, result.EmitDiagnostics)); + }) + .AssertPassed(); + + [Scenario("Reports diagnostics for invalid competing consumer declarations")] + [Fact] + public Task Reports_Diagnostics_For_Invalid_Competing_Consumer_Declarations() + => Given("invalid competing consumer declarations", () => new[] + { + Compile(""" + using PatternKit.Generators.Messaging; + [GenerateCompetingConsumerGroup(typeof(string), typeof(int))] + public static class ConsumerHost; + """), + Compile(""" + using PatternKit.Generators.Messaging; + [GenerateCompetingConsumerGroup(typeof(string), typeof(int), MaxConcurrentDeliveries = 0)] + public static partial class ConsumerHost; + """) + }) + .Then("diagnostics identify the invalid declarations", results => + { + ScenarioExpect.Contains(results[0].Diagnostics, diagnostic => diagnostic.Id == "PKCNS001"); + ScenarioExpect.Contains(results[1].Diagnostics, diagnostic => diagnostic.Id == "PKCNS002"); + }) + .AssertPassed(); + + private static GeneratorResult Compile(string source) + { + var compilation = RoslynTestHelpers.CreateCompilation( + source, + "CompetingConsumerGroupGeneratorTests", + extra: MetadataReference.CreateFromFile(typeof(CompetingConsumerGroup<,>).Assembly.Location)); + _ = RoslynTestHelpers.Run(compilation, new CompetingConsumerGroupGenerator(), out var run, out var updated); + var result = run.Results.Single(); + var emit = updated.Emit(Stream.Null); + return new GeneratorResult( + result.Diagnostics.ToArray(), + result.GeneratedSources.Select(static source => source.SourceText.ToString()).ToArray(), + emit.Success, + emit.Diagnostics.Select(static diagnostic => diagnostic.ToString()).ToArray()); + } + + private sealed record GeneratorResult( + IReadOnlyList Diagnostics, + IReadOnlyList GeneratedSources, + bool EmitSuccess, + IReadOnlyList EmitDiagnostics); +} diff --git a/test/PatternKit.Generators.Tests/InterpreterGeneratorTests.cs b/test/PatternKit.Generators.Tests/InterpreterGeneratorTests.cs index f317be5d..64e55000 100644 --- a/test/PatternKit.Generators.Tests/InterpreterGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/InterpreterGeneratorTests.cs @@ -1,4 +1,4 @@ -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using PatternKit.Generators.Interpreter; using TinyBDD; diff --git a/test/PatternKit.Generators.Tests/ObserverGeneratorTests.cs b/test/PatternKit.Generators.Tests/ObserverGeneratorTests.cs index df7db3f3..c7788d3c 100644 --- a/test/PatternKit.Generators.Tests/ObserverGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/ObserverGeneratorTests.cs @@ -1,5 +1,5 @@ -using Microsoft.CodeAnalysis; using System.Runtime.Loader; +using Microsoft.CodeAnalysis; using TinyBDD; namespace PatternKit.Generators.Tests; @@ -198,7 +198,7 @@ public static string Run() var demoType = asm.GetType("PatternKit.Examples.Generators.Demo"); var runMethod = demoType!.GetMethod("Run"); var result = (string)runMethod!.Invoke(null, null)!; - + // After first publish: both handlers; after second: only H2 ScenarioExpect.Equal("H1:10|H2:10|H2:20", result); } @@ -375,7 +375,7 @@ public static string Run() var demoType = asm.GetType("PatternKit.Examples.Generators.Demo"); var runMethod = demoType!.GetMethod("Run"); var result = (string)runMethod!.Invoke(null, null)!; - + // All three handlers should execute (H1, exception, H3) ScenarioExpect.Equal("H1|H3", result); } @@ -674,7 +674,7 @@ public static async System.Threading.Tasks.Task Run() if (!task.Wait(TimeSpan.FromSeconds(30))) throw new TimeoutException("Demo.Run() did not complete within 30 seconds."); var result = task.Result; - + // Both handlers should have been invoked ScenarioExpect.Contains("Sync", result); ScenarioExpect.Contains("Async", result); @@ -808,7 +808,7 @@ public static string Run() var demoType = asm.GetType("PatternKit.Examples.Generators.Demo"); var runMethod = demoType!.GetMethod("Run"); var result = (string)runMethod!.Invoke(null, null)!; - + ScenarioExpect.Equal("Handler1:23.5|Handler2:23.5", result); } finally @@ -908,7 +908,7 @@ public static string Run() var demoType = asm.GetType("PatternKit.Examples.Generators.Demo"); var runMethod = demoType!.GetMethod("Run"); var result = (string)runMethod!.Invoke(null, null)!; - + // With RegistrationOrder, order should be preserved ScenarioExpect.Equal("Handler1:23.5|Handler2:23.5", result); } @@ -973,7 +973,7 @@ public static string Run() var demoType = asm.GetType("PatternKit.Examples.Generators.Demo"); var runMethod = demoType!.GetMethod("Run"); var result = (string)runMethod!.Invoke(null, null)!; - + // With Undefined order, both handlers should still be invoked (order not guaranteed) ScenarioExpect.Contains("Handler1:23.5", result); ScenarioExpect.Contains("Handler2:23.5", result); diff --git a/test/PatternKit.Generators.Tests/Properties/AssemblyCoverage.cs b/test/PatternKit.Generators.Tests/Properties/AssemblyCoverage.cs index 598a1a76..29178265 100644 --- a/test/PatternKit.Generators.Tests/Properties/AssemblyCoverage.cs +++ b/test/PatternKit.Generators.Tests/Properties/AssemblyCoverage.cs @@ -1,4 +1,4 @@ #if NETSTANDARD2_1 // Exclude the entire assembly from coverage when built for netstandard2.1 [assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] -#endif \ No newline at end of file +#endif diff --git a/test/PatternKit.Generators.Tests/ProxyGeneratorTests.cs b/test/PatternKit.Generators.Tests/ProxyGeneratorTests.cs index 4990db2a..0df19596 100644 --- a/test/PatternKit.Generators.Tests/ProxyGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/ProxyGeneratorTests.cs @@ -1,5 +1,5 @@ -using Microsoft.CodeAnalysis; using System.IO; +using Microsoft.CodeAnalysis; using TinyBDD; namespace PatternKit.Generators.Tests; diff --git a/test/PatternKit.Generators.Tests/RoslynTestHelpers.cs b/test/PatternKit.Generators.Tests/RoslynTestHelpers.cs index 891c5efd..c7e820b6 100644 --- a/test/PatternKit.Generators.Tests/RoslynTestHelpers.cs +++ b/test/PatternKit.Generators.Tests/RoslynTestHelpers.cs @@ -1,4 +1,4 @@ -using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; namespace PatternKit.Generators.Tests; diff --git a/test/PatternKit.Generators.Tests/StateMachineGeneratorTests.cs b/test/PatternKit.Generators.Tests/StateMachineGeneratorTests.cs index f3e7a1b6..997f1290 100644 --- a/test/PatternKit.Generators.Tests/StateMachineGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/StateMachineGeneratorTests.cs @@ -350,7 +350,7 @@ private void OnEnterPaid() { } var generatedSource = result.Results[0].GeneratedSources[0].SourceText.ToString(); ScenarioExpect.Contains("OnEnterSubmitted()", generatedSource); ScenarioExpect.Contains("OnEnterPaid()", generatedSource); - + // Verify State is updated before entry hooks var submitIndex = generatedSource.IndexOf("State = global::PatternKit.Examples.OrderState.Submitted"); var entrySubmittedIndex = generatedSource.IndexOf("OnEnterSubmitted()"); @@ -890,19 +890,19 @@ private async ValueTask OnTransitionAsync(CancellationToken ct) // Should have PKST008 diagnostic var diagnostics = result.Results.SelectMany(r => r.Diagnostics).ToArray(); - + // Debug: print all diagnostics if (diagnostics.Length == 0) { // Check if code was even generated var hasGeneratedCode = result.Results.Any(r => r.GeneratedSources.Length > 0); ScenarioExpect.True(hasGeneratedCode, "No code was generated"); - + // Check compilation diagnostics var compDiags = updated.GetDiagnostics().Where(d => d.Id.StartsWith("PKST")).ToArray(); ScenarioExpect.True(compDiags.Length > 0, $"No PKST diagnostics found. Generated code: {result.Results[0].GeneratedSources.Length} files"); } - + ScenarioExpect.Contains(diagnostics, d => d.Id == "PKST008"); // Verify FireAsync is NOT generated diff --git a/test/PatternKit.Generators.Tests/StrategyGeneratorTests.cs b/test/PatternKit.Generators.Tests/StrategyGeneratorTests.cs index db19a8e5..4b46e71e 100644 --- a/test/PatternKit.Generators.Tests/StrategyGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/StrategyGeneratorTests.cs @@ -425,4 +425,4 @@ public static string Run() ScenarioExpect.Equal("int:42|str:hello", result); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Generators.Tests/UnitOfWorkGeneratorTests.cs b/test/PatternKit.Generators.Tests/UnitOfWorkGeneratorTests.cs index c5efdec3..2584bbba 100644 --- a/test/PatternKit.Generators.Tests/UnitOfWorkGeneratorTests.cs +++ b/test/PatternKit.Generators.Tests/UnitOfWorkGeneratorTests.cs @@ -1,94 +1,94 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using PatternKit.Application.UnitOfWork; -using PatternKit.Generators.UnitOfWork; -using TinyBDD; - -namespace PatternKit.Generators.Tests; - -public sealed class UnitOfWorkGeneratorTests -{ - [Scenario("Generates unit of work factory")] - [Fact] - public void GeneratesUnitOfWorkFactory() - { - var source = """ - using System.Threading; - using System.Threading.Tasks; - using PatternKit.Generators.UnitOfWork; - - [GenerateUnitOfWork(FactoryName = "Build")] - public static partial class CheckoutWork - { - [UnitOfWorkStep("reserve", 10, RollbackMethodName = nameof(UndoReserve))] - private static ValueTask Reserve(CancellationToken ct) => default; - - private static ValueTask UndoReserve(CancellationToken ct) => default; - } - """; - - var comp = CreateCompilation(source, nameof(GeneratesUnitOfWorkFactory)); - var gen = new UnitOfWorkGenerator(); - _ = RoslynTestHelpers.Run(comp, gen, out var run, out var updated); - - ScenarioExpect.All(run.Results, result => ScenarioExpect.Empty(result.Diagnostics)); - var generated = ScenarioExpect.Single(run.Results.SelectMany(result => result.GeneratedSources)); - ScenarioExpect.Equal("CheckoutWork.UnitOfWork.g.cs", generated.HintName); - var text = generated.SourceText.ToString(); - ScenarioExpect.Contains("Build", text); - ScenarioExpect.Contains("builder.Enlist(\"reserve\", Reserve, UndoReserve);", text); - ScenarioExpect.True(updated.Emit(Stream.Null).Success); - } - - [Scenario("Reports diagnostic for non partial unit of work")] - [Fact] - public void ReportsDiagnosticForNonPartialUnitOfWork() - { - var comp = CreateCompilation(""" - using PatternKit.Generators.UnitOfWork; - [GenerateUnitOfWork] - public static class CheckoutWork; - """, nameof(ReportsDiagnosticForNonPartialUnitOfWork)); - _ = RoslynTestHelpers.Run(comp, new UnitOfWorkGenerator(), out var run, out _); - - ScenarioExpect.Equal("PKUOW001", ScenarioExpect.Single(run.Results.SelectMany(result => result.Diagnostics)).Id); - } - - [Scenario("Reports diagnostic for missing unit of work steps")] - [Fact] - public void ReportsDiagnosticForMissingUnitOfWorkSteps() - { - var comp = CreateCompilation(""" - using PatternKit.Generators.UnitOfWork; - [GenerateUnitOfWork] - public static partial class CheckoutWork; - """, nameof(ReportsDiagnosticForMissingUnitOfWorkSteps)); - _ = RoslynTestHelpers.Run(comp, new UnitOfWorkGenerator(), out var run, out _); - - ScenarioExpect.Equal("PKUOW002", ScenarioExpect.Single(run.Results.SelectMany(result => result.Diagnostics)).Id); - } - - [Scenario("Reports diagnostic for invalid unit of work step")] - [Fact] - public void ReportsDiagnosticForInvalidUnitOfWorkStep() - { - var comp = CreateCompilation(""" - using PatternKit.Generators.UnitOfWork; - [GenerateUnitOfWork] - public static partial class CheckoutWork - { - [UnitOfWorkStep("reserve", 10)] - private static void Reserve() { } - } - """, nameof(ReportsDiagnosticForInvalidUnitOfWorkStep)); - _ = RoslynTestHelpers.Run(comp, new UnitOfWorkGenerator(), out var run, out _); - - ScenarioExpect.Equal("PKUOW003", ScenarioExpect.Single(run.Results.SelectMany(result => result.Diagnostics)).Id); - } - - private static CSharpCompilation CreateCompilation(string source, string assemblyName) - => RoslynTestHelpers.CreateCompilation( - source, - assemblyName, - extra: MetadataReference.CreateFromFile(typeof(PatternKit.Application.UnitOfWork.UnitOfWork).Assembly.Location)); -} +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using PatternKit.Application.UnitOfWork; +using PatternKit.Generators.UnitOfWork; +using TinyBDD; + +namespace PatternKit.Generators.Tests; + +public sealed class UnitOfWorkGeneratorTests +{ + [Scenario("Generates unit of work factory")] + [Fact] + public void GeneratesUnitOfWorkFactory() + { + var source = """ + using System.Threading; + using System.Threading.Tasks; + using PatternKit.Generators.UnitOfWork; + + [GenerateUnitOfWork(FactoryName = "Build")] + public static partial class CheckoutWork + { + [UnitOfWorkStep("reserve", 10, RollbackMethodName = nameof(UndoReserve))] + private static ValueTask Reserve(CancellationToken ct) => default; + + private static ValueTask UndoReserve(CancellationToken ct) => default; + } + """; + + var comp = CreateCompilation(source, nameof(GeneratesUnitOfWorkFactory)); + var gen = new UnitOfWorkGenerator(); + _ = RoslynTestHelpers.Run(comp, gen, out var run, out var updated); + + ScenarioExpect.All(run.Results, result => ScenarioExpect.Empty(result.Diagnostics)); + var generated = ScenarioExpect.Single(run.Results.SelectMany(result => result.GeneratedSources)); + ScenarioExpect.Equal("CheckoutWork.UnitOfWork.g.cs", generated.HintName); + var text = generated.SourceText.ToString(); + ScenarioExpect.Contains("Build", text); + ScenarioExpect.Contains("builder.Enlist(\"reserve\", Reserve, UndoReserve);", text); + ScenarioExpect.True(updated.Emit(Stream.Null).Success); + } + + [Scenario("Reports diagnostic for non partial unit of work")] + [Fact] + public void ReportsDiagnosticForNonPartialUnitOfWork() + { + var comp = CreateCompilation(""" + using PatternKit.Generators.UnitOfWork; + [GenerateUnitOfWork] + public static class CheckoutWork; + """, nameof(ReportsDiagnosticForNonPartialUnitOfWork)); + _ = RoslynTestHelpers.Run(comp, new UnitOfWorkGenerator(), out var run, out _); + + ScenarioExpect.Equal("PKUOW001", ScenarioExpect.Single(run.Results.SelectMany(result => result.Diagnostics)).Id); + } + + [Scenario("Reports diagnostic for missing unit of work steps")] + [Fact] + public void ReportsDiagnosticForMissingUnitOfWorkSteps() + { + var comp = CreateCompilation(""" + using PatternKit.Generators.UnitOfWork; + [GenerateUnitOfWork] + public static partial class CheckoutWork; + """, nameof(ReportsDiagnosticForMissingUnitOfWorkSteps)); + _ = RoslynTestHelpers.Run(comp, new UnitOfWorkGenerator(), out var run, out _); + + ScenarioExpect.Equal("PKUOW002", ScenarioExpect.Single(run.Results.SelectMany(result => result.Diagnostics)).Id); + } + + [Scenario("Reports diagnostic for invalid unit of work step")] + [Fact] + public void ReportsDiagnosticForInvalidUnitOfWorkStep() + { + var comp = CreateCompilation(""" + using PatternKit.Generators.UnitOfWork; + [GenerateUnitOfWork] + public static partial class CheckoutWork + { + [UnitOfWorkStep("reserve", 10)] + private static void Reserve() { } + } + """, nameof(ReportsDiagnosticForInvalidUnitOfWorkStep)); + _ = RoslynTestHelpers.Run(comp, new UnitOfWorkGenerator(), out var run, out _); + + ScenarioExpect.Equal("PKUOW003", ScenarioExpect.Single(run.Results.SelectMany(result => result.Diagnostics)).Id); + } + + private static CSharpCompilation CreateCompilation(string source, string assemblyName) + => RoslynTestHelpers.CreateCompilation( + source, + assemblyName, + extra: MetadataReference.CreateFromFile(typeof(PatternKit.Application.UnitOfWork.UnitOfWork).Assembly.Location)); +} diff --git a/test/PatternKit.Tests/Application/UnitOfWork/UnitOfWorkTests.cs b/test/PatternKit.Tests/Application/UnitOfWork/UnitOfWorkTests.cs index e8eef9f8..27b1e859 100644 --- a/test/PatternKit.Tests/Application/UnitOfWork/UnitOfWorkTests.cs +++ b/test/PatternKit.Tests/Application/UnitOfWork/UnitOfWorkTests.cs @@ -1,77 +1,77 @@ -using PatternKit.Application.UnitOfWork; -using TinyBDD; - -namespace PatternKit.Tests.Application.UnitOfWork; - -public sealed class UnitOfWorkTests -{ - [Scenario("CommitAsync ExecutesStepsInOrder")] - [Fact] - public async Task CommitAsync_ExecutesStepsInOrder() - { - var log = new List(); - var unit = PatternKit.Application.UnitOfWork.UnitOfWork.Create() - .Enlist("reserve", _ => { log.Add("reserve"); return default; }) - .Enlist("persist", _ => { log.Add("persist"); return default; }) - .Build(); - - var result = await unit.CommitAsync(); - - ScenarioExpect.True(result.Committed); - ScenarioExpect.Equal(["reserve", "persist"], log); - ScenarioExpect.Equal(["reserve", "persist"], result.CommittedSteps); - } - - [Scenario("CommitAsync RollsBackCommittedStepsWhenLaterStepFails")] - [Fact] - public async Task CommitAsync_RollsBackCommittedStepsWhenLaterStepFails() - { - var log = new List(); - var unit = PatternKit.Application.UnitOfWork.UnitOfWork.Create() - .Enlist("reserve", _ => { log.Add("reserve"); return default; }, _ => { log.Add("undo-reserve"); return default; }) - .Enlist("persist", _ => throw new InvalidOperationException("db failed")) - .Build(); - - var result = await unit.CommitAsync(); - - ScenarioExpect.False(result.Committed); - ScenarioExpect.Equal("persist", result.FailedStep); - ScenarioExpect.Equal(["reserve", "undo-reserve"], log); - ScenarioExpect.True(result.Rollback!.Succeeded); - ScenarioExpect.Equal(["reserve"], result.Rollback.RolledBackSteps); - } - - [Scenario("RollbackAsync RunsCompensationsInReverseOrder")] - [Fact] - public async Task RollbackAsync_RunsCompensationsInReverseOrder() - { - var log = new List(); - var unit = PatternKit.Application.UnitOfWork.UnitOfWork.Create() - .Enlist("one", _ => default, _ => { log.Add("undo-one"); return default; }) - .Enlist("two", _ => default, _ => { log.Add("undo-two"); return default; }) - .Build(); - - var result = await unit.RollbackAsync(); - - ScenarioExpect.True(result.Succeeded); - ScenarioExpect.Equal(["undo-two", "undo-one"], log); - ScenarioExpect.Equal(["two", "one"], result.RolledBackSteps); - } - - [Scenario("UnitOfWork ValidatesInputsAndCancellation")] - [Fact] - public async Task UnitOfWork_ValidatesInputsAndCancellation() - { - ScenarioExpect.Throws(() => PatternKit.Application.UnitOfWork.UnitOfWork.Create().Enlist("", _ => default)); - ScenarioExpect.Throws(() => PatternKit.Application.UnitOfWork.UnitOfWork.Create().Enlist("step", null!)); - ScenarioExpect.Throws(() => PatternKit.Application.UnitOfWork.UnitOfWork.Create().Enlist("step", _ => default).Enlist("step", _ => default)); - ScenarioExpect.Throws(() => new UnitOfWorkStep("", _ => default, _ => default)); - ScenarioExpect.Throws(() => new UnitOfWorkStep("step", null!, _ => default)); - ScenarioExpect.Throws(() => new UnitOfWorkStep("step", _ => default, null!)); - - using var source = new CancellationTokenSource(); - source.Cancel(); - var unit = PatternKit.Application.UnitOfWork.UnitOfWork.Create().Enlist("step", _ => default).Build(); - await ScenarioExpect.ThrowsAsync(async () => await unit.CommitAsync(source.Token)); - } -} +using PatternKit.Application.UnitOfWork; +using TinyBDD; + +namespace PatternKit.Tests.Application.UnitOfWork; + +public sealed class UnitOfWorkTests +{ + [Scenario("CommitAsync ExecutesStepsInOrder")] + [Fact] + public async Task CommitAsync_ExecutesStepsInOrder() + { + var log = new List(); + var unit = PatternKit.Application.UnitOfWork.UnitOfWork.Create() + .Enlist("reserve", _ => { log.Add("reserve"); return default; }) + .Enlist("persist", _ => { log.Add("persist"); return default; }) + .Build(); + + var result = await unit.CommitAsync(); + + ScenarioExpect.True(result.Committed); + ScenarioExpect.Equal(["reserve", "persist"], log); + ScenarioExpect.Equal(["reserve", "persist"], result.CommittedSteps); + } + + [Scenario("CommitAsync RollsBackCommittedStepsWhenLaterStepFails")] + [Fact] + public async Task CommitAsync_RollsBackCommittedStepsWhenLaterStepFails() + { + var log = new List(); + var unit = PatternKit.Application.UnitOfWork.UnitOfWork.Create() + .Enlist("reserve", _ => { log.Add("reserve"); return default; }, _ => { log.Add("undo-reserve"); return default; }) + .Enlist("persist", _ => throw new InvalidOperationException("db failed")) + .Build(); + + var result = await unit.CommitAsync(); + + ScenarioExpect.False(result.Committed); + ScenarioExpect.Equal("persist", result.FailedStep); + ScenarioExpect.Equal(["reserve", "undo-reserve"], log); + ScenarioExpect.True(result.Rollback!.Succeeded); + ScenarioExpect.Equal(["reserve"], result.Rollback.RolledBackSteps); + } + + [Scenario("RollbackAsync RunsCompensationsInReverseOrder")] + [Fact] + public async Task RollbackAsync_RunsCompensationsInReverseOrder() + { + var log = new List(); + var unit = PatternKit.Application.UnitOfWork.UnitOfWork.Create() + .Enlist("one", _ => default, _ => { log.Add("undo-one"); return default; }) + .Enlist("two", _ => default, _ => { log.Add("undo-two"); return default; }) + .Build(); + + var result = await unit.RollbackAsync(); + + ScenarioExpect.True(result.Succeeded); + ScenarioExpect.Equal(["undo-two", "undo-one"], log); + ScenarioExpect.Equal(["two", "one"], result.RolledBackSteps); + } + + [Scenario("UnitOfWork ValidatesInputsAndCancellation")] + [Fact] + public async Task UnitOfWork_ValidatesInputsAndCancellation() + { + ScenarioExpect.Throws(() => PatternKit.Application.UnitOfWork.UnitOfWork.Create().Enlist("", _ => default)); + ScenarioExpect.Throws(() => PatternKit.Application.UnitOfWork.UnitOfWork.Create().Enlist("step", null!)); + ScenarioExpect.Throws(() => PatternKit.Application.UnitOfWork.UnitOfWork.Create().Enlist("step", _ => default).Enlist("step", _ => default)); + ScenarioExpect.Throws(() => new UnitOfWorkStep("", _ => default, _ => default)); + ScenarioExpect.Throws(() => new UnitOfWorkStep("step", null!, _ => default)); + ScenarioExpect.Throws(() => new UnitOfWorkStep("step", _ => default, null!)); + + using var source = new CancellationTokenSource(); + source.Cancel(); + var unit = PatternKit.Application.UnitOfWork.UnitOfWork.Create().Enlist("step", _ => default).Build(); + await ScenarioExpect.ThrowsAsync(async () => await unit.CommitAsync(source.Token)); + } +} diff --git a/test/PatternKit.Tests/Behavioral/AsyncTemplateFluentTests.cs b/test/PatternKit.Tests/Behavioral/AsyncTemplateFluentTests.cs index 58b3757b..81e2ee2b 100644 --- a/test/PatternKit.Tests/Behavioral/AsyncTemplateFluentTests.cs +++ b/test/PatternKit.Tests/Behavioral/AsyncTemplateFluentTests.cs @@ -154,4 +154,4 @@ public Task Synchronized_Enforces_Mutex() .Then("all results are 4", r => r.results.All(v => v == 4)) .And("max concurrency is 1", r => r.holder[1] == 1) .AssertPassed(); -} \ No newline at end of file +} diff --git a/test/PatternKit.Tests/Behavioral/AsyncTemplateMethodTests.cs b/test/PatternKit.Tests/Behavioral/AsyncTemplateMethodTests.cs index 217ee2d3..1d61e3eb 100644 --- a/test/PatternKit.Tests/Behavioral/AsyncTemplateMethodTests.cs +++ b/test/PatternKit.Tests/Behavioral/AsyncTemplateMethodTests.cs @@ -237,4 +237,4 @@ protected override async ValueTask StepAsync(int context, CancellationTo } } -#endregion \ No newline at end of file +#endregion diff --git a/test/PatternKit.Tests/Behavioral/Chain/ActionChainTests.cs b/test/PatternKit.Tests/Behavioral/Chain/ActionChainTests.cs index 66d03097..897eb8ec 100644 --- a/test/PatternKit.Tests/Behavioral/Chain/ActionChainTests.cs +++ b/test/PatternKit.Tests/Behavioral/Chain/ActionChainTests.cs @@ -439,4 +439,4 @@ public void Concurrent_Execution_Safe() } } -#endregion \ No newline at end of file +#endregion diff --git a/test/PatternKit.Tests/Behavioral/Chain/ResultChainTests.cs b/test/PatternKit.Tests/Behavioral/Chain/ResultChainTests.cs index 57a7066b..9fae6ed5 100644 --- a/test/PatternKit.Tests/Behavioral/Chain/ResultChainTests.cs +++ b/test/PatternKit.Tests/Behavioral/Chain/ResultChainTests.cs @@ -225,4 +225,4 @@ await Given("a chain with a producing head and a logging tail", () => .And("tail logged", c => c.Log.Contains("tail")) .AssertPassed(); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Tests/Behavioral/Command/CommandTests.cs b/test/PatternKit.Tests/Behavioral/Command/CommandTests.cs index fe6642bc..8fd47ec2 100644 --- a/test/PatternKit.Tests/Behavioral/Command/CommandTests.cs +++ b/test/PatternKit.Tests/Behavioral/Command/CommandTests.cs @@ -772,4 +772,4 @@ public async Task Macro_CancellationToken_Propagates() } } -#endregion \ No newline at end of file +#endregion diff --git a/test/PatternKit.Tests/Behavioral/Iterator/ReplayableSequenceTests.cs b/test/PatternKit.Tests/Behavioral/Iterator/ReplayableSequenceTests.cs index 1d2b24f7..1f102474 100644 --- a/test/PatternKit.Tests/Behavioral/Iterator/ReplayableSequenceTests.cs +++ b/test/PatternKit.Tests/Behavioral/Iterator/ReplayableSequenceTests.cs @@ -400,4 +400,4 @@ public async Task AsAsyncEnumerable_RespectsToken() #endif } -#endregion \ No newline at end of file +#endregion diff --git a/test/PatternKit.Tests/Behavioral/Memento/MementoTests.cs b/test/PatternKit.Tests/Behavioral/Memento/MementoTests.cs index 6d07c1a2..e5591847 100644 --- a/test/PatternKit.Tests/Behavioral/Memento/MementoTests.cs +++ b/test/PatternKit.Tests/Behavioral/Memento/MementoTests.cs @@ -492,4 +492,4 @@ public void SaveAfterUndo_TruncatesForwardHistory() } } -#endregion \ No newline at end of file +#endregion diff --git a/test/PatternKit.Tests/Behavioral/Strategy/ActionStrategyTests.cs b/test/PatternKit.Tests/Behavioral/Strategy/ActionStrategyTests.cs index 9f60f830..9667c891 100644 --- a/test/PatternKit.Tests/Behavioral/Strategy/ActionStrategyTests.cs +++ b/test/PatternKit.Tests/Behavioral/Strategy/ActionStrategyTests.cs @@ -138,4 +138,4 @@ await Given("a strategy with overlapping predicates in order", () => .Then("should only run the first action", c => string.Join("|", c.Log) == "first") .AssertPassed(); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Tests/Behavioral/Strategy/CoercerTryStrategyTests.cs b/test/PatternKit.Tests/Behavioral/Strategy/CoercerTryStrategyTests.cs index af78bced..ed415e49 100644 --- a/test/PatternKit.Tests/Behavioral/Strategy/CoercerTryStrategyTests.cs +++ b/test/PatternKit.Tests/Behavioral/Strategy/CoercerTryStrategyTests.cs @@ -71,4 +71,4 @@ static TryStrategy BuildCoercer() static object? Execute(TryStrategy s, JsonElement je) => s.Execute(in je, out var r) ? r : null; } -} \ No newline at end of file +} diff --git a/test/PatternKit.Tests/Behavioral/Strategy/SelectorStrategyTests.cs b/test/PatternKit.Tests/Behavioral/Strategy/SelectorStrategyTests.cs index 6c3c2619..01a7fa2f 100644 --- a/test/PatternKit.Tests/Behavioral/Strategy/SelectorStrategyTests.cs +++ b/test/PatternKit.Tests/Behavioral/Strategy/SelectorStrategyTests.cs @@ -52,4 +52,4 @@ await Given("same selector", BuildSelector) .Default(DefaultHandler) .Build(); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Tests/Behavioral/TemplateFluentTests.cs b/test/PatternKit.Tests/Behavioral/TemplateFluentTests.cs index adca5089..bbed20b1 100644 --- a/test/PatternKit.Tests/Behavioral/TemplateFluentTests.cs +++ b/test/PatternKit.Tests/Behavioral/TemplateFluentTests.cs @@ -545,4 +545,4 @@ public void ActionTemplate_TryExecute_Synchronized_Error() } } -#endregion \ No newline at end of file +#endregion diff --git a/test/PatternKit.Tests/Behavioral/TemplateMethodTests.cs b/test/PatternKit.Tests/Behavioral/TemplateMethodTests.cs index a73f6ac1..d8a4f74c 100644 --- a/test/PatternKit.Tests/Behavioral/TemplateMethodTests.cs +++ b/test/PatternKit.Tests/Behavioral/TemplateMethodTests.cs @@ -146,4 +146,4 @@ public void Multiple_Executions_Independent() } } -#endregion \ No newline at end of file +#endregion diff --git a/test/PatternKit.Tests/Creational/Builder/ComposerTests.cs b/test/PatternKit.Tests/Creational/Builder/ComposerTests.cs index e643f540..0bac0001 100644 --- a/test/PatternKit.Tests/Creational/Builder/ComposerTests.cs +++ b/test/PatternKit.Tests/Creational/Builder/ComposerTests.cs @@ -139,4 +139,4 @@ await Given("a composer seeded with default", () => NewComposer(SeedDefault)) static PersonState A(PersonState s) => SetAge(s, 10); static PersonState B(PersonState s) => SetAge(s, 20); } -} \ No newline at end of file +} diff --git a/test/PatternKit.Tests/Messaging/ControlBus/ControlBusTests.cs b/test/PatternKit.Tests/Messaging/ControlBus/ControlBusTests.cs index c65f1b0e..4eed19aa 100644 --- a/test/PatternKit.Tests/Messaging/ControlBus/ControlBusTests.cs +++ b/test/PatternKit.Tests/Messaging/ControlBus/ControlBusTests.cs @@ -1,104 +1,104 @@ -using PatternKit.Messaging; -using ControlBusUnderTest = global::PatternKit.Messaging.ControlBus.ControlBus; +using PatternKit.Messaging; +using TinyBDD; using ControlBusHeaders = global::PatternKit.Messaging.ControlBus.ControlBusHeaders; using ControlBusResult = global::PatternKit.Messaging.ControlBus.ControlBusResult; -using TinyBDD; - -namespace PatternKit.Tests.Messaging.ControlBus; - -public sealed class ControlBusTests -{ - [Scenario("Dispatch RoutesNamedControlCommand")] - [Fact] - public void Dispatch_RoutesNamedControlCommand() - { - var bus = ControlBusUnderTest.Create("fulfillment-control") - .Handle("pause", "pause-processor", static (_, _) => ControlBusResult.Success()) - .Handle("resume", "resume-processor", static (_, _) => ControlBusResult.Success()) - .Build(); - - var result = bus.Dispatch(Message.Create(new("pause")).WithHeader(ControlBusHeaders.CommandName, "pause")); - - ScenarioExpect.True(result.Succeeded); - ScenarioExpect.Equal("fulfillment-control", result.BusName); - ScenarioExpect.Equal("pause", result.CommandName); - ScenarioExpect.Equal("pause-processor", result.HandlerName); - } - - [Scenario("Dispatch UsesCustomCommandSelector")] - [Fact] - public void Dispatch_UsesCustomCommandSelector() - { - var bus = ControlBusUnderTest.Create() - .SelectCommand(static (message, _) => message.Payload.Name) - .Handle("drain", "drain-processor", static (_, _) => ControlBusResult.Success()) - .Build(); - - var result = bus.Dispatch(Message.Create(new("drain"))); - - ScenarioExpect.True(result.Succeeded); - ScenarioExpect.Equal("drain", result.CommandName); - } - - [Scenario("Dispatch RejectsUnknownOrBlankCommands")] - [Fact] - public void Dispatch_RejectsUnknownOrBlankCommands() - { - var bus = ControlBusUnderTest.Create() - .Handle("pause", "pause-processor", static (_, _) => ControlBusResult.Success()) - .Build(); - - var blank = bus.Dispatch(Message.Create(new("pause"))); - var unknown = bus.Dispatch(Message.Create(new("resume")).WithHeader(ControlBusHeaders.CommandName, "resume")); - - ScenarioExpect.False(blank.Succeeded); - ScenarioExpect.Equal("Control command name was not supplied.", blank.RejectionReason); - ScenarioExpect.False(unknown.Succeeded); - ScenarioExpect.Equal("No control bus handler is registered for the command.", unknown.RejectionReason); - } - - [Scenario("DispatchPreservesHandlerFailure")] - [Fact] - public void Dispatch_PreservesHandlerFailure() - { - var bus = ControlBusUnderTest.Create() - .SelectCommand(static (message, _) => message.Payload.Name) - .Handle("pause", "pause-processor", static (_, _) => ControlBusResult.Failure("Processor is already paused.")) - .Build(); - - var result = bus.Dispatch(Message.Create(new("pause"))); - - ScenarioExpect.False(result.Succeeded); - ScenarioExpect.Equal("pause-processor", result.HandlerName); - ScenarioExpect.Equal("Processor is already paused.", result.RejectionReason); - } - - [Scenario("BuilderRejectsInvalidConfiguration")] - [Fact] - public void Builder_RejectsInvalidConfiguration() - { - ScenarioExpect.Throws(() => ControlBusUnderTest.Create("")); - ScenarioExpect.Throws(() => ControlBusUnderTest.Create().SelectCommand(null!)); - ScenarioExpect.Throws(() => ControlBusUnderTest.Create().Handle("", "handler", static (_, _) => ControlBusResult.Success())); - ScenarioExpect.Throws(() => ControlBusUnderTest.Create().Handle("pause", "", static (_, _) => ControlBusResult.Success())); - ScenarioExpect.Throws(() => ControlBusUnderTest.Create().Handle("pause", "handler", null!)); - ScenarioExpect.Throws(() => ControlBusUnderTest.Create().Build()); - ScenarioExpect.Throws(() => ControlBusUnderTest.Create() - .Handle("pause", "one", static (_, _) => ControlBusResult.Success()) - .Handle("pause", "two", static (_, _) => ControlBusResult.Success())); - ScenarioExpect.Throws(() => ControlBusResult.Failure("")); - } - - [Scenario("DispatchRejectsNullMessage")] - [Fact] - public void Dispatch_RejectsNullMessage() - { - var bus = ControlBusUnderTest.Create() - .Handle("pause", "pause-processor", static (_, _) => ControlBusResult.Success()) - .Build(); - - ScenarioExpect.Throws(() => bus.Dispatch(null!)); - } - - public sealed record Command(string Name); -} +using ControlBusUnderTest = global::PatternKit.Messaging.ControlBus.ControlBus; + +namespace PatternKit.Tests.Messaging.ControlBus; + +public sealed class ControlBusTests +{ + [Scenario("Dispatch RoutesNamedControlCommand")] + [Fact] + public void Dispatch_RoutesNamedControlCommand() + { + var bus = ControlBusUnderTest.Create("fulfillment-control") + .Handle("pause", "pause-processor", static (_, _) => ControlBusResult.Success()) + .Handle("resume", "resume-processor", static (_, _) => ControlBusResult.Success()) + .Build(); + + var result = bus.Dispatch(Message.Create(new("pause")).WithHeader(ControlBusHeaders.CommandName, "pause")); + + ScenarioExpect.True(result.Succeeded); + ScenarioExpect.Equal("fulfillment-control", result.BusName); + ScenarioExpect.Equal("pause", result.CommandName); + ScenarioExpect.Equal("pause-processor", result.HandlerName); + } + + [Scenario("Dispatch UsesCustomCommandSelector")] + [Fact] + public void Dispatch_UsesCustomCommandSelector() + { + var bus = ControlBusUnderTest.Create() + .SelectCommand(static (message, _) => message.Payload.Name) + .Handle("drain", "drain-processor", static (_, _) => ControlBusResult.Success()) + .Build(); + + var result = bus.Dispatch(Message.Create(new("drain"))); + + ScenarioExpect.True(result.Succeeded); + ScenarioExpect.Equal("drain", result.CommandName); + } + + [Scenario("Dispatch RejectsUnknownOrBlankCommands")] + [Fact] + public void Dispatch_RejectsUnknownOrBlankCommands() + { + var bus = ControlBusUnderTest.Create() + .Handle("pause", "pause-processor", static (_, _) => ControlBusResult.Success()) + .Build(); + + var blank = bus.Dispatch(Message.Create(new("pause"))); + var unknown = bus.Dispatch(Message.Create(new("resume")).WithHeader(ControlBusHeaders.CommandName, "resume")); + + ScenarioExpect.False(blank.Succeeded); + ScenarioExpect.Equal("Control command name was not supplied.", blank.RejectionReason); + ScenarioExpect.False(unknown.Succeeded); + ScenarioExpect.Equal("No control bus handler is registered for the command.", unknown.RejectionReason); + } + + [Scenario("DispatchPreservesHandlerFailure")] + [Fact] + public void Dispatch_PreservesHandlerFailure() + { + var bus = ControlBusUnderTest.Create() + .SelectCommand(static (message, _) => message.Payload.Name) + .Handle("pause", "pause-processor", static (_, _) => ControlBusResult.Failure("Processor is already paused.")) + .Build(); + + var result = bus.Dispatch(Message.Create(new("pause"))); + + ScenarioExpect.False(result.Succeeded); + ScenarioExpect.Equal("pause-processor", result.HandlerName); + ScenarioExpect.Equal("Processor is already paused.", result.RejectionReason); + } + + [Scenario("BuilderRejectsInvalidConfiguration")] + [Fact] + public void Builder_RejectsInvalidConfiguration() + { + ScenarioExpect.Throws(() => ControlBusUnderTest.Create("")); + ScenarioExpect.Throws(() => ControlBusUnderTest.Create().SelectCommand(null!)); + ScenarioExpect.Throws(() => ControlBusUnderTest.Create().Handle("", "handler", static (_, _) => ControlBusResult.Success())); + ScenarioExpect.Throws(() => ControlBusUnderTest.Create().Handle("pause", "", static (_, _) => ControlBusResult.Success())); + ScenarioExpect.Throws(() => ControlBusUnderTest.Create().Handle("pause", "handler", null!)); + ScenarioExpect.Throws(() => ControlBusUnderTest.Create().Build()); + ScenarioExpect.Throws(() => ControlBusUnderTest.Create() + .Handle("pause", "one", static (_, _) => ControlBusResult.Success()) + .Handle("pause", "two", static (_, _) => ControlBusResult.Success())); + ScenarioExpect.Throws(() => ControlBusResult.Failure("")); + } + + [Scenario("DispatchRejectsNullMessage")] + [Fact] + public void Dispatch_RejectsNullMessage() + { + var bus = ControlBusUnderTest.Create() + .Handle("pause", "pause-processor", static (_, _) => ControlBusResult.Success()) + .Build(); + + ScenarioExpect.Throws(() => bus.Dispatch(null!)); + } + + public sealed record Command(string Name); +} diff --git a/test/PatternKit.Tests/Messaging/Routing/ResequencerTests.cs b/test/PatternKit.Tests/Messaging/Routing/ResequencerTests.cs index 706c8c1a..69c4ff76 100644 --- a/test/PatternKit.Tests/Messaging/Routing/ResequencerTests.cs +++ b/test/PatternKit.Tests/Messaging/Routing/ResequencerTests.cs @@ -1,6 +1,6 @@ using PatternKit.Messaging; -using ResequencerUnderTest = global::PatternKit.Messaging.Routing.Resequencer; using TinyBDD; +using ResequencerUnderTest = global::PatternKit.Messaging.Routing.Resequencer; namespace PatternKit.Tests.Messaging.Routing; diff --git a/test/PatternKit.Tests/Messaging/Routing/ScatterGatherTests.cs b/test/PatternKit.Tests/Messaging/Routing/ScatterGatherTests.cs index 20bdeda0..9856ceee 100644 --- a/test/PatternKit.Tests/Messaging/Routing/ScatterGatherTests.cs +++ b/test/PatternKit.Tests/Messaging/Routing/ScatterGatherTests.cs @@ -1,8 +1,8 @@ using PatternKit.Messaging; +using TinyBDD; +using ScatterGatherCountUnderTest = global::PatternKit.Messaging.Routing.ScatterGather; using ScatterGatherReply = global::PatternKit.Messaging.Routing.ScatterGatherReply; using ScatterGatherUnderTest = global::PatternKit.Messaging.Routing.ScatterGather; -using ScatterGatherCountUnderTest = global::PatternKit.Messaging.Routing.ScatterGather; -using TinyBDD; namespace PatternKit.Tests.Messaging.Routing; diff --git a/test/PatternKit.Tests/Messaging/Transformation/KeyedNormalizerTests.cs b/test/PatternKit.Tests/Messaging/Transformation/KeyedNormalizerTests.cs index d64ca4b2..e3b2fdd6 100644 --- a/test/PatternKit.Tests/Messaging/Transformation/KeyedNormalizerTests.cs +++ b/test/PatternKit.Tests/Messaging/Transformation/KeyedNormalizerTests.cs @@ -13,7 +13,7 @@ public async Task NormalizeAsync_RegisteredKey_DispatchesToCorrectHandler() { var normalizer = KeyedNormalizer.Create() .When("json", (raw, _) => new ValueTask(new Order(raw, "json"))) - .When("xml", (raw, _) => new ValueTask(new Order(raw, "xml"))) + .When("xml", (raw, _) => new ValueTask(new Order(raw, "xml"))) .Build(); var result = await normalizer.NormalizeAsync("json", "payload-1"); @@ -27,17 +27,17 @@ public async Task NormalizeAsync_RegisteredKey_DispatchesToCorrectHandler() public async Task NormalizeAsync_MultipleKeys_EachRoutesCorrectly() { var normalizer = KeyedNormalizer.Create() - .When("csv", (raw, _) => new ValueTask(new Order(raw, "csv"))) - .When("avro", (raw, _) => new ValueTask(new Order(raw, "avro"))) + .When("csv", (raw, _) => new ValueTask(new Order(raw, "csv"))) + .When("avro", (raw, _) => new ValueTask(new Order(raw, "avro"))) .When("proto", (raw, _) => new ValueTask(new Order(raw, "proto"))) .Build(); - var csv = await normalizer.NormalizeAsync("csv", "c"); - var avro = await normalizer.NormalizeAsync("avro", "a"); + var csv = await normalizer.NormalizeAsync("csv", "c"); + var avro = await normalizer.NormalizeAsync("avro", "a"); var proto = await normalizer.NormalizeAsync("proto", "p"); - ScenarioExpect.Equal("csv", csv.Format); - ScenarioExpect.Equal("avro", avro.Format); + ScenarioExpect.Equal("csv", csv.Format); + ScenarioExpect.Equal("avro", avro.Format); ScenarioExpect.Equal("proto", proto.Format); } diff --git a/test/PatternKit.Tests/Properties/AssemblyCoverage.cs b/test/PatternKit.Tests/Properties/AssemblyCoverage.cs index 598a1a76..29178265 100644 --- a/test/PatternKit.Tests/Properties/AssemblyCoverage.cs +++ b/test/PatternKit.Tests/Properties/AssemblyCoverage.cs @@ -1,4 +1,4 @@ #if NETSTANDARD2_1 // Exclude the entire assembly from coverage when built for netstandard2.1 [assembly: System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] -#endif \ No newline at end of file +#endif diff --git a/test/PatternKit.Tests/Structural/Facade/FacadeTests.cs b/test/PatternKit.Tests/Structural/Facade/FacadeTests.cs index 36ba1f07..b49e9579 100644 --- a/test/PatternKit.Tests/Structural/Facade/FacadeTests.cs +++ b/test/PatternKit.Tests/Structural/Facade/FacadeTests.cs @@ -314,4 +314,4 @@ public Task Complex_Coordination() .And("order flow correct", r => r.log[0] == "1:validate" && r.log[4] == "5:send-confirmation") .And("return flow correct", r => r.log[5] == "1:validate-return" && r.log[8] == "4:restock-inventory") .AssertPassed(); -} \ No newline at end of file +} diff --git a/test/PatternKit.Tests/Structural/Facade/TypedFacadeTests.cs b/test/PatternKit.Tests/Structural/Facade/TypedFacadeTests.cs index 43674103..52c1f0b7 100644 --- a/test/PatternKit.Tests/Structural/Facade/TypedFacadeTests.cs +++ b/test/PatternKit.Tests/Structural/Facade/TypedFacadeTests.cs @@ -1,6 +1,6 @@ -using PatternKit.Structural.Facade; using System.Linq.Expressions; using System.Reflection; +using PatternKit.Structural.Facade; using TinyBDD; using TinyBDD.Xunit; using Xunit.Abstractions; @@ -286,16 +286,16 @@ public Task TypedFacade_DuplicateMappings_Cover_All_Arities() [Fact] public Task TypedFacade_PrivateValidation_Covers_Invalid_Selectors_And_Signatures() => Given("private validation helpers", () => new - { - Extract = typeof(TypedFacade.Builder).GetMethod( + { + Extract = typeof(TypedFacade.Builder).GetMethod( "ExtractMethodInfo", BindingFlags.NonPublic | BindingFlags.Static)!, - Validate = typeof(TypedFacade.Builder).GetMethod( + Validate = typeof(TypedFacade.Builder).GetMethod( "ValidateMethodSignature", BindingFlags.NonPublic | BindingFlags.Static)!, - GetStatus = typeof(ISimpleService).GetMethod(nameof(ISimpleService.GetStatus))!, - Operation1 = typeof(IComplexService).GetMethod(nameof(IComplexService.Operation1))! - }) + GetStatus = typeof(ISimpleService).GetMethod(nameof(ISimpleService.GetStatus))!, + Operation1 = typeof(IComplexService).GetMethod(nameof(IComplexService.Operation1))! + }) .When("invoking invalid selectors and signature checks", helpers => { Expression> notMethodSelector = _ => 1; diff --git a/test/PatternKit.Tests/Structural/Flyweight/FlyweightTests.cs b/test/PatternKit.Tests/Structural/Flyweight/FlyweightTests.cs index 2915630f..4b69e1bf 100644 --- a/test/PatternKit.Tests/Structural/Flyweight/FlyweightTests.cs +++ b/test/PatternKit.Tests/Structural/Flyweight/FlyweightTests.cs @@ -346,4 +346,4 @@ public void Concurrent_Preload_And_Factory() } } -#endregion \ No newline at end of file +#endregion