mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-21 00:56:28 +08:00
ecc-testing-fixes-2
34 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
59374fc81d |
Generate MatrixOf<T> properties for OneOrMoreDimension types (#3625) (#3868)
# Description Closes the original PR #3619 TODO and extends the `MatrixOf<T>` opt-in to every place the source generator previously fell back to `Variant` for `ValueRank="OneOrMoreDimensions"`. ## Generator changes (`Tools/Opc.Ua.SourceGeneration.Core`) ### Site 1 — DataType structure fields (`DataTypeGenerator.cs`) Fields declared with matrix rank now render as `global::Opc.Ua.MatrixOf<T>` instead of `Variant`, mirroring the existing `ArrayOf<T>` treatment for `Array` rank. Encode/decode is routed per the field's `DataType`: | Field `DataType` | Property | Encode | Decode | | ------------------------------------------------- | --------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------- | | primitive (`Boolean`, `Int32`, `String`, …) | `MatrixOf<bool>` etc. | `WriteVariant(name, Variant.From(field));` | `ReadVariant(name).GetBooleanMatrix();` (etc.) | | `Structure` / abstract structure | `MatrixOf<ExtensionObject>` | `WriteVariant(name, Variant.From(field));` | `ReadVariant(name).GetExtensionObjectMatrix();` | | concrete `IEncodeable` (e.g. `Vector`) | `MatrixOf<Vector>` | `WriteEncodeableMatrix(name, field);` | `ReadEncodeableMatrix<Vector>(name);` | | typed enum | `MatrixOf<MyEnum>` | `WriteVariant(name, Variant.From(field));` | `ReadVariant(name).GetEnumerationMatrix<MyEnum>();` | | `BaseDataType` / `Number` / `Integer` / `UInteger`| `MatrixOf<Variant>` | `WriteVariant(name, Variant.From(field));` | `ReadVariant(name).GetVariantMatrix();` | ### Site 2 — VariableType State classes (`NodeStateGenerator.cs`) Replaces the original `// TODO: matrixOf;` from #3619. Concrete matrix variable types now inherit the typed `<MatrixOf<T>>` chain. Standard model: - `XYArrayItemState : ArrayItemState<MatrixOf<XVType>>.Implementation<StructureBuilder<XVType>>` Abstract bases (`ArrayItemType`, `CubeItemType`, `ImageItemType`, `NDimensionArrayItemType` — all `DataType="BaseDataType"`) keep the existing `<T>` early-return. ### Site 3 — Property / Variable instances (`ModelDesignExtensions.GetNodeStateClassName`) Adds a `OneOrMoreDimensions` branch after the existing `Array` branch and refines `IsTemplateParameterRequired` / `IsIndeterminateType` so matrix-rank concrete types are no longer treated as indeterminate. Standard model: - `EnumDictionaryEntries: PropertyState<MatrixOf<NodeId>>` - `FailureSystemIdentifier: BaseDataVariableState<MatrixOf<byte>>` ### Site 4 — Method parameters (`ClientApiGenerator` / `ServerApiGenerator`) `CollectParameters` opts in to `useMatrixTypeInsteadOfVariant` via `SupportsMatrixOf()`. Zero standard-service impact (no OPC UA service declares matrix args). ## Encoder / decoder API Adds the parameterless overload `MatrixOf<T> ReadEncodeableMatrix<T>(string? fieldName) where T : IEncodeable, new()` to `IDecoder` and all implementations (`BinaryDecoder`, `JsonDecoder`, `XmlDecoder`, `XmlParser`, `PubSubJsonDecoder`), mirroring the existing `ReadEncodeableArray<T>(string?)` shape so the generator does not need a runtime encoding-id lookup. ## Consumer migration - `Applications/Quickstarts.Servers/ReferenceServer/ReferenceNodeManager.cs` — `CreateXYArrayItemVariable` updated from `Variant.FromStructure(ArrayOf.Wrapped(...))` to `new XVType[] { … }.ToMatrixOf(5)` to match the new typed `XYArrayItemState.Value` surface. ## Tests added - **Generator snippet tests**: `GenerateMatrixValueDataType_EmitsMatrixOfPropertiesAndCalls` (custom data-type matrix fields) and `NodeStateGeneratorEmitsMatrixOfTemplateParameterForStandardModel` (standard-model VariableType + instance types). - **Encoder round-trip**: new `EncodeableMatrixRoundTripTests` exercises `WriteEncodeableMatrix` ↔ `ReadEncodeableMatrix<T>(string?)` through Binary, XML, and parameterless overloads with null-matrix and populated payloads. - **Extension tests**: parameterised `GetDotNetTypeName_OneOrMoreDimensionsValueRankWithBasicDataTypes_ReturnsCorrectMatrixOfType` and `IsTemplateParameterRequired_OneOrMoreDimensionsWith…` tables; `SupportsMatrixOf` coverage including `DiagnosticInfo → false` and `ArgumentNullException` for null receiver. - **Test resource models** (`TestDataDesign.xml`, `DemoModel.xml`, `TestModel.xml`): new `MatrixValueDataType` / `SampleStructureWithMatrixFields` exercise every branch end-to-end through the existing `GenerateAndCompileDesignFileAsync` integration test. ## Documentation `Docs/MigrationGuide.md` — new sub-section "Generated data type fields with ValueRank=OneOrMoreDimensions" with a per-`BasicDataType` mapping table, the `IDecoder.ReadEncodeableMatrix<T>(string?)` overload note for custom decoder implementations, and a sibling block covering VariableType State classes, property-state instances, and service parameters with before/after code samples. ## Verification | Suite (net10.0) | Result | | --------------- | ------ | | `Opc.Ua.Types.Tests` | 7553 passed | | `Opc.Ua.SourceGeneration.Core.Tests` | 3623 passed, 8 skipped (analyzer-conditional) | | `Opc.Ua.SourceGeneration.Stack.Tests` | 90 passed | | `Opc.Ua.SourceGeneration.Tests` | 40 passed | | `Opc.Ua.Server.Tests` (focused on `ReferenceServer`/`ArrayItem`) | 37 passed | | Full `UA.slnx` build | 0 errors (42 pre-existing unrelated CA2007 warnings) | The `// TODO: matrixOf;` comment is gone from `NodeStateGenerator.cs`. ## Related Issues - Fixes #3625 ## Checklist - [x] I have signed the [CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf) and read the [CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md) doc. - [x] I have added tests that prove my fix is effective or that my feature works and increased code coverage. - [x] I have added all necessary documentation. - [x] I have verified that my changes do not introduce (new) build or analyzer warnings. - [x] I ran **all** tests locally using the **UA.slnx** solution against at least .net **framework** and .net **10**, and all passed. - [ ] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [ ] I have addressed **all** PR feedback received. |
||
|
|
a81d981755 |
dotnet format sweep (whitespace, IDE, RCS) + code-style enforcer agent fix (#3865)
# Description
Pure code-style sweep across the repo — no behavioral changes. Drives
`dotnet format` info-level diagnostics down on a large slice of the
codebase (Stack, Libraries, Tests, Tools).
Six commits, applied bottom-up in safety order so each batch leaves the
build green:
1. **`style: fix whitespace and final-newline formatting (WHITESPACE,
FINALNEWLINE)`**
197 hits across ~30 files; pure mechanical cleanup.
2. **`style: apply dotnet format style fixes (IDE rules)`**
IDE-rule batch via `dotnet format style --severity info` —
`var`/explicit type, simplify names, collection expressions, expression
bodies, unused usings, etc.
3. **`style: apply dotnet format analyzers fixes (RCS blank-line
formatting)`**
Roslynator formatting (RCS0xxx) blank-line and punctuation rules.
4. **`style: convert comments to doc comments and inline local vars
(RCS1181, RCS1124)`**
24 files. RCS1181 promotes `// summary`-style comments above
public/internal members to `/// <summary>` doc comments; RCS1124 inlines
locals used exactly once. Generated `Tools/` files were reverted to keep
the source-generator outputs deterministic.
5. **`docs(agent): correct --diagnostics flag form and verify Roslynator
4.x code fixers`**
Updates `.github/agents/opc-ua-codestyle-enforcer.agent.md` with two
corrections discovered while running this sweep:
- `dotnet format --diagnostics "RULE1 RULE2"` (single quoted,
space-separated) silently fixes nothing on `dotnet format` 10.x — it
parses as one unknown ID and exits 0. The correct form is `--diagnostics
RULE1 --diagnostics RULE2 …`, repeated per rule.
- Roslynator 4.15.0 **does** ship code fixers for
RCS1078/1118/1124/1140/1142/1181/1221/1260 (the previous "no auto-fixer"
list was outdated). RCS1140/1142 default to `Hidden` so need `--severity
info` to surface and fire; RCS1078 requires
`roslynator_empty_string_style = field` (already set in
`.editorconfig`). Only NUnit4002/2046/2010 genuinely lack auto-fixers in
this stack.
6. **`style: format new code from master merge (dotnet format sweep)`**
After merging master into the branch (commit `e3ebc8742`), re-ran the
same three-phase format sweep on the 151 .cs files brought in by the
merge, scoped per project via repeated `--include`. 81 files changed;
same rule families as commits 1–4.
- Hand-fixed `Tests/Opc.Ua.MigrationAnalyzer.Tests/AnalyzerHarness.cs`
for `RCS1174` (redundant `async`/`await` removal) because the auto-fixer
didn't apply for that specific case.
- Reverted files that the formatter would break:
- `Libraries/Opc.Ua.Server/Server/ServerInternalData.cs` — multi-TFM
analysis disagreement injected `<<<<<<<` / `=======` / `>>>>>>>`
markers.
-
`Tools/Opc.Ua.MigrationAnalyzer.Core/{Core/Stack/Client/ChannelBase.cs,
Core/Stack/Types/IUserIdentityTokenHandler.cs,
Client/Session/Session.cs}` — IDE0005 removed `using
Opc.Ua.Security.Certificates` that IS used (the files are 1.5.378
reference fixtures for the analyzer).
- `Tests/Opc.Ua.Gds.Tests/PushTest.cs` — IDE0002 over-simplified
`OpcUa.ObjectTypeIds` to `ObjectTypeIds`, which then resolves to a
conflicting type.
### What this PR does **not** touch
- No behavioral or semantic logic changes.
- No `.editorconfig` rule promotions (rules stay at their current
severities; this is a backlog-burndown pass, not a rule tightening).
- Generated source under `Tools/` is intentionally excluded.
- Higher-risk rule families (`RCS1090`/`CA2007` `ConfigureAwait`,
`RCS1249` null-forgiving cleanup, `IDE0270`/`IDE0059`) are left for
follow-up sweeps because they need per-TFM build verification or
semantic review.
## Related Issues
_No tracking issue — this is a non-functional style sweep and the
agent-doc correction is a follow-up to the same work. Happy to open one
if the maintainers prefer._
## Checklist
- [ ] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage. _(N/A — style-only, no
behavioral change)_
- [x] I have added all necessary documentation. _(agent doc updated with
the two corrections)_
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings. _(verified clean on `net10.0` and `net48`; only
pre-existing `NETSDK1005`/`NETSDK1207` failures on Tools/AOT projects)_
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed. _(build
verified on net10 and net48 per batch; full test suite not yet run
locally — relying on CI)_
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.
---------
Co-authored-by: agent <agent@local>
|
||
|
|
2966f693b2 |
2.0 Migration Analyzer and codefixer with Agent update (#3820)
Introduces `OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer` — a single NuGet package that ships **three Roslyn components + a runtime shim** to make the 1.5.378 → 2.0 upgrade as close to "install package, run `dotnet format`, remove package" as possible: | DLL | Where | Purpose | |-----|-------|---------| | `Opc.Ua.MigrationAnalyzer.dll` | `analyzers/dotnet/cs/` | 19 Roslyn analyzers (`UA0001`–`UA0022`) covering every breaking-change pattern in [`Docs/MigrationGuide.md`](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/Docs/MigrationGuide.md). Built against the stable Roslyn 4.14 analyzer API — loads cleanly in csc.exe (no `Microsoft.CodeAnalysis.Workspaces` reference). | | `Opc.Ua.MigrationAnalyzer.CodeFixer.dll` | `analyzers/dotnet/cs/` | 14 companion `CodeFixProvider`s; loaded only by Workspaces-aware hosts (Visual Studio, `dotnet format analyzers`). | | `Opc.Ua.MigrationAnalyzer.Generator.dll` | `analyzers/dotnet/cs/` | Roslyn `IIncrementalGenerator` that emits per-consumer `internal sealed [Obsolete] class <Name>Collection : List<TElement>` shims for every `<Type>Collection` wrapper the consumer references — including **arbitrary model-compiled `<UserType>Collection` patterns**, not just the 30 well-known built-in ones. | | `Opc.Ua.MigrationAnalyzer.Core.dll` | `lib/<tfm>/` for `net472, net48, netstandard2.1, net8.0, net9.0, net10.0` | 1.5.378 → 2.0 runtime compatibility shim. Re-exposes the obsolete extension surface so 1.5.378-style call sites keep compiling against 2.0 with warnings instead of errors. | ### Migration workflow the package enables 1. **Bump every `OPCFoundation.NetStandard.Opc.Ua.*` PackageReference to `2.0.*-*`.** 2. **Add the migration package** as a build-only dependency: ```xml <PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer" Version="2.0.*-*" PrivateAssets="all" /> ``` 3. **Run `dotnet build`.** The Core shim DLL re-supplies obsolete extension members; the source generator covers `<Type>Collection` references; what remains are `[Obsolete]` warnings + `UA00xx` analyzer diagnostics + (occasionally) `MIG01` for unresolvable model-compiled element types. 4. **Apply auto-fixes** in the IDE or from the command line: ```bash dotnet format analyzers <solution>.sln \ --diagnostics UA0002 UA0003 UA0004 UA0005 UA0006 UA0007 UA0008 \ UA0009 UA0010 UA0012 UA0014 UA0019 UA0020 UA0022 \ --severity warn ``` 5. **Walk the residual** `UA0001` / `UA0011` / `UA0015` / `UA0018` / `UA0021` diagnostics manually — they cover patterns that require human judgement. 6. **Remove the migration package.** You are now on clean 2.0 with no shim dependency. ### Source generator (`Opc.Ua.MigrationAnalyzer.Generator.dll`) Per-consumer Roslyn `IIncrementalGenerator` that emits `.g.cs` files for every `<Name>Collection` reference in the consumer's compilation that fails to bind: - **Catalog override (30 entries)** — pins element types that renamed across the 1.5.378 → 2.0 boundary: `DateTime`→`DateTimeUtc`, `Guid`→`Uuid`, `byte[]`→`ByteString`, `XmlElement`→`Opc.Ua.XmlElement`, plus the primitives and built-in opc types whose element name didn't rename. - **Semantic lookup** — for model-compiled `<UserType>Collection` patterns the model compiler historically emitted for any user-defined complex type. Strips the `Collection` suffix, runs `Compilation.GetSymbolsWithName` against the unique element short name, emits the shim with the fully-qualified type reference. - **`MIG01` diagnostic** — fires when the element type can't be uniquely resolved (zero or multiple candidates). User adds the missing `using` or migrates the site manually. Each generated file emits a class shaped exactly like the 1.5.378 wrapper: ```csharp [global::System.Obsolete("'Int32Collection' was removed in 2.0. Use 'List<int>' or 'ArrayOf<int>' instead. (UA0002)")] internal sealed class Int32Collection : global::System.Collections.Generic.List<int> { public Int32Collection() { } public Int32Collection(int capacity) : base(capacity) { } public Int32Collection(global::System.Collections.Generic.IEnumerable<int> collection) : base(collection) { } public static implicit operator global::Opc.Ua.ArrayOf<int>(Int32Collection? value) => value is null ? default : value.ToArrayOf(); } ``` **Design choice — `internal` (not `public`):** the generated shim never leaks through the consumer's public API surface. Consumers with *public* methods or properties returning a `<Type>Collection` will hit `CS0050: Inconsistent accessibility` — the intended signal that the public surface must migrate to `List<T>` / `ArrayOf<T>` first; internal call sites keep compiling under the shim so iteration is incremental. ### 19-rule analyzer reference | Rule | Replaces | Default | Auto-fix | |------|----------|---------|----------| | `UA0001` | `Utils.Trace` / `Utils.LogX` | Info | No (telemetry plumbing requires manual review) | | `UA0002` | Removed `<Type>Collection` wrappers | Warning | Yes (→ `List<T>` / `ArrayOf<T>`); the source generator keeps the call site compiling in the meantime | | `UA0003` | `x == null` on now-struct built-ins | Warning | Yes (→ `x.IsNull`) | | `UA0004` | `?.` on now-struct built-ins | Warning | Yes (drop the `?`) | | `UA0005` | `byte[]` where `ByteString` is expected | Warning | Yes (append `.ToByteString()`) | | `UA0006` | `new Variant(object\|DateTime\|Guid\|byte[])` | Warning | Yes (→ `Variant.From(...)`) | | `UA0007` | `new NodeId(string)` / `new ExpandedNodeId(string)` | Warning | Yes (→ `Parse`) | | `UA0008` | `Session.Call(..., params object[])` | Warning | Yes (wrap with `Variant.From`) | | `UA0009` | `[DataContract]` / `[DataMember]` on config extensions | Warning | Yes (→ `[DataType]` / `[DataTypeField]`) | | `UA0010` | `using` / `Dispose` on `CertificateIdentifier` / `UserIdentity` / `IUserIdentityTokenHandler` | Warning | Yes (drop the disposable) | | `UA0011` | Sync `IUserIdentityTokenHandler.{Encrypt,Decrypt,Sign,Verify}` | Info | No (async promotion required) | | `UA0012` | `CertificateFactory.*` static helpers | Warning | Yes (→ instance methods) | | `UA0014` | `DataValue.IsGood(dv)` static helper | Warning | Yes (→ `dv.IsGood`) | | `UA0015` | Sync / APM members on GDS / LDS clients | Info | No (async promotion required) | | `UA0018` | `CertificateIdentifier.Certificate` getter | Info | No (→ `LoadCertificate2Async`) | | `UA0019` | `new DataValue(StatusCode[, ts])` | Warning | Yes (→ object-initializer form) | | `UA0020` | `EncodeableFactory.GlobalFactory` / `Create()` | Warning | Yes (→ `ServiceMessageContext.Factory` / `Fork()`) | | `UA0021` | `CertificateValidator` / `CertificateValidationEventArgs` (structural rename) | Info | No (see migration guide §Certificate validation) | | `UA0022` | `ApplicationConfiguration.CertificateValidator` / `ServerBase.CertificateValidator` property rename | Warning | Yes (→ `.CertificateManager`) | Plus one generator-only diagnostic: | Rule | Source | Default | Triggers | |------|--------|---------|----------| | `MIG01` | Generator | Warning | Generator can't uniquely resolve the element type for a `<Foo>Collection` reference (zero or multiple candidates). The user adds a `using` for the namespace defining `Foo`, or migrates the call site manually. | ### Runtime shim coverage (`Opc.Ua.MigrationAnalyzer.Core.dll`) C# 14 `extension` members so 1.5.378 call sites continue to compile: - **Moved obsolete extensions** the 2.0 libraries no longer carry inline: `NodeId` / `Variant` / `DataValue` null-check helpers, `Session` sync helpers, `Subscription` sync helpers, `ApplicationInstance` helpers, `ServerBase.Start` / `Stop`, `TransportChannel` APM, `ChannelBase` static factory methods, etc. - **New shims for genuinely-removed members**: `EncodeableFactory.GlobalFactory`, `CertificateIdentifier.Certificate` (throws), sync wrappers for `IUserIdentityTokenHandler.{Encrypt,Decrypt,Sign,Verify}`, sync + APM wrappers for the GDS / LDS client APIs, `GlobalDiscoverySampleServer` 1.5.378-shape ctor (in-tree `Libraries/Opc.Ua.Gds.Server.Common/`). > ⚠ The sync shims wrap their `*Async` counterparts via `Task.Run(…).GetAwaiter().GetResult()`. Intended as a **migration aid only** — port to `await` before shipping. ### Repo layout ``` Tools/Opc.Ua.MigrationAnalyzer/ # analyzer DLL Analyzers/UA00xxAnalyzer.cs # 19 DiagnosticAnalyzer impls Diagnostics/{DiagnosticIds,Descriptors,WellKnownProperties}.cs Helpers/{SymbolExtensions,UaSymbols}.cs Opc.Ua.MigrationAnalyzer.nuspec # ships all 3 analyzer DLLs + 6-TFM Core OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer.props Tools/Opc.Ua.MigrationAnalyzer.CodeFixer/ # code-fix DLL CodeFixes/UA00xxCodeFix.cs # 14 CodeFixProvider impls Tools/Opc.Ua.MigrationAnalyzer.Generator/ # source generator DLL (NEW) MigrationGenerator.cs # IIncrementalGenerator CollectionShimCatalog.cs # 30-entry element-type overrides Diagnostics/GeneratorDiagnostics.cs # MIG01 Tools/Opc.Ua.MigrationAnalyzer.Core/ # runtime shim (multi-TFM) Client/, Configuration/, Core/, Gds.Client.Common/, Types/, Marker/ Tools/Roslyn.slnx # source-gen + migration projects Tests/Opc.Ua.MigrationAnalyzer.Tests/ # 142 tests Analyzers/UA00xxTests.cs # 107 analyzer + code-fix tests Generators/MigrationGeneratorTests.cs # 35 generator tests (NEW) Tests/Opc.Ua.MigrationAnalyzer.Core.Tests/ # 13 runtime-shim tests ``` ### Documentation - [`Docs/MigrationGuide.md`](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/Docs/MigrationGuide.md) — §3 Collection Type Migration gains a tip pointing at the generator so CS0246 is replaced with `[Obsolete]` warnings + UA0002. - [`.github/agents/opcua-v20-migration.agent.md`](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/.github/agents/opcua-v20-migration.agent.md) — Strategy section mentions the three Roslyn components + runtime shim explicitly, plus the MIG01 diagnostic and the "internal-by-design" CS0050 hint. ### Central package pinning `Directory.Packages.props` pins `Microsoft.CodeAnalysis.*` (Common, CSharp, CSharp.Workspaces, Workspaces.Common) to **4.14.0** — the stable analyzer API surface. The earlier 5.3 pin was the *csc-internal* version, which is not safe for analyzer hosts. ### Dogfood story The full 42-sample dogfood against `OPCFoundation/UA-.NETStandard-Samples` surfaced a **critical analyzer-loader bug** in an earlier iteration: the analyzer DLL initially co-shipped its code-fix providers in one assembly, which transitively referenced `Microsoft.CodeAnalysis.Workspaces.dll`. csc.exe's analyzer host ships only `Microsoft.CodeAnalysis.dll` + `CSharp.dll` in its bincore and **silently swallows** load failures — net result: zero diagnostics across all samples. Fix landed in commit `861fa6ee1`: 1. **Split** the assembly: analyzer in `Opc.Ua.MigrationAnalyzer.dll` (Workspaces-free, csc-safe), code-fixes in `Opc.Ua.MigrationAnalyzer.CodeFixer.dll` (Workspaces-aware, IDE-only). 2. **Downgrade** to Roslyn 4.14 — the stable analyzer API. 3. `/p:ReportAnalyzer=true` confirms all 19 analyzers initialise and execute on real consumer code. This PR's new generator was smoke-tested against a minimal consumer that exercises all 30 catalog entries + a model-compiled element type + the unresolvable case: - 30 catalog patterns + model-compiled `MyThingCollection` → all emit shims, fire CS0618 with `(UA0002)` marker - Element-type renames verified: `DateTimeCollection` → `DateTimeUtc`, `ByteStringCollection` → `ByteString`, `GuidCollection` → `Uuid`, etc. - `NeverHeardOfItCollection` → `MIG01` fires with help link to the migration guide Known compatibility gaps (documented in the migration agent): - Legacy WinForms `.Net4` sample projects use pre-SDK MSBuild XML and **ignore** `Directory.Build.targets` `<PackageReference>` injection — consumers in this format must add the migration package to their csproj inline. ### Packaging design notes - Hand-authored nuspec ships 3 DLLs in `analyzers/dotnet/cs/` + 6 TFMs of Core (shim) DLLs under `lib/`. All 6 OPC UA runtime package dependencies are declared per-TFM-group. - `build/OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer.props` is auto-imported by NuGet (file name must match package id exactly) and injects all three analyzer DLLs as `<Analyzer>` items. - `DiagnosticIds.cs` / `DiagnosticDescriptors.cs` / `WellKnownProperties.cs` / `Helpers/*.cs` are **shared via `<Compile Link=…>`** between the analyzer and code-fixer projects to break what would otherwise be a NuGet restore cycle. The generator has no compile dependency on the analyzer; the 30-entry override table is duplicated in `CollectionShimCatalog.cs` (the analyzer table also drives diagnostic messages, so the duplication is small and intentional). - `Opc.Ua.MigrationAnalyzer.Core` is multi-TFM (`net472, net48, netstandard2.1, net8.0, net9.0, net10.0`) and **non-packable on its own**; the parent migration package's nuspec consumes each TFM's DLL by path. |
||
|
|
4756e7c245 |
DI (OPC 10000-100) with samples (Pump, SW Update), fluent API gap closures and model dependency implementation (#3808)
This PR implements the **OPC UA Device Integration (DI, OPC 10000-100)** companion-spec library trio (`Opc.Ua.Di` / `Opc.Ua.Di.Server` / `Opc.Ua.Di.Client`) plus a worked example (`Applications/MinimalPumpServer`) demonstrating the OPC 40223 Pumps companion specification end-to-end with full simulation. It also closes 11 fluent-API gaps in `Opc.Ua.Server.Fluent`, three source-generator bugs, integrates the DI layer into the unified `services.AddOpcUa()` Microsoft.Extensions DI hosting pattern, and adds 250+ new tests. **Worked example — `Applications/MinimalPumpServer/`** - AOT-compatible console host using `Host.CreateApplicationBuilder` + `AddOpcUa()`. - `PumpNodeManager` inherits from `DiNodeManager`; multi-namespace (DI + Machinery + Pumps) via runtime NodeSet2 loading and `ModelLoaderBuilder`. - Demonstrates declarative second-pump creation via `.ConfigureDevicesFor<PumpNodeManager>(...)` and software-package seeding from the same configurator. - Full simulation: pressure, temperatures, power, flow, efficiency, level, cavitation/overheat fault injection, alarm setup, NAMUR-style supervision. **Documentation** - `Docs/Opc.Ua.Di/` — README, DeviceBuilder, Hosting, LockService, SoftwareUpdate, ClientHelpers (6 new developer guides). - `Docs/Opc.Ua.Di/ComplianceMatrix.md` — every DI declaration mapped to In-v1 / Generated / Deferred / Excluded. - `Docs/CompanionSpecLibraries.md` — packaging guide for new companion-spec libraries. - `Docs/FluentApiGaps.md` — historical record of G1–G11. - `Docs/SourceGeneratedNodeManagers.md` updated for richer node managers. - `Docs/plans/StateMachineBuilder.md` — deferred state-machine builder design. |
||
|
|
0000513cde |
Pluggable user-identity provider model (#3807)
# Description Introduces a pluggable user-identity provider model covering all OPC UA Part 6 §6.5 mechanisms (Anonymous, UserName, X509, IssuedToken/JWT) on both client and server, with full `Microsoft.Extensions.DependencyInjection` integration, plus the Part 12 §9 `AuthorizationService` two-phase token-request flow **including refresh-token rotation**, the Part 12 §8 KeyCredential Push model, and a clean provider model for OPC 10000-12 §7.2 `ApplicationSelfAdmin`. The work is split across phase-by-phase commits so it can be reviewed independently; nothing here changes wire-level behaviour or forces existing applications to migrate. ### Documentation All under `Docs/`: - `IdentityProviders.md` — full developer guide: three-layer model, recipes, configuration reference, "what gets auto-wired" matrix, JWS algorithm table, identity-augmenters section, **"Implementing your own provider"** how-to subsections for Entra / OIDC / Windows / AspNetCore (sibling files merged in per review feedback). - `DependencyInjection.md` — `Identity` sections with `appsettings.json` examples, identity-extension matrix, `WithAuthorizationService` + `WithKeyCredentialPush` + `AddIdentityAugmenter` extensions documented. - `RoleBasedUserManagement.md` — claim-criteria callout describing `IIdentityClaims` probe surface. - `AuthorizationService.md` — Architecture diagram + `IAccessTokenProvider` conceptual narrative restored from master; modern `StartRequestToken` / `FinishRequestToken` flow leads; refresh-token recipe added. - `KeyCredentialService.md` — Push model + Pull vs Push vs Bridge decision matrix + Hybrid (Push + Pull) section; explicit experimental warning for the bridge. - `GDS.md` — KeyCredential Push, `StartRequestToken`, `GdsApplicationSelfAdminProvider`, **shipped Refresh-token support with rotation policy and audit semantics** all documented. - `MigrationGuide.md` — User Identity Providers section listing `[Obsolete]` markers + mechanical recipes; SelfAdmin migration via `IIdentityAugmenter`; `EnableRefreshTokens` default note. - `README.md` index entries. ## Checklist - [x] I have signed the [CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf) and read the [CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md) doc. - [x] I have added tests that prove my fix is effective or that my feature works and increased code coverage. - [x] I have added all necessary documentation. - [x] I have verified that my changes do not introduce (new) build or analyzer warnings. - [x] I ran **all** tests locally using the **UA.slnx** solution against at least .net **framework** and .net **10**, and all passed. - [x] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [x] I have addressed **all** PR feedback received. |
||
|
|
6db9a67a0a |
Fix TypeInfo.Construct for generic encodeable (#3802)
Prioritize the encodeable check over the enumerable check in `TypeInfo.Construct(Type type)` to prevent representing a generic type that implements `IEncodeable` as `TypeInfo.Unknown`. Fixes #3800 Somewhat related to #3597 --------- Co-authored-by: Marc Schier <marcschier@users.noreply.github.com> Co-authored-by: Marc Schier <marcschier@hotmail.com> |
||
|
|
eb40a59566 |
More format and diagnostic fixes (#3780)
Drive the solution to zero warnings / zero errors with analyzers on, promote the consistently-fixed rules to error, and lock in coverage on the only line of new logic. |
||
|
|
889572472f |
Convert DataValue from class to readonly struct for further GC relief (#3796)
Convert `DataValue` from a mutable reference type (`class`) to a `readonly struct` to eliminate per-allocation GC pressure on every attribute read, subscription publish, and history sample. ### Key API changes (user-visible) | Before | After | Pattern | |---|---|---| | `class DataValue` | `readonly struct DataValue : INullable` | Foundation | | `Equals(DataValue?)` / `operator ==(DataValue?, DataValue?)` | `Equals(DataValue)` / `operator ==(DataValue, DataValue)` | Value semantics | | `IEncoder.WriteDataValue(string?, DataValue?)` | `IEncoder.WriteDataValue(string?, DataValue)` | Non-nullable wire API | | `IDecoder.ReadDataValue(...) -> DataValue?` | `IDecoder.ReadDataValue(...) -> DataValue` | Same | | `IDataChangeMonitoredItemQueue.PeekLast/Oldest()` | `TryPeekLastValue/Oldest(out DataValue)` | TryGet pattern | | `IAggregateCalculator.GetProcessedValue(bool)` | `TryGetProcessedValue(bool, out DataValue)` | Same | | `IUaPubSubDataStore.ReadPublishedDataItem(...)` | `TryReadPublishedDataItem(NodeId, uint, out DataValue)` | Same | | `Dictionary<uint, DataValue?>` (NodeCacheContext) | `Dictionary<uint, DataValue>` | Default + IsNull | | `IHistoryDataSource.FirstRaw/NextRaw` | `TryFirstRaw/TryNextRaw(out DataValue)` | TryGet pattern | | `NodeState.ReadAttribute(... DataValue)` | `NodeState.ReadAttribute(... ref DataValue)` | Sync mutation via ref | | `NodeState.ReadAttributeAsync(... DataValue)` | `NodeState.ReadAttributeAsync(...) -> ValueTask<(ServiceResult, DataValue)>` | Async return tuple | | `obj as DataValue` (heterogeneous Dictionary<string, object>) | `obj is DataValue dv ? dv : default(DataValue)` | Safe struct cast | | `Assert.That(dv, Is.Not.Null)` (tests) | `Assert.That(dv.IsNull, Is.False)` | Struct test pattern | | `[Obsolete] Value` setter, all property setters | Removed; use ctor or `With*()` | Immutability | | `[DataContract]` + `[DataMember]` | Removed; surrogate via `SerializableDataValue` + `DataValueSurrogateProvider` | Serialization | ### Wire format Wire format is **byte-identical** to the previous class-based implementation across binary / JSON / XML encoders. Default DataValue (`.IsNull == true`) is treated as the equivalent of the old null reference (writes JSON `null`, binary `byte 0`, XML omitted element). ### Why TryGet pattern (instead of leaving `DataValue?`) For methods that previously returned `DataValue?` to signal "no value available" (queue peek, aggregate result, data store lookup, history navigation), the conversion to `bool TryGet(out DataValue)` matches BCL conventions (`Dictionary.TryGetValue`, `Queue.TryPeek`, `Int32.TryParse`) and gives the caller an explicit "may be absent" affordance without `Nullable<DataValue>` overhead. ### Breaking changes summary - `DataValue` is now a `readonly struct` - boxing/unboxing semantics change for callers using `object`-typed APIs. - `IEncoder.WriteDataValue` / `IDecoder.ReadDataValue` / `ReadDataValueArray` interface signatures lose the `Nullable` wrapper. - `IDataChangeMonitoredItemQueue.PeekLastValue` / `PeekOldestValue` -> `TryPeekLastValue` / `TryPeekOldestValue` (out parameter). - `IAggregateCalculator.GetProcessedValue` -> `TryGetProcessedValue` (out parameter). - `IUaPubSubDataStore.ReadPublishedDataItem` -> `TryReadPublishedDataItem` (out parameter). - `NodeState.ReadAttribute` takes `ref DataValue`; `ReadAttributeAsync` returns `ValueTask<(ServiceResult, DataValue)>`. - `DataValue` property setters removed (use constructor + `With*` mutators). |
||
|
|
df2425540d |
Fix/extension object preserve encoding typeid (#3761)
* fix: preserve wire encoding TypeId in ExtensionObject on decode BinaryDecoder, JsonDecoder, and XmlDecoder were overwriting ExtensionObject.TypeId with the DataType NodeId (e.g., i=887) instead of preserving the encoding NodeId from the wire (e.g., i=889). Use ExtensionObject(typeId, encodeable) to retain the original encoding NodeId per OPC 10000-6 §5.2.2.15. * fix: preserve encoding TypeId for XML-in-binary body path * Preserve TypeId in ExtensionObject decoding tests. Exisitng tet used in XmlDecoderTests. Introduced a test encodeable with distinct TypeId and BinaryEncodingId for validation. * ExpandedNodeId used in CreateExtensionObject for tests * copy parameter comment added * fix: JsonEncoder must write DataType NodeId per OPC UA Part 6 §5.4.2.16 Per §5.4.2.16, the UaTypeId field in JSON encoding must be the NodeId of a DataType Node, not a DataTypeEncoding Node. Previously, the JsonEncoder used ExtensionObject.TypeId directly, which after the decoder fix to preserve encoding TypeIds could contain a Binary or XML encoding NodeId when re-encoding from another format. Changed WriteExtensionObject to use encodeable.TypeId (the DataType NodeId) when the body is IEncodeable, falling back to value.TypeId only for raw bodies (ByteString, string) where no IEncodeable is available. This ensures correct cross-encoding behavior (e.g., XML→JSON or Binary→JSON) where the ExtensionObject carries an encoding-specific TypeId from the source format but must emit the DataType NodeId in JSON. * Fix nullable encodeable handling in JsonEncoder --------- Co-authored-by: Marc Schier <marcschier@users.noreply.github.com> Co-authored-by: romanett <romanett98@gmail.com> |
||
|
|
10c67fcccd |
Relax ExtensionObject equality to match across encoding ids (#3777)
An IEncodeable exposes three distinct node ids (TypeId, BinaryEncodingId, XmlEncodingId) that all identify the same logical data type. Depending on the encoder that produced an ExtensionObject (binary, XML, JSON, or direct construction), the wrapper TypeId may carry any one of those three ids, so two ExtensionObjects wrapping the same encodeable value can compare as unequal under the strict TypeId check. Relax Equals(ExtensionObject) so the incoming TypeId on either side may match any of the inner IEncodeable's three node ids; strict TypeId equality is still required when neither side has an IEncodeable body. Update GetHashCode to use the encodeable's canonical TypeId so equal values continue to share a hash. Add unit tests covering matches against each of the three ids, cross-encoding-id match (Binary <-> Xml), body inequality, unrelated TypeId+body, strict equality for ByteString / string bodies, hash stability, == / != operators, and symmetry. |
||
|
|
3e5f129c6f | Enable nullable in Stack, Libraries (9), and Applications projects (#3732) | ||
|
|
70b4498db8 |
Certificate manager and ref counted certificate type (#3688)
* New certificate and secrete abstraction with certificate infrastructure and certificate/secret stores. * leak testing for certificate resources to validate new ref counting in every test assembly * Migration guide updated and documentation added for all * Remove IDisposable from Nodestate and UserIdentity. * UserCertificateTokenHandler now just points into certificate registry/stores, no dispose required * Fix CA2000 warnings and cleanup of other diagnostics, increase warning levels in .editorconfig |
||
|
|
bd4543e961 |
ManagedSession, Pluggable Subscription engine, and fluent builder + DI (#3730)
- Add new managed session, wrapping session and providing connection management and failover handling - Add new Subscription engine that can act as alternative to current engine, but is based on channels with worker tasks - Add a fluent builder for managed session clients - Replace NodeCache with LruNodeCache, rename ILruNodeCache and LruNodeCache to INodeCache and NodeCache - Update migration guide and document new functionality. |
||
|
|
54cc3d88b1 | Prepare for C# 15 union types: UnionAttribute polyfill, TryGetValue rename, HasValue (#3727) | ||
|
|
b2cbf6b03b |
Fix DataValue(int) overload resolution bug (#3721)
new DataValue(42) silently resolved to DataValue(StatusCode) instead of DataValue(Variant) due to C# 'better conversion target' rule — StatusCode wins because it implicitly converts to Variant, making it 'more specific'. This caused m_value = Variant.Null and downstream BadTypeMismatch failures. Changes: - Add [OverloadResolutionPriority(1)] on DataValue(Variant) constructor - Obsolete DataValue(StatusCode) and DataValue(StatusCode, DateTimeUtc) - Add DataValue.FromStatusCode() static factory methods (2 overloads) - Delete DataValue(DataValue) copy constructor - Add DataValue.Copy() instance method using base.MemberwiseClone() - Rewrite Clone()/MemberwiseClone() to delegate to Copy() - Migrate all call sites across 14 files - Add tests verifying new DataValue(42) wraps value correctly - Update MigrationGuide.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
70abb05841 |
Remove Default JSON encoding infrastructure (#3713)
* Remove Default JSON encoding infrastructure Remove IJsonEncodeable interface, JsonEncodingId properties, DefaultJson constants, and all source generator JSON encoding output. The actual JsonEncoder/JsonDecoder and PubSub JSON encoding are not affected. - Delete IJsonEncodeable interface from IEncodable.cs - Remove DataTypeAttribute.JsonEncodingId and simplify TryGetTypeIdsFromType - Remove JSON encoding from 9 source generator files - Remove IJsonEncodeable from 13 built-in types and 12 node types - Remove JSON registration from EncodeableFactory and unboundTypeIds infra - Remove jsonEncodingId from OptionSet, ComplexTypeSystem, IComplexTypeFactory - Remove BrowseNames.DefaultJson and 25 *_Encoding_DefaultJson constants - Update ~14 test files and 2 documentation files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add IJsonEncodeable removal to migration guide Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * minor --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
f23fac928a |
fix status code equals (#3711)
* fix status code equals * add tests verifying StatusCode equality fix: full code comparison including flags Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/8159cd97-f318-4a35-9dfe-663b2f6f4c0e Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> |
||
|
|
d14cd10a86 |
Model dependency annotations using source generator + flaky test fixes (#3687)
* Fix publish/dispose race that hangs Client tests
Subscription.Dispose pre-disposed m_publishTimer and m_messageWorkerCts
before calling ResetPublishTimerAndWorkerState, causing Cancel() to throw
ObjectDisposedException and leaving the publish worker stuck. Removed the
duplicate disposal so the reset method is the single owner of those resources,
and guarded Cancel/Dispose with try/catch ObjectDisposedException for defense
in depth.
Session.OnPublishComplete could run after Session.Dispose disposed
m_reconnectLock, throwing ObjectDisposedException from SemaphoreSlim.Wait()
and re-arming via the throttle path indefinitely. Added an early Disposed
guard, wrapped Wait/Release in try/catch ObjectDisposedException, and added
a Disposed guard in QueueBeginPublish so the throttle cannot reschedule
publishes after disposal.
Fixes the macOS net10.0 hang seen in Azure pipeline build 13257
(TransferSubscriptionAsync, ReconnectWithSavedSessionSecretsAsync).
* fix lockout test and use UserName token for SuccessfulAuthenticationClearsFailedAttempts test
After
|
||
|
|
36c936a361 | Update SourceGenerator dependencies resolution mechanism. (#3680) | ||
|
|
64ca85fce3 |
Increase code coverage across solution (#3662)
Add additional tests to increase code coverage across the solution |
||
|
|
fd41681f4b |
Add support to publish OPC UA applications as Native AOT (#3633)
* make most ptojects aot compatible * Remove newtonsoft * Migrate all projects from Mono.Options to System.CommandLine 2.0.5 * Fix array clone * Replace serializers for storage using new attribute driven type geberator * Add new AOT integration tests covering all functional areas * Documentation updates |
||
|
|
23f10d89ee |
[Server] Introduce RequestLifetime for request handling and cancellation (#3643)
Use RequestLifetime throughout the server stack for unified request lifetime and cancellation management. Update all service method signatures, OperationContext, and request processing logic to use RequestLifetime, enabling precise tracking of cancellation reasons with UA StatusCodes. Remove obsolete synchronous request handling and legacy delegates. Update code generation, tests, and interfaces to support the new model. This change improves cancellation, timeout, and abort handling, and prepares the server for advanced request management features. |
||
|
|
5a1e547250 | Code cleanup and modernization of test assertions to comply with project standards. (#3631) | ||
|
|
03777ecb09 |
New Json decoder/encoders, array/matrix abstractions, ByteString, and more. (#3619)
- **Collections overhaul** — new/rewritten collection types (`ArrayOf`, `Collections` commits)
- **`Variant` builder/accessor** — new APIs for constructing and accessing Variants
- **`NodeId` operators made explicit** — breaking change for implicit conversions
- **Version bumped to 1.6** with preview build support
- **NumericRange** uses Variant
- **object** type accessors and general usage removed.
### 🏗️ Infrastructure
- Build config updated; `.NET 10` targeting
- InternalsVisibleTo moved to `.csproj`
- Pipeline/CI adjustments
|
||
|
|
25a4882145 |
Fix non enumerable generic type info construction (#3597)
* test(type-info): add failing test * fix(type-info): require IEnumerable implementation before treating generic type as array * test(type-info): add test for coverage |
||
|
|
a0e1e9f42e |
[Server] Optimize NodeState.ReadAttributes & base ReferenceNodeManager on AsyncCustomNodeManager (#3574)
* Use Interfaces Introduced with 1.5.378 Refactor to use interfaces for node managers and server Replaced concrete types with interfaces (e.g., IMasterNodeManager, ICoreNodeManager, IDiagnosticsNodeManager, IConfigurationNodeManager, IServerBase) across method signatures, properties, and internal structures to improve abstraction and flexibility. * Refactor CoreNodeManager to be Based on CustomNodeManager2 * Add Test * Add INodeManager3 with role permission validation Introduce INodeManager3 interface extending INodeManager2, adding synchronous role permission validation methods. Update all node manager interfaces and classes to use INodeManager3. Extend IAsyncNodeManager with async permission validation methods and update adapters for sync/async bridging. Deprecate FindNodeInAddressSpace in favor of new async FindNodeInAddressSpaceAsync. Refactor MonitoredNode2 to use thread-safe collections and locking for monitored items. Enhance event reporting with security and permission checks. Update constructors and documentation to reflect new interfaces and best practices. * Implement AsyncCustomNodeManager * fix comment * fix * Add tests * fix * Implement better locking strategy * fix * Add more tests * Add tests * Add tests * Add Tests * cleanup * cleanup * Add tests that verifies for AnalogItemState the instrument range is checked brefore writing * only assign new NodeID in default factory if NodeId isNull * Run all tests also with sampling groups * Add Docs * cleanup * Add chaos test * fix test * Use AsyncCustomNodeManager for ReferenceNodeManger & imrpove ReadAttributes method of NodeState * fixes * fixes and code review comments |
||
|
|
601cabf86f | Replace all use of object in code and API with Variant (#3550) | ||
|
|
f66ceffd75 |
Immutable built in types and code generation (#3534)
Generate stack and application code using source generators Change built in types to readonly structs Update localized text implementation to use JSON text serializer Status code with symbolic names Immutable node ids No boxing for all built in types <= 8 bytes in Variant. Split user identity token and token handling via token handler Add migration guide for breaking changes |
||
|
|
43ce7ed229 |
Code clean up and improvements (#3532)
This pull request modernizes the OPC UA .NET codebase and tests, removes .NET Standard 2.0 support from certificate/security code, and updates test code to use C# 12 and .NET 8+ features for clarity and maintainability. - Certificate and BouncyCastle interop files (e.g., CertificateBuilder.cs, X509Extensions.cs, X509SignatureFactory.cs) are refactored to drop NETSTANDARD2_0 support and use modern .NET APIs and conditional compilation. - Test code across the codebase is updated to use default, strongly-typed Parse methods, collection expressions, and improved async/await patterns. - Exception handling and assertions in tests are modernized, and test method naming is made consistent with Async suffixes. - The project and build files are updated to clarify Roslynator analyzer usage and remove obsolete netstandard tags. - General code and test cleanup includes improved null safety, type safety, and removal of deprecated or unused code. |
||
|
|
bafd63db5a |
Hook lookup of symbol in types project and set hook in opc ua core on assembly loading (#3520)
* Hook lookup of symbol in types project and set hook in opc ua core on assembly loading * Use module initializer instead of static constructor |
||
|
|
288f02f20a |
Allow status code variant creation from uint (#3472)
* Allow status code variant creation from uint * Initial plan * Add comprehensive tests for StatusCode variant creation from uint Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com> * Remove redundant assertions in StatusCode variant tests Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com> |
||
|
|
2960388560 |
Update headers and license files (#3388)
Update license headers to copy right year 2025, replace RCL/GPL headers with MIT, replace the nuget license with MIT (via license expression). |
||
|
|
35db52a7a6 | Move from .net 9 to .net 10 SDK and build new target framework .net 10 (#3333) | ||
|
|
712e770fbe |
Restructure core and built in types into base assembly and nuget (#3326)
This change adds a **new Opc.Ua.Types** nuget that contains core types that do not rely on generated code. Why the name? Because almost all code that was in the Types subfolder is part of it, and because we do not want to change the name of the Opc.Ua.Core nuget/assembly because code relies on it. Any other name like base or bootstrap felt out of place due to the current structure already defining the name "types". Key design is to depend on only a small set of libraries with limited transitive dependencies, that includes hashcode, logging.abstraction, and for non standard20 builds System.Text.Json (needed for localizedText mul parsing). Also, key is to support .netstd 2.0 to support source generators and to allow removal of EEC_SUPPORT defines by removing std2.0 from core and all libraries. The changes are mostly restructuring, and thus small but contain some key changes: - **Status code** struct now comes with a Symbol field, which is used to carry symbols in case the code is not generated. Currently (until generated) the status code struct must be manually created with a symbol or the ToSymbolicId extension must be called in the core project. Future will generate Status code constants just like NodeId that contain the symbol which also removes the reflection-based lookup. Several tests needed to be adjusted as they checked the status code symbol strings instead of the code. - **Core identifiers** are copied as they were needed for code to compile, that includes attributes, a subset of status codes and node identifiers. These will never change so no need to generate them. - The types folder now contains **encoders**, except for json which is still in core. Once the json encoder is ported to system.text.json it will also be included and Newtonsoft.Json dropped as dependency (-> #3329). - Since types relies on **IOperationContext** and **ISystemContext**, and these export IUserIdentity which relies on crypto, these were split and extended in core with ISessionOperationContext and ISessionSystemContext, which mean changes to ServerSystemContext and introduction of SessionOperationContext and SessionSystemContext classes that extend OperationContext and SystemContext. Some runtime checks in the server are therefore needed to get at the session and auth info, however, those are anyway optional fields and are not on the critical paths, and thus a type check is in order (and was done in the past already, but against OperationContext class). - **Manifest resources** are now split between Core (nodeset zip, some generated resoures) and Types (built in bsd/xsds). This needs to be revisited later if the bsd/xsd need to be regenerated during type generation. Note that the embedded resource names changed as a result. Since these are only used internally and do not constitute public API this feels reasonable vs duplication of resources in 2 assemblies. - Reflection however now needs to load not just the built in **encodeables** from Opc.Ua.Types assembly, but also the generated encodeables from Opc.Ua.Core assembly. For this a new helper Utils method was added to get the Core assembly when linked against Opc.Ua.Core otherwise null. - Whatever utils methods needed to be split out into the new Opc.Ua.Types assembly, they are now in **CoreUtils** static class in Opc.Ua.Types, and Utils.xxxx forwards to them to ensure minimal changes. Later we would want to obsolete them in favor of CoreUtils, although it might make sense to split them again into domain specific utilities, such as networking, files, etc |