docs(xmldoc): fill missing XML docs + strip tracking-ID comments across src
v2-ci / build (push) Failing after 41s
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>/<returns>/<inheritdoc> where missing and removes
project bookkeeping IDs (task/tracking refs) from shipped code comments,
so the docs read cleanly and CommentChecker is quiet except for known
false positives (PLC/protocol terms, event/IEqualityComparer inheritdoc).
Doc/comment-only; no logic changed; solution builds clean.
This commit is contained in:
Joseph Doherty
2026-07-07 12:38:39 -04:00
parent 384dbd7d36
commit 9cad9ed0fc
375 changed files with 1899 additions and 2493 deletions
@@ -15,7 +15,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus;
/// spreadsheets from any of those tools without per-tag manual translation.
/// </para>
/// <para>
/// Examples (post-#146 type codes — verified against Wonderware DASMBTCP + Ignition):
/// Examples (type codes — verified against Wonderware DASMBTCP + Ignition):
/// <list type="bullet">
/// <item><c>40001</c> — HoldingRegisters[0], Int16 (default).</item>
/// <item><c>400001</c> — HoldingRegisters[0], Int16 (6-digit form).</item>
@@ -30,7 +30,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus;
/// </list>
/// </para>
/// <para>
/// <b>Grammar scope — out of band (Driver.Modbus.Addressing-007):</b> per-string byte
/// <b>Grammar scope — out of band:</b> per-string byte
/// order (<see cref="ModbusStringByteOrder"/>) is NOT expressible through this grammar.
/// The DL205 low-byte-first string-packing knob is configurable only via the structured
/// tag form (the driver's <c>ModbusTagDefinition.StringByteOrder</c> field). The 3rd
@@ -46,7 +46,7 @@ public static class ModbusAddressParser
/// <returns>The parsed Modbus address.</returns>
public static ParsedModbusAddress Parse(string address) => Parse(address, ModbusFamily.Generic, MelsecFamily.Q_L_iQR);
/// <summary>Parse with a family hint (#144 family-native branch).</summary>
/// <summary>Parse with a family hint (family-native branch).</summary>
/// <param name="address">The address string to parse.</param>
/// <param name="family">The Modbus family hint.</param>
/// <param name="melsecSubFamily">The MELSEC subfamily hint.</param>
@@ -113,7 +113,7 @@ public static class ModbusAddressParser
// else surfaces a clear error in whichever slot it lands.
if (parts.Length == 3)
{
// Driver.Modbus.Addressing-002: reject an empty 3rd field (e.g. "40001:F:") rather
// Reject an empty 3rd field (e.g. "40001:F:") rather
// than silently dropping it. Enumerable.All returns true for an empty sequence, so
// without this guard the empty string would be classified as a valid array count and
// then quietly ignored, leaving the user with no diagnostic for a typo'd trailing colon.
@@ -126,7 +126,7 @@ public static class ModbusAddressParser
else if (parts[2].All(char.IsDigit)) countPart = parts[2];
else
{
// Driver.Modbus.Addressing-003: when TryParseByteOrder would fail on a 4-letter
// When TryParseByteOrder would fail on a 4-letter
// token that looks like a type code (e.g. BOOL), improve the diagnostic so the
// user knows field 3 is a byte order and field 2 is the type.
var mightBeTypeCode = parts[2].Length == 4 && parts[2].All(char.IsLetterOrDigit);
@@ -223,7 +223,7 @@ public static class ModbusAddressParser
}
// Optional bit suffix: '.N' at the end, N in 0..15. Strip before parsing region/offset.
// Driver.Modbus.Addressing-004: use LastIndexOf so a multi-dot input like "40001.5.3"
// Use LastIndexOf so a multi-dot input like "40001.5.3"
// produces a descriptive error ("bit index '5.3' must be 0..15") rather than silently
// parsing "5" as the bit and leaving ".3" as part of the address text. Also validate
// the address segment is non-empty (a leading dot like ".5" is not a valid Modbus addr).
@@ -252,7 +252,7 @@ public static class ModbusAddressParser
bit = bitVal;
}
// Family-native branch (#144) — when a non-Generic family is configured, try its native
// Family-native branch — when a non-Generic family is configured, try its native
// syntax first. Successful native parse wins; failure falls through to Modicon / mnemonic.
// The order matters for cross-family ambiguity: DL205 'C100' is a control relay, not a
// Modicon coil, when the user has explicitly selected DL205.
@@ -271,11 +271,11 @@ public static class ModbusAddressParser
if (TryParseMnemonicAddress(addrText, out region, out offset, out error))
return true;
// Fall back to Modicon (5/6-digit). Reuses #136's parser.
// Fall back to Modicon (5/6-digit). Reuses the shared Modicon parser.
if (ModbusModiconAddress.TryParse(addrText, out region, out offset, out error))
return true;
// Driver.Modbus.Addressing-005: when a non-Generic family was configured and the
// When a non-Generic family was configured and the
// family-native parser set a specific error (meaning the address matched a recognised
// family prefix but the value was invalid, e.g. "contains non-octal digit"), prefer
// that error over the generic Modicon fallback diagnostic, which otherwise says
@@ -371,7 +371,7 @@ public static class ModbusAddressParser
}
catch (Exception ex)
{
// Driver.Modbus.Addressing-006: a try-parse method must never throw, so any helper
// A try-parse method must never throw, so any helper
// exception is converted to a structured error. The current helpers throw only
// ArgumentException (incl. ArgumentOutOfRangeException) and OverflowException, but
// catching narrowly would silently break the TryParse contract if a helper ever
@@ -447,17 +447,17 @@ public static class ModbusAddressParser
return true;
}
// #146 — codes aligned with Wonderware DASMBTCP + Ignition Modbus driver after the
// Codes aligned with Wonderware DASMBTCP + Ignition Modbus driver after the
// 2026-04-25 vendor-doc verification:
// - `:I` is Int32 (Wonderware: "letter 'I' follow ... 32-bit signed quantity, two
// consecutive registers"). Ignition's HRI is also Int32. The pre-#146 mapping
// consecutive registers"). Ignition's HRI is also Int32. The previous mapping
// `:I` = Int16 silently produced wrong-typed data + offset-shifted neighbours when
// a tag spreadsheet was pasted from another vendor.
// - `:S` is the explicit Int16 code (Wonderware: "letter 'S' ... 16-bit signed").
// - `:US` is UInt16 (Ignition: HRUS = "Unsigned Short").
// - `:UI` is UInt32 (parallel to `:I` shape; matches Ignition HRUI).
// - `:I_64` / `:UI_64` for 64-bit (Ignition HRI_64 / HRUI_64 underscore-N convention).
// - `:BCD_32` for 32-bit BCD (Ignition HRBCD_32). The pre-#146 `:LBCD` is dropped.
// - `:BCD_32` for 32-bit BCD (Ignition HRBCD_32). The previous `:LBCD` is dropped.
// - HR/IR with no explicit type still default to Int16 (matches Ignition `HR`).
type = text.ToUpperInvariant() switch
{
@@ -503,13 +503,12 @@ public static class ModbusAddressParser
if ((int)order == -1)
{
// Driver.Modbus.Addressing-003: if the unknown token is a VALID type code in this
// parser, direct the user to put it in field 2 instead. Only BOOL (4-letter) and
// STR<n> are valid type codes that could appear here. "REAL", "DINT", "UINT" look
// like type names from other tools (STEP 7 / RSLogix) but are NOT valid in this
// parser's type table (Driver.Modbus.Addressing-010) — listing them here would give
// advice that leads to a second error ("Unknown type code 'REAL'").
var upper = text.ToUpperInvariant();
// If the unknown token is a VALID type code in this parser, direct the user to put
// it in field 2 instead. Only BOOL (4-letter) and STR<n> are valid type codes that
// could appear here. "REAL", "DINT", "UINT" look like type names from other tools
// (STEP 7 / RSLogix) but are NOT valid in this parser's type table — listing them
// here would give advice that leads to a second error ("Unknown type code 'REAL'").
var isActualTypeCode = upper is "BOOL"
|| (text.Length > 3 && text.StartsWith("STR", StringComparison.OrdinalIgnoreCase)
&& text[3..].All(char.IsDigit));