< Summary

Information
Class: UIBlazor.Components.ToolViews.DiffView
Assembly: UIBlazor
File(s): /home/runner/work/InvAit/InvAit/UIBlazor/Components/ToolViews/DiffView.razor
Tag: 71_26091983037
Line coverage
0%
Covered lines: 0
Uncovered lines: 61
Coverable lines: 61
Total lines: 146
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 32
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
BuildRenderTree(...)0%7280%
get_LinesCount()100%210%
get_ToolParams()100%210%
get_IsClosed()100%210%
get_FilePath()100%210%
.ctor()100%210%
get_elapsed()100%210%
ShouldRender()0%4260%
DelayRender()100%210%
Dispose()0%2040%
OnParametersSet()100%210%
ParseDiff()0%210140%

File(s)

/home/runner/work/InvAit/InvAit/UIBlazor/Components/ToolViews/DiffView.razor

#LineLine coverage
 1@using System.Text
 2@using DiffPlex
 3@using DiffPlex.Chunkers
 4@using DiffPlex.DiffBuilder
 5@using DiffPlex.DiffBuilder.Model
 6
 7<div class="diff-view">
 08    @if (!string.IsNullOrEmpty(FilePath))
 9    {
 010        <div @key="@FilePath" class="tool-file-header">@FilePath</div>
 11    }
 12    <div class="diff-block">
 013        @for (var i = 0; i < diffs.Count; i++)
 14        {
 015            @if (diffs[i] == null)
 16            {
 17                continue;
 18            }
 019            @if (i > 0)
 20            {
 21                <hr />
 22            }
 23            <DiffViewSection Model="diffs[i]" />
 24        }
 25    </div>
 26</div>
 27
 28@implements IDisposable
 29
 30@code {
 031    [Parameter] public int LinesCount { get; set; } = 0;
 032    [Parameter] public Dictionary<string, object> ToolParams { get; set; } = [];
 033    [Parameter] public bool IsClosed { get; set; } = true;
 34
 035    private string? FilePath { get; set; }
 036    private List<SideBySideDiffModel?> diffs = [null];
 37    private int processedLines = 0;
 38    private bool showDiffSeparator = false;
 39
 40    private bool _changed = false;
 041    private DateTime _lastRenderTime = DateTime.MinValue;
 042    private readonly int _interval = 500; // рендерить не чаще
 043    private double elapsed => (DateTime.Now - _lastRenderTime).TotalMilliseconds;
 44    private CancellationTokenSource? _pendingRenderCts;
 45
 46    protected override bool ShouldRender()
 47    {
 048        if (!_changed) return false;
 49
 050        if (elapsed >= _interval)
 51        {
 052            _lastRenderTime = DateTime.Now;
 053            _changed = false;
 054            return true;
 55        }
 56
 57        // Отменяем предыдущую отложенную задачу
 058        _pendingRenderCts?.Cancel();
 059        _pendingRenderCts = new CancellationTokenSource();
 60        // Запускаем отложенную проверку для "последнего вызова"
 061        _ = DelayRender(_pendingRenderCts.Token);
 062        return false;
 63    }
 64
 65    private async Task DelayRender(CancellationToken cancellationToken)
 66    {
 67        try
 68        {
 069            await Task.Delay(_interval, cancellationToken);
 070            _changed = true; // Гарантируем рендер
 071            StateHasChanged();
 072        }
 073        catch (TaskCanceledException)
 74        {
 75            // Игнорируем отмену
 076        }
 077    }
 78
 79    public void Dispose()
 80    {
 081        _pendingRenderCts?.Cancel();
 082        _pendingRenderCts?.Dispose();
 083    }
 84
 85    protected override void OnParametersSet()
 86    {
 087        ParseDiff();
 088    }
 89
 90    private void ParseDiff()
 91    {
 092        if (LinesCount < 2)
 93        {
 094            return;
 95        }
 96
 097        _changed = LinesCount > processedLines;
 98
 099        if (!_changed)
 100        {
 0101            return;
 102        }
 103
 0104        FilePath ??= ToolParams["param1"].ToString();
 105
 0106        if (ToolParams.ContainsKey("param2"))
 107        {
 108            // обычный параметр должен быть только один. Если это не так, то нечего рендерить.
 0109            FilePath = "Error: Corrupted tool input.";
 0110            return;
 111        }
 112
 113        // не перерисовывать DiffModel если он уже не дополнялся строками
 114        // дополняться новыми строками может только последний DiffModel
 115        // то есть при каждом парсинге нужно пропускать модели,
 116        // которые уже были сделаны кроме последней (она может дополняться строками)
 0117        for (var i = diffs.Count - 1; i < ToolParams.Count - 1; i++)
 118        {
 0119            var diffRepl = ToolParams[$"diff{i + 1}"] as DiffReplacement;
 0120            if (diffRepl is not null)
 121            {
 0122                var diffBuiler = SideBySideDiffBuilder.Diff(
 0123                    Differ.Instance,
 0124                    string.Join('\n', diffRepl.Search),
 0125                    string.Join('\n', diffRepl.Replace),
 0126                    false,
 0127                    false,
 0128                    lineChunker: LineChunker.Instance,
 0129                    wordChunker: CharacterChunker.Instance
 0130                );
 131
 0132                if (i >= diffs.Count)
 133                {
 0134                    diffs.Add(diffBuiler);
 135                }
 136                else
 137                {
 0138                    diffs[i] = diffBuiler;
 139                }
 140            }
 141        }
 142
 0143        processedLines = LinesCount;
 0144        showDiffSeparator = diffs.Count > 1;
 0145    }
 146}