From 1309866c5e4bab4fbda1c10e02c367a6fc98480c Mon Sep 17 00:00:00 2001 From: Gerard Smit Date: Wed, 3 Jan 2024 02:51:21 +0100 Subject: [PATCH] Improve incremental source generator --- src/Directory.Build.props | 4 +- .../Extensions/EquatableArray.cs | 234 ++++++ .../Extensions/EquatableArrayBuilder.cs | 62 ++ .../Extensions/HashCode.cs | 205 +++++ .../Extensions/IndentedStringBuilder.cs | 178 +++++ .../Extensions/SpanExtensions.cs | 47 ++ .../Extensions/StringBuilderExtensions.cs | 126 ++- .../Extensions/StringExtensions.cs | 20 +- .../Mediator.SourceGenerator.csproj | 2 +- .../Models/ExtensionMethod.cs | 8 + .../Models/ExtensionMethodReference.cs | 22 +- .../Models/HandlerReference.cs | 5 + .../Models/SimpleConstructor.cs | 32 + .../Models/SimpleMethod.cs | 36 + .../Models/SimpleParameter.cs | 35 + .../Models/SimpleType.cs | 116 +++ .../Models/SimpleTypeParameter.cs | 42 + .../Models/SourceResult.cs | 12 + .../SenderGenerator.cs | 751 +++++++++--------- src/Mediator/Mediator.csproj | 3 +- ...teGeneric#Request_Extensions.g.verified.cs | 21 + ...GeneratorTests.GenerateGeneric.verified.cs | 14 - ...onstraint#Request_Extensions.g.verified.cs | 25 + ...ests.GenerateGenericConstraint.verified.cs | 18 - ...aintClass#Request_Extensions.g.verified.cs | 25 + ...GenerateGenericConstraintClass.verified.cs | 18 - ...entResult#Request_Extensions.g.verified.cs | 21 + ...GenerateGenericDifferentResult.verified.cs | 14 - ...tion#Notification_Extensions.g.verified.cs | 21 + ...atorTests.GenerateNotification.verified.cs | 14 - ...teRequest#Request_Extensions.g.verified.cs | 21 + ...GeneratorTests.GenerateRequest.verified.cs | 14 - ...eam#StreamRequest_Extensions.g.verified.cs | 21 + .../GeneratorTests.GenerateStream.verified.cs | 14 - ...tion#Notification_Extensions.g.verified.cs | 21 + ...sts.GenerateStructNotification.verified.cs | 14 - .../GeneratorTests.cs | 1 + ...ts.GenerateAddAssemblyHandlers.received.cs | 10 - ...ts.GenerateAddAssemblyHandlers.verified.cs | 1 - ...teHandler#AssemblyExtensions.g.verified.cs | 13 + ...teHandler#Request_Extensions.g.verified.cs | 33 + .../HandlerTests.GenerateHandler.verified.cs | 14 - .../IncrementalTests.cs | 133 ++++ .../Mediator.SourceGenerator.Tests.csproj | 18 +- .../ModuleInitializer.cs | 2 +- ...ollection#AssemblyExtensions.g.verified.cs | 13 + ...ollection#Request_Extensions.g.verified.cs | 33 + ...ectionTests.GenerateCollection.verified.cs | 26 - ...ollection#AssemblyExtensions.g.verified.cs | 13 + ...ollection#Request_Extensions.g.verified.cs | 33 + ...ests.GenerateGenericCollection.verified.cs | 26 - ...Attribute#Request_Extensions.g.verified.cs | 21 + ...onTests.IgnoreHandlerAttribute.verified.cs | 25 - .../TestHelper.cs | 7 +- 54 files changed, 1978 insertions(+), 680 deletions(-) create mode 100644 src/Mediator.SourceGenerator/Extensions/EquatableArray.cs create mode 100644 src/Mediator.SourceGenerator/Extensions/EquatableArrayBuilder.cs create mode 100644 src/Mediator.SourceGenerator/Extensions/HashCode.cs create mode 100644 src/Mediator.SourceGenerator/Extensions/IndentedStringBuilder.cs create mode 100644 src/Mediator.SourceGenerator/Extensions/SpanExtensions.cs create mode 100644 src/Mediator.SourceGenerator/Models/ExtensionMethod.cs create mode 100644 src/Mediator.SourceGenerator/Models/HandlerReference.cs create mode 100644 src/Mediator.SourceGenerator/Models/SimpleConstructor.cs create mode 100644 src/Mediator.SourceGenerator/Models/SimpleMethod.cs create mode 100644 src/Mediator.SourceGenerator/Models/SimpleParameter.cs create mode 100644 src/Mediator.SourceGenerator/Models/SimpleType.cs create mode 100644 src/Mediator.SourceGenerator/Models/SimpleTypeParameter.cs create mode 100644 src/Mediator.SourceGenerator/Models/SourceResult.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGeneric#Request_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGeneric.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraint#Request_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraint.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraintClass#Request_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraintClass.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericDifferentResult#Request_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericDifferentResult.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateNotification#Notification_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateNotification.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateRequest#Request_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateRequest.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStream#StreamRequest_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStream.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStructNotification#Notification_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStructNotification.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateAddAssemblyHandlers.received.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateAddAssemblyHandlers.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler#AssemblyExtensions.g.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler#Request_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/IncrementalTests.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection#AssemblyExtensions.g.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection#Request_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection#AssemblyExtensions.g.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection#Request_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection.verified.cs create mode 100644 tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.IgnoreHandlerAttribute#Request_Extensions.g.verified.cs delete mode 100644 tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.IgnoreHandlerAttribute.verified.cs diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 7b8f72d..312d424 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,8 +1,8 @@ - 1.0.0-alpha.8 - 1.0.0-alpha.8 + 1.0.0-alpha.9 + 1.0.0-alpha.9 Zapto https://github.com/zapto-dev/Mediator Copyright © 2023 Zapto diff --git a/src/Mediator.SourceGenerator/Extensions/EquatableArray.cs b/src/Mediator.SourceGenerator/Extensions/EquatableArray.cs new file mode 100644 index 0000000..9615094 --- /dev/null +++ b/src/Mediator.SourceGenerator/Extensions/EquatableArray.cs @@ -0,0 +1,234 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace Zapto.Mediator.Generator; + +/// +/// An immutable, equatable array. This is equivalent to but with value equality support. +/// +/// The type of values in the array. +internal readonly struct EquatableArray : IEquatable>, IEnumerable + where T : IEquatable +{ + public static readonly EquatableArray Empty = new(ImmutableArray.Empty); + + /// + /// The underlying array. + /// + private readonly T[]? _array; + + /// + /// Initializes a new instance of the struct. + /// + /// The input to wrap. + public EquatableArray(ImmutableArray array) + { + _array = Unsafe.As, T[]>(ref array); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The input to wrap. + public EquatableArray(T[]? array) + { + _array = array; + } + + /// + /// Gets the number of items in the array. + /// + public int Length + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => AsImmutableArray().Length; + } + + /// + /// Gets a value indicating whether the current array is empty. + /// + public bool IsEmpty + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => AsImmutableArray().IsEmpty; + } + + /// + /// Gets a reference to an item at a specified position within the array. + /// + /// The index of the item to retrieve a reference to. + /// A reference to an item at a specified position within the array. + public ref readonly T this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => ref AsImmutableArray().ItemRef(index); + } + + /// + /// Implicitly converts an to . + /// + /// An instance from a given . + public static implicit operator EquatableArray(ImmutableArray array) + { + return FromImmutableArray(array); + } + + /// + /// Implicitly converts an to . + /// + /// An instance from a given . + public static implicit operator ImmutableArray(EquatableArray array) + { + return array.AsImmutableArray(); + } + + /// + /// Checks whether two values are the same. + /// + /// The first value. + /// The second value. + /// Whether and are equal. + public static bool operator ==(EquatableArray left, EquatableArray right) + { + return left.Equals(right); + } + + /// + /// Checks whether two values are not the same. + /// + /// The first value. + /// The second value. + /// Whether and are not equal. + public static bool operator !=(EquatableArray left, EquatableArray right) + { + return !left.Equals(right); + } + + /// + /// Creates an instance from a given . + /// + /// The input instance. + /// An instance from a given . + public static EquatableArray FromImmutableArray(ImmutableArray array) + { + return new(array); + } + + /// + public bool Equals(EquatableArray array) + { + return AsSpan().SequenceEqual(array.AsSpan()); + } + + /// + public override bool Equals([NotNullWhen(true)] object? obj) + { + return obj is EquatableArray array && Equals(this, array); + } + + /// + public override int GetHashCode() + { + if (this._array is not T[] array) + { + return 0; + } + + HashCode hashCode = default; + + foreach (T item in array) + { + hashCode.Add(item); + } + + return hashCode.ToHashCode(); + } + + /// + /// Gets an instance from the current . + /// + /// The from the current . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ImmutableArray AsImmutableArray() + { + return _array is null ? ImmutableArray.Empty : Unsafe.As>(ref Unsafe.AsRef(in _array)); + } + + public EquatableArray Select(EquatableArray array, Func selector) + where TResult : IEquatable + { + var builder = new EquatableArrayBuilder(array.Length); + + foreach (var item in array) + { + builder.Add(selector(item)); + } + + return builder.ToEquatableArray(); + } + + /// + /// Returns a wrapping the current items. + /// + /// A wrapping the current items. + public ReadOnlySpan AsSpan() + { + return AsImmutableArray().AsSpan(); + } + + /// + /// Copies the contents of this instance to a mutable array. + /// + /// The newly instantiated array. + public T[] ToArray() + { + return AsImmutableArray().ToArray(); + } + + /// + /// Gets an value to traverse items in the current array. + /// + /// An value to traverse items in the current array. + public ImmutableArray.Enumerator GetEnumerator() + { + return AsImmutableArray().GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)AsImmutableArray()).GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)AsImmutableArray()).GetEnumerator(); + } +} + +/// +/// Extensions for . +/// +internal static class EquatableArray +{ + /// + /// Creates an instance from a given . + /// + /// The type of items in the input array. + /// The input instance. + /// An instance from a given . + public static EquatableArray AsEquatableArray(this ImmutableArray array) + where T : IEquatable + { + return new(array); + } +} \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/Extensions/EquatableArrayBuilder.cs b/src/Mediator.SourceGenerator/Extensions/EquatableArrayBuilder.cs new file mode 100644 index 0000000..1a05d1a --- /dev/null +++ b/src/Mediator.SourceGenerator/Extensions/EquatableArrayBuilder.cs @@ -0,0 +1,62 @@ +using System; +using System.Buffers; +using System.Collections.Immutable; + +namespace Zapto.Mediator.Generator; + +internal ref struct EquatableArrayBuilder where T : IEquatable +{ + private IMemoryOwner? _memory; + private int _index; + + public EquatableArrayBuilder() + { + } + + public EquatableArrayBuilder(int capacity) + { + _memory = MemoryPool.Shared.Rent(capacity); + } + + public int Count => _index; + + public void EnsureCapacity(int capacity) + { + if (_memory is null) + { + _memory = MemoryPool.Shared.Rent(capacity); + } + else if (_memory.Memory.Length < capacity) + { + var oldMemory = _memory; + + _memory = MemoryPool.Shared.Rent(capacity); + oldMemory.Memory.CopyTo(_memory.Memory); + oldMemory.Memory.Span.Clear(); + + oldMemory.Dispose(); + } + } + + public void Add(T item) + { + if (item is null) + { + throw new ArgumentNullException(nameof(item)); + } + + EnsureCapacity(_index + 1); + _memory!.Memory.Span[_index++] = item; + } + + public EquatableArray ToEquatableArray() + { + return _memory is null ? default : new EquatableArray(_memory.Memory.Slice(0, Count).ToArray()); + } + + public void Dispose() + { + _memory?.Memory.Span.Clear(); + _memory?.Dispose(); + } +} diff --git a/src/Mediator.SourceGenerator/Extensions/HashCode.cs b/src/Mediator.SourceGenerator/Extensions/HashCode.cs new file mode 100644 index 0000000..91c10bb --- /dev/null +++ b/src/Mediator.SourceGenerator/Extensions/HashCode.cs @@ -0,0 +1,205 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Security.Cryptography; + +#pragma warning disable CS0809 + +namespace Zapto.Mediator.Generator; + +/// +/// A polyfill type that mirrors some methods from on .NET 6. +/// +internal struct HashCode : IEquatable +{ + private const uint Prime1 = 2654435761U; + private const uint Prime2 = 2246822519U; + private const uint Prime3 = 3266489917U; + private const uint Prime4 = 668265263U; + private const uint Prime5 = 374761393U; + + private static readonly uint Seed = GenerateGlobalSeed(); + + private uint v1; + private uint v2; + private uint v3; + private uint v4; + private uint queue1; + private uint queue2; + private uint queue3; + private uint length; + + /// + /// Adds a single value to the current hash. + /// + /// The type of the value to add into the hash code. + /// The value to add into the hash code. + public void Add(T value) + { + Add(value?.GetHashCode() ?? 0); + } + + /// + /// Gets the resulting hashcode from the current instance. + /// + /// The resulting hashcode from the current instance. + public readonly int ToHashCode() + { + var length = this.length; + var position = length % 4; + var hash = length < 4 ? MixEmptyState() : MixState(this.v1, this.v2, this.v3, this.v4); + + hash += length * 4; + + if (position > 0) + { + hash = QueueRound(hash, this.queue1); + + if (position > 1) + { + hash = QueueRound(hash, this.queue2); + + if (position > 2) + { + hash = QueueRound(hash, this.queue3); + } + } + } + + hash = MixFinal(hash); + + return (int)hash; + } + + /// + [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", error: true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => throw new NotSupportedException(); + + /// + [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object? obj) => throw new NotSupportedException(); + + public bool Equals(HashCode other) + { + return this.v1 == other.v1 + && this.v2 == other.v2 + && this.v3 == other.v3 + && this.v4 == other.v4 + && this.queue1 == other.queue1 + && this.queue2 == other.queue2 + && this.queue3 == other.queue3 + && this.length == other.length; + } + + /// + /// Initializes the default seed. + /// + /// A random seed. + private static uint GenerateGlobalSeed() + { + var bytes = new byte[4]; + + using (var generator = RandomNumberGenerator.Create()) + { + generator.GetBytes(bytes); + } + + return BitConverter.ToUInt32(bytes, 0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4) + { + v1 = Seed + Prime1 + Prime2; + v2 = Seed + Prime2; + v3 = Seed; + v4 = Seed - Prime1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint Round(uint hash, uint input) + { + return RotateLeft(hash + (input * Prime2), 13) * Prime1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint QueueRound(uint hash, uint queuedValue) + { + return RotateLeft(hash + (queuedValue * Prime3), 17) * Prime4; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint MixState(uint v1, uint v2, uint v3, uint v4) + { + return RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint MixEmptyState() + { + return Seed + Prime5; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint MixFinal(uint hash) + { + hash ^= hash >> 15; + hash *= Prime2; + hash ^= hash >> 13; + hash *= Prime3; + hash ^= hash >> 16; + + return hash; + } + + /// + /// Rotates the specified value left by the specified number of bits. + /// Similar in behavior to the x86 instruction ROL. + /// + /// The value to rotate. + /// The number of bits to rotate by. + /// Any value outside the range [0..31] is treated as congruent mod 32. + /// The rotated value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint RotateLeft(uint value, int offset) + { + return (value << offset) | (value >> (32 - offset)); + } + + private void Add(int value) + { + var val = (uint)value; + var previousLength = this.length++; + var position = previousLength % 4; + + if (position == 0) + { + this.queue1 = val; + } + else if (position == 1) + { + this.queue2 = val; + } + else if (position == 2) + { + this.queue3 = val; + } + else + { + if (previousLength == 3) + { + Initialize(out this.v1, out this.v2, out this.v3, out this.v4); + } + + this.v1 = Round(this.v1, this.queue1); + this.v2 = Round(this.v2, this.queue2); + this.v3 = Round(this.v3, this.queue3); + this.v4 = Round(this.v4, val); + } + } +} \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/Extensions/IndentedStringBuilder.cs b/src/Mediator.SourceGenerator/Extensions/IndentedStringBuilder.cs new file mode 100644 index 0000000..eb2c293 --- /dev/null +++ b/src/Mediator.SourceGenerator/Extensions/IndentedStringBuilder.cs @@ -0,0 +1,178 @@ +using System; +using System.Text; + +namespace Zapto.Mediator.Generator; + +internal class IndentedStringBuilder +{ + private static readonly string[] IndentCache = new string[16]; + + static IndentedStringBuilder() + { + for (var i = 0; i < IndentCache.Length; i++) + { + IndentCache[i] = new string(' ', i * 4); + } + } + + private int _level; + private string _indent = string.Empty; + private bool _newLine = true; + + private int Level + { + get => _level; + set + { + if (_level == value) + { + return; + } + + _level = value; + _indent = IndentCache[value]; + } + } + + private StringBuilder Builder { get; } + + public int Length => Builder.Length; + + public char this[int index] + { + get => Builder[index]; + set => Builder[index] = value; + } + + public IndentedStringBuilder(int level = 0) + { + Level = level; + Builder = new StringBuilder(); + } + + public IndentedStringBuilder AppendLine() + { + return AppendLine(Environment.NewLine); + } + + private void WriteIndentIfNeeded() + { + if (_newLine) + { + Builder.Append(_indent); + _newLine = false; + } + } + + public IndentedStringBuilder Append(char c) + { + WriteIndentIfNeeded(); + Builder.Append(c); + return this; + } + + public IndentedStringBuilder Append(string? text) + { + if (text is null or "") + { + return this; + } + + if (text.HasNewLine()) + { + foreach (var line in text.GetLines()) + { + AppendLine(line); + } + } + else + { + WriteIndentIfNeeded(); + Builder.Append(text); + } + + return this; + } + + public IndentedStringBuilder AppendLine(string text) + { + if (text.HasNewLine()) + { + Append(text); + Builder.AppendLine(); + } + else + { + WriteIndentIfNeeded(); + Builder.AppendLine(text); + } + + _newLine = true; + return this; + } + + public IndentedStringBuilder AppendLine(ReadOnlySpan text) + { + WriteIndentIfNeeded(); + + var offset = Builder.Length; + + Builder.Length += text.Length; + + for (var i = 0; i < text.Length; i++) + { + Builder[offset + i] = text[i]; + } + + Builder.AppendLine(); + _newLine = true; + + return this; + } + + public IndentedStringBuilder Indent() + { + Level++; + return this; + } + + public IndentedStringBuilder Dedent() + { + Level--; + return this; + } + + /// + /// Write a new scope and take a lambda to write to the builder within it. This way it is easy to ensure the + /// scope is closed correctly. + /// + public DisposeCodeBlock CodeBlock(string openingLine = "", string open = "{", string close = "}") + { + if (!string.IsNullOrEmpty(openingLine)) + { + AppendLine(openingLine); + AppendLine(open); + } + else + { + AppendLine(open); + } + + Indent(); + return new DisposeCodeBlock(close, this); + } + + public override string ToString() + { + return Builder.ToString(); + } + + public readonly struct DisposeCodeBlock(string close, IndentedStringBuilder builder) : IDisposable + { + public void Dispose() + { + builder.Dedent(); + builder.AppendLine(close); + } + } +} diff --git a/src/Mediator.SourceGenerator/Extensions/SpanExtensions.cs b/src/Mediator.SourceGenerator/Extensions/SpanExtensions.cs new file mode 100644 index 0000000..094d107 --- /dev/null +++ b/src/Mediator.SourceGenerator/Extensions/SpanExtensions.cs @@ -0,0 +1,47 @@ +using System; + +namespace Zapto.Mediator.Generator; + +public static class SpanExtensions +{ + public static SpanSplitLinesEnumerator SplitLines(this ReadOnlySpan span) + { + return new SpanSplitLinesEnumerator(span); + } + + public ref struct SpanSplitLinesEnumerator(ReadOnlySpan remaining) + { + private ReadOnlySpan _remaining = remaining; + + public SpanSplitLinesEnumerator GetEnumerator() => this; + + public bool MoveNext() + { + var span = _remaining; + if (span.Length == 0) + { + return false; + } + + var index = span.IndexOfAny('\r', '\n'); + + if (index == -1) + { + _remaining = ReadOnlySpan.Empty; + Current = span; + return true; + } + + if (span[index] == '\r' && index + 1 < span.Length && span[index + 1] == '\n') + { + index++; + } + + Current = span.Slice(0, index); + _remaining = span.Slice(index + 1); + return true; + } + + public ReadOnlySpan Current { get; private set; } = default; + } +} diff --git a/src/Mediator.SourceGenerator/Extensions/StringBuilderExtensions.cs b/src/Mediator.SourceGenerator/Extensions/StringBuilderExtensions.cs index 0212293..1cd3e97 100644 --- a/src/Mediator.SourceGenerator/Extensions/StringBuilderExtensions.cs +++ b/src/Mediator.SourceGenerator/Extensions/StringBuilderExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Globalization; +using System.Linq; using System.Text; using Microsoft.CodeAnalysis; @@ -20,30 +21,10 @@ public static string GetNamespace(this ITypeSymbol? symbol) { var ns = symbol?.ContainingNamespace; - if (ns is null or { Name: null or null }) - { - return string.Empty; - } - - var sb = new StringBuilder(); - AppendNamespace(sb, ns.ContainingNamespace); - sb.Append(ns.Name); - return sb.ToString(); + return ns?.ToDisplayString() ?? ""; } - public static void AppendNamespace(this StringBuilder sb, INamespaceSymbol type) - { - if (type is {Name: null or ""}) - { - return; - } - - AppendNamespace(sb, type.ContainingNamespace); - sb.Append(type.Name); - sb.Append('.'); - } - - public static void AppendValue(this StringBuilder sb, object? value) + internal static void AppendValue(this IndentedStringBuilder sb, object? value) { sb.Append(value switch { @@ -55,11 +36,11 @@ public static void AppendValue(this StringBuilder sb, object? value) }); } - public static void AppendType( - this StringBuilder sb, - ITypeSymbol type, + internal static void AppendType( + this IndentedStringBuilder sb, + SimpleType type, bool addNullable = true, - Func? middleware = null, + Func? middleware = null, bool addGenericNames = true) { if (type is not {SpecialType: SpecialType.None}) @@ -73,7 +54,7 @@ public static void AppendType( return; } - if (type is ITypeParameterSymbol) + if (type.IsTypeParameter) { sb.Append(type.Name); addNullable = false; @@ -81,20 +62,26 @@ public static void AppendType( else { sb.Append("global::"); - AppendNamespace(sb, type.ContainingNamespace); + + if (type.Namespace is not null) + { + sb.Append(type.Namespace); + sb.Append('.'); + } + sb.Append(type.Name); } - if (type is INamedTypeSymbol {IsGenericType: true} namedTypeSymbol) + if (type.IsGenericType) { sb.Append('<'); - var length = namedTypeSymbol.TypeArguments.Length; + var length = type.TypeArguments.Length; for (var i = 0; i < length; i++) { if (addGenericNames) { - AppendType(sb, namedTypeSymbol.TypeArguments[i], false, middleware); + AppendType(sb, type.TypeArguments[i], false, middleware); if (i != length - 1) { @@ -119,12 +106,12 @@ type.Name is not ("Nullable" or "ValueTask") && } } - public static void AppendParameters( - this StringBuilder sb, - IReadOnlyList symbols, - Func? middleware = null) + internal static void AppendParameters( + this IndentedStringBuilder sb, + EquatableArray symbols, + Func? middleware = null) { - var length = symbols.Count; + var length = symbols.Length; for (var i = 0; i < length; i++) { var parameter = symbols[i]; @@ -141,12 +128,12 @@ public static void AppendParameters( } } - public static void AppendParameterDefinitions( - this StringBuilder sb, - IReadOnlyList symbols, - Func? middleware = null) + internal static void AppendParameterDefinitions( + this IndentedStringBuilder sb, + EquatableArray symbols, + Func? middleware = null) { - var length = symbols.Count; + var length = symbols.Length; for (var i = 0; i < length; i++) { @@ -179,4 +166,61 @@ public static void AppendParameterDefinitions( } } + + + internal static void AppendGenericConstraints(this IndentedStringBuilder sb, SimpleType type) + { + if (!type.IsGenericType) + { + return; + } + + foreach (var parameter in type.TypeParameters) + { + var valid = parameter.ConstraintTypes.Length > 0 || parameter.HasReferenceTypeConstraint || + parameter.HasValueTypeConstraint || + parameter.HasUnmanagedTypeConstraint || parameter.HasConstructorConstraint; + + if (!valid) + { + continue; + } + + sb.Append("where "); + sb.Append(parameter.Name); + sb.Append(" : "); + + int j; + for (j = 0; j < parameter.ConstraintTypes.Length; j++) + { + if (j > 1) sb.Append(", "); + sb.AppendType(parameter.ConstraintTypes[j], false); + } + + if (parameter.HasReferenceTypeConstraint) + { + if (j++ > 1) sb.Append(", "); + sb.Append("class"); + } + else if (parameter.HasValueTypeConstraint) + { + if (j++ > 1) sb.Append(", "); + sb.Append("struct"); + } + else if (parameter.HasUnmanagedTypeConstraint) + { + if (j++ > 1) sb.Append(", "); + sb.Append("unmanaged"); + } + + if (parameter.HasConstructorConstraint) + { + if (j > 1) sb.Append(", "); + sb.Append("new()"); + } + + sb.AppendLine(); + } + } + } diff --git a/src/Mediator.SourceGenerator/Extensions/StringExtensions.cs b/src/Mediator.SourceGenerator/Extensions/StringExtensions.cs index 95e7282..a99ac6b 100644 --- a/src/Mediator.SourceGenerator/Extensions/StringExtensions.cs +++ b/src/Mediator.SourceGenerator/Extensions/StringExtensions.cs @@ -1,7 +1,25 @@ -namespace Zapto.Mediator.Generator; +using System; + +namespace Zapto.Mediator.Generator; public static class StringExtensions { + /// Splits the specified based on line ending. + /// The input string to split. + /// An array of each line in the string. + public static SpanExtensions.SpanSplitLinesEnumerator GetLines(this string value) + { + return string.IsNullOrWhiteSpace(value) ? default : value.AsSpan().SplitLines(); + } + + /// Verifies if the string contains a new line. + /// The input string to check. + /// True if the string contains a new line, false otherwise. + public static bool HasNewLine(this string value) + { + return value.AsSpan().IndexOfAny('\r', '\n') != -1; + } + public static string RemoveSuffix(this string name, string suffix) { if (name.EndsWith(suffix) && name.Length != suffix.Length) diff --git a/src/Mediator.SourceGenerator/Mediator.SourceGenerator.csproj b/src/Mediator.SourceGenerator/Mediator.SourceGenerator.csproj index 9bde133..c9dac3d 100644 --- a/src/Mediator.SourceGenerator/Mediator.SourceGenerator.csproj +++ b/src/Mediator.SourceGenerator/Mediator.SourceGenerator.csproj @@ -4,7 +4,7 @@ Zapto.Mediator.SourceGenerator Zapto.Mediator.Generator netstandard2.0 - 10 + 12 false enable true diff --git a/src/Mediator.SourceGenerator/Models/ExtensionMethod.cs b/src/Mediator.SourceGenerator/Models/ExtensionMethod.cs new file mode 100644 index 0000000..9b9b820 --- /dev/null +++ b/src/Mediator.SourceGenerator/Models/ExtensionMethod.cs @@ -0,0 +1,8 @@ +namespace Zapto.Mediator.Generator; + +internal record struct ExtensionMethod( + SimpleType ContainingMethod, + SimpleType Type, + SimpleMethod Method, + (string Namespace, string Type) ParameterType +); \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/Models/ExtensionMethodReference.cs b/src/Mediator.SourceGenerator/Models/ExtensionMethodReference.cs index aa3f7db..7ac1ca9 100644 --- a/src/Mediator.SourceGenerator/Models/ExtensionMethodReference.cs +++ b/src/Mediator.SourceGenerator/Models/ExtensionMethodReference.cs @@ -3,22 +3,8 @@ namespace Zapto.Mediator.Generator; -public record struct ExtensionMethod( - INamedTypeSymbol Type, - IMethodSymbol Method, - (string Namespace, string Type) ParameterType, - INamedTypeSymbol? Constraint -); - -public record ExtensionMethodReference( +internal record ExtensionMethodReference( Accessibility Accessibility, - INamedTypeSymbol Type, - INamedTypeSymbol Interface, - List Methods -); - - -public record HandlerReference( - INamedTypeSymbol Type, - INamedTypeSymbol Interface -); + SimpleType Interface, + EquatableArray Methods +); \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/Models/HandlerReference.cs b/src/Mediator.SourceGenerator/Models/HandlerReference.cs new file mode 100644 index 0000000..4ebf880 --- /dev/null +++ b/src/Mediator.SourceGenerator/Models/HandlerReference.cs @@ -0,0 +1,5 @@ +namespace Zapto.Mediator.Generator; + +internal record HandlerReference( + SimpleType Interface +); \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/Models/SimpleConstructor.cs b/src/Mediator.SourceGenerator/Models/SimpleConstructor.cs new file mode 100644 index 0000000..828d8ca --- /dev/null +++ b/src/Mediator.SourceGenerator/Models/SimpleConstructor.cs @@ -0,0 +1,32 @@ +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace Zapto.Mediator.Generator; + +internal record SimpleConstructor( + byte DeclaredAccessibilityByte, + EquatableArray Parameters) +{ + public Accessibility DeclaredAccessibility => (Accessibility) DeclaredAccessibilityByte; + + public static EquatableArray FromArray(ImmutableArray constructors) + { + var builder = new EquatableArrayBuilder(constructors.Length); + + foreach (var constructor in constructors) + { + builder.Add(FromSymbol(constructor)); + } + + return builder.ToEquatableArray(); + } + + private static SimpleConstructor FromSymbol(IMethodSymbol constructor) + { + return new SimpleConstructor( + (byte)constructor.DeclaredAccessibility, + SimpleParameter.FromArray(constructor.Parameters) + ); + } +} diff --git a/src/Mediator.SourceGenerator/Models/SimpleMethod.cs b/src/Mediator.SourceGenerator/Models/SimpleMethod.cs new file mode 100644 index 0000000..c6694dc --- /dev/null +++ b/src/Mediator.SourceGenerator/Models/SimpleMethod.cs @@ -0,0 +1,36 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace Zapto.Mediator.Generator; + +internal record SimpleMethod( + string Name, + bool IsGenericMethod, + SimpleType ReturnType, + EquatableArray Parameters, + EquatableArray TypeParameters +) +{ + public static EquatableArray FromArray(ImmutableArray symbolMethods) + { + var builder = ImmutableArray.CreateBuilder(symbolMethods.Length); + + foreach (var symbolMethod in symbolMethods) + { + builder.Add(FromSymbol(symbolMethod)); + } + + return new EquatableArray(builder.MoveToImmutable()); + } + + public static SimpleMethod FromSymbol(IMethodSymbol symbol) + { + return new SimpleMethod( + symbol.Name, + symbol.IsGenericMethod, + SimpleType.FromSymbol(symbol.ReturnType), + SimpleParameter.FromArray(symbol.Parameters), + SimpleTypeParameter.FromArray(symbol.TypeParameters) + ); + } +} \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/Models/SimpleParameter.cs b/src/Mediator.SourceGenerator/Models/SimpleParameter.cs new file mode 100644 index 0000000..5e311a8 --- /dev/null +++ b/src/Mediator.SourceGenerator/Models/SimpleParameter.cs @@ -0,0 +1,35 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace Zapto.Mediator.Generator; + +internal record SimpleParameter( + string Name, + SimpleType Type, + bool HasExplicitDefaultValue, + object? ExplicitDefaultValue +) +{ + public static EquatableArray FromArray(ImmutableArray symbolParameters) + { + var builder = ImmutableArray.CreateBuilder(symbolParameters.Length); + + foreach (var symbolParameter in symbolParameters) + { + builder.Add(FromSymbol(symbolParameter)); + } + + return new EquatableArray(builder.MoveToImmutable()); + } + + private static SimpleParameter FromSymbol(IParameterSymbol parameter) + { + return new SimpleParameter( + parameter.Name, + SimpleType.FromSymbol(parameter.Type), + parameter.HasExplicitDefaultValue, + parameter.HasExplicitDefaultValue ? parameter.ExplicitDefaultValue : null + ); + } + +} \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/Models/SimpleType.cs b/src/Mediator.SourceGenerator/Models/SimpleType.cs new file mode 100644 index 0000000..886cfc7 --- /dev/null +++ b/src/Mediator.SourceGenerator/Models/SimpleType.cs @@ -0,0 +1,116 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace Zapto.Mediator.Generator; + +internal record SimpleType( + byte DeclaredAccessibilityByte, + byte NullableAnnotationByte, + sbyte SpecialTypeByte, + string Name, + bool IsGenericType, + bool IsTypeParameter, + bool IsValueType, + string? Namespace, + string ContainingAssembly, + EquatableArray TypeParameters, + EquatableArray TypeArguments, + EquatableArray Constructors +) +{ + public string UniqueId => Namespace is null ? Name : $"{Namespace.Replace('.', '_')}_{Name}"; + + public Accessibility DeclaredAccessibility => (Accessibility) DeclaredAccessibilityByte; + + public NullableAnnotation NullableAnnotation => (NullableAnnotation) NullableAnnotationByte; + + public SpecialType SpecialType => (SpecialType) SpecialTypeByte; + + public static EquatableArray FromArray(ImmutableArray symbolTypeParameters) + { + var builder = new EquatableArrayBuilder(symbolTypeParameters.Length); + + foreach (var symbolTypeParameter in symbolTypeParameters) + { + builder.Add(FromSymbol(symbolTypeParameter)); + } + + return builder.ToEquatableArray(); + } + + public static SimpleType FromSymbol(ITypeSymbol symbol, bool withConstructors = false) + { + if (symbol is not INamedTypeSymbol namedTypeSymbol) + { + return new SimpleType( + (byte)symbol.DeclaredAccessibility, + (byte)symbol.NullableAnnotation, + (sbyte)symbol.SpecialType, + symbol.Name, + false, + symbol is ITypeParameterSymbol, + symbol.IsValueType, + symbol.ContainingNamespace.IsGlobalNamespace ? null : symbol.GetNamespace(), + symbol.ContainingAssembly.Name, + EquatableArray.Empty, + EquatableArray.Empty, + EquatableArray.Empty + ); + } + + return new SimpleType( + (byte)namedTypeSymbol.DeclaredAccessibility, + (byte)namedTypeSymbol.NullableAnnotation, + (sbyte)namedTypeSymbol.SpecialType, + namedTypeSymbol.Name, + namedTypeSymbol.IsGenericType, + false, + namedTypeSymbol.IsValueType, + namedTypeSymbol.ContainingNamespace.IsGlobalNamespace ? null : namedTypeSymbol.GetNamespace(), + namedTypeSymbol.ContainingAssembly.Name, + SimpleTypeParameter.FromArray(namedTypeSymbol.TypeParameters), + FromArray(namedTypeSymbol.TypeArguments), + withConstructors? SimpleConstructor.FromArray(namedTypeSymbol.Constructors) : EquatableArray.Empty + ); + } + + public string ToDisplayString() + { + return SpecialType switch + { + SpecialType.System_Object => "object", + SpecialType.System_Enum => "enum", + SpecialType.System_Void => "void", + SpecialType.System_Boolean => "bool", + SpecialType.System_Char => "char", + SpecialType.System_SByte => "sbyte", + SpecialType.System_Byte => "byte", + SpecialType.System_Int16 => "short", + SpecialType.System_UInt16 => "ushort", + SpecialType.System_Int32 => "int", + SpecialType.System_UInt32 => "uint", + SpecialType.System_Int64 => "long", + SpecialType.System_UInt64 => "ulong", + SpecialType.System_Decimal => "decimal", + SpecialType.System_Single => "float", + SpecialType.System_Double => "double", + SpecialType.System_String => "string", + SpecialType.System_IntPtr => "nint", + SpecialType.System_UIntPtr => "nuint", + SpecialType.System_Array => $"{Namespace}.{Name}[]", + _ when Namespace is not null && IsGenericType => $"{Namespace}.{Name}<{string.Join(", ", TypeArguments)}>", + _ when Namespace is not null => $"{Namespace}.{Name}", + _ when IsGenericType => $"{Name}<{string.Join(", ", TypeArguments)}>", + _ => Name, + }; + } + + public override string ToString() => ToDisplayString(); + + public virtual bool SimpleEquals(SimpleType? other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Name == other.Name && Namespace == other.Namespace && ContainingAssembly == other.ContainingAssembly && TypeParameters.Equals(other.TypeParameters); + } +} \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/Models/SimpleTypeParameter.cs b/src/Mediator.SourceGenerator/Models/SimpleTypeParameter.cs new file mode 100644 index 0000000..1091288 --- /dev/null +++ b/src/Mediator.SourceGenerator/Models/SimpleTypeParameter.cs @@ -0,0 +1,42 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace Zapto.Mediator.Generator; + +internal record SimpleTypeParameter( + string Name, + EquatableArray ConstraintTypes, + ushort SpecialTypeShort, + bool HasReferenceTypeConstraint, + bool HasValueTypeConstraint, + bool HasUnmanagedTypeConstraint, + bool HasConstructorConstraint +) +{ + public SpecialType SpecialType => (SpecialType) SpecialTypeShort; + + public static EquatableArray FromArray(ImmutableArray symbolTypeParameters) + { + var builder = ImmutableArray.CreateBuilder(symbolTypeParameters.Length); + + foreach (var symbolTypeParameter in symbolTypeParameters) + { + builder.Add(FromSymbol(symbolTypeParameter)); + } + + return new EquatableArray(builder.MoveToImmutable()); + } + + private static SimpleTypeParameter FromSymbol(ITypeParameterSymbol parameter) + { + return new SimpleTypeParameter( + parameter.Name, + SimpleType.FromArray(parameter.ConstraintTypes), + (ushort)parameter.SpecialType, + parameter.HasReferenceTypeConstraint, + parameter.HasValueTypeConstraint, + parameter.HasUnmanagedTypeConstraint, + parameter.HasConstructorConstraint + ); + } +} \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/Models/SourceResult.cs b/src/Mediator.SourceGenerator/Models/SourceResult.cs new file mode 100644 index 0000000..52b6b52 --- /dev/null +++ b/src/Mediator.SourceGenerator/Models/SourceResult.cs @@ -0,0 +1,12 @@ +namespace Zapto.Mediator.Generator; + +internal record SourceResult( + SimpleType Type, + EquatableArray Requests, + EquatableArray Handlers +); + +internal record SourceWithHandlerResult( + SimpleType Type, + EquatableArray<(ExtensionMethodReference, SimpleType?)> Requests +); \ No newline at end of file diff --git a/src/Mediator.SourceGenerator/SenderGenerator.cs b/src/Mediator.SourceGenerator/SenderGenerator.cs index 924b0af..dd75d1e 100644 --- a/src/Mediator.SourceGenerator/SenderGenerator.cs +++ b/src/Mediator.SourceGenerator/SenderGenerator.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; +using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; @@ -13,45 +13,206 @@ namespace Zapto.Mediator.Generator; [Generator] public class SenderGenerator : IIncrementalGenerator { + private bool _generateAssemblyInfo; + private static readonly string[] Interfaces = { "Zapto.Mediator.ISender", "Zapto.Mediator.IPublisher" }; + public SenderGenerator() + : this(generateAssemblyInfo: true) + { + } + + public SenderGenerator(bool generateAssemblyInfo) + { + _generateAssemblyInfo = generateAssemblyInfo; + } + public void Initialize(IncrementalGeneratorInitializationContext context) { - var classDeclorations = context.SyntaxProvider + IncrementalValuesProvider results = context.SyntaxProvider .CreateSyntaxProvider( predicate: static (s, _) => s is ClassDeclarationSyntax or RecordDeclarationSyntax, - transform: static (ctx, _) => ctx.Node); + transform: static (ctx, _) => GetResult(ctx)) + .WithTrackingName("FindClasses") + .Where(static i => i is not null)!; + + var handlers = results + .SelectMany(GetAllHandlers) + .Collect(); + + var resultsWithHandlers = results + .Combine(handlers) + .Select(static (ctx, _) => + { + var builder = ImmutableArray.CreateBuilder<(ExtensionMethodReference, SimpleType?)>(ctx.Left.Requests.Length); + var requestType = ctx.Left.Type; + + foreach (var request in ctx.Left.Requests) + { + var (handlerType, _) = ctx.Right.FirstOrDefault(i => + request.Interface.Name == "IRequest" && + i.Handler.Interface.Name == "IRequestHandler" && + i.Handler.Interface.TypeArguments[0].SimpleEquals(requestType) && + i.Handler.Interface.TypeArguments[1].SimpleEquals(request.Interface.TypeArguments[0])); + + builder.Add((request, handlerType)); + } + + return new SourceWithHandlerResult( + Type: ctx.Left.Type, + Requests: builder.ToImmutable() + ); + }) + .WithTrackingName("FindHandlers")!; + + if (_generateAssemblyInfo) + { + context.RegisterSourceOutput(handlers, static (spc, source) => CreateAssemblyInfo(spc, source)); + } + + context.RegisterSourceOutput(resultsWithHandlers, static (spc, source) => CreateSource(spc, source)); + } + + private ImmutableArray<(SimpleType Type, HandlerReference Handler)> GetAllHandlers(SourceResult result, CancellationToken _) + { + if (result.Handlers.IsEmpty) + { + return ImmutableArray<(SimpleType, HandlerReference)>.Empty; + } + + var builder = new EquatableArrayBuilder<(SimpleType, HandlerReference)>(result.Handlers.Length); + + foreach (var handler in result.Handlers) + { + builder.Add((result.Type, handler)); + } + + return builder.ToEquatableArray(); + } + + private static void CreateAssemblyInfo(SourceProductionContext spc, ImmutableArray<(SimpleType, HandlerReference)> handlers) + { + if (handlers.IsEmpty) + { + return; + } + + const string builder = "global::Zapto.Mediator.IMediatorBuilder"; + + var sb = new IndentedStringBuilder(); + + sb.AppendLine(); - IncrementalValueProvider<(Compilation, ImmutableArray)> compilationAndClasses - = context.CompilationProvider.Combine(classDeclorations.Collect()); + using (sb.CodeBlock("namespace Zapto.Mediator")) + using (sb.CodeBlock("internal static class AssemblyExtensions")) + using (sb.CodeBlock($"public static {builder} AddAssemblyHandlers(this {builder} builder)")) + { + foreach (var (type, handler) in handlers) + { + if (handler.Interface.Name is "IRequestHandler") + { + sb.Append("builder.AddRequestHandler(typeof("); + sb.AppendType(type, addNullable: false, addGenericNames: false); + sb.AppendLine("));"); + } + else if (handler.Interface.Name == "INotificationHandler") + { + sb.Append("builder.AddNotificationHandler(typeof("); + sb.AppendType(type, addNullable: false, addGenericNames: false); + sb.AppendLine("));"); + } + else if (handler.Interface.Name == "IStreamRequestHandler") + { + sb.Append("builder.AddStreamRequestHandler(typeof("); + sb.AppendType(type, addNullable: false, addGenericNames: false); + sb.AppendLine("));"); + } + } + + sb.AppendLine("return builder;"); + } - context.RegisterSourceOutput(compilationAndClasses, - static (spc, source) => Execute(source.Item1, source.Item2, spc)); + spc.AddSource("AssemblyExtensions.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); } - public static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext context) + private static SourceResult? GetResult(GeneratorSyntaxContext context) { - var models = new Dictionary(); - var requests = new List(); - var handlers = new List(); + Accessibility accessibility; + BaseListSyntax? baseList; + + if (context.Node is ClassDeclarationSyntax classDeclaration) + { + accessibility = classDeclaration.Modifiers.GetAccessibility(); + baseList = classDeclaration.BaseList; + } + else if (context.Node is RecordDeclarationSyntax recordDeclaration) + { + accessibility = recordDeclaration.Modifiers.GetAccessibility(); + baseList = recordDeclaration.BaseList; + } + else + { + return null; + } - SemanticModel GetModel(SyntaxNode item) + if (baseList is null) { - var tree = item.SyntaxTree; + return null; + } + + var compilation = context.SemanticModel.Compilation; + Dictionary<(string Namespace, string Type), EquatableArray>? methodsByType = null; + + var symbol = (INamedTypeSymbol) context.SemanticModel.GetDeclaredSymbol(context.Node)!; + + var requests = new EquatableArrayBuilder(); + var handlers = new EquatableArrayBuilder(); + + foreach (var current in symbol.AllInterfaces) + { + if (current.Name is ("IRequest" or "INotification" or "IStreamRequest") && + (methodsByType ??= GetInterfaceMethods(compilation)).TryGetValue((current.GetNamespace(), current.Name), out var results) && + results.Any(i => i.Type.IsGenericType == current.IsGenericType && i.Type.TypeArguments.Length == current.TypeArguments.Length)) + { + requests.Add(new ExtensionMethodReference( + accessibility, + SimpleType.FromSymbol(current), + results + )); + } - if (!models.TryGetValue(tree, out var model)) + if (!symbol.IsAbstract && + current.IsGenericType && + current + is { Name: "IRequestHandler", TypeArguments.Length: 2 } + or { Name: "INotificationHandler", TypeArguments.Length: 1 } + or { Name: "IStreamRequestHandler", TypeArguments.Length: 2 } && + !symbol.GetAttributes().Any(i => i.AttributeClass?.Name == "IgnoreHandlerAttribute")) { - model = compilation.GetSemanticModel(tree); - models.Add(tree, model); + handlers.Add(new HandlerReference( + SimpleType.FromSymbol(current) + )); } + } - return model; + if (requests.Count == 0 && handlers.Count == 0) + { + return null; } + return new SourceResult( + Type: SimpleType.FromSymbol(symbol, withConstructors: true), + requests.ToEquatableArray(), + handlers.ToEquatableArray() + ); + } + + private static Dictionary<(string Namespace, string Type), EquatableArray> GetInterfaceMethods(Compilation compilation) + { var types = Interfaces .Select(i => compilation.GetTypeByMetadataName(i)!) .Where(i => i is not null) @@ -65,92 +226,31 @@ SemanticModel GetModel(SyntaxNode item) var type = m.TypeParameters[0].ConstraintTypes[0]; return new ExtensionMethod( - Type: i, - Method: m, + ContainingMethod: SimpleType.FromSymbol(m.ContainingType), + Type: SimpleType.FromSymbol(type), + Method: SimpleMethod.FromSymbol(m), ParameterType: ( Namespace: type.GetNamespace(), Type: type.Name - ), - type as INamedTypeSymbol + ) ); - })) - .ToList(); + })); var methodsByType = types .GroupBy(i => i.ParameterType) - .ToDictionary(g => g.Key, g => g.ToList()); - - foreach (var syntaxNode in classes.Distinct()) - { - Accessibility accessibility; - BaseListSyntax? baseList; - - if (syntaxNode is ClassDeclarationSyntax classDeclaration) - { - accessibility = classDeclaration.Modifiers.GetAccessibility(); - baseList = classDeclaration.BaseList; - } - else if (syntaxNode is RecordDeclarationSyntax recordDeclaration) - { - accessibility = recordDeclaration.Modifiers.GetAccessibility(); - baseList = recordDeclaration.BaseList; - } - else - { - continue; - } - - if (baseList is null) - { - continue; - } + .ToDictionary(g => g.Key, g => new EquatableArray(g.ToArray())); - var symbol = (INamedTypeSymbol) GetModel(syntaxNode).GetDeclaredSymbol(syntaxNode)!; - - foreach (var current in symbol.AllInterfaces) - { - if (methodsByType.TryGetValue((current.GetNamespace(), current.Name), out var results) && - results.Any(i => i.Constraint == null || i.Constraint.IsGenericType == current.IsGenericType && i.Constraint.TypeArguments.Length == current.TypeArguments.Length)) - { - requests.Add(new ExtensionMethodReference( - accessibility, - symbol, - current, - results - )); - } - - if (!symbol.IsAbstract && - current.IsGenericType && - current - is { Name: "IRequestHandler", TypeArguments.Length: 2 } - or { Name: "INotificationHandler", TypeArguments.Length: 1 } - or { Name: "IStreamRequestHandler", TypeArguments.Length: 2 } && - !symbol.GetAttributes().Any(i => i.AttributeClass?.Name == "IgnoreHandlerAttribute")) - { - handlers.Add(new HandlerReference( - symbol, - current - )); - } - } - } + return methodsByType; + } - if (requests.Count == 0) + internal static void CreateSource(SourceProductionContext context, SourceWithHandlerResult result) + { + if (result.Requests.IsEmpty) { return; } - var sb = new StringBuilder(); - var intentDepth = 0; - - void AppendIntend() - { - for (var i = 0; i < intentDepth; i++) - { - sb.Append(" "); - } - } + var sb = new IndentedStringBuilder(); bool TryGetVisibility(Accessibility visibility, [NotNullWhen(true)] out string? value) { @@ -168,70 +268,19 @@ bool TryGetVisibility(Accessibility visibility, [NotNullWhen(true)] out string? } } - void AppendGenericConstraints(ExtensionMethodReference request) - { - if (request.Type.IsGenericType) - { - var parameters = request.Type.TypeParameters - .Where(i => i.ConstraintTypes.Length > 0 || i.HasReferenceTypeConstraint || - i.HasValueTypeConstraint || - i.HasUnmanagedTypeConstraint || i.HasConstructorConstraint) - .ToArray(); - - foreach (var parameter in parameters) - { - AppendIntend(); - sb.Append("where "); - sb.Append(parameter.Name); - sb.Append(" : "); - - int j; - for (j = 0; j < parameter.ConstraintTypes.Length; j++) - { - if (j > 1) sb.Append(", "); - sb.AppendType(parameter.ConstraintTypes[j], false); - } - - if (parameter.HasReferenceTypeConstraint) - { - if (j++ > 1) sb.Append(", "); - sb.Append("class"); - } - else if (parameter.HasValueTypeConstraint) - { - if (j++ > 1) sb.Append(", "); - sb.Append("struct"); - } - else if (parameter.HasUnmanagedTypeConstraint) - { - if (j++ > 1) sb.Append(", "); - sb.Append("unmanaged"); - } - - if (parameter.HasConstructorConstraint) - { - if (j > 1) sb.Append(", "); - sb.Append("new()"); - } - - sb.AppendLine(); - } - } - } - - void AppendGenerics(ExtensionMethodReference request) + void AppendGenerics() { - if (!request.Type.IsGenericType) + if (!result.Type.IsGenericType) { return; } - - var length = request.Type.TypeParameters.Length; + + var length = result.Type.TypeParameters.Length; sb.Append('<'); for (var i = 0; i < length; i++) { - var parameter = request.Type.TypeParameters[i]; + var parameter = result.Type.TypeParameters[i]; sb.Append(parameter.Name); @@ -247,295 +296,231 @@ void AppendGenerics(ExtensionMethodReference request) sb.AppendLine("#nullable enable"); sb.AppendLine(); - // Dependency injection - if (compilation.GetTypeByMetadataName("Zapto.Mediator.ServiceProviderMediator") != null) + // Send message + if (result.Type.Namespace is not null) { - AppendIntend(); - sb.AppendLine("namespace Zapto.Mediator"); - AppendIntend(); + sb.Append("namespace "); + sb.AppendLine(result.Type.Namespace); sb.AppendLine("{"); - intentDepth++; - { - AppendIntend(); - var assemblyName = compilation.Assembly.Name.Replace('.', '_'); - sb.AppendLine("internal static class AssemblyExtensions_" + assemblyName); - AppendIntend(); - sb.AppendLine("{"); - intentDepth++; - - const string builder = "global::Zapto.Mediator.IMediatorBuilder"; - - AppendIntend(); - sb.AppendLine($"public static {builder} AddAssemblyHandlers(this {builder} builder)"); - AppendIntend(); - sb.AppendLine("{"); - intentDepth++; - - foreach (var handler in handlers) - { - AppendIntend(); - - if (handler.Interface.Name is "IRequestHandler") - { - sb.Append("builder.AddRequestHandler(typeof("); - sb.AppendType(handler.Type, addNullable: false, addGenericNames: false); - sb.AppendLine("));"); - } - else if (handler.Interface.Name == "INotificationHandler") - { - sb.Append("builder.AddNotificationHandler(typeof("); - sb.AppendType(handler.Type, addNullable: false, addGenericNames: false); - sb.AppendLine("));"); - } - else if (handler.Interface.Name == "IStreamRequestHandler") - { - sb.Append("builder.AddStreamRequestHandler(typeof("); - sb.AppendType(handler.Type, addNullable: false, addGenericNames: false); - sb.AppendLine("));"); - } - } - - AppendIntend(); - sb.AppendLine("return builder;"); - - intentDepth--; - AppendIntend(); - sb.AppendLine("}"); - } - intentDepth--; - AppendIntend(); - sb.AppendLine("}"); - - intentDepth--; - AppendIntend(); - sb.AppendLine("}"); - sb.AppendLine(); + sb.Indent(); } - // Send message - foreach (var group in requests.GroupBy(i => ( - Namespace: i.Type.ContainingNamespace is { Name: null or "" } ? "" : i.Type.ContainingNamespace.ToDisplayString(), - Assembly: i.Type.ContainingAssembly?.Name ?? "" - ))) - { - var hasNamespace = !string.IsNullOrWhiteSpace(group.Key.Namespace); + sb.AppendLine("public static partial class SenderExtensions"); + sb.AppendLine("{"); - intentDepth = hasNamespace ? 1 : 0; + sb.Indent(); - if (hasNamespace) + foreach (var (request, handlerType) in result.Requests) + { + void AddXmlDoc() { - sb.Append("namespace "); - sb.AppendLine(group.Key.Namespace); - sb.AppendLine("{"); + if (handlerType != null) + { + sb.AppendLine("/// "); + sb.Append("/// Sends a request to the handler ."); + sb.AppendLine("/// "); + } } - AppendIntend(); - var assemblyName = group.Key.Assembly.Replace('.', '_'); - sb.AppendLine($"public static class {assemblyName}SenderExtensions"); - - AppendIntend(); - sb.AppendLine("{"); - - intentDepth++; + var suffix = request.Interface.Name.RemovePrefix("I"); + var name = result.Type.Name.RemoveSuffix(suffix); + var typeNames = request.Interface.TypeParameters + .Select((t, i) => (t.Name, Value: request.Interface.TypeArguments[i])) + .ToDictionary(t => t.Name, t => t.Value); - foreach (var request in group) + for (var i = 0; i < request.Methods.Length; i++) { - var suffix = request.Interface.Name.RemovePrefix("I"); - var name = request.Type.Name.RemoveSuffix(suffix); - var typeNames = request.Interface.TypeParameters - .Select((t, i) => (t.Name, Value: request.Interface.TypeArguments[i])) - .ToDictionary(t => t.Name, t => t.Value); - - foreach (var (type, method, _, _) in request.Methods) + if (i > 0) { - var parameterName = method.TypeParameters[0].Name; - var skipConstructorWithoutParameters = request.Type.IsValueType && request.Type.Constructors.Any(i => i.Parameters.Length > 0); - + sb.AppendLine(); + } - void AppendMethodGenerics() + var (sender, type, method, _) = request.Methods[i]; + var parameterName = method.TypeParameters[0].Name; + var skipConstructorWithoutParameters = result.Type.IsValueType && + result.Type.Constructors.Any(i => i.Parameters.Length > 0); + + void AppendMethodGenerics() + { + if (method.IsGenericMethod) { - if (method.IsGenericMethod) + var length = method.TypeParameters.Length; + + sb.Append('<'); + for (var i = 0; i < length; i++) { - var length = method.TypeParameters.Length; + var parameter = method.TypeParameters[i]; - sb.Append('<'); - for (var i = 0; i < length; i++) + if (parameter.Name == parameterName) { - var parameter = method.TypeParameters[i]; - - if (parameter.Name == parameterName) - { - sb.AppendType(request.Type, false); - } - else if (typeNames.TryGetValue(parameter.Name, out var result)) - { - sb.AppendType(result, false); - } - - if (i != length - 1) - { - sb.Append(", "); - } + sb.AppendType(result.Type, false); + } + else if (typeNames.TryGetValue(parameter.Name, out var result)) + { + sb.AppendType(result, false); } - sb.Append('>'); + if (i != length - 1) + { + sb.Append(", "); + } } + + sb.Append('>'); } - - if (TryGetVisibility(request.Type.DeclaredAccessibility, out var visibilityValue)) - { - AppendIntend(); - sb.Append("[global::System.Diagnostics.DebuggerStepThrough] "); - sb.Append(visibilityValue); - sb.Append(" static "); - sb.AppendType(method.ReturnType, - addNullable: false, - middleware: t => - { - if (!typeNames.TryGetValue(t.Name, out var result)) - { - return false; - } - - sb.AppendType(result, addNullable: false); - return true; - }); - sb.Append(' '); - sb.Append(name); - sb.Append("Async"); - AppendGenerics(request); - sb.Append("(this "); - sb.AppendType(type, false); - sb.Append(" sender, "); - sb.AppendParameterDefinitions(method.Parameters, t => + } + + if (TryGetVisibility(result.Type.DeclaredAccessibility, out var visibilityValue)) + { + AddXmlDoc(); + sb.AppendLine("[global::System.Diagnostics.DebuggerStepThrough]"); + sb.Append(visibilityValue); + sb.Append(" static "); + sb.AppendType(method.ReturnType, + addNullable: false, + middleware: t => { - if (t.Type.Name == parameterName) + if (!typeNames.TryGetValue(t.Name, out var result)) { - sb.AppendType(request.Type, addNullable: false); - return AppendResult.Type; - } - - if (typeNames.TryGetValue(t.Type.Name, out var typeName)) - { - sb.AppendType(typeName); - return AppendResult.Type; + return false; } - return AppendResult.None; + sb.AppendType(result, addNullable: false); + return true; }); - sb.AppendLine(")"); - - intentDepth++; - - AppendGenericConstraints(request); - - AppendIntend(); - sb.Append("=> sender."); - sb.Append(method.Name); - AppendMethodGenerics(); - sb.Append('('); - sb.AppendParameters(method.Parameters); - sb.AppendLine(");"); - intentDepth--; - } - - foreach (var constructor in request.Type.Constructors) + sb.Append(' '); + sb.Append(name); + sb.Append("Async"); + AppendGenerics(); + sb.Append("(this "); + sb.AppendType(sender, false); + sb.Append(" sender, "); + sb.AppendParameterDefinitions(method.Parameters, t => { - if (skipConstructorWithoutParameters && constructor.Parameters.Length == 0) + if (t.Type.Name == parameterName) { - continue; + sb.AppendType(result.Type, addNullable: false); + return AppendResult.Type; } - var visibility = constructor.DeclaredAccessibility.GetLowest(request.Accessibility); - - if (!TryGetVisibility(visibility, out visibilityValue)) + if (typeNames.TryGetValue(t.Type.Name, out var typeName)) { - continue; + sb.AppendType(typeName); + return AppendResult.Type; } - AppendIntend(); - sb.Append("[global::System.Diagnostics.DebuggerStepThrough] "); - sb.Append(visibilityValue); - sb.Append(" static "); - sb.AppendType(method.ReturnType, - addNullable: false, - middleware: t => - { - if (!typeNames.TryGetValue(t.Name, out var result)) - { - return false; - } - - sb.AppendType(result, addNullable: false); - return true; - }); - - sb.Append(' '); - sb.Append(name); - sb.Append("Async"); - AppendGenerics(request); - sb.Append("(this "); - sb.AppendType(type, false); - sb.Append(" sender, "); - sb.AppendParameterDefinitions(method.Parameters, t => - { - if (t.Type.Name == parameterName) - { - sb.AppendParameterDefinitions(constructor.Parameters); - return AppendResult.TypeAndName; - } + return AppendResult.None; + }); + sb.AppendLine(")"); - if (typeNames.TryGetValue(t.Type.Name, out var typeName)) - { - sb.AppendType(typeName); - return AppendResult.Type; - } + sb.Indent(); + sb.AppendGenericConstraints(result.Type); + sb.Dedent(); - return AppendResult.None; - }); - sb.AppendLine(")"); + sb.Append("=> sender."); + sb.Append(method.Name); + AppendMethodGenerics(); + sb.Append('('); + sb.AppendParameters(method.Parameters); + sb.AppendLine(");"); + } - intentDepth++; + foreach (var constructor in result.Type.Constructors) + { + if (skipConstructorWithoutParameters && constructor.Parameters.Length == 0) + { + continue; + } - AppendGenericConstraints(request); + var visibility = constructor.DeclaredAccessibility.GetLowest(request.Accessibility); - AppendIntend(); - sb.Append("=> sender."); - sb.Append(method.Name); - AppendMethodGenerics(); + if (!TryGetVisibility(visibility, out visibilityValue)) + { + continue; + } - sb.Append('('); - sb.AppendParameters(method.Parameters, t => + sb.AppendLine(); + AddXmlDoc(); + sb.AppendLine("[global::System.Diagnostics.DebuggerStepThrough]"); + sb.Append(visibilityValue); + sb.Append(" static "); + sb.AppendType(method.ReturnType, + addNullable: false, + middleware: t => { - if (t.Type.Name != parameterName) + if (!typeNames.TryGetValue(t.Name, out var result)) { return false; } - sb.Append("new "); - sb.AppendType(request.Type, false); - sb.Append('('); - sb.AppendParameters(constructor.Parameters); - sb.Append(')'); + sb.AppendType(result, addNullable: false); return true; }); - sb.AppendLine(");"); - intentDepth--; - } + + sb.Append(' '); + sb.Append(name); + sb.Append("Async"); + AppendGenerics(); + sb.Append("(this "); + sb.AppendType(sender, false); + sb.Append(" sender, "); + sb.AppendParameterDefinitions(method.Parameters, t => + { + if (t.Type.Name == parameterName) + { + sb.AppendParameterDefinitions(constructor.Parameters); + return AppendResult.TypeAndName; + } + + if (typeNames.TryGetValue(t.Type.Name, out var typeName)) + { + sb.AppendType(typeName); + return AppendResult.Type; + } + + return AppendResult.None; + }); + sb.AppendLine(")"); + + sb.Indent(); + sb.AppendGenericConstraints(result.Type); + sb.Dedent(); + + sb.Append("=> sender."); + sb.Append(method.Name); + AppendMethodGenerics(); + + sb.Append('('); + sb.AppendParameters(method.Parameters, t => + { + if (t.Type.Name != parameterName) + { + return false; + } + + sb.Append("new "); + sb.AppendType(result.Type, false); + sb.Append('('); + sb.AppendParameters(constructor.Parameters); + sb.Append(')'); + return true; + }); + sb.AppendLine(");"); } } + } - intentDepth--; + sb.Dedent(); + sb.AppendLine("}"); - AppendIntend(); + if (result.Type.Namespace is not null) + { + sb.Dedent(); sb.AppendLine("}"); - - if (hasNamespace) - { - sb.AppendLine("}"); - } } - context.AddSource("MediatorExtensions.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); + context.AddSource($"{result.Type.UniqueId}_Extensions.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); } } diff --git a/src/Mediator/Mediator.csproj b/src/Mediator/Mediator.csproj index fe0e027..7e50a08 100644 --- a/src/Mediator/Mediator.csproj +++ b/src/Mediator/Mediator.csproj @@ -13,13 +13,14 @@ - + + diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGeneric#Request_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGeneric#Request_Extensions.g.verified.cs new file mode 100644 index 0000000..b6ceac1 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGeneric#Request_Extensions.g.verified.cs @@ -0,0 +1,21 @@ +//HintName: Request_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, T>(request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, T Argument, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, T>(new global::Request(Argument), cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, T>(ns, request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, T Argument, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, T>(ns, new global::Request(Argument), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGeneric.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGeneric.verified.cs deleted file mode 100644 index ae962b7..0000000 --- a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGeneric.verified.cs +++ /dev/null @@ -1,14 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, T>(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, T Argument, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, T>(new global::Request(Argument), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, T>(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, T Argument, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, T>(ns, new global::Request(Argument), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraint#Request_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraint#Request_Extensions.g.verified.cs new file mode 100644 index 0000000..108e990 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraint#Request_Extensions.g.verified.cs @@ -0,0 +1,25 @@ +//HintName: Request_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + where T : global::MediatR.IRequest + => sender.Send, T>(request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, T Argument, global::System.Threading.CancellationToken cancellationToken = default) + where T : global::MediatR.IRequest + => sender.Send, T>(new global::Request(Argument), cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + where T : global::MediatR.IRequest + => sender.Send, T>(ns, request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, T Argument, global::System.Threading.CancellationToken cancellationToken = default) + where T : global::MediatR.IRequest + => sender.Send, T>(ns, new global::Request(Argument), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraint.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraint.verified.cs deleted file mode 100644 index e413ac9..0000000 --- a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraint.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - where T : global::MediatR.IRequest - => sender.Send, T>(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, T Argument, global::System.Threading.CancellationToken cancellationToken = default) - where T : global::MediatR.IRequest - => sender.Send, T>(new global::Request(Argument), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - where T : global::MediatR.IRequest - => sender.Send, T>(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, T Argument, global::System.Threading.CancellationToken cancellationToken = default) - where T : global::MediatR.IRequest - => sender.Send, T>(ns, new global::Request(Argument), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraintClass#Request_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraintClass#Request_Extensions.g.verified.cs new file mode 100644 index 0000000..cfc5d24 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraintClass#Request_Extensions.g.verified.cs @@ -0,0 +1,25 @@ +//HintName: Request_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + where T : class + => sender.Send, T>(request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, T Argument, global::System.Threading.CancellationToken cancellationToken = default) + where T : class + => sender.Send, T>(new global::Request(Argument), cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + where T : class + => sender.Send, T>(ns, request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, T Argument, global::System.Threading.CancellationToken cancellationToken = default) + where T : class + => sender.Send, T>(ns, new global::Request(Argument), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraintClass.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraintClass.verified.cs deleted file mode 100644 index ed505b3..0000000 --- a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericConstraintClass.verified.cs +++ /dev/null @@ -1,18 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - where T : class - => sender.Send, T>(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, T Argument, global::System.Threading.CancellationToken cancellationToken = default) - where T : class - => sender.Send, T>(new global::Request(Argument), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - where T : class - => sender.Send, T>(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, T Argument, global::System.Threading.CancellationToken cancellationToken = default) - where T : class - => sender.Send, T>(ns, new global::Request(Argument), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericDifferentResult#Request_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericDifferentResult#Request_Extensions.g.verified.cs new file mode 100644 index 0000000..b572087 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericDifferentResult#Request_Extensions.g.verified.cs @@ -0,0 +1,21 @@ +//HintName: Request_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, string>(request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, T Argument, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, string>(new global::Request(Argument), cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, string>(ns, request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, T Argument, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, string>(ns, new global::Request(Argument), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericDifferentResult.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericDifferentResult.verified.cs deleted file mode 100644 index b582dce..0000000 --- a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateGenericDifferentResult.verified.cs +++ /dev/null @@ -1,14 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, string>(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, T Argument, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, string>(new global::Request(Argument), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, string>(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, T Argument, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, string>(ns, new global::Request(Argument), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateNotification#Notification_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateNotification#Notification_Extensions.g.verified.cs new file mode 100644 index 0000000..4cee280 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateNotification#Notification_Extensions.g.verified.cs @@ -0,0 +1,21 @@ +//HintName: Notification_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Notification notification, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Publish(notification, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Publish(new global::Notification(Argument, OptionalArgument), cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Zapto.Mediator.MediatorNamespace ns, global::Notification notification, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Publish(ns, notification, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Zapto.Mediator.MediatorNamespace ns, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Publish(ns, new global::Notification(Argument, OptionalArgument), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateNotification.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateNotification.verified.cs deleted file mode 100644 index 5fa1eea..0000000 --- a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateNotification.verified.cs +++ /dev/null @@ -1,14 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Notification notification, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Publish(notification, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Publish(new global::Notification(Argument, OptionalArgument), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Zapto.Mediator.MediatorNamespace ns, global::Notification notification, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Publish(ns, notification, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Zapto.Mediator.MediatorNamespace ns, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Publish(ns, new global::Notification(Argument, OptionalArgument), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateRequest#Request_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateRequest#Request_Extensions.g.verified.cs new file mode 100644 index 0000000..64f96ac --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateRequest#Request_Extensions.g.verified.cs @@ -0,0 +1,21 @@ +//HintName: Request_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(new global::Request(Argument, OptionalArgument), cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(ns, request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(ns, new global::Request(Argument, OptionalArgument), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateRequest.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateRequest.verified.cs deleted file mode 100644 index 6dfda75..0000000 --- a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateRequest.verified.cs +++ /dev/null @@ -1,14 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(new global::Request(Argument, OptionalArgument), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(ns, new global::Request(Argument, OptionalArgument), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStream#StreamRequest_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStream#StreamRequest_Extensions.g.verified.cs new file mode 100644 index 0000000..d43ed93 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStream#StreamRequest_Extensions.g.verified.cs @@ -0,0 +1,21 @@ +//HintName: StreamRequest_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Collections.Generic.IAsyncEnumerable StreamRequestAsync(this global::Zapto.Mediator.ISender sender, global::StreamRequest request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.CreateStream(request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Collections.Generic.IAsyncEnumerable StreamRequestAsync(this global::Zapto.Mediator.ISender sender, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) + => sender.CreateStream(new global::StreamRequest(Argument, OptionalArgument), cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Collections.Generic.IAsyncEnumerable StreamRequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::StreamRequest request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.CreateStream(ns, request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Collections.Generic.IAsyncEnumerable StreamRequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) + => sender.CreateStream(ns, new global::StreamRequest(Argument, OptionalArgument), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStream.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStream.verified.cs deleted file mode 100644 index a86ee57..0000000 --- a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStream.verified.cs +++ /dev/null @@ -1,14 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Collections.Generic.IAsyncEnumerable StreamRequestAsync(this global::Zapto.Mediator.ISender sender, global::StreamRequest request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.CreateStream(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Collections.Generic.IAsyncEnumerable StreamRequestAsync(this global::Zapto.Mediator.ISender sender, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) - => sender.CreateStream(new global::StreamRequest(Argument, OptionalArgument), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Collections.Generic.IAsyncEnumerable StreamRequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::StreamRequest request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.CreateStream(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Collections.Generic.IAsyncEnumerable StreamRequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) - => sender.CreateStream(ns, new global::StreamRequest(Argument, OptionalArgument), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStructNotification#Notification_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStructNotification#Notification_Extensions.g.verified.cs new file mode 100644 index 0000000..4cee280 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStructNotification#Notification_Extensions.g.verified.cs @@ -0,0 +1,21 @@ +//HintName: Notification_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Notification notification, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Publish(notification, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Publish(new global::Notification(Argument, OptionalArgument), cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Zapto.Mediator.MediatorNamespace ns, global::Notification notification, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Publish(ns, notification, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Zapto.Mediator.MediatorNamespace ns, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Publish(ns, new global::Notification(Argument, OptionalArgument), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStructNotification.verified.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStructNotification.verified.cs deleted file mode 100644 index 5fa1eea..0000000 --- a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.GenerateStructNotification.verified.cs +++ /dev/null @@ -1,14 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Notification notification, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Publish(notification, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Publish(new global::Notification(Argument, OptionalArgument), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Zapto.Mediator.MediatorNamespace ns, global::Notification notification, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Publish(ns, notification, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask NotificationAsync(this global::Zapto.Mediator.IPublisher sender, global::Zapto.Mediator.MediatorNamespace ns, string Argument, int OptionalArgument = 0, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Publish(ns, new global::Notification(Argument, OptionalArgument), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.cs b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.cs index 677c965..8eeeb58 100644 --- a/tests/Mediator.SourceGenerator.Tests/GeneratorTests.cs +++ b/tests/Mediator.SourceGenerator.Tests/GeneratorTests.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using VerifyTests; using Zapto.Mediator.Generator; using VerifyXunit; using Xunit; diff --git a/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateAddAssemblyHandlers.received.cs b/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateAddAssemblyHandlers.received.cs deleted file mode 100644 index 1371675..0000000 --- a/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateAddAssemblyHandlers.received.cs +++ /dev/null @@ -1,10 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(new global::Request(), cancellationToken); - public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(ns, new global::Request(), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateAddAssemblyHandlers.verified.cs b/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateAddAssemblyHandlers.verified.cs deleted file mode 100644 index 5f28270..0000000 --- a/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateAddAssemblyHandlers.verified.cs +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler#AssemblyExtensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler#AssemblyExtensions.g.verified.cs new file mode 100644 index 0000000..fb98cb5 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler#AssemblyExtensions.g.verified.cs @@ -0,0 +1,13 @@ +//HintName: AssemblyExtensions.g.cs + +namespace Zapto.Mediator +{ + internal static class AssemblyExtensions + { + public static global::Zapto.Mediator.IMediatorBuilder AddAssemblyHandlers(this global::Zapto.Mediator.IMediatorBuilder builder) + { + builder.AddRequestHandler(typeof(global::RequestHandler)); + return builder; + } + } +} diff --git a/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler#Request_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler#Request_Extensions.g.verified.cs new file mode 100644 index 0000000..b8ef3e5 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler#Request_Extensions.g.verified.cs @@ -0,0 +1,33 @@ +//HintName: Request_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(request, cancellationToken); + + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(new global::Request(), cancellationToken); + + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(ns, request, cancellationToken); + + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(ns, new global::Request(), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler.verified.cs b/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler.verified.cs deleted file mode 100644 index e193d57..0000000 --- a/tests/Mediator.SourceGenerator.Tests/HandlerTests.GenerateHandler.verified.cs +++ /dev/null @@ -1,14 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(new global::Request(), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(ns, new global::Request(), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/IncrementalTests.cs b/tests/Mediator.SourceGenerator.Tests/IncrementalTests.cs new file mode 100644 index 0000000..b0aef50 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/IncrementalTests.cs @@ -0,0 +1,133 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using MediatR; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Xunit; +using Zapto.Mediator; +using Zapto.Mediator.Generator; + +namespace Mediator.SourceGenerator.Tests; + +public class IncrementalGeneratorTests +{ + [Theory] + + [InlineData( + IncrementalStepRunReason.Unchanged, + IncrementalStepRunReason.Cached, + """ + using MediatR; + + public record Request(T Argument) : IRequest; + """, + """ + using MediatR; + + public record Request(T Argument) : IRequest + { + public int OptionalArgument { get; set; } + } + """)] + + [InlineData( + IncrementalStepRunReason.Modified, + IncrementalStepRunReason.Modified, + """ + using MediatR; + + public record Request(T Argument) : IRequest; + """, + """ + using MediatR; + + public record Request(T Argument, int ExtraArgument) : IRequest; + """)] + + [InlineData( + IncrementalStepRunReason.Unchanged, + IncrementalStepRunReason.Modified, + """ + using MediatR; + + public record Request : IRequest; + """, + """ + using MediatR; + using Zapto.Mediator; + + public record Request : IRequest; + + public class RequestHandler : IRequestHandler + { + public ValueTask Handle(IServiceProvider provider, Request request, CancellationToken cancellationToken) + { + return default; + } + } + """)] + + [InlineData( + IncrementalStepRunReason.Unchanged, + IncrementalStepRunReason.Unchanged, + """ + using MediatR; + + public record Request : IRequest; + """, + """ + using MediatR; + using Zapto.Mediator; + + public record Request : IRequest; + + public record OtherRequest : IRequest; + + public class OtherRequestHandler : IRequestHandler + { + public ValueTask Handle(IServiceProvider provider, OtherRequest request, CancellationToken cancellationToken) + { + return default; + } + } + """)] + + public void CheckGeneratorIsIncremental( + IncrementalStepRunReason executeStepReason, + IncrementalStepRunReason combineStepReason, + string source, + string sourceUpdated) + { + SyntaxTree baseSyntaxTree = CSharpSyntaxTree.ParseText(source); + + Compilation compilation = CSharpCompilation.Create( + "compilation", + new[] { baseSyntaxTree }, + new[] + { + MetadataReference.CreateFromFile(typeof(IRequest).Assembly.Location), + MetadataReference.CreateFromFile(typeof(IMediator).Assembly.Location), + }, + new CSharpCompilationOptions(OutputKind.ConsoleApplication)); + + ISourceGenerator sourceGenerator = new SenderGenerator( + generateAssemblyInfo: false + ).AsSourceGenerator(); + + GeneratorDriver driver = CSharpGeneratorDriver.Create( + generators: new[] { sourceGenerator }, + driverOptions: new GeneratorDriverOptions(default, trackIncrementalGeneratorSteps: true)); + + // Run the generator + driver = driver.RunGenerators(compilation); + + // Update the compilation and rerun the generator + compilation = compilation.ReplaceSyntaxTree(baseSyntaxTree, CSharpSyntaxTree.ParseText(sourceUpdated)); + driver = driver.RunGenerators(compilation); + + GeneratorRunResult result = driver.GetRunResult().Results.Single(); + Assert.Equal(executeStepReason, result.TrackedSteps["FindClasses"].First().Outputs[0].Reason); + Assert.Equal(combineStepReason, result.TrackedSteps["FindHandlers"].First().Outputs[0].Reason); + } +} \ No newline at end of file diff --git a/tests/Mediator.SourceGenerator.Tests/Mediator.SourceGenerator.Tests.csproj b/tests/Mediator.SourceGenerator.Tests/Mediator.SourceGenerator.Tests.csproj index 91d392d..6da934e 100644 --- a/tests/Mediator.SourceGenerator.Tests/Mediator.SourceGenerator.Tests.csproj +++ b/tests/Mediator.SourceGenerator.Tests/Mediator.SourceGenerator.Tests.csproj @@ -5,23 +5,25 @@ enable false + + 11 - - - - + + + + - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/Mediator.SourceGenerator.Tests/ModuleInitializer.cs b/tests/Mediator.SourceGenerator.Tests/ModuleInitializer.cs index aac7501..fbfc36c 100644 --- a/tests/Mediator.SourceGenerator.Tests/ModuleInitializer.cs +++ b/tests/Mediator.SourceGenerator.Tests/ModuleInitializer.cs @@ -8,6 +8,6 @@ public static class ModuleInitializer [ModuleInitializer] public static void Init() { - VerifySourceGenerators.Enable(); + VerifySourceGenerators.Initialize(); } } diff --git a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection#AssemblyExtensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection#AssemblyExtensions.g.verified.cs new file mode 100644 index 0000000..fb98cb5 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection#AssemblyExtensions.g.verified.cs @@ -0,0 +1,13 @@ +//HintName: AssemblyExtensions.g.cs + +namespace Zapto.Mediator +{ + internal static class AssemblyExtensions + { + public static global::Zapto.Mediator.IMediatorBuilder AddAssemblyHandlers(this global::Zapto.Mediator.IMediatorBuilder builder) + { + builder.AddRequestHandler(typeof(global::RequestHandler)); + return builder; + } + } +} diff --git a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection#Request_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection#Request_Extensions.g.verified.cs new file mode 100644 index 0000000..b8ef3e5 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection#Request_Extensions.g.verified.cs @@ -0,0 +1,33 @@ +//HintName: Request_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(request, cancellationToken); + + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(new global::Request(), cancellationToken); + + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(ns, request, cancellationToken); + + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(ns, new global::Request(), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection.verified.cs b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection.verified.cs deleted file mode 100644 index d798afc..0000000 --- a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateCollection.verified.cs +++ /dev/null @@ -1,26 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -namespace Zapto.Mediator -{ - internal static class AssemblyExtensions_Tests - { - public static global::Zapto.Mediator.IMediatorBuilder AddAssemblyHandlers(this global::Zapto.Mediator.IMediatorBuilder builder) - { - builder.AddRequestHandler(typeof(global::RequestHandler)); - return builder; - } - } -} - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(new global::Request(), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(ns, new global::Request(), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection#AssemblyExtensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection#AssemblyExtensions.g.verified.cs new file mode 100644 index 0000000..43f5639 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection#AssemblyExtensions.g.verified.cs @@ -0,0 +1,13 @@ +//HintName: AssemblyExtensions.g.cs + +namespace Zapto.Mediator +{ + internal static class AssemblyExtensions + { + public static global::Zapto.Mediator.IMediatorBuilder AddAssemblyHandlers(this global::Zapto.Mediator.IMediatorBuilder builder) + { + builder.AddRequestHandler(typeof(global::RequestHandler<>)); + return builder; + } + } +} diff --git a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection#Request_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection#Request_Extensions.g.verified.cs new file mode 100644 index 0000000..d0d9df6 --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection#Request_Extensions.g.verified.cs @@ -0,0 +1,33 @@ +//HintName: Request_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, global::MediatR.Unit>(request, cancellationToken); + + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, global::MediatR.Unit>(new global::Request(), cancellationToken); + + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, global::MediatR.Unit>(ns, request, cancellationToken); + + /// + /// Sends a request to the handler . + /// + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send, global::MediatR.Unit>(ns, new global::Request(), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection.verified.cs b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection.verified.cs deleted file mode 100644 index 71a6d91..0000000 --- a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.GenerateGenericCollection.verified.cs +++ /dev/null @@ -1,26 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -namespace Zapto.Mediator -{ - internal static class AssemblyExtensions_Tests - { - public static global::Zapto.Mediator.IMediatorBuilder AddAssemblyHandlers(this global::Zapto.Mediator.IMediatorBuilder builder) - { - builder.AddRequestHandler(typeof(global::RequestHandler<>)); - return builder; - } - } -} - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, global::MediatR.Unit>(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, global::MediatR.Unit>(new global::Request(), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, global::MediatR.Unit>(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send, global::MediatR.Unit>(ns, new global::Request(), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.IgnoreHandlerAttribute#Request_Extensions.g.verified.cs b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.IgnoreHandlerAttribute#Request_Extensions.g.verified.cs new file mode 100644 index 0000000..382e43f --- /dev/null +++ b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.IgnoreHandlerAttribute#Request_Extensions.g.verified.cs @@ -0,0 +1,21 @@ +//HintName: Request_Extensions.g.cs +#nullable enable + +public static partial class SenderExtensions +{ + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(new global::Request(), cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(ns, request, cancellationToken); + + [global::System.Diagnostics.DebuggerStepThrough] + public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::System.Threading.CancellationToken cancellationToken = default) + => sender.Send(ns, new global::Request(), cancellationToken); +} diff --git a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.IgnoreHandlerAttribute.verified.cs b/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.IgnoreHandlerAttribute.verified.cs deleted file mode 100644 index 33a48b4..0000000 --- a/tests/Mediator.SourceGenerator.Tests/ServiceCollectionTests.IgnoreHandlerAttribute.verified.cs +++ /dev/null @@ -1,25 +0,0 @@ -//HintName: MediatorExtensions.g.cs -#nullable enable - -namespace Zapto.Mediator -{ - internal static class AssemblyExtensions_Tests - { - public static global::Zapto.Mediator.IMediatorBuilder AddAssemblyHandlers(this global::Zapto.Mediator.IMediatorBuilder builder) - { - return builder; - } - } -} - -public static class TestsSenderExtensions -{ - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(new global::Request(), cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::Request request, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(ns, request, cancellationToken); - [global::System.Diagnostics.DebuggerStepThrough] public static global::System.Threading.Tasks.ValueTask RequestAsync(this global::Zapto.Mediator.ISender sender, global::Zapto.Mediator.MediatorNamespace ns, global::System.Threading.CancellationToken cancellationToken = default) - => sender.Send(ns, new global::Request(), cancellationToken); -} diff --git a/tests/Mediator.SourceGenerator.Tests/TestHelper.cs b/tests/Mediator.SourceGenerator.Tests/TestHelper.cs index b8e282f..b8232d7 100644 --- a/tests/Mediator.SourceGenerator.Tests/TestHelper.cs +++ b/tests/Mediator.SourceGenerator.Tests/TestHelper.cs @@ -1,5 +1,8 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; using System.Threading.Tasks; using Zapto.Mediator; using MediatR; @@ -30,8 +33,8 @@ public static Task Verify(string source, params Type[] extraTypes) CSharpCompilation compilation = CSharpCompilation.Create( assemblyName: "Tests", syntaxTrees: new[] { syntaxTree }, - references: references); - + references: references, + options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); var generator = new TGenerator();