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
@@ -30,6 +30,7 @@ public sealed class DriverTypeRegistry
/// <see cref="_writeLock"/> so concurrent <see cref="Register"/> calls cannot silently
/// discard each other's registrations — see Core.Abstractions-004.
/// </remarks>
/// <param name="metadata">The driver type metadata to register.</param>
public void Register(DriverTypeMetadata metadata)
{
ArgumentNullException.ThrowIfNull(metadata);
@@ -53,6 +54,7 @@ public sealed class DriverTypeRegistry
}
/// <summary>Look up a driver type by name. Throws if unknown.</summary>
/// <param name="driverType">The driver type name to look up.</param>
public DriverTypeMetadata Get(string driverType)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverType);
@@ -66,6 +68,7 @@ public sealed class DriverTypeRegistry
}
/// <summary>Try to look up a driver type by name. Returns null if unknown (no exception).</summary>
/// <param name="driverType">The driver type name to look up.</param>
public DriverTypeMetadata? TryGet(string driverType)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverType);
@@ -23,6 +23,11 @@ public interface IHistorianDataSource : IDisposable
/// <summary>
/// Read raw historical samples for a single tag over a time range.
/// </summary>
/// <param name="fullReference">The full reference of the tag to read.</param>
/// <param name="startUtc">The start of the time range in UTC.</param>
/// <param name="endUtc">The end of the time range in UTC.</param>
/// <param name="maxValuesPerNode">The maximum number of values to return per node.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
Task<HistoryReadResult> ReadRawAsync(
string fullReference,
DateTime startUtc,
@@ -35,6 +40,12 @@ public interface IHistorianDataSource : IDisposable
/// A bucket with no source data returns a sample whose
/// <see cref="DataValueSnapshot.StatusCode"/> indicates BadNoData.
/// </summary>
/// <param name="fullReference">The full reference of the tag to read.</param>
/// <param name="startUtc">The start of the time range in UTC.</param>
/// <param name="endUtc">The end of the time range in UTC.</param>
/// <param name="interval">The interval for bucketing samples.</param>
/// <param name="aggregate">The aggregation function to apply to each bucket.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
Task<HistoryReadResult> ReadProcessedAsync(
string fullReference,
DateTime startUtc,
@@ -49,6 +60,9 @@ public interface IHistorianDataSource : IDisposable
/// backend's policy. The returned list MUST be the same length and order as
/// <paramref name="timestampsUtc"/>; gaps are returned as Bad-quality snapshots.
/// </summary>
/// <param name="fullReference">The full reference of the tag to read.</param>
/// <param name="timestampsUtc">The list of timestamps to read values at.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
Task<HistoryReadResult> ReadAtTimeAsync(
string fullReference,
IReadOnlyList<DateTime> timestampsUtc,
@@ -74,6 +88,11 @@ public interface IHistorianDataSource : IDisposable
/// methods so legacy drivers can stay raw-only. The asymmetry is intentional
/// (Core.Abstractions-008).
/// </remarks>
/// <param name="sourceName">The source name to filter events, or null to return events from all sources.</param>
/// <param name="startUtc">The start of the time range in UTC.</param>
/// <param name="endUtc">The end of the time range in UTC.</param>
/// <param name="maxEvents">The maximum number of events to return, or a non-positive value to use the default backend cap.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
Task<HistoricalEventsResult> ReadEventsAsync(
string? sourceName,
DateTime startUtc,
@@ -34,6 +34,9 @@ public interface IAddressSpaceBuilder
/// read once at build time (e.g. OPC 40010 Identification fields per the schemas-repo
/// <c>_base</c> equipment-class template).
/// </summary>
/// <param name="browseName">The property browse name.</param>
/// <param name="dataType">The property data type.</param>
/// <param name="value">The property value.</param>
void AddProperty(string browseName, DriverDataType dataType, object? value);
}
@@ -52,6 +55,7 @@ public interface IVariableHandle
/// to surface the state (e.g. OPC UA <c>AlarmConditionState.Activate</c>,
/// <c>Acknowledge</c>, <c>Deactivate</c>).
/// </summary>
/// <param name="info">The alarm condition information.</param>
IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info);
}
@@ -107,5 +111,6 @@ public sealed record AlarmConditionInfo(
public interface IAlarmConditionSink
{
/// <summary>Push an alarm transition (Active / Acknowledged / Inactive) for this condition.</summary>
/// <param name="args">The alarm event arguments.</param>
void OnTransition(AlarmEventArgs args);
}
@@ -11,14 +11,20 @@ public interface IAlarmSource
/// Subscribe to alarm events for a node-set (typically: a folder or equipment subtree).
/// The driver fires <see cref="OnAlarmEvent"/> for every alarm transition.
/// </summary>
/// <param name="sourceNodeIds">The driver node IDs to subscribe to.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
Task<IAlarmSubscriptionHandle> SubscribeAlarmsAsync(
IReadOnlyList<string> sourceNodeIds,
CancellationToken cancellationToken);
/// <summary>Cancel an alarm subscription returned by <see cref="SubscribeAlarmsAsync"/>.</summary>
/// <param name="handle">The subscription handle returned from <see cref="SubscribeAlarmsAsync"/>.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken);
/// <summary>Acknowledge one or more active alarms by source node ID + condition ID.</summary>
/// <param name="acknowledgements">The batch of alarm acknowledgement requests.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
Task AcknowledgeAsync(
IReadOnlyList<AlarmAcknowledgeRequest> acknowledgements,
CancellationToken cancellationToken);
@@ -21,6 +21,8 @@ public interface IDriver
string DriverType { get; }
/// <summary>Initialize the driver from its <c>DriverConfig</c> JSON; open connections; prepare for first use.</summary>
/// <param name="driverConfigJson">The driver configuration as JSON.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken);
/// <summary>
@@ -33,9 +35,12 @@ public interface IDriver
/// only Core-initiated recovery path for in-process drivers; if it fails, the driver instance
/// is marked Faulted and its nodes go Bad quality, but the server process keeps running.
/// </remarks>
/// <param name="driverConfigJson">The driver configuration as JSON.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken);
/// <summary>Stop the driver, close connections, release resources. Called on shutdown or driver removal.</summary>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
Task ShutdownAsync(CancellationToken cancellationToken);
/// <summary>Current health snapshot, polled by Core for the status dashboard and ServiceLevel.</summary>
@@ -57,5 +62,6 @@ public interface IDriver
/// Drop optional caches (symbol cache, browse cache, etc.) to bring footprint back below budget.
/// Required-for-correctness state must NOT be flushed.
/// </summary>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
Task FlushOptionalCachesAsync(CancellationToken cancellationToken);
}
@@ -14,6 +14,10 @@ public interface IDriverFactory
/// <c>null</c> when no factory is registered for that type (missing assembly, typo, etc.).
/// The DriverHostActor logs + skips the row rather than failing the whole apply.
/// </summary>
/// <param name="driverType">The driver type name (e.g., "Modbus", "FOCAS").</param>
/// <param name="driverInstanceId">The driver instance identifier.</param>
/// <param name="driverConfigJson">The driver configuration as a JSON string.</param>
/// <returns>A new IDriver instance, or null if the driver type is not supported.</returns>
IDriver? TryCreate(string driverType, string driverInstanceId, string driverConfigJson);
/// <summary>Driver-type names this factory can materialise. Mostly for diagnostics + logs.</summary>
@@ -30,6 +34,12 @@ public sealed class NullDriverFactory : IDriverFactory
public static readonly NullDriverFactory Instance = new();
private NullDriverFactory() { }
/// <summary>Creates a driver (always returns null in this null implementation).</summary>
/// <param name="driverType">The driver type name.</param>
/// <param name="driverInstanceId">The driver instance identifier.</param>
/// <param name="driverConfigJson">The driver configuration as a JSON string.</param>
/// <returns>Always returns null.</returns>
public IDriver? TryCreate(string driverType, string driverInstanceId, string driverConfigJson) => null;
/// <summary>Gets the collection of supported driver types (empty in this null implementation).</summary>
public IReadOnlyCollection<string> SupportedTypes { get; } = Array.Empty<string>();
}
@@ -20,6 +20,12 @@ public interface IHistoryProvider
/// Read raw historical samples for a single attribute over a time range.
/// The Core wraps this with continuation-point handling.
/// </summary>
/// <param name="fullReference">The full reference path to the attribute.</param>
/// <param name="startUtc">Inclusive lower bound on the time range (UTC).</param>
/// <param name="endUtc">Exclusive upper bound on the time range (UTC).</param>
/// <param name="maxValuesPerNode">Maximum number of values to return per node.</param>
/// <param name="cancellationToken">A cancellation token to stop the operation.</param>
/// <returns>A task that returns the history read result containing samples and optional continuation point.</returns>
Task<HistoryReadResult> ReadRawAsync(
string fullReference,
DateTime startUtc,
@@ -31,6 +37,13 @@ public interface IHistoryProvider
/// Read processed (aggregated) samples — interval-bucketed average / min / max / etc.
/// Optional — drivers that only support raw history can throw <see cref="NotSupportedException"/>.
/// </summary>
/// <param name="fullReference">The full reference path to the attribute.</param>
/// <param name="startUtc">Inclusive lower bound on the time range (UTC).</param>
/// <param name="endUtc">Exclusive upper bound on the time range (UTC).</param>
/// <param name="interval">The time interval for bucketing samples.</param>
/// <param name="aggregate">The aggregate function to apply to each bucket.</param>
/// <param name="cancellationToken">A cancellation token to stop the operation.</param>
/// <returns>A task that returns the history read result containing aggregated samples and optional continuation point.</returns>
Task<HistoryReadResult> ReadProcessedAsync(
string fullReference,
DateTime startUtc,
@@ -49,6 +62,10 @@ public interface IHistoryProvider
/// <c>IHistoryProvider</c> implementations compiling without forcing a ReadAtTime path
/// they may not have a backend for.
/// </remarks>
/// <param name="fullReference">The full reference path to the attribute.</param>
/// <param name="timestampsUtc">The list of timestamps at which to read values.</param>
/// <param name="cancellationToken">A cancellation token to stop the operation.</param>
/// <returns>A task that returns the history read result containing samples at the requested times.</returns>
Task<HistoryReadResult> ReadAtTimeAsync(
string fullReference,
IReadOnlyList<DateTime> timestampsUtc,
@@ -30,5 +30,7 @@ public interface IPerCallHostResolver
/// used as the <c>hostName</c> argument to the Phase 6.1 <c>CapabilityInvoker</c> so
/// per-host breaker isolation + per-host bulkhead accounting both kick in.
/// </summary>
/// <param name="fullReference">The full reference of the tag or resource.</param>
/// <returns>The host name responsible for serving the reference.</returns>
string ResolveHost(string fullReference);
}
@@ -19,6 +19,9 @@ public interface IReadable
/// Per-reference failures should be reported via the snapshot's <see cref="DataValueSnapshot.StatusCode"/>
/// (Bad-coded), not as exceptions. The whole call should throw only if the driver itself is unreachable.
/// </remarks>
/// <param name="fullReferences">The list of full driver-side references to read.</param>
/// <param name="cancellationToken">A cancellation token for the operation.</param>
/// <returns>A task that returns a read-only list of data value snapshots, one per requested reference in the same order.</returns>
Task<IReadOnlyList<DataValueSnapshot>> ReadAsync(
IReadOnlyList<string> fullReferences,
CancellationToken cancellationToken);
@@ -14,6 +14,9 @@ public interface ISubscribable
/// The driver MAY fire <see cref="OnDataChange"/> immediately with the current value
/// (initial-data callback per OPC UA convention) and again on every change.
/// </summary>
/// <param name="fullReferences">The full references of the attributes to subscribe to.</param>
/// <param name="publishingInterval">The desired interval at which to receive data change notifications.</param>
/// <param name="cancellationToken">A cancellation token to observe for cancellation.</param>
/// <returns>An opaque subscription handle the caller passes to <see cref="UnsubscribeAsync"/>.</returns>
Task<ISubscriptionHandle> SubscribeAsync(
IReadOnlyList<string> fullReferences,
@@ -21,6 +24,9 @@ public interface ISubscribable
CancellationToken cancellationToken);
/// <summary>Cancel a subscription returned by <see cref="SubscribeAsync"/>.</summary>
/// <param name="handle">The subscription handle to cancel.</param>
/// <param name="cancellationToken">A cancellation token to observe for cancellation.</param>
/// <returns>A task representing the asynchronous unsubscribe operation.</returns>
Task UnsubscribeAsync(ISubscriptionHandle handle, CancellationToken cancellationToken);
/// <summary>
@@ -11,5 +11,7 @@ public interface ITagDiscovery
/// Discover the driver's tag set and stream nodes to the builder.
/// The driver decides ordering (root → leaf typically) and may yield as many calls as needed.
/// </summary>
/// <param name="builder">The address space builder to stream discovered nodes into.</param>
/// <param name="cancellationToken">A cancellation token for the discovery operation.</param>
Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken);
}
@@ -66,6 +66,8 @@ public sealed class PollGroupEngine : IAsyncDisposable
}
/// <summary>Register a new polled subscription and start its background loop.</summary>
/// <param name="fullReferences">The list of tag references to poll.</param>
/// <param name="publishingInterval">The desired polling interval; will be clamped to the configured minimum.</param>
public ISubscriptionHandle Subscribe(IReadOnlyList<string> fullReferences, TimeSpan publishingInterval)
{
ArgumentNullException.ThrowIfNull(fullReferences);
@@ -81,6 +83,7 @@ public sealed class PollGroupEngine : IAsyncDisposable
/// <summary>Cancel the background loop for a handle returned by <see cref="Subscribe"/>.</summary>
/// <returns><c>true</c> when the handle was known to the engine and has been torn down.</returns>
/// <param name="handle">The subscription handle to cancel.</param>
public bool Unsubscribe(ISubscriptionHandle handle)
{
if (handle is PollSubscriptionHandle h && _subscriptions.TryRemove(h.Id, out var state))
@@ -235,6 +238,7 @@ public sealed class PollGroupEngine : IAsyncDisposable
TimeSpan Interval,
CancellationTokenSource Cts)
{
/// <summary>Gets the cache of last-seen values per tag reference.</summary>
public ConcurrentDictionary<string, DataValueSnapshot> LastValues { get; }
= new(StringComparer.OrdinalIgnoreCase);
@@ -249,6 +253,7 @@ public sealed class PollGroupEngine : IAsyncDisposable
private sealed record PollSubscriptionHandle(long Id) : ISubscriptionHandle
{
/// <summary>Gets a diagnostic identifier for this subscription.</summary>
public string DiagnosticId => $"poll-sub-{Id}";
}
}