< Summary

Information
Class: NexusLabs.Needlr.Generators.Models.GeneratedConstructorModel
Assembly: NexusLabs.Needlr.Generators
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Generators/Models/Constructors/GeneratedConstructorModel.cs
Line coverage
100%
Covered lines: 39
Uncovered lines: 0
Coverable lines: 39
Total lines: 129
Line coverage: 100%
Branch coverage
90%
Covered branches: 20
Total branches: 22
Branch coverage: 90.9%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_ContainingNamespace()100%11100%
get_ContainingTypeName()100%11100%
get_TypeParameterList()100%11100%
get_Arity()100%11100%
get_NullGuardMode()100%11100%
get_Fields()100%11100%
get_SourceFilePath()100%11100%
Equals(...)100%1212100%
Equals(...)50%22100%
GetHashCode()75%44100%
op_Equality(...)100%11100%
op_Inequality(...)100%11100%
FieldsEqual(...)100%44100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.Generators/Models/Constructors/GeneratedConstructorModel.cs

#LineLine coverage
 1using System;
 2using System.Linq;
 3
 4namespace NexusLabs.Needlr.Generators.Models;
 5
 6/// <summary>
 7/// The complete shared model describing a generated constructor for a single partial
 8/// class. Consumed by both source emission and Needlr's type-registry constructor
 9/// discovery so both agree on the effective constructor shape.
 10/// </summary>
 11/// <remarks>
 12/// Implements value equality (rather than the default struct member-by-member
 13/// reflection-based comparison) — in particular <see cref="Fields"/> is compared
 14/// element-by-element rather than by array reference — so that the incremental
 15/// generator pipeline can cache this model across unrelated edits: an edit to one
 16/// type's fields must not force every other eligible type's model to be considered
 17/// "changed" just because a new (but equal) model instance was rebuilt for it.
 18/// </remarks>
 19internal readonly struct GeneratedConstructorModel : IEquatable<GeneratedConstructorModel>
 20{
 21    public GeneratedConstructorModel(
 22        string containingNamespace,
 23        string containingTypeName,
 24        string typeParameterList,
 25        int arity,
 26        GeneratedConstructorNullGuardMode nullGuardMode,
 27        EligibleConstructorField[] fields,
 28        string? sourceFilePath)
 29    {
 15530        ContainingNamespace = containingNamespace;
 15531        ContainingTypeName = containingTypeName;
 15532        TypeParameterList = typeParameterList;
 15533        Arity = arity;
 15534        NullGuardMode = nullGuardMode;
 15535        Fields = fields;
 15536        SourceFilePath = sourceFilePath;
 15537    }
 38
 39    /// <summary>
 40    /// The containing namespace, or an empty string for the global namespace.
 41    /// </summary>
 47242    public string ContainingNamespace { get; }
 43
 44    /// <summary>
 45    /// The simple containing type name, without namespace or type parameters.
 46    /// </summary>
 55847    public string ContainingTypeName { get; }
 48
 49    /// <summary>
 50    /// The type parameter list syntax (e.g. <c>&lt;T&gt;</c>), or an empty string for
 51    /// non-generic types.
 52    /// </summary>
 38053    public string TypeParameterList { get; }
 54
 55    /// <summary>
 56    /// The type's generic arity (number of type parameters). Used, alongside
 57    /// <see cref="ContainingNamespace"/> and <see cref="ContainingTypeName"/>, as a
 58    /// deterministic hint-name discriminator so that two distinct types sharing the
 59    /// same namespace and name but different arity (e.g. <c>Foo</c> and
 60    /// <c>Foo&lt;T&gt;</c>) never collide on the same generated file name — the same
 61    /// discriminator the CLR itself uses to distinguish same-named generic arities
 62    /// within a namespace.
 63    /// </summary>
 20264    public int Arity { get; }
 65
 66    /// <summary>
 67    /// The class-level null-guard mode in effect for this constructor.
 68    /// </summary>
 21169    public GeneratedConstructorNullGuardMode NullGuardMode { get; }
 70
 71    /// <summary>
 72    /// Eligible fields, in deterministic declaration order, that become constructor
 73    /// parameters.
 74    /// </summary>
 97375    public EligibleConstructorField[] Fields { get; }
 76
 77    /// <summary>
 78    /// The source file path of the containing type declaration, used for breadcrumbs.
 79    /// </summary>
 11080    public string? SourceFilePath { get; }
 81
 82    public bool Equals(GeneratedConstructorModel other)
 83    {
 5884        return string.Equals(ContainingNamespace, other.ContainingNamespace, StringComparison.Ordinal) &&
 5885            string.Equals(ContainingTypeName, other.ContainingTypeName, StringComparison.Ordinal) &&
 5886            string.Equals(TypeParameterList, other.TypeParameterList, StringComparison.Ordinal) &&
 5887            Arity == other.Arity &&
 5888            NullGuardMode == other.NullGuardMode &&
 5889            string.Equals(SourceFilePath, other.SourceFilePath, StringComparison.Ordinal) &&
 5890            FieldsEqual(Fields, other.Fields);
 91    }
 92
 293    public override bool Equals(object? obj) => obj is GeneratedConstructorModel other && Equals(other);
 94
 95    public override int GetHashCode()
 96    {
 97        unchecked
 98        {
 499            var hash = ContainingNamespace.GetHashCode();
 4100            hash = (hash * 397) ^ ContainingTypeName.GetHashCode();
 4101            hash = (hash * 397) ^ TypeParameterList.GetHashCode();
 4102            hash = (hash * 397) ^ Arity;
 4103            hash = (hash * 397) ^ (int)NullGuardMode;
 4104            hash = (hash * 397) ^ (SourceFilePath?.GetHashCode() ?? 0);
 105
 16106            foreach (var field in Fields)
 107            {
 4108                hash = (hash * 397) ^ field.GetHashCode();
 109            }
 110
 4111            return hash;
 112        }
 113    }
 114
 1115    public static bool operator ==(GeneratedConstructorModel left, GeneratedConstructorModel right) => left.Equals(right
 116
 1117    public static bool operator !=(GeneratedConstructorModel left, GeneratedConstructorModel right) => !left.Equals(righ
 118
 119    private static bool FieldsEqual(EligibleConstructorField[] left, EligibleConstructorField[] right)
 120    {
 52121        if (ReferenceEquals(left, right))
 9122            return true;
 123
 43124        if (left.Length != right.Length)
 3125            return false;
 126
 40127        return left.SequenceEqual(right);
 128    }
 129}