< Summary

Information
Class: SwiftCollections.Diagnostics.DiagnosticInterpolatedStringHandler
Assembly: SwiftCollections
File(s): /home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Diagnostics/DiagnosticInterpolatedStringHandler.cs
Line coverage
100%
Covered lines: 52
Uncovered lines: 0
Coverable lines: 52
Total lines: 332
Line coverage: 100%
Branch coverage
100%
Covered branches: 26
Total branches: 26
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%22100%
.ctor(...)100%22100%
get_IsEnabled()100%11100%
AppendLiteral(...)100%22100%
AppendFormatted(...)100%22100%
AppendFormatted(...)100%22100%
AppendFormatted(...)100%22100%
AppendFormatted(...)100%22100%
AppendFormatted(...)100%22100%
AppendFormatted(...)100%22100%
AppendFormatted(...)100%22100%
AppendFormatted(...)100%22100%
AppendFormatted(...)100%22100%
AppendFormatted(...)100%22100%
GetFormattedText()100%11100%

File(s)

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Diagnostics/DiagnosticInterpolatedStringHandler.cs

#LineLine coverage
 1//=======================================================================
 2// DiagnosticInterpolatedStringHandler.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024–present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8namespace SwiftCollections.Diagnostics;
 9
 10using System;
 11using System.Runtime.CompilerServices;
 12using System.Text;
 13
 14/// <summary>
 15/// Builds diagnostic messages for enabled diagnostic levels while allowing disabled levels
 16/// to skip formatted interpolation expression evaluation.
 17/// </summary>
 18[InterpolatedStringHandler]
 19public ref struct DiagnosticInterpolatedStringHandler
 20{
 21    private readonly bool _isEnabled;
 22#if NET6_0_OR_GREATER
 23    private DefaultInterpolatedStringHandler _builder;
 24#else
 25    private StringBuilder? _builder;
 26#endif
 27
 28    /// <summary>
 29    /// Initializes a new instance of the <see cref="DiagnosticInterpolatedStringHandler"/> struct.
 30    /// </summary>
 31    /// <param name="literalLength">The combined length of literal portions in the interpolated string.</param>
 32    /// <param name="formattedCount">The number of formatted expressions in the interpolated string.</param>
 33    /// <param name="channel">The diagnostic channel that will receive the message.</param>
 34    /// <param name="level">The severity level being evaluated.</param>
 35    /// <param name="isEnabled">
 36    /// Set to <c>true</c> when formatted expressions should be evaluated; otherwise, <c>false</c>.
 37    /// </param>
 38    public DiagnosticInterpolatedStringHandler(
 39        int literalLength,
 40        int formattedCount,
 41        DiagnosticChannel channel,
 42        DiagnosticLevel level,
 43        out bool isEnabled)
 5944        : this(literalLength, formattedCount, channel != null && channel.IsEnabled(level), out isEnabled)
 45    {
 5946    }
 47
 48    internal DiagnosticInterpolatedStringHandler(
 49        int literalLength,
 50        int formattedCount,
 51        bool shouldFormat,
 52        out bool isEnabled)
 53    {
 6254        isEnabled = shouldFormat;
 6255        _isEnabled = isEnabled;
 56#if NET6_0_OR_GREATER
 6257        _builder = isEnabled ? new DefaultInterpolatedStringHandler(literalLength, formattedCount) : default;
 58#else
 59        _ = formattedCount;
 60        _builder = isEnabled ? new StringBuilder(literalLength) : null;
 61#endif
 6262    }
 63
 64    /// <summary>
 65    /// Gets a value indicating whether this handler is actively building a diagnostic message.
 66    /// </summary>
 6867    public bool IsEnabled => _isEnabled;
 68
 69    /// <summary>
 70    /// Appends a literal string segment.
 71    /// </summary>
 72    /// <param name="value">The literal string segment.</param>
 73    public void AppendLiteral(string value)
 74    {
 3775        if (!_isEnabled)
 276            return;
 77
 78#if NET6_0_OR_GREATER
 3579        _builder.AppendLiteral(value);
 80#else
 81        _builder!.Append(value);
 82#endif
 3583    }
 84
 85    /// <summary>
 86    /// Appends a formatted value.
 87    /// </summary>
 88    /// <typeparam name="T">The type of value to append.</typeparam>
 89    /// <param name="value">The value to append.</param>
 90    public void AppendFormatted<T>(T value)
 91    {
 1192        if (!_isEnabled)
 193            return;
 94
 95#if NET6_0_OR_GREATER
 1096        _builder.AppendFormatted(value);
 97#else
 98        _builder!.Append(value);
 99#endif
 10100    }
 101
 102    /// <summary>
 103    /// Appends a formatted value using the specified format string.
 104    /// </summary>
 105    /// <typeparam name="T">The type of value to append.</typeparam>
 106    /// <param name="value">The value to append.</param>
 107    /// <param name="format">The format string to apply.</param>
 108    public void AppendFormatted<T>(T value, string? format)
 109    {
 3110        if (!_isEnabled)
 1111            return;
 112
 113#if NET6_0_OR_GREATER
 2114        _builder.AppendFormatted(value, format);
 115#else
 116        AppendFormattedValue(value, 0, format);
 117#endif
 2118    }
 119
 120    /// <summary>
 121    /// Appends a formatted value with the specified alignment.
 122    /// </summary>
 123    /// <typeparam name="T">The type of value to append.</typeparam>
 124    /// <param name="value">The value to append.</param>
 125    /// <param name="alignment">The minimum width for the formatted value.</param>
 126    public void AppendFormatted<T>(T value, int alignment)
 127    {
 3128        if (!_isEnabled)
 1129            return;
 130
 131#if NET6_0_OR_GREATER
 2132        _builder.AppendFormatted(value, alignment);
 133#else
 134        AppendFormattedValue(value, alignment, null);
 135#endif
 2136    }
 137
 138    /// <summary>
 139    /// Appends a formatted value with the specified alignment and format string.
 140    /// </summary>
 141    /// <typeparam name="T">The type of value to append.</typeparam>
 142    /// <param name="value">The value to append.</param>
 143    /// <param name="alignment">The minimum width for the formatted value.</param>
 144    /// <param name="format">The format string to apply.</param>
 145    public void AppendFormatted<T>(T value, int alignment, string? format)
 146    {
 3147        if (!_isEnabled)
 1148            return;
 149
 150#if NET6_0_OR_GREATER
 2151        _builder.AppendFormatted(value, alignment, format);
 152#else
 153        AppendFormattedValue(value, alignment, format);
 154#endif
 2155    }
 156
 157    /// <summary>
 158    /// Appends a string value.
 159    /// </summary>
 160    /// <param name="value">The value to append.</param>
 161    public void AppendFormatted(string? value)
 162    {
 3163        if (!_isEnabled)
 1164            return;
 165
 166#if NET6_0_OR_GREATER
 2167        _builder.AppendFormatted(value);
 168#else
 169        _builder!.Append(value);
 170#endif
 2171    }
 172
 173    /// <summary>
 174    /// Appends a string value with the specified alignment.
 175    /// </summary>
 176    /// <param name="value">The value to append.</param>
 177    /// <param name="alignment">The minimum width for the formatted value.</param>
 178    public void AppendFormatted(string? value, int alignment)
 179    {
 2180        if (!_isEnabled)
 1181            return;
 182
 183#if NET6_0_OR_GREATER
 1184        _builder.AppendFormatted(value, alignment);
 185#else
 186        AppendAligned(value, alignment);
 187#endif
 1188    }
 189
 190    /// <summary>
 191    /// Appends a string value with the specified alignment and format string.
 192    /// </summary>
 193    /// <param name="value">The value to append.</param>
 194    /// <param name="alignment">The minimum width for the formatted value.</param>
 195    /// <param name="format">The format string to apply.</param>
 196    public void AppendFormatted(string? value, int alignment, string? format)
 197    {
 2198        if (!_isEnabled)
 1199            return;
 200
 201#if NET6_0_OR_GREATER
 1202        _builder.AppendFormatted(value, alignment, format);
 203#else
 204        AppendAligned(value, alignment);
 205#endif
 1206    }
 207
 208    /// <summary>
 209    /// Appends a character span.
 210    /// </summary>
 211    /// <param name="value">The span to append.</param>
 212    public void AppendFormatted(ReadOnlySpan<char> value)
 213    {
 2214        if (!_isEnabled)
 1215            return;
 216
 217#if NET6_0_OR_GREATER
 1218        _builder.AppendFormatted(value);
 219#else
 220        _builder!.Append(value);
 221#endif
 1222    }
 223
 224    /// <summary>
 225    /// Appends a character span with the specified alignment.
 226    /// </summary>
 227    /// <param name="value">The span to append.</param>
 228    /// <param name="alignment">The minimum width for the formatted value.</param>
 229    public void AppendFormatted(ReadOnlySpan<char> value, int alignment)
 230    {
 2231        if (!_isEnabled)
 1232            return;
 233
 234#if NET6_0_OR_GREATER
 1235        _builder.AppendFormatted(value, alignment);
 236#else
 237        AppendAligned(value, alignment);
 238#endif
 1239    }
 240
 241    /// <summary>
 242    /// Appends a character span with the specified alignment and format string.
 243    /// </summary>
 244    /// <param name="value">The span to append.</param>
 245    /// <param name="alignment">The minimum width for the formatted value.</param>
 246    /// <param name="format">The format string to apply.</param>
 247    public void AppendFormatted(ReadOnlySpan<char> value, int alignment, string? format)
 248    {
 2249        if (!_isEnabled)
 1250            return;
 251
 252#if NET6_0_OR_GREATER
 1253        _builder.AppendFormatted(value, alignment, format);
 254#else
 255        AppendAligned(value, alignment);
 256#endif
 1257    }
 258
 259    internal string GetFormattedText()
 260    {
 261#if NET6_0_OR_GREATER
 17262        return _builder.ToStringAndClear();
 263#else
 264        return _builder?.ToString() ?? string.Empty;
 265#endif
 266    }
 267
 268#if !NET6_0_OR_GREATER
 269    private void AppendFormattedValue<T>(T value, int alignment, string? format)
 270    {
 271        string? text = value is IFormattable formattable
 272            ? formattable.ToString(format, null)
 273            : value?.ToString();
 274
 275        AppendAligned(text, alignment);
 276    }
 277
 278    private void AppendAligned(string? value, int alignment)
 279    {
 280        value ??= string.Empty;
 281
 282        if (alignment == 0)
 283        {
 284            _builder!.Append(value);
 285            return;
 286        }
 287
 288        int width = alignment < 0 ? -alignment : alignment;
 289        int padding = width - value.Length;
 290
 291        if (padding <= 0)
 292        {
 293            _builder!.Append(value);
 294            return;
 295        }
 296
 297        if (alignment > 0)
 298            _builder!.Append(' ', padding);
 299
 300        _builder!.Append(value);
 301
 302        if (alignment < 0)
 303            _builder!.Append(' ', padding);
 304    }
 305
 306    private void AppendAligned(ReadOnlySpan<char> value, int alignment)
 307    {
 308        if (alignment == 0)
 309        {
 310            _builder!.Append(value);
 311            return;
 312        }
 313
 314        int width = alignment < 0 ? -alignment : alignment;
 315        int padding = width - value.Length;
 316
 317        if (padding <= 0)
 318        {
 319            _builder!.Append(value);
 320            return;
 321        }
 322
 323        if (alignment > 0)
 324            _builder!.Append(' ', padding);
 325
 326        _builder!.Append(value);
 327
 328        if (alignment < 0)
 329            _builder!.Append(' ', padding);
 330    }
 331#endif
 332}