Commit Graph

3 Commits

Author SHA1 Message Date
Marc Schier 0357380335 Source generator: typed NodeSet method signatures and referenced model accessors (#4124)
**Stack 2/5** — base #4123. Part of the #4096 split; see #4096 for the
overall picture.

> Review after #4123. The diff shown against `master` will include #4123
until that merges.

## What this is

Source generator only; no runtime library changes.

## Contents

- **Typed NodeSet method signatures.** A method imported from a NodeSet
now gets a typed signature. Methods that share a declared signature are
grouped onto one generated `MethodType`, named after its owner when the
plain name would collide, so two unrelated `Execute` methods no longer
share a class.
- **An override that keeps the signature it inherits keeps the
declaration it overrides.** Pointing `MethodDeclarationNode` at the
override itself made `MethodDeclarationId` self-referential. OPC 10000-4
lets a caller invoke a method with the NodeId of its declaration in the
ObjectType *or any supertype*, and `MethodState.MethodDeclarationId` is
what the server matches on, so `Call` stopped resolving and returned
`Bad_MethodInvalid` for every alarm subtype. An override that genuinely
changes its signature still becomes its own declaration.
- **`StateNumbers` / `TransitionNumbers` were emitted empty for every
NodeSet-sourced model**, because such children arrive as
`VariableDesign` rather than `PropertyDesign` and were filtered out. Any
companion model built from a NodeSet was writing `StateNumber = 0` on
the wire — a Part 16 defect well beyond the models in this stack. The
ModelDesign path is unchanged.
- **Referenced models can contribute fluent accessors**, carried by a
model dependency payload so a downstream model can extend an upstream
one.

## Notes for the reviewer

- `tests/Opc.Ua.SourceGeneration.Tests` is left at its `master` content
here. Its new vendor-subtype test uses the Robotics NodeSet as its
fixture, so it can only land with the Robotics change at the top of the
stack (5/5).
- `PumpInstanceNodeIdRegressionTests` gains six
`InputArguments`/`OutputArguments` entries for argument-less standard
condition methods. Typed method signatures materialise those properties
from the `ConditionType` declaration even where the method takes none.
That is a real deviation, pinned rather than hidden so it stays visible;
it is worth a follow-up.

## Validation

`dotnet build UA.slnx` — 0 errors.

| Suite | Result |
| --- | --- |
| Opc.Ua.SourceGeneration.Core.Tests | 3739 / 0 |
| Opc.Ua.SourceGeneration.Tests | 81 / 0 |
| Opc.Ua.Di.Tests | 304 / 0 |
| Opc.Ua.History.Tests | 506 / 0 |
| Opc.Ua.Gds.Tests | 1095 / 0 |

History and GDS are listed because they are what the method-declaration
fix above is load-bearing for: without it they fail with 10 and 370
errors respectively.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8cbb8cd0-f0cb-4ab0-bea2-6202fbf69485
2026-08-01 07:55:57 +02:00
Marc Schier 5b9bcedc62 Add OPC UA ISA-95 Common Model and Job Control support (#4089)
# Description

Adds first-class support for the OPC UA ISA-95 companion specifications:

- OPC-10030 Common Model.
- OPC-10031-4 Job Control V1.
- OPC-10031-4 Job Control V2.

The change introduces `Opc.Ua.ISA95`, `Opc.Ua.ISA95.Client`, and
`Opc.Ua.ISA95.Server`, together with a NativeAOT-compatible minimal
server sample and comprehensive tests.

## Highlights

- Compiles the three canonical NodeSets and identifier mapping CSV files
through the source generator.
- Adds NodeSet identifier mapping validation, typed method
arguments/results, companion event records, and generated method
argument nodes.
- Provides typed Common Model builders with normative relationships and
an injectable `GeoSpatialLocationType` provider.
- Implements lossless V1/V2 Job Control providers over a shared
version-neutral store, including state paths, status events, comments,
response queries, catalog changes, and cohesive DI registration.
- Adds subtype-aware typed clients, standalone encodeable registration,
`IIsa95ClientFactory`, and V2 status-event streaming.
- Adds the `MinimalIsa95Server` sample, package documentation, and an
ISA-95 guide with conformance and HA guidance.
- Tracks typed RSL/GPOS integration as follow-up issue #4095.

## Validation

- `Opc.Ua.ISA95.Tests`: 137/137 passed on `net10.0` and `net48`.
- Source-generator suites: 81/81 model, 90/90 stack, 3718 passed / 8
skipped core.
- `EventRecordFieldReaders` feedback tests: 6/6 on `net10.0` and
`net48`.
- `EventRecordFieldReaders` changed-method patch coverage: 100% line
coverage (36/36) and 100% branch coverage (22/22).
- `Opc.Ua.ISA95`, `.Client`, and `.Server` build across all configured
target frameworks without new diagnostics.
- Cobertura line coverage: 88.08% model, 90.04% client, 91.19% server.
- NativeAOT sample publishes and passes a live typed V2
Store/status-event validation.
- The ISA-95 NativeAOT smoke test passes in the source-generated native
test executable.
- OPC UA KB NodeSet validation reports zero errors for Common, V1, and
V2.

The broader NativeAOT executable still reports unrelated existing GDS
and complex-type test failures; the ISA-95-specific native test passes.

## Node state generator fixes

Generating method arguments inline for imported nodesets regressed every
model that already emits `InputArguments` / `OutputArguments` child node
factories:

- The inline block ran before the child factories.
`MethodState.CreateOrReplaceInputArguments` keeps the property that was
assigned first, so the child carrying the well-known NodeId was dropped
and a NodeId-less placeholder remained in the address space. This broke
browsing (reference descriptions without a target) and made method
arguments unreachable at their well-known NodeIds.
- The `MethodDeclarationId` fallback keyed on an autogenerated display
name redirected every declared method of the standard address space to
its own NodeId, which made method calls fail.

The inline block is now emitted after the child factories and reduced to
a value assignment when a child factory exists. The value is only
re-emitted when an argument references a namespace other than OPC UA,
because the value of an imported property is the verbatim XML of the
source nodeset whose namespace indices do not survive the import. The
`MethodDeclarationId` fallback is restricted to declarations without a
resolvable NodeId. The generated OPC UA address space is byte-identical
to `master` again.

## Related Issues

- Fixes #4088
- Follow-up: #4095
2026-07-28 12:01:57 +02:00
Marc Schier 7cec2d614d Move repository files to the consolidated layout 2026-07-16 06:25:54 +02:00