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
@@ -22,6 +22,7 @@ public sealed class HistorianSampleDto
/// <summary>Raw OPC DA quality byte from the historian SDK (low 8 bits of OpcQuality).</summary>
[Key(1)] public byte Quality { get; set; }
/// <summary>Gets or sets the timestamp in UTC ticks.</summary>
[Key(2)] public long TimestampUtcTicks { get; set; }
}
@@ -29,7 +30,10 @@ public sealed class HistorianSampleDto
[MessagePackObject]
public sealed class HistorianAggregateSampleDto
{
/// <summary>Gets or sets the aggregate value.</summary>
[Key(0)] public double? Value { get; set; }
/// <summary>Gets or sets the timestamp in UTC ticks.</summary>
[Key(1)] public long TimestampUtcTicks { get; set; }
}
@@ -37,11 +41,22 @@ public sealed class HistorianAggregateSampleDto
[MessagePackObject]
public sealed class HistorianEventDto
{
/// <summary>Gets or sets the event identifier.</summary>
[Key(0)] public string EventId { get; set; } = string.Empty;
/// <summary>Gets or sets the event source name.</summary>
[Key(1)] public string? Source { get; set; }
/// <summary>Gets or sets the event time in UTC ticks.</summary>
[Key(2)] public long EventTimeUtcTicks { get; set; }
/// <summary>Gets or sets the received time in UTC ticks.</summary>
[Key(3)] public long ReceivedTimeUtcTicks { get; set; }
/// <summary>Gets or sets the display text.</summary>
[Key(4)] public string? DisplayText { get; set; }
/// <summary>Gets or sets the severity.</summary>
[Key(5)] public ushort Severity { get; set; }
}
@@ -49,13 +64,28 @@ public sealed class HistorianEventDto
[MessagePackObject]
public sealed class AlarmHistorianEventDto
{
/// <summary>Gets or sets the event identifier.</summary>
[Key(0)] public string EventId { get; set; } = string.Empty;
/// <summary>Gets or sets the source name.</summary>
[Key(1)] public string SourceName { get; set; } = string.Empty;
/// <summary>Gets or sets the condition identifier.</summary>
[Key(2)] public string? ConditionId { get; set; }
/// <summary>Gets or sets the alarm type.</summary>
[Key(3)] public string AlarmType { get; set; } = string.Empty;
/// <summary>Gets or sets the alarm message.</summary>
[Key(4)] public string? Message { get; set; }
/// <summary>Gets or sets the severity.</summary>
[Key(5)] public ushort Severity { get; set; }
/// <summary>Gets or sets the event time in UTC ticks.</summary>
[Key(6)] public long EventTimeUtcTicks { get; set; }
/// <summary>Gets or sets the acknowledgment comment.</summary>
[Key(7)] public string? AckComment { get; set; }
}
@@ -64,19 +94,35 @@ public sealed class AlarmHistorianEventDto
[MessagePackObject]
public sealed class ReadRawRequest
{
/// <summary>Gets or sets the tag name.</summary>
[Key(0)] public string TagName { get; set; } = string.Empty;
/// <summary>Gets or sets the start time in UTC ticks.</summary>
[Key(1)] public long StartUtcTicks { get; set; }
/// <summary>Gets or sets the end time in UTC ticks.</summary>
[Key(2)] public long EndUtcTicks { get; set; }
/// <summary>Gets or sets the maximum number of values to return.</summary>
[Key(3)] public int MaxValues { get; set; }
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(4)] public string CorrelationId { get; set; } = string.Empty;
}
[MessagePackObject]
public sealed class ReadRawReply
{
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(0)] public string CorrelationId { get; set; } = string.Empty;
/// <summary>Gets or sets a value indicating whether the request succeeded.</summary>
[Key(1)] public bool Success { get; set; }
/// <summary>Gets or sets the error message if the request failed.</summary>
[Key(2)] public string? Error { get; set; }
/// <summary>Gets or sets the historical samples.</summary>
[Key(3)] public HistorianSampleDto[] Samples { get; set; } = Array.Empty<HistorianSampleDto>();
}
@@ -85,9 +131,16 @@ public sealed class ReadRawReply
[MessagePackObject]
public sealed class ReadProcessedRequest
{
/// <summary>Gets or sets the tag name.</summary>
[Key(0)] public string TagName { get; set; } = string.Empty;
/// <summary>Gets or sets the start time in UTC ticks.</summary>
[Key(1)] public long StartUtcTicks { get; set; }
/// <summary>Gets or sets the end time in UTC ticks.</summary>
[Key(2)] public long EndUtcTicks { get; set; }
/// <summary>Gets or sets the interval in milliseconds.</summary>
[Key(3)] public double IntervalMs { get; set; }
/// <summary>
@@ -95,15 +148,24 @@ public sealed class ReadProcessedRequest
/// The .NET 10 client maps OPC UA aggregate enum → column.
/// </summary>
[Key(4)] public string AggregateColumn { get; set; } = string.Empty;
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(5)] public string CorrelationId { get; set; } = string.Empty;
}
[MessagePackObject]
public sealed class ReadProcessedReply
{
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(0)] public string CorrelationId { get; set; } = string.Empty;
/// <summary>Gets or sets a value indicating whether the request succeeded.</summary>
[Key(1)] public bool Success { get; set; }
/// <summary>Gets or sets the error message if the request failed.</summary>
[Key(2)] public string? Error { get; set; }
/// <summary>Gets or sets the aggregate sample buckets.</summary>
[Key(3)] public HistorianAggregateSampleDto[] Buckets { get; set; } = Array.Empty<HistorianAggregateSampleDto>();
}
@@ -112,17 +174,29 @@ public sealed class ReadProcessedReply
[MessagePackObject]
public sealed class ReadAtTimeRequest
{
/// <summary>Gets or sets the tag name.</summary>
[Key(0)] public string TagName { get; set; } = string.Empty;
/// <summary>Gets or sets the timestamps in UTC ticks.</summary>
[Key(1)] public long[] TimestampsUtcTicks { get; set; } = Array.Empty<long>();
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(2)] public string CorrelationId { get; set; } = string.Empty;
}
[MessagePackObject]
public sealed class ReadAtTimeReply
{
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(0)] public string CorrelationId { get; set; } = string.Empty;
/// <summary>Gets or sets a value indicating whether the request succeeded.</summary>
[Key(1)] public bool Success { get; set; }
/// <summary>Gets or sets the error message if the request failed.</summary>
[Key(2)] public string? Error { get; set; }
/// <summary>Gets or sets the historical samples.</summary>
[Key(3)] public HistorianSampleDto[] Samples { get; set; } = Array.Empty<HistorianSampleDto>();
}
@@ -131,19 +205,35 @@ public sealed class ReadAtTimeReply
[MessagePackObject]
public sealed class ReadEventsRequest
{
/// <summary>Gets or sets the source name.</summary>
[Key(0)] public string? SourceName { get; set; }
/// <summary>Gets or sets the start time in UTC ticks.</summary>
[Key(1)] public long StartUtcTicks { get; set; }
/// <summary>Gets or sets the end time in UTC ticks.</summary>
[Key(2)] public long EndUtcTicks { get; set; }
/// <summary>Gets or sets the maximum number of events to return.</summary>
[Key(3)] public int MaxEvents { get; set; }
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(4)] public string CorrelationId { get; set; } = string.Empty;
}
[MessagePackObject]
public sealed class ReadEventsReply
{
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(0)] public string CorrelationId { get; set; } = string.Empty;
/// <summary>Gets or sets a value indicating whether the request succeeded.</summary>
[Key(1)] public bool Success { get; set; }
/// <summary>Gets or sets the error message if the request failed.</summary>
[Key(2)] public string? Error { get; set; }
/// <summary>Gets or sets the historian events.</summary>
[Key(3)] public HistorianEventDto[] Events { get; set; } = Array.Empty<HistorianEventDto>();
}
@@ -152,15 +242,23 @@ public sealed class ReadEventsReply
[MessagePackObject]
public sealed class WriteAlarmEventsRequest
{
/// <summary>Gets or sets the alarm events to write.</summary>
[Key(0)] public AlarmHistorianEventDto[] Events { get; set; } = Array.Empty<AlarmHistorianEventDto>();
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(1)] public string CorrelationId { get; set; } = string.Empty;
}
[MessagePackObject]
public sealed class WriteAlarmEventsReply
{
/// <summary>Gets or sets the correlation identifier.</summary>
[Key(0)] public string CorrelationId { get; set; } = string.Empty;
/// <summary>Gets or sets a value indicating whether the request succeeded.</summary>
[Key(1)] public bool Success { get; set; }
/// <summary>Gets or sets the error message if the request failed.</summary>
[Key(2)] public string? Error { get; set; }
/// <summary>Per-event success flag, parallel to <see cref="WriteAlarmEventsRequest.Events"/>.</summary>
@@ -17,12 +17,18 @@ public sealed class FrameReader : IDisposable
private readonly Stream _stream;
private readonly bool _leaveOpen;
/// <summary>Initializes a new instance of the <see cref="FrameReader"/> class.</summary>
/// <param name="stream">The stream to read frames from.</param>
/// <param name="leaveOpen">Whether to leave the stream open when disposing.</param>
public FrameReader(Stream stream, bool leaveOpen = false)
{
_stream = stream ?? throw new ArgumentNullException(nameof(stream));
_leaveOpen = leaveOpen;
}
/// <summary>Reads the next frame asynchronously from the stream.</summary>
/// <param name="ct">Cancellation token for the operation.</param>
/// <returns>A tuple of message kind and body, or null if EOF is encountered cleanly.</returns>
public async Task<(MessageKind Kind, byte[] Body)?> ReadFrameAsync(CancellationToken ct)
{
var lengthPrefix = new byte[Framing.LengthPrefixSize];
@@ -43,6 +49,9 @@ public sealed class FrameReader : IDisposable
return ((MessageKind)(byte)kindByte, body);
}
/// <summary>Deserializes the message body to the specified type.</summary>
/// <typeparam name="T">The type to deserialize to.</typeparam>
/// <param name="body">The serialized message body.</param>
public static T Deserialize<T>(byte[] body) => MessagePackSerializer.Deserialize<T>(body);
private async Task<bool> ReadExactAsync(byte[] buffer, CancellationToken ct)
@@ -61,6 +70,7 @@ public sealed class FrameReader : IDisposable
return true;
}
/// <summary>Disposes the frame reader and optionally closes the underlying stream.</summary>
public void Dispose()
{
if (!_leaveOpen) _stream.Dispose();
@@ -18,12 +18,20 @@ public sealed class FrameWriter : IDisposable
private readonly SemaphoreSlim _gate = new(1, 1);
private readonly bool _leaveOpen;
/// <summary>Initializes a new instance of the FrameWriter.</summary>
/// <param name="stream">The stream to write frames to.</param>
/// <param name="leaveOpen">Whether to leave the stream open when disposed.</param>
public FrameWriter(Stream stream, bool leaveOpen = false)
{
_stream = stream ?? throw new ArgumentNullException(nameof(stream));
_leaveOpen = leaveOpen;
}
/// <summary>Writes a frame with the specified message kind and serialized message.</summary>
/// <typeparam name="T">The type of message being written.</typeparam>
/// <param name="kind">The message kind identifier.</param>
/// <param name="message">The message to serialize and write.</param>
/// <param name="ct">The cancellation token.</param>
public async Task WriteAsync<T>(MessageKind kind, T message, CancellationToken ct)
{
var body = MessagePackSerializer.Serialize(message, cancellationToken: ct);
@@ -49,6 +57,7 @@ public sealed class FrameWriter : IDisposable
finally { _gate.Release(); }
}
/// <summary>Disposes the frame writer and releases resources.</summary>
public void Dispose()
{
_gate.Dispose();
@@ -12,21 +12,30 @@ public sealed class Hello
public const int CurrentMajor = 1;
public const int CurrentMinor = 0;
/// <summary>Gets or sets the protocol major version.</summary>
[Key(0)] public int ProtocolMajor { get; set; } = CurrentMajor;
/// <summary>Gets or sets the protocol minor version.</summary>
[Key(1)] public int ProtocolMinor { get; set; } = CurrentMinor;
/// <summary>Gets or sets the peer name.</summary>
[Key(2)] public string PeerName { get; set; } = string.Empty;
/// <summary>Per-process shared secret — verified against the value the supervisor passed at spawn time.</summary>
[Key(3)] public string SharedSecret { get; set; } = string.Empty;
}
/// <summary>Response to a Hello handshake message.</summary>
[MessagePackObject]
public sealed class HelloAck
{
/// <summary>Gets or sets the protocol major version.</summary>
[Key(0)] public int ProtocolMajor { get; set; } = Hello.CurrentMajor;
/// <summary>Gets or sets the protocol minor version.</summary>
[Key(1)] public int ProtocolMinor { get; set; } = Hello.CurrentMinor;
/// <summary>Gets or sets a value indicating whether the handshake was accepted.</summary>
[Key(2)] public bool Accepted { get; set; }
/// <summary>Gets or sets the rejection reason if Accepted is false.</summary>
[Key(3)] public string? RejectReason { get; set; }
/// <summary>Gets or sets the host name of the server.</summary>
[Key(4)] public string HostName { get; set; } = string.Empty;
}
@@ -20,6 +20,10 @@ public sealed class HistorianFrameHandler : IFrameHandler
private readonly IAlarmEventWriter? _alarmWriter;
private readonly ILogger _logger;
/// <summary>Initializes a new instance of the HistorianFrameHandler class.</summary>
/// <param name="historian">The historian data source to query.</param>
/// <param name="logger">The logger instance.</param>
/// <param name="alarmWriter">Optional alarm event writer for writebacks.</param>
public HistorianFrameHandler(
IHistorianDataSource historian,
ILogger logger,
@@ -30,6 +34,11 @@ public sealed class HistorianFrameHandler : IFrameHandler
_alarmWriter = alarmWriter;
}
/// <summary>Handles an incoming frame by dispatching to the appropriate historian operation.</summary>
/// <param name="kind">The frame message kind.</param>
/// <param name="body">The frame body bytes.</param>
/// <param name="writer">The frame writer for sending responses.</param>
/// <param name="ct">Cancellation token.</param>
public Task HandleAsync(MessageKind kind, byte[] body, FrameWriter writer, CancellationToken ct)
=> kind switch
{
@@ -251,5 +260,7 @@ public interface IAlarmEventWriter
/// persisted vs. retry-please. The SQLite store-and-forward sink retries failed
/// slots on the next drain tick.
/// </summary>
/// <param name="events">Alarm events to write.</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task<bool[]> WriteAsync(AlarmHistorianEventDto[] events, CancellationToken cancellationToken);
}
@@ -13,6 +13,9 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Ipc;
/// </summary>
public static class PipeAcl
{
/// <summary>Creates a strict PipeSecurity for the historian sidecar pipe.</summary>
/// <param name="allowedSid">The security identifier that should have read-write access to the pipe.</param>
/// <returns>A configured PipeSecurity object with strict access control.</returns>
public static PipeSecurity Create(SecurityIdentifier allowedSid)
{
if (allowedSid is null) throw new ArgumentNullException(nameof(allowedSid));
@@ -29,11 +29,25 @@ public sealed class PipeServer : IDisposable
/// <see cref="VerifyCaller"/>; tests can substitute one that ignores the pipe ACL
/// to exercise the rejection paths.
/// </summary>
/// <param name="pipe">The named pipe server stream to verify.</param>
/// <param name="allowedSid">The allowed security identifier.</param>
/// <param name="reason">The rejection reason if verification fails.</param>
internal delegate bool CallerVerifier(NamedPipeServerStream pipe, SecurityIdentifier allowedSid, out string reason);
/// <summary>Initializes a new instance of the <see cref="PipeServer"/> class.</summary>
/// <param name="pipeName">The name of the named pipe.</param>
/// <param name="allowedSid">The security identifier allowed to connect.</param>
/// <param name="sharedSecret">The shared secret for client authentication.</param>
/// <param name="logger">The logger for diagnostic messages.</param>
public PipeServer(string pipeName, SecurityIdentifier allowedSid, string sharedSecret, ILogger logger)
: this(pipeName, allowedSid, sharedSecret, logger, DefaultVerifier) { }
/// <summary>Initializes a new instance of the <see cref="PipeServer"/> class with a custom verifier.</summary>
/// <param name="pipeName">The name of the named pipe.</param>
/// <param name="allowedSid">The security identifier allowed to connect.</param>
/// <param name="sharedSecret">The shared secret for client authentication.</param>
/// <param name="logger">The logger for diagnostic messages.</param>
/// <param name="verifier">The caller verification delegate.</param>
internal PipeServer(
string pipeName, SecurityIdentifier allowedSid, string sharedSecret, ILogger logger,
CallerVerifier verifier)
@@ -52,6 +66,8 @@ public sealed class PipeServer : IDisposable
/// Accepts one connection, performs Hello handshake, then dispatches frames to
/// <paramref name="handler"/> until EOF or cancel. Returns when the client disconnects.
/// </summary>
/// <param name="handler">The frame handler to process frames.</param>
/// <param name="ct">Cancellation token for the operation.</param>
public async Task RunOneConnectionAsync(IFrameHandler handler, CancellationToken ct)
{
using var linked = CancellationTokenSource.CreateLinkedTokenSource(_cts.Token, ct);
@@ -161,6 +177,8 @@ public sealed class PipeServer : IDisposable
/// If <see cref="MaxConsecutiveFailures"/> consecutive failures occur the method
/// throws so the supervisor can restart the sidecar.
/// </summary>
/// <param name="handler">The frame handler to process frames.</param>
/// <param name="ct">Cancellation token for the operation.</param>
public async Task RunAsync(IFrameHandler handler, CancellationToken ct)
{
var consecutiveFailures = 0;
@@ -215,6 +233,7 @@ public sealed class PipeServer : IDisposable
catch (Exception ex) { reason = ex.Message; return false; }
}
/// <summary>Disposes the pipe server and cancels any pending operations.</summary>
public void Dispose()
{
_cts.Cancel();
@@ -230,5 +249,10 @@ public sealed class PipeServer : IDisposable
/// </summary>
public interface IFrameHandler
{
/// <summary>Handles a frame from the pipe server.</summary>
/// <param name="kind">The type of message being handled.</param>
/// <param name="body">The serialized message body.</param>
/// <param name="writer">The frame writer to send responses.</param>
/// <param name="ct">Cancellation token for the operation.</param>
Task HandleAsync(MessageKind kind, byte[] body, FrameWriter writer, CancellationToken ct);
}