fix(twincat): update BrowseSymbolsAsync doc + cache adapter fields + Flat-mode note (review)

- ITwinCATClient.BrowseSymbolsAsync XML doc updated: states the implementation now
  expands struct/UDT/FB symbols into atomic member leaves via TwinCATSymbolExpander;
  callers receive only atomic/array leaves with full InstancePaths, never struct containers.
- AdsSymbolNode: cache IsStruct, Mapped, Children, ReadOnly as readonly fields computed
  once in the ctor so repeated property access during recursive expansion doesn't
  re-materialize or re-invoke MapSymbolType/IsSymbolWritable.
- BrowseSymbolsAsync: add operator-gated live risk note next to SymbolsLoadMode.Flat
  warning that a real TC3 target may not populate SubSymbols in Flat mode, with
  guidance to switch to VirtualTree if members don't surface — do not change mode now.
- TwinCATSymbolExpanderTests: simplify confusing `new string('.', 0)` no-op to `""`.
This commit is contained in:
Joseph Doherty
2026-06-17 20:22:45 -04:00
parent 0f929ae668
commit fdd6b332fe
3 changed files with 42 additions and 15 deletions
@@ -99,11 +99,14 @@ public interface ITwinCATClient : IDisposable
CancellationToken cancellationToken);
/// <summary>
/// Walk the target's symbol table via the TwinCAT <c>SymbolLoaderFactory</c> (flat mode).
/// Yields each top-level symbol the PLC exposes — global variables, program-scope locals,
/// function-block instance fields. Filters for our atomic type surface; structured /
/// UDT / function-block typed symbols surface with <c>DataType = null</c> so callers can
/// decide whether to drill in via their own walker.
/// Walk the target's symbol table via the TwinCAT <c>SymbolLoaderFactory</c> (flat mode)
/// and expand all struct / UDT / function-block symbols to their atomic member leaves.
/// The implementation uses <see cref="TwinCATSymbolExpander.ExpandLeaves"/> to recursively
/// descend each struct/UDT/FB-instance symbol into its addressable atomic members,
/// yielding only atomic leaves (scalars or 1-D arrays with a non-null
/// <see cref="TwinCATDiscoveredSymbol.DataType"/>) and dropping struct/UDT/FB containers.
/// Callers receive fully-qualified <c>InstancePath</c>s (e.g. <c>MAIN.Motor1.Speed</c>)
/// and never see struct-typed entries — expansion is performed here, not in the caller.
/// </summary>
/// <param name="cancellationToken">Cancellation token for the enumeration operation.</param>
IAsyncEnumerable<TwinCATDiscoveredSymbol> BrowseSymbolsAsync(CancellationToken cancellationToken);