< Summary

Information
Class: NGql.Core.Abstractions.NamedFragmentDefinition
Assembly: NGql.Core
File(s): /home/runner/work/NGql/NGql/src/Core/Abstractions/NamedFragmentDefinition.cs
Line coverage
100%
Covered lines: 21
Uncovered lines: 0
Coverable lines: 21
Total lines: 108
Line coverage: 100%
Branch coverage
100%
Covered branches: 16
Total branches: 16
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%44100%
get_Name()100%11100%
get_OnType()100%11100%
get_Fields()100%22100%
GetOrCreateFieldsStore()100%22100%
get_InlineFragments()100%22100%
get_SpreadFragments()100%22100%
.cctor()100%11100%
Equals(...)100%44100%
GetHashCode()100%11100%

File(s)

/home/runner/work/NGql/NGql/src/Core/Abstractions/NamedFragmentDefinition.cs

#LineLine coverage
 1using System.Diagnostics.CodeAnalysis;
 2using System.Text.Json.Serialization;
 3
 4namespace NGql.Core.Abstractions;
 5
 6/// <summary>
 7///     Represents a GraphQL named fragment — a reusable selection set declared at the operation
 8///     top level and referenced from one or more field selection sets via the <c>...Name</c>
 9///     spread syntax. Renders as <c>fragment Name on TypeName { … }</c> after the operation
 10///     block.
 11/// </summary>
 12/// <remarks>
 13///     Named fragments live on <see cref="QueryDefinition.NamedFragments"/> (operation-scoped),
 14///     not on <see cref="FieldDefinition.InlineFragments"/> (field-scoped). They are referenced
 15///     from a field's selection set by adding the fragment's <see cref="Name"/> to
 16///     <see cref="FieldDefinition.SpreadFragments"/>; the renderer emits <c>...Name</c> at
 17///     each spread site.
 18///
 19///     Naming follows the GraphQL spec: ASCII letters, digits, and underscores; first character
 20///     must be a letter or underscore. Validation is intentionally minimal — invalid names
 21///     render verbatim and the server rejects them with a clear error.
 22/// </remarks>
 23[SuppressMessage("Minor Code Smell", "S2292:Trivial properties should be auto-implemented")]
 24public sealed record NamedFragmentDefinition
 25{
 26    internal FieldChildren? _fields;
 27    internal Dictionary<string, InlineFragmentDefinition>? _fragments;
 28    internal List<string>? _spreadFragments;
 29
 30    /// <summary>
 31    /// Creates a named fragment with the given <paramref name="name"/> on <paramref name="onType"/>
 32    /// and no children.
 33    /// </summary>
 34    /// <param name="name">The fragment's identifier, used at spread sites (<c>...Name</c>).
 35    /// Cannot be null or whitespace.</param>
 36    /// <param name="onType">The GraphQL type the fragment is declared on. Rendered verbatim
 37    /// after <c>fragment Name on </c>.</param>
 27638    public NamedFragmentDefinition(string name, string onType)
 39    {
 27640        if (string.IsNullOrWhiteSpace(name))
 41        {
 942            throw new ArgumentException("Named fragment name cannot be null or whitespace.", nameof(name));
 43        }
 26744        if (string.IsNullOrWhiteSpace(onType))
 45        {
 946            throw new ArgumentException("Named fragment type name cannot be null or whitespace.", nameof(onType));
 47        }
 48
 25849        Name = name;
 25850        OnType = onType;
 25851    }
 52
 53    /// <summary>
 54    /// The fragment's identifier. Used by spreads (<see cref="FieldDefinition.SpreadFragments"/>)
 55    /// to reference this fragment.
 56    /// </summary>
 57    [JsonPropertyName("name")]
 50458    public string Name { get; init; }
 59
 60    /// <summary>
 61    /// The GraphQL type the fragment is declared on. Rendered verbatim after <c>fragment Name on </c>.
 62    /// </summary>
 63    [JsonPropertyName("onType")]
 50764    public string OnType { get; init; }
 65
 66    /// <summary>
 67    /// Fields selected by this fragment.
 68    /// </summary>
 69    [JsonPropertyName("fields")]
 70    public IReadOnlyDictionary<string, FieldDefinition> Fields
 1571        => (IReadOnlyDictionary<string, FieldDefinition>?)_fields ?? EmptyFields;
 72
 73    /// <summary>
 74    /// Get-or-add the underlying <see cref="FieldChildren"/> store. Internal so the builder
 75    /// can pass a stable reference when the user's lambda adds fields to the fragment.
 76    /// </summary>
 77    internal FieldChildren GetOrCreateFieldsStore()
 20478        => _fields ??= new FieldChildren();
 79
 80    /// <summary>
 81    /// Inline fragments inside this named fragment's selection set. Useful when the fragment's
 82    /// fields themselves return union/interface types that need further narrowing.
 83    /// </summary>
 84    [JsonPropertyName("inlineFragments")]
 85    public IReadOnlyDictionary<string, InlineFragmentDefinition> InlineFragments
 1286        => (IReadOnlyDictionary<string, InlineFragmentDefinition>?)_fragments ?? EmptyFragments;
 87
 88    /// <summary>
 89    /// Names of other <see cref="NamedFragmentDefinition"/>s spread inside this fragment's
 90    /// selection set. See <see cref="FieldDefinition.SpreadFragments"/> for the contract.
 91    /// </summary>
 92    [JsonPropertyName("spreadFragments")]
 93    public IReadOnlyList<string> SpreadFragments
 694        => (IReadOnlyList<string>?)_spreadFragments ?? EmptySpreadFragments;
 95
 396    private static readonly IReadOnlyDictionary<string, FieldDefinition> EmptyFields = new Dictionary<string, FieldDefin
 397    private static readonly IReadOnlyDictionary<string, InlineFragmentDefinition> EmptyFragments = new Dictionary<string
 398    private static readonly IReadOnlyList<string> EmptySpreadFragments = Array.Empty<string>();
 99
 100    public bool Equals(NamedFragmentDefinition? other)
 101    {
 24102        if (other is null) return false;
 21103        if (ReferenceEquals(this, other)) return true;
 15104        return string.Equals(Name, other.Name, StringComparison.Ordinal);
 105    }
 106
 6107    public override int GetHashCode() => StringComparer.Ordinal.GetHashCode(Name);
 108}