fix(driver-modbus-addressing): resolve Low code-review findings (Driver.Modbus.Addressing-006,007,009)

- Driver.Modbus.Addressing-006: broaden the catch in TryParseFamilyNative
  so a future helper throwing a non-Argument/Overflow type still satisfies
  the try-parse contract.
- Driver.Modbus.Addressing-007: document that the address grammar does
  not carry ModbusStringByteOrder (the structured-tag path does);
  add a 'Grammar scope' bullet to docs/v2/dl205.md.
- Driver.Modbus.Addressing-009: reword the ModbusModiconAddress comments
  so they don't imply a leading-digit invariant the parser doesn't
  enforce.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-05-23 08:18:15 -04:00
parent 1f29b215c8
commit 9263519852
6 changed files with 178 additions and 15 deletions

View File

@@ -7,7 +7,7 @@
| Review date | 2026-05-22 |
| Commit reviewed | `76d35d1` |
| Status | Reviewed |
| Open findings | 3 |
| Open findings | 0 |
## Checklist coverage
@@ -157,7 +157,7 @@ overwrite it.
| Severity | Low |
| Category | Error handling & resilience |
| Location | `ModbusAddressParser.cs:297-301` |
| Status | Open |
| Status | Resolved |
**Description:** `TryParseFamilyNative` catches only `ArgumentException` and `OverflowException`.
The current helpers throw only those (including `ArgumentOutOfRangeException`, which derives from
@@ -171,7 +171,13 @@ depend on.
narrow catch, or broaden to a general catch-all that records the message — a try-parse method
should never throw.
**Resolution:** _(open)_
**Resolution:** Resolved 2026-05-23 — broadened the `catch` filter in
`ModbusAddressParser.TryParseFamilyNative` from `ArgumentException or OverflowException` to a
general `catch (Exception ex)` so any future helper exception type is converted to a structured
`(false, error)` rather than escaping the `TryParse` method. Added `DL205_TryParse_NeverThrows`
and `MELSEC_TryParse_NeverThrows` parameterised regression tests in
`ModbusAddressEdgeCaseTests` covering ~20 pathological inputs (empty prefixes, octal/hex digit
violations, overflow inputs, unknown prefixes) to pin the defensive contract.
### Driver.Modbus.Addressing-007
@@ -180,7 +186,7 @@ should never throw.
| Severity | Low |
| Category | Design-document adherence |
| Location | `ModbusDataType.cs:91-95`, `docs/v2/dl205.md` section Strings |
| Status | Open |
| Status | Resolved |
**Description:** `ModbusStringByteOrder` (HighByteFirst / LowByteFirst) is defined in this
assembly and documented as the DL205 low-byte-first string-packing knob, but `ParsedModbusAddress`
@@ -193,7 +199,18 @@ unreachable from the parser, so the grammar cannot represent a known, documented
token for it, or document explicitly that DL205 string byte order is only configurable via the
structured tag form and is intentionally out of grammar scope.
**Resolution:** _(open)_
**Resolution:** Resolved 2026-05-23 — chose the "document the limitation" branch of the
recommendation rather than adding a grammar token: the 3rd field slot is the multi-register
word/byte order and the 4th is the array count, so a 5th `:<order>` suffix would conflict with
the existing count-shape disambiguation; `ModbusStringByteOrder` is already plumbed through the
structured tag form (`ModbusDriverFactoryExtensions.ModbusTagDto.StringByteOrder`
`ModbusTagDefinition.StringByteOrder`) which is the canonical config path. Added an explicit
"Grammar scope" remarks block to `ModbusStringByteOrder` and to the `ModbusAddressParser`
`<remarks>` block stating that string byte order is configurable only via the structured tag
form. Added a corresponding bullet to `docs/v2/dl205.md` §Strings. Added two regression tests
(`Parser_STR_grammar_does_not_carry_StringByteOrder` reflecting on `ParsedModbusAddress`, and
`Parser_rejects_unknown_string_byte_order_token_in_grammar`) pinning the contract so a future
grammar change can't quietly add a conflicting token.
### Driver.Modbus.Addressing-008
@@ -226,7 +243,7 @@ finding -001.
| Severity | Low |
| Category | Documentation & comments |
| Location | `ModbusModiconAddress.cs:55-64`, `ModbusModiconAddress.cs:104-110` |
| Status | Open |
| Status | Resolved |
**Description:** The comments on `ModbusModiconAddress.TryParse` are slightly inaccurate. The
remark that 5-digit Modicon is always exactly 5 chars (40001..49999) and 6-digit is exactly 6
@@ -238,4 +255,11 @@ says the 5-digit form caps at 9999 by construction while the adjacent code path
**Recommendation:** Reword the range examples to cover all four region digits and drop the
caps-at-9999 aside or restate it as a precise statement about trailing-digit count.
**Resolution:** _(open)_
**Resolution:** Resolved 2026-05-23 — reworded the up-front range-check comment to describe all
four region digits (0/1/3/4) and give examples covering each region (coils 00001..09999 /
000001..065536, holding registers 40001..49999 / 400001..465536). Reworded the lower
`> 65536` comment to drop the misleading "5-digit form caps at 9999 by construction" framing and
state precisely that the check is reached only by the 6-digit form in practice, but applied to
both for safety rather than relying on the digit-count invariant. Pure documentation change —
no behavioural change; the existing `ModbusModiconAddressTests` already pin the cross-region
5-digit ranges (00001..09999 / 10001..19999 / 30001..39999 / 40001..49999).