docs: backfill XML documentation across 756 files
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped

Adds <summary>, <param>, <typeparam>, and <inheritdoc/> tags to public
members surfaced by commentchecker — resolves 5,847 of 5,869 issues
(99.6%) across three /fixdocs passes.
This commit is contained in:
Joseph Doherty
2026-05-28 08:10:17 -04:00
parent f9fc7dd2e1
commit 64e3fbe035
756 changed files with 9876 additions and 96 deletions
@@ -11,6 +11,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli;
/// </summary>
public abstract class AbCipCommandBase : DriverCommandBase
{
/// <summary>Gets the canonical AB CIP gateway address.</summary>
[CommandOption("gateway", 'g', Description =
"Canonical AB CIP gateway: ab://host[:port]/cip-path. Port defaults to 44818 " +
"(EtherNet/IP). cip-path is family-specific: ControlLogix / CompactLogix need " +
@@ -19,10 +20,12 @@ public abstract class AbCipCommandBase : DriverCommandBase
IsRequired = true)]
public string Gateway { get; init; } = default!;
/// <summary>Gets the PLC family type.</summary>
[CommandOption("family", 'f', Description =
"ControlLogix / CompactLogix / Micro800 / GuardLogix (default ControlLogix).")]
public AbCipPlcFamily Family { get; init; } = AbCipPlcFamily.ControlLogix;
/// <summary>Gets the per-operation timeout in milliseconds.</summary>
[CommandOption("timeout-ms", Description = "Per-operation timeout in ms (default 5000).")]
public int TimeoutMs { get; init; } = 5000;
@@ -56,6 +59,7 @@ public abstract class AbCipCommandBase : DriverCommandBase
/// supplies. Probe + alarm projection are disabled — CLI runs are one-shot; the
/// probe loop would race the operator's own reads.
/// </summary>
/// <param name="tags">The list of tag definitions to include in the options.</param>
protected AbCipDriverOptions BuildOptions(IReadOnlyList<AbCipTagDefinition> tags) => new()
{
Devices = [new AbCipDeviceOptions(
@@ -82,6 +86,7 @@ public abstract class AbCipCommandBase : DriverCommandBase
/// Throws a <see cref="CliFx.Exceptions.CommandException"/> if <paramref name="type"/>
/// is <see cref="AbCipDataType.Structure"/>.
/// </summary>
/// <param name="type">The data type to validate.</param>
protected static void RejectStructure(AbCipDataType type)
{
if (type == AbCipDataType.Structure)
@@ -12,16 +12,19 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli.Commands;
[Command("probe", Description = "Verify the AB CIP gateway is reachable and a sample tag reads.")]
public sealed class ProbeCommand : AbCipCommandBase
{
/// <summary>Gets the tag path to probe.</summary>
[CommandOption("tag", 't', Description =
"Tag path to probe. ControlLogix default is '@raw_cpu_type' (the canonical libplctag " +
"system tag); Micro800 takes a user-supplied global (e.g. '_SYSVA_CLOCK_HOUR').",
IsRequired = true)]
public string TagPath { get; init; } = default!;
/// <summary>Gets the data type of the probe tag.</summary>
[CommandOption("type", Description =
"Logix atomic type of the probe tag (default DInt).")]
public AbCipDataType DataType { get; init; } = AbCipDataType.DInt;
/// <inheritdoc />
public override async ValueTask ExecuteAsync(IConsole console)
{
ConfigureLogging();
@@ -13,17 +13,22 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli.Commands;
[Command("read", Description = "Read a single Logix tag by symbolic path.")]
public sealed class ReadCommand : AbCipCommandBase
{
/// <summary>Gets the tag path to read.</summary>
[CommandOption("tag", 't', Description =
"Logix symbolic path. Controller scope: 'Motor01_Speed'. Program scope: " +
"'Program:Main.Motor01_Speed'. Array element: 'Recipe[3]'. UDT member: " +
"'Motor01.Speed'.", IsRequired = true)]
public string TagPath { get; init; } = default!;
/// <summary>Gets the data type to read as.</summary>
[CommandOption("type", Description =
"Bool / SInt / Int / DInt / LInt / USInt / UInt / UDInt / ULInt / Real / LReal / " +
"String / Dt / Structure (default DInt).")]
public AbCipDataType DataType { get; init; } = AbCipDataType.DInt;
/// <summary>Executes the read operation.</summary>
/// <param name="console">The console for output and cancellation handling.</param>
/// <inheritdoc />
public override async ValueTask ExecuteAsync(IConsole console)
{
ConfigureLogging();
@@ -59,6 +64,8 @@ public sealed class ReadCommand : AbCipCommandBase
/// Tag-name key the driver uses internally. The path + type pair is already unique
/// so we use them verbatim — keeps tag-level diagnostics readable without mangling.
/// </summary>
/// <param name="tagPath">The symbolic tag path.</param>
/// <param name="type">The data type.</param>
internal static string SynthesiseTagName(string tagPath, AbCipDataType type)
=> $"{tagPath}:{type}";
}
@@ -13,20 +13,24 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli.Commands;
[Command("subscribe", Description = "Watch a Logix tag via polled subscription until Ctrl+C.")]
public sealed class SubscribeCommand : AbCipCommandBase
{
/// <summary>Gets or sets the Logix tag path to subscribe to.</summary>
[CommandOption("tag", 't', Description =
"Logix symbolic path — same format as `read`.", IsRequired = true)]
public string TagPath { get; init; } = default!;
/// <summary>Gets or sets the data type of the tag.</summary>
[CommandOption("type", Description =
"Bool / SInt / Int / DInt / LInt / USInt / UInt / UDInt / ULInt / Real / LReal / " +
"String / Dt (default DInt).")]
public AbCipDataType DataType { get; init; } = AbCipDataType.DInt;
/// <summary>Gets or sets the subscription interval in milliseconds.</summary>
[CommandOption("interval-ms", 'i', Description =
"Publishing interval in milliseconds (default 1000). PollGroupEngine floors " +
"sub-250ms values.")]
public int IntervalMs { get; init; } = 1000;
/// <inheritdoc />
public override async ValueTask ExecuteAsync(IConsole console)
{
ConfigureLogging();
@@ -98,6 +102,7 @@ public sealed class SubscribeCommand : AbCipCommandBase
/// <c>SubscribeAsync</c>; the CLI should fail fast with an actionable error rather
/// than relying on the downstream <c>PollGroupEngine</c> to clamp the value.
/// </summary>
/// <param name="intervalMs">The interval in milliseconds.</param>
internal static void ValidateInterval(int intervalMs)
{
if (intervalMs <= 0)
@@ -15,20 +15,24 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli.Commands;
[Command("write", Description = "Write a single Logix tag by symbolic path.")]
public sealed class WriteCommand : AbCipCommandBase
{
/// <summary>Gets the Logix symbolic path of the tag to write.</summary>
[CommandOption("tag", 't', Description =
"Logix symbolic path — same format as `read`.", IsRequired = true)]
public string TagPath { get; init; } = default!;
/// <summary>Gets the data type to write.</summary>
[CommandOption("type", Description =
"Bool / SInt / Int / DInt / LInt / USInt / UInt / UDInt / ULInt / Real / LReal / " +
"String / Dt (default DInt).")]
public AbCipDataType DataType { get; init; } = AbCipDataType.DInt;
/// <summary>Gets the value to write, as a string.</summary>
[CommandOption("value", 'v', Description =
"Value to write. Parsed per --type (booleans accept true/false/1/0).",
IsRequired = true)]
public string Value { get; init; } = default!;
/// <inheritdoc />
public override async ValueTask ExecuteAsync(IConsole console)
{
ConfigureLogging();
@@ -73,6 +77,9 @@ public sealed class WriteCommand : AbCipCommandBase
/// <see cref="CliFx.Exceptions.CommandException"/> so CliFx renders a clean one-line
/// error rather than a full .NET stack trace.
/// </summary>
/// <param name="raw">The raw string value to parse.</param>
/// <param name="type">The AbCip data type to parse the value into.</param>
/// <returns>The parsed value as an object.</returns>
internal static object ParseValue(string raw, AbCipDataType type)
{
try