0ffd4bdbea
Comment/XML-doc changes only, no code logic: - strip project-tracking references (WP*, P*-*, row-NN, #NN, Task N) from comments, keeping the explanatory rationale - add missing summaries, <param>, <returns>, <typeparam> and <inheritdoc/> - replace misused <inheritdoc/> with real docs; where <inheritdoc/> was combined with useful remarks, move the rationale into // comments - drop stale replicationActor <param> on DeploymentManagerActor ctor Remaining 5 are false positives (CWE-1236 x2, failures-1, year-0001, M365). Build 0 errors / 0 warnings.
110 lines
4.6 KiB
C#
110 lines
4.6 KiB
C#
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.CLI;
|
|
|
|
public static class OutputFormatter
|
|
{
|
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
|
{
|
|
WriteIndented = true,
|
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
|
};
|
|
|
|
/// <summary>Serializes <paramref name="data"/> to indented JSON and writes it to standard output.</summary>
|
|
/// <param name="data">The object to serialize; <c>null</c> is serialized as JSON <c>null</c>.</param>
|
|
public static void WriteJson(object? data)
|
|
{
|
|
Console.WriteLine(JsonSerializer.Serialize(data, JsonOptions));
|
|
}
|
|
|
|
/// <summary>Writes a JSON error envelope with the given message and code to standard error.</summary>
|
|
/// <param name="message">Human-readable error description.</param>
|
|
/// <param name="code">Machine-readable error code.</param>
|
|
public static void WriteError(string message, string code)
|
|
{
|
|
Console.Error.WriteLine(JsonSerializer.Serialize(new { error = message, code }, JsonOptions));
|
|
}
|
|
|
|
/// <summary>Writes a plain-text padded table to standard output with the given column headers and data rows.</summary>
|
|
/// <param name="rows">Data rows; each inner array corresponds to a column in the same order as <paramref name="headers"/>.</param>
|
|
/// <param name="headers">Column header labels.</param>
|
|
public static void WriteTable(IEnumerable<string[]> rows, string[] headers)
|
|
=> WriteTable(rows.Select(TableRow.Columns), headers);
|
|
|
|
/// <summary>
|
|
/// One row for the <see cref="TableRow"/> overload of <c>WriteTable</c>: either padded
|
|
/// column cells like the plain <see cref="string[]"/> overload, or an already-formatted
|
|
/// line printed verbatim with no column padding/alignment at all — used for a note/log line folded onto a step, which must render as a raw
|
|
/// indented line under that step's row rather than as a cell in a table column (every
|
|
/// other row's cell there would otherwise render blank, and the line's own leading
|
|
/// whitespace would be swallowed by column padding).
|
|
/// </summary>
|
|
internal readonly struct TableRow
|
|
{
|
|
private TableRow(string[]? cells, string? rawLine)
|
|
{
|
|
Cells = cells;
|
|
RawLine = rawLine;
|
|
}
|
|
|
|
/// <summary>The column cells of a normal row, or null for a raw line.</summary>
|
|
internal string[]? Cells { get; }
|
|
|
|
/// <summary>The verbatim line of a raw row, or null for a column row.</summary>
|
|
internal string? RawLine { get; }
|
|
|
|
/// <summary>A normal row, rendered as padded columns aligned with the header set.</summary>
|
|
/// <param name="cells">The column cell values.</param>
|
|
/// <returns>A column row.</returns>
|
|
internal static TableRow Columns(string[] cells) => new(cells, null);
|
|
|
|
/// <summary>An already-formatted line, printed exactly as given with no column alignment.</summary>
|
|
/// <param name="line">The preformatted line.</param>
|
|
/// <returns>A raw row.</returns>
|
|
internal static TableRow Raw(string line) => new(null, line);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes a plain-text padded table like <see cref="WriteTable(IEnumerable{string[]}, string[])"/>,
|
|
/// except a <see cref="TableRow.Raw"/> row is printed verbatim — unpadded, uninvolved in the
|
|
/// column-width computation — at its position in the row sequence, immediately after
|
|
/// whatever row precedes it.
|
|
/// </summary>
|
|
/// <param name="rows">Data rows, each either padded columns or a raw line.</param>
|
|
/// <param name="headers">Column header labels.</param>
|
|
internal static void WriteTable(IEnumerable<TableRow> rows, string[] headers)
|
|
{
|
|
var rowList = rows.ToList();
|
|
var widths = new int[headers.Length];
|
|
|
|
void Consider(string[] row)
|
|
{
|
|
for (int i = 0; i < Math.Min(row.Length, widths.Length); i++)
|
|
widths[i] = Math.Max(widths[i], (row[i] ?? "").Length);
|
|
}
|
|
|
|
Consider(headers);
|
|
foreach (var row in rowList)
|
|
if (row.Cells != null)
|
|
Consider(row.Cells);
|
|
|
|
void PrintColumns(string[] row)
|
|
{
|
|
for (int i = 0; i < headers.Length; i++)
|
|
Console.Write((i < row.Length ? row[i] ?? "" : "").PadRight(widths[i] + 2));
|
|
Console.WriteLine();
|
|
}
|
|
|
|
PrintColumns(headers);
|
|
foreach (var row in rowList)
|
|
{
|
|
if (row.RawLine != null)
|
|
Console.WriteLine(row.RawLine);
|
|
else
|
|
PrintColumns(row.Cells!);
|
|
}
|
|
}
|
|
}
|