Skip to content

Commit c71f2e7

Browse files
marcschierCopilot
andauthored
Fix source generator generated structures with optional fields (#3674)
Split validator load/validate; split DesignFileCollection Targets/Dependencies ModelDesignValidator.LoadNodes now skips ValidateDictionary when a model is loaded purely as a dependency. The flag is plumbed through LoadModelDesign and LoadDesignFile; the dep loop in ValidateModel passes false, the primary target passes true. This lets callers supply unrelated or reverse dependencies (deps that import the target) without triggering premature validation failures. DesignFileCollection exposes Targets + Dependencies; generators and tests updated. MergeNamespace preserves FilePath across PublicationDate-based replacement so later loads can still find the source file. Tester simplified to treat every other xml/csv pair as a dependency of each target. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 34ed571 commit c71f2e7

17 files changed

Lines changed: 1030 additions & 87 deletions

File tree

.github/workflows/buildandtest.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: Build and Test .NET 10.0
22

33
on:
44
push:
5+
branches: [ master, main, develop/* ]
56
pull_request:
67
branches: [ master, main, develop/* ]
78
paths:

Tests/Opc.Ua.SourceGeneration.Core.Tests/CompilerUtils.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,8 @@ public void CreateOrReplaceSetPosition(
822822
public class StateMachineStateState : BaseObjectState
823823
{
824824
public StateMachineStateState(NodeState? parent) : base(parent) { }
825+
public void CreateOrReplaceStateNumber(
826+
ISystemContext context, BaseInstanceState replacement) { }
825827
}
826828
public class StateMachineInitialStateState : StateMachineStateState
827829
{
@@ -831,6 +833,28 @@ public class StateMachineTransitionState : StateMachineStateState
831833
{
832834
public StateMachineTransitionState(NodeState? parent) : base(parent) { }
833835
}
836+
public class StateMachineState : BaseObjectState
837+
{
838+
public StateMachineState(NodeState? parent) : base(parent) { }
839+
public void CreateOrReplaceStateNumber(
840+
ISystemContext context, BaseInstanceState replacement) { }
841+
public void CreateOrReplaceCurrentState(
842+
ISystemContext context, BaseInstanceState replacement) { }
843+
public void CreateOrReplaceLastTransition(
844+
ISystemContext context, BaseInstanceState replacement) { }
845+
}
846+
public class StateVariableState : BaseDataVariableState
847+
{
848+
public StateVariableState(NodeState? parent) : base(parent) { }
849+
public void CreateOrReplaceId(
850+
ISystemContext context, BaseInstanceState replacement) { }
851+
public void CreateOrReplaceName(
852+
ISystemContext context, BaseInstanceState replacement) { }
853+
public void CreateOrReplaceNumber(
854+
ISystemContext context, BaseInstanceState replacement) { }
855+
public void CreateOrReplaceEffectiveDisplayName(
856+
ISystemContext context, BaseInstanceState replacement) { }
857+
}
834858
public class AddCommentMethodState : MethodState
835859
{
836860
public AddCommentMethodState(NodeState? parent) : base(parent) { }

Tests/Opc.Ua.SourceGeneration.Core.Tests/DesignFileTests.cs

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void Group_NullDesignFiles_ThrowsArgumentNullException()
6666
// Arrange
6767
var collection = new DesignFileCollection
6868
{
69-
DesignFiles = null,
69+
Targets = null,
7070
IdentifierFilePath = null,
7171
Options = null
7272
};
@@ -83,7 +83,7 @@ public void Group_EmptyDesignFiles_ReturnsEmptyEnumerable()
8383
// Arrange
8484
var collection = new DesignFileCollection
8585
{
86-
DesignFiles = [],
86+
Targets = [],
8787
IdentifierFilePath = null,
8888
Options = null
8989
};
@@ -108,7 +108,7 @@ public void Group_SingleDesignFile_ReturnsSingleGroup()
108108
};
109109
var collection = new DesignFileCollection
110110
{
111-
DesignFiles =
111+
Targets =
112112
[
113113
designFile
114114
],
@@ -120,9 +120,9 @@ public void Group_SingleDesignFile_ReturnsSingleGroup()
120120
// Assert
121121
Assert.That(result, Is.Not.Null);
122122
Assert.That(result, Has.Count.EqualTo(1));
123-
Assert.That(result[0].DesignFiles, Is.Not.Null);
124-
Assert.That(result[0].DesignFiles, Has.Count.EqualTo(1));
125-
Assert.That(result[0].DesignFiles[0], Is.EqualTo(designFile));
123+
Assert.That(result[0].Targets, Is.Not.Null);
124+
Assert.That(result[0].Targets, Has.Count.EqualTo(1));
125+
Assert.That(result[0].Targets[0], Is.EqualTo(designFile));
126126
Assert.That(result[0].IdentifierFilePath, Is.EqualTo("global.csv"));
127127
Assert.That(result[0].Options, Is.EqualTo(options));
128128
}
@@ -147,7 +147,7 @@ public void Group_MultipleFilesInSameDirectory_ReturnsSingleGroup()
147147
};
148148
var collection = new DesignFileCollection
149149
{
150-
DesignFiles = designFiles,
150+
Targets = designFiles,
151151
IdentifierFilePath = "fallback.csv",
152152
Options = options
153153
};
@@ -156,9 +156,9 @@ public void Group_MultipleFilesInSameDirectory_ReturnsSingleGroup()
156156
// Assert
157157
Assert.That(result, Is.Not.Null);
158158
Assert.That(result, Has.Count.EqualTo(1));
159-
Assert.That(result[0].DesignFiles, Is.Not.Null);
160-
Assert.That(result[0].DesignFiles, Has.Count.EqualTo(3));
161-
Assert.That(result[0].DesignFiles, Is.EquivalentTo(designFiles));
159+
Assert.That(result[0].Targets, Is.Not.Null);
160+
Assert.That(result[0].Targets, Has.Count.EqualTo(3));
161+
Assert.That(result[0].Targets, Is.EquivalentTo(designFiles));
162162
Assert.That(result[0].IdentifierFilePath, Is.EqualTo("fallback.csv"));
163163
Assert.That(result[0].Options, Is.EqualTo(options));
164164
}
@@ -185,7 +185,7 @@ public void Group_FilesInDifferentDirectories_ReturnsMultipleGroups()
185185
};
186186
var collection = new DesignFileCollection
187187
{
188-
DesignFiles = designFiles,
188+
Targets = designFiles,
189189
IdentifierFilePath = "default.csv",
190190
Options = options
191191
};
@@ -196,8 +196,8 @@ public void Group_FilesInDifferentDirectories_ReturnsMultipleGroups()
196196
Assert.That(result, Has.Count.EqualTo(3));
197197
foreach (DesignFileCollection group in result)
198198
{
199-
Assert.That(group.DesignFiles, Is.Not.Null);
200-
Assert.That(group.DesignFiles, Has.Count.EqualTo(1));
199+
Assert.That(group.Targets, Is.Not.Null);
200+
Assert.That(group.Targets, Has.Count.EqualTo(1));
201201
Assert.That(group.IdentifierFilePath, Is.EqualTo("default.csv"));
202202
Assert.That(group.Options, Is.EqualTo(options));
203203
}
@@ -217,7 +217,7 @@ public void Group_NullIdentifierFilesParameter_UsesCollectionIdentifierFilePath(
217217
};
218218
var collection = new DesignFileCollection
219219
{
220-
DesignFiles = designFiles,
220+
Targets = designFiles,
221221
IdentifierFilePath = "collection_identifier.csv",
222222
Options = null
223223
};
@@ -243,7 +243,7 @@ public void Group_EmptyIdentifierFilesList_UsesCollectionIdentifierFilePath()
243243
};
244244
var collection = new DesignFileCollection
245245
{
246-
DesignFiles = designFiles,
246+
Targets = designFiles,
247247
IdentifierFilePath = "fallback.csv",
248248
Options = null
249249
};
@@ -274,7 +274,7 @@ public void Group_IdentifierFileInMatchingDirectory_UsesIdentifierFile()
274274
};
275275
var collection = new DesignFileCollection
276276
{
277-
DesignFiles = designFiles,
277+
Targets = designFiles,
278278
IdentifierFilePath = "fallback.csv",
279279
Options = null
280280
};
@@ -306,7 +306,7 @@ public void Group_MultipleIdentifierFilesInSameDirectory_UsesFirstIdentifierFile
306306
};
307307
var collection = new DesignFileCollection
308308
{
309-
DesignFiles = designFiles,
309+
Targets = designFiles,
310310
IdentifierFilePath = "fallback.csv",
311311
Options = null
312312
};
@@ -337,7 +337,7 @@ public void Group_IdentifierFilesInNonMatchingDirectories_UsesCollectionIdentifi
337337
};
338338
var collection = new DesignFileCollection
339339
{
340-
DesignFiles = designFiles,
340+
Targets = designFiles,
341341
IdentifierFilePath = "fallback.csv",
342342
Options = null
343343
};
@@ -372,7 +372,7 @@ public void Group_MultipleDirectoriesWithIdentifierFiles_CorrectlyMapsIdentifier
372372
};
373373
var collection = new DesignFileCollection
374374
{
375-
DesignFiles = designFiles,
375+
Targets = designFiles,
376376
IdentifierFilePath = "fallback.csv",
377377
Options = null
378378
};
@@ -381,13 +381,13 @@ public void Group_MultipleDirectoriesWithIdentifierFiles_CorrectlyMapsIdentifier
381381
// Assert
382382
Assert.That(result, Is.Not.Null);
383383
Assert.That(result, Has.Count.EqualTo(3));
384-
DesignFileCollection group1 = result.FirstOrDefault(g => g.DesignFiles.Contains(Path.Combine(dir1, "Design1.xml")));
384+
DesignFileCollection group1 = result.FirstOrDefault(g => g.Targets.Contains(Path.Combine(dir1, "Design1.xml")));
385385
Assert.That(group1, Is.Not.Null);
386386
Assert.That(group1.IdentifierFilePath, Is.EqualTo(Path.Combine(dir1, "id1.csv")));
387-
DesignFileCollection group2 = result.FirstOrDefault(g => g.DesignFiles.Contains(Path.Combine(dir2, "Design2.xml")));
387+
DesignFileCollection group2 = result.FirstOrDefault(g => g.Targets.Contains(Path.Combine(dir2, "Design2.xml")));
388388
Assert.That(group2, Is.Not.Null);
389389
Assert.That(group2.IdentifierFilePath, Is.EqualTo("fallback.csv"));
390-
DesignFileCollection group3 = result.FirstOrDefault(g => g.DesignFiles.Contains(Path.Combine(dir3, "Design3.xml")));
390+
DesignFileCollection group3 = result.FirstOrDefault(g => g.Targets.Contains(Path.Combine(dir3, "Design3.xml")));
391391
Assert.That(group3, Is.Not.Null);
392392
Assert.That(group3.IdentifierFilePath, Is.EqualTo(Path.Combine(dir3, "id3.csv")));
393393
}
@@ -421,7 +421,7 @@ public void Group_ComplexScenario_CorrectlyGroupsAndAssignsIdentifierFiles()
421421
};
422422
var collection = new DesignFileCollection
423423
{
424-
DesignFiles = designFiles,
424+
Targets = designFiles,
425425
IdentifierFilePath = "global_fallback.csv",
426426
Options = options
427427
};
@@ -430,14 +430,14 @@ public void Group_ComplexScenario_CorrectlyGroupsAndAssignsIdentifierFiles()
430430
// Assert
431431
Assert.That(result, Is.Not.Null);
432432
Assert.That(result, Has.Count.EqualTo(2));
433-
DesignFileCollection group1 = result.FirstOrDefault(g => g.DesignFiles.Contains(Path.Combine(dir1, "DesignA.xml")));
433+
DesignFileCollection group1 = result.FirstOrDefault(g => g.Targets.Contains(Path.Combine(dir1, "DesignA.xml")));
434434
Assert.That(group1, Is.Not.Null);
435-
Assert.That(group1.DesignFiles, Has.Count.EqualTo(2));
435+
Assert.That(group1.Targets, Has.Count.EqualTo(2));
436436
Assert.That(group1.IdentifierFilePath, Is.EqualTo("global_fallback.csv"));
437437
Assert.That(group1.Options, Is.EqualTo(options));
438-
DesignFileCollection group2 = result.FirstOrDefault(g => g.DesignFiles.Contains(Path.Combine(dir2, "DesignC.xml")));
438+
DesignFileCollection group2 = result.FirstOrDefault(g => g.Targets.Contains(Path.Combine(dir2, "DesignC.xml")));
439439
Assert.That(group2, Is.Not.Null);
440-
Assert.That(group2.DesignFiles, Has.Count.EqualTo(3));
440+
Assert.That(group2.Targets, Has.Count.EqualTo(3));
441441
Assert.That(group2.IdentifierFilePath, Is.EqualTo(Path.Combine(dir2, "identifiers_dir2.csv")));
442442
Assert.That(group2.Options, Is.EqualTo(options));
443443
}
@@ -456,7 +456,7 @@ public void Group_NullCollectionIdentifierFilePath_ReturnsNullIdentifierFilePath
456456
};
457457
var collection = new DesignFileCollection
458458
{
459-
DesignFiles = designFiles,
459+
Targets = designFiles,
460460
IdentifierFilePath = null,
461461
Options = null
462462
};
@@ -482,7 +482,7 @@ public void Group_EmptyStringCollectionIdentifierFilePath_ReturnsEmptyIdentifier
482482
};
483483
var collection = new DesignFileCollection
484484
{
485-
DesignFiles = designFiles,
485+
Targets = designFiles,
486486
IdentifierFilePath = string.Empty,
487487
Options = null
488488
};
@@ -509,7 +509,7 @@ public void Group_DesignFilesWithRelativePaths_GroupsByDirectory()
509509
};
510510
var collection = new DesignFileCollection
511511
{
512-
DesignFiles = designFiles,
512+
Targets = designFiles,
513513
IdentifierFilePath = "default.csv",
514514
Options = null
515515
};
@@ -542,7 +542,7 @@ public void Group_WithCompleteOptions_PreservesAllOptionProperties()
542542
};
543543
var collection = new DesignFileCollection
544544
{
545-
DesignFiles = designFiles,
545+
Targets = designFiles,
546546
IdentifierFilePath = "test.csv",
547547
Options = options
548548
};

Tests/Opc.Ua.SourceGeneration.Core.Tests/GenerateCodeTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ private static Dictionary<string, string> GenerateCodeFromModel(
205205
using var fileSystem = new VirtualFileSystem();
206206
Generators.GenerateCode(new DesignFileCollection
207207
{
208-
DesignFiles = [Path.Combine(
208+
Targets = [Path.Combine(
209209
Directory.GetCurrentDirectory(),
210210
"Resources",
211211
modelDesignFile)],

Tests/Opc.Ua.SourceGeneration.Core.Tests/GeneratorsTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public void GenerateCode_EmptyDesignFilesCollection_ReturnsEarlyWithoutProcessin
5353
// Arrange
5454
var designFiles = new DesignFileCollection
5555
{
56-
DesignFiles = []
56+
Targets = []
5757
};
5858
var mockFileSystem = new Mock<IFileSystem>(MockBehavior.Strict);
5959
var mockTelemetry = new Mock<ITelemetryContext>(MockBehavior.Strict);

0 commit comments

Comments
 (0)