< Summary

Information
Class: NexusLabs.Needlr.Generators.ConstructorGuardAttribute
Assembly: NexusLabs.Needlr.Generators.Attributes
File(s): /_work/nick-alienware-needlr-1-1784953859-3e8997/needlr/needlr/src/NexusLabs.Needlr.Generators.Attributes/ConstructorGuardAttribute.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 13
Coverable lines: 13
Total lines: 149
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
.ctor(...)100%210%
.ctor(...)100%210%
get_Kind()100%210%
get_GuardType()100%210%
get_MethodName()100%210%

File(s)

/_work/nick-alienware-needlr-1-1784953859-3e8997/needlr/needlr/src/NexusLabs.Needlr.Generators.Attributes/ConstructorGuardAttribute.cs

#LineLine coverage
 1using System;
 2
 3namespace NexusLabs.Needlr.Generators;
 4
 5/// <summary>
 6/// Requests a constructor guard clause for a field participating in generated
 7/// constructor generation or a property participating in a generated positional-record
 8/// constructor overload.
 9/// </summary>
 10/// <remarks>
 11/// <para>
 12/// On an eligible field, applying this attribute with any kind other than
 13/// <see cref="ConstructorGuardKind.None"/>, or with a custom guard type, is itself a
 14/// positive trigger: it enables constructor generation with
 15/// <see cref="ConstructorNullGuardMode.None"/> even if the containing class does not
 16/// carry <see cref="GenerateConstructorAttribute"/>. On a property, the guard is valid
 17/// only when the property also carries
 18/// <see cref="RecordConstructorOverloadParameterAttribute"/>; a property guard does not
 19/// trigger an overload by itself.
 20/// </para>
 21/// <para>
 22/// A custom guard type must expose an accessible <see langword="static"/> method
 23/// compatible with <c>void Validate(T value, string parameterName)</c>, where
 24/// <c>T</c> is compatible with the guarded member's type. The generator emits a
 25/// direct, fully-qualified call to that method -- never a reflection-based invocation.
 26/// </para>
 27/// <para>
 28/// This attribute may be applied more than once to the same field or participating
 29/// property to request several
 30/// guards additively. The class-level default guard (when applicable) is always
 31/// composed first, followed by every explicit <see cref="ConstructorGuardAttribute"/>
 32/// in source declaration order. Identical effective guard calls -- the same built-in
 33/// <see cref="ConstructorGuardKind"/>, or the same resolved custom guard type and
 34/// method -- are emitted only once even if requested more than once.
 35/// </para>
 36/// </remarks>
 37/// <example>
 38/// <code>
 39/// public partial class TenantService
 40/// {
 41///     [ConstructorGuard(ConstructorGuardKind.NotNullOrWhiteSpace)]
 42///     private readonly string _tenantName;
 43/// }
 44/// </code>
 45/// <code>
 46/// public partial class OrderService
 47/// {
 48///     [ConstructorGuard(typeof(CollectionNotEmptyGuard))]
 49///     private readonly IReadOnlyCollection&lt;Order&gt; _orders;
 50/// }
 51///
 52/// // Generated call: CollectionNotEmptyGuard.Validate(orders, nameof(orders));
 53/// </code>
 54/// <code>
 55/// public partial class RetryPolicy
 56/// {
 57///     [ConstructorGuard(typeof(NumberGuards), nameof(NumberGuards.ValidatePositive))]
 58///     private readonly int _retryCount;
 59/// }
 60///
 61/// // Generated call: NumberGuards.ValidatePositive(retryCount, nameof(retryCount));
 62/// </code>
 63/// <code>
 64/// public partial class OrderService
 65/// {
 66///     [ConstructorGuard(ConstructorGuardKind.NotNullOrWhiteSpace)]
 67///     [ConstructorGuard(typeof(OrderIdFormatGuard))]
 68///     private readonly string _orderId;
 69/// }
 70///
 71/// // Generated calls, in declaration order:
 72/// // global::System.ArgumentException.ThrowIfNullOrWhiteSpace(orderId);
 73/// // OrderIdFormatGuard.Validate(orderId, nameof(orderId));
 74/// </code>
 75/// <code>
 76/// public partial record PreparedRequest(string Query)
 77/// {
 78///     [RecordConstructorOverloadParameter]
 79///     [ConstructorGuard(ConstructorGuardKind.NotNull)]
 80///     public PreparedScope? PreparedScope { get; init; }
 81/// }
 82/// </code>
 83/// </example>
 84[AttributeUsage(
 85    AttributeTargets.Field | AttributeTargets.Property,
 86    Inherited = false,
 87    AllowMultiple = true)]
 88public sealed class ConstructorGuardAttribute : Attribute
 89{
 90    /// <summary>
 91    /// Initializes a new instance of the <see cref="ConstructorGuardAttribute"/> class
 92    /// requesting a built-in guard kind.
 93    /// </summary>
 94    /// <param name="kind">The built-in guard clause to emit for this member.</param>
 095    public ConstructorGuardAttribute(ConstructorGuardKind kind)
 96    {
 097        Kind = kind;
 098    }
 99
 100    /// <summary>
 101    /// Initializes a new instance of the <see cref="ConstructorGuardAttribute"/> class
 102    /// requesting a custom guard type using the conventional <c>Validate</c> method.
 103    /// </summary>
 104    /// <param name="guardType">
 105    /// A type exposing an accessible <see langword="static"/> method named
 106    /// <c>Validate</c>, compatible with <c>void Validate(T value, string parameterName)</c>.
 107    /// </param>
 0108    public ConstructorGuardAttribute(Type guardType)
 109    {
 0110        GuardType = guardType;
 0111    }
 112
 113    /// <summary>
 114    /// Initializes a new instance of the <see cref="ConstructorGuardAttribute"/> class
 115    /// requesting a custom guard type and an explicit validation method name.
 116    /// </summary>
 117    /// <param name="guardType">
 118    /// A type exposing an accessible <see langword="static"/> method matching
 119    /// <paramref name="methodName"/>, compatible with
 120    /// <c>void Validate(T value, string parameterName)</c>.
 121    /// </param>
 122    /// <param name="methodName">
 123    /// The name of the static validation method to call, typically supplied via
 124    /// <see langword="nameof"/>.
 125    /// </param>
 0126    public ConstructorGuardAttribute(Type guardType, string methodName)
 127    {
 0128        GuardType = guardType;
 0129        MethodName = methodName;
 0130    }
 131
 132    /// <summary>
 133    /// Gets the requested built-in guard kind, or <see cref="ConstructorGuardKind.None"/>
 134    /// when a custom <see cref="GuardType"/> was supplied instead.
 135    /// </summary>
 0136    public ConstructorGuardKind Kind { get; }
 137
 138    /// <summary>
 139    /// Gets the custom guard type supplied to this attribute, or
 140    /// <see langword="null"/> when a built-in <see cref="Kind"/> was supplied instead.
 141    /// </summary>
 0142    public Type? GuardType { get; }
 143
 144    /// <summary>
 145    /// Gets the explicit validation method name supplied to this attribute, or
 146    /// <see langword="null"/> when the conventional <c>Validate</c> method name applies.
 147    /// </summary>
 0148    public string? MethodName { get; }
 149}