< Summary

Information
Class: Chronicler.ChronicleContext
Assembly: Chronicler
File(s): /home/runner/work/Chronicler/Chronicler/src/Chronicler/Context/ChronicleContext.cs
Line coverage
100%
Covered lines: 57
Uncovered lines: 0
Coverable lines: 57
Total lines: 113
Line coverage: 100%
Branch coverage
95%
Covered branches: 19
Total branches: 20
Branch coverage: 95%
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_Links()100%11100%
QueueDeferredLink(...)100%11100%
ResolveDeferredLinks()100%1414100%
.ctor(...)50%22100%
TryResolve(...)100%22100%
Describe()100%22100%

File(s)

/home/runner/work/Chronicler/Chronicler/src/Chronicler/Context/ChronicleContext.cs

#LineLine coverage
 1using SwiftCollections;
 2using System;
 3using System.Text;
 4
 5namespace Chronicler;
 6
 7/// <summary>
 8/// Carries session-scoped serialization services such as stable link resolution.
 9/// </summary>
 10public sealed class ChronicleContext
 11{
 10112    private readonly SwiftList<IDeferredRecordLink> _deferredLinks = new();
 13
 14    /// <summary>
 15    /// Creates a new context with an empty link registry.
 16    /// </summary>
 10117    public ChronicleContext()
 10118    {
 10119        Links = new ChronicleLinkRegistry();
 10120    }
 21
 22    /// <summary>
 23    /// Gets the registry used to save and load stable links to external or runtime-owned objects.
 24    /// </summary>
 7425    public ChronicleLinkRegistry Links { get; }
 26
 27    internal void QueueDeferredLink<T>(string name, string id, string? slot, Action<T> assignLoadedValue)
 628    {
 629        _deferredLinks.Add(new DeferredRecordLink<T>(name, id, slot, assignLoadedValue));
 630    }
 31
 32    /// <summary>
 33    /// Attempts to resolve all deferred links queued during loading.
 34    /// </summary>
 35    public void ResolveDeferredLinks()
 4036    {
 4037        if (_deferredLinks.Count == 0)
 3438            return;
 39
 840        while (_deferredLinks.Count > 0)
 641        {
 642            int resolvedCount = 0;
 2443            for (int i = _deferredLinks.Count - 1; i >= 0; i--)
 644            {
 645                if (!_deferredLinks[i].TryResolve(Links))
 446                    continue;
 47
 248                _deferredLinks.RemoveAt(i);
 249                resolvedCount++;
 250            }
 51
 652            if (resolvedCount == 0)
 453                break;
 254        }
 55
 656        if (_deferredLinks.Count == 0)
 257            return;
 58
 459        var builder = new StringBuilder();
 460        builder.Append("Unable to resolve deferred links:");
 2061        foreach (IDeferredRecordLink deferredLink in _deferredLinks)
 462        {
 463            builder.Append(' ');
 464            builder.Append('[');
 465            builder.Append(deferredLink.Describe());
 466            builder.Append(']');
 467        }
 68
 469        throw new InvalidOperationException(builder.ToString());
 3670    }
 71
 72    private interface IDeferredRecordLink
 73    {
 74        bool TryResolve(ChronicleLinkRegistry registry);
 75
 76        string Describe();
 77    }
 78
 79    private sealed class DeferredRecordLink<T> : IDeferredRecordLink
 80    {
 81        private readonly string _name;
 82        private readonly string _id;
 83        private readonly string? _slot;
 84        private readonly Action<T> _assignLoadedValue;
 85
 686        public DeferredRecordLink(string name, string id, string? slot, Action<T> assignLoadedValue)
 687        {
 688            _name = name;
 689            _id = id;
 690            _slot = slot;
 691            _assignLoadedValue = assignLoadedValue ?? throw new ArgumentNullException(nameof(assignLoadedValue));
 692        }
 93
 94        public bool TryResolve(ChronicleLinkRegistry registry)
 695        {
 96            T? value;
 697            if (!registry.TryResolve(_id, out value, _slot))
 498                return false;
 99
 2100            _assignLoadedValue(value!);
 2101            return true;
 6102        }
 103
 104        public string Describe()
 4105        {
 4106            string typeName = typeof(T).Name;
 4107            if (string.IsNullOrEmpty(_slot))
 2108                return $"{_name}:{typeName}:{_id}";
 109
 2110            return $"{_name}:{typeName}:{_id}@{_slot}";
 4111        }
 112    }
 113}