Skip to content

Commit b1a57c1

Browse files
authored
Merge branch 'develop' into copilot/address-mstest-analyzer-warnings
2 parents a09c31e + 15fb448 commit b1a57c1

File tree

11 files changed

+86
-36
lines changed

11 files changed

+86
-36
lines changed

src/Benchmarks/Benchmarks.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="BenchmarkDotNet" Version="0.15.4" />
12+
<PackageReference Include="BenchmarkDotNet" Version="0.15.5" />
1313
</ItemGroup>
1414

1515
<ItemGroup>

src/Hl7.Fhir.Base/FhirPath/Expressions/OrderedNode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
namespace Hl7.FhirPath.Expressions;
1414

15-
internal record OrderedNode(PrimitiveType Primitive, PocoNodeOrList ParentNode, int? Index, string Name = null, bool Descending = false) : PrimitiveNode(Primitive, ParentNode, Index, Name)
15+
internal record OrderedNode(PrimitiveType Primitive, PocoNode Parent, int? Index, string Name = null, bool Descending = false) : PrimitiveNode(Primitive, Parent, Index, Name)
1616
{
1717
internal static OrderedNode FromPrimitiveNode(PocoNode primitiveNode, bool descending = false) =>
1818
new((PrimitiveType)primitiveNode.Poco, primitiveNode.Parent, primitiveNode.Index, primitiveNode.Name, descending);

src/Hl7.Fhir.Base/Model/IExtendable.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,30 @@ public static void RemoveExtension(this IExtendable extendable, string uri)
208208
}
209209
}
210210

211+
/// <summary>
212+
/// Remove all extensions that are specified in the uris list, if any.
213+
/// </summary>
214+
/// <param name="extendable"></param>
215+
/// <param name="uris"></param>
216+
internal static void RemoveExtensions(this IExtendable extendable, IEnumerable<string> uris)
217+
{
218+
var remove = extendable.Extension.Where(ext => uris.Contains(ext.Url)).ToList();
219+
220+
foreach (var ext in remove)
221+
extendable.Extension.Remove(ext);
222+
223+
if (extendable is IModifierExtendable me)
224+
{
225+
remove = me.ModifierExtension.Where(ext => uris.Contains(ext.Url)).ToList();
226+
227+
foreach (var ext in remove)
228+
me.ModifierExtension.Remove(ext);
229+
}
230+
}
231+
211232

212233
/// <summary>
213-
/// Add an extension with the given uri and value, removing any pre-existsing extensions
234+
/// Add an extension with the given uri and value, removing any pre-existing extensions
214235
/// with the same uri.
215236
/// </summary>
216237
/// <param name="extendable"></param>

src/Hl7.Fhir.Base/Model/PocoNode.Primitives.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public static IEnumerable<PocoNode> FromAnyList(IEnumerable<object> values) =>
6262
values.Select(v => v as PocoNode ?? ForAnyPrimitive(v));
6363
}
6464

65-
public record PrimitiveNode(PrimitiveType Primitive, PocoNodeOrList? ParentNode, int? Index, string? Name = null) : PocoNode(Primitive, ParentNode, Index, Name)
65+
public record PrimitiveNode(PrimitiveType Primitive, PocoNode? Parent, int? Index, string? Name = null) : PocoNode(Primitive, Parent, Index, Name)
6666
{
6767
protected override object? ValueInternal => Primitive.ToITypedElementValue();
6868
internal object? Value => ValueInternal;
@@ -86,10 +86,10 @@ public record PrimitiveNode(PrimitiveType Primitive, PocoNodeOrList? ParentNode,
8686
protected override string? TextInternal => Primitive.ToString();
8787
}
8888

89-
internal record PrimitiveListNode(IReadOnlyList<PrimitiveType> Primitives, PocoNodeOrList? ParentNode, string? Name = null) : PocoListNode(Primitives, ParentNode, Name ?? "value")
89+
internal record PrimitiveListNode(IReadOnlyList<PrimitiveType> Primitives, PocoNode? Parent, string? Name = null) : PocoListNode(Primitives, Parent, Name ?? "value")
9090
{
9191
public override IEnumerator<PocoNode> GetEnumerator() =>
92-
Primitives.Select((primitive, index) => new PrimitiveNode(primitive, ParentNode, index, Name)).GetEnumerator();
92+
Primitives.Select((primitive, index) => new PrimitiveNode(primitive, Parent, index, Name)).GetEnumerator();
9393

9494
internal IEnumerable<object?> Values => Primitives.Select(p => p.JsonValue);
9595
}

src/Hl7.Fhir.Base/Model/PocoNodeExtensions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,9 @@ internal static IEnumerable<PocoNode> Where<T>(this PocoListNode pln, Func<T, bo
298298
/// <typeparam name="T"></typeparam>
299299
/// <returns></returns>
300300
public static PocoNode? FirstOrDefault<T>(this IEnumerable<PocoNode> node, Func<T, bool> predicate) where T : Base =>
301-
node.FirstOrDefault(n => n.Poco is T t && predicate(t));
301+
node is PocoListNode pln
302+
? pln.FirstOrDefault(predicate)
303+
: node.FirstOrDefault(n => n.Poco is T t && predicate(t));
302304

303305
/// <summary>
304306
/// Navigates to a child node or set of child nodes using a path. The path is a string that can contain dot-separated names and array indices, much like navigation in FhirPath.

src/Hl7.Fhir.Base/Model/PocoNodeOrList.cs

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,9 @@ namespace Hl7.Fhir.Model;
1515
/// A singular node in a POCO node tree. This node represents either a repeating or singular POCO instance.
1616
/// </summary>
1717
/// <param name="Name"></param>
18-
public abstract record PocoNodeOrList(string Name) : IEnumerable<PocoNode>
18+
/// <param name="Parent"></param>
19+
public abstract record PocoNodeOrList(string Name, PocoNode? Parent) : IEnumerable<PocoNode>
1920
{
20-
/// <summary>
21-
/// The parent of this node. This is always a singular PocoNode. If the Parent field is set to a PocoListNode, this will construct and return the PocoNode at the specified index.
22-
/// </summary>
23-
public abstract PocoNode? Parent { get; }
24-
2521
public abstract IEnumerator<PocoNode> GetEnumerator();
2622
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
2723

@@ -36,20 +32,12 @@ public abstract record PocoNodeOrList(string Name) : IEnumerable<PocoNode>
3632
/// A singular node in a POCO node tree. This node represents a single POCO instance.
3733
/// </summary>
3834
/// <param name="Poco"></param>
39-
/// <param name="ParentNode"></param>
35+
/// <param name="Parent"></param>
4036
/// <param name="Index">This Poco's index in a list, if it is contained in one</param>
4137
/// <param name="Name"></param>
42-
public partial record PocoNode(Base Poco, PocoNodeOrList? ParentNode, int? Index, string? Name)
43-
: PocoNodeOrList(Name ?? Poco.TypeName), ITypedElement, IShortPathGenerator, ISourceNode, IFhirValueProvider, IResourceTypeSupplier, IAnnotatable
38+
public partial record PocoNode(Base Poco, PocoNode? Parent, int? Index, string? Name)
39+
: PocoNodeOrList(Name ?? Poco.TypeName, Parent), ITypedElement, IShortPathGenerator, ISourceNode, IFhirValueProvider, IResourceTypeSupplier, IAnnotatable
4440
{
45-
/// <inheritdoc />
46-
public override PocoNode? Parent => ParentNode switch
47-
{
48-
PocoListNode nodes => nodes[Index!.Value],
49-
PocoNode node => node,
50-
_ => null
51-
};
52-
5341
/// <summary>
5442
/// Enumerates all children of this node. These can each either be singular or repeating PocoNodes.
5543
/// </summary>
@@ -83,8 +71,8 @@ private PocoNodeOrList nodeFor(string name, object value) =>
8371
{
8472
PrimitiveType primitive => new PrimitiveNode(primitive, this, null, name),
8573
Base b => new PocoNode(b, this, null, name),
86-
IEnumerable<PrimitiveType> primitiveList => new PrimitiveListNode(primitiveList.ToList(), this, name),
87-
IEnumerable<Base> list => new PocoListNode(list.ToList(), this, name),
74+
IReadOnlyList<PrimitiveType> primitiveList => new PrimitiveListNode(primitiveList.ToList(), this, name),
75+
IReadOnlyList<Base> list => new PocoListNode(list.ToList(), this, name),
8876
_ => throw new InvalidOperationException("Unexpected element in child list")
8977
};
9078

@@ -153,11 +141,10 @@ IEnumerable<object> IAnnotated.Annotations(Type type)
153141
/// A single node for a repeating element. Note that since a repeating element has a single parent, this cannot be used for grouping "separate" pocos that are not repeating in the specification.
154142
/// </summary>
155143
/// <param name="Pocos"></param>
156-
/// <param name="ParentNode"></param>
144+
/// <param name="Parent"></param>
157145
/// <param name="Name"></param>
158-
public record PocoListNode(IReadOnlyList<Base> Pocos, PocoNodeOrList? ParentNode, string Name) : PocoNodeOrList(Name)
146+
public record PocoListNode(IReadOnlyList<Base> Pocos, PocoNode? Parent, string Name) : PocoNodeOrList(Name, Parent)
159147
{
160148
public PocoNode this[int index] => new(Pocos[index], Parent, index, Name);
161-
public override PocoNode? Parent => ParentNode as PocoNode; // safe because FHIR knows no nested lists
162149
public override IEnumerator<PocoNode> GetEnumerator() => Pocos.Select((poco, index) => new PocoNode(poco, Parent, index, Name)).GetEnumerator();
163150
}

src/Hl7.Fhir.Base/Specification/Snapshot/SnapshotGeneratorExtensions.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,29 @@ public static void RemoveAllConstrainedByDiffExtensions<T>(this IEnumerable<T> e
8888
}
8989
}
9090

91+
internal static bool HasAnyNonInheritableExtensions(this Element element)
92+
{
93+
if (element == null) return false;
94+
if (element.HasNonInheritableExtensions()) return true;
95+
#pragma warning disable CS0618 // Type or member is obsolete
96+
return element.Children().OfType<Element>().Any(child => child.HasAnyNonInheritableExtensions());
97+
#pragma warning restore CS0618 // Type or member is obsolete
98+
}
99+
100+
internal static bool HasNonInheritableExtensions(this IExtendable element)
101+
{
102+
if (element == null)
103+
return false;
104+
105+
if (element.Extension.Any(ext => _nonInheritableExtensions.Contains(ext.Url)))
106+
return true;
107+
108+
if (element is IModifierExtendable modifierElement)
109+
return modifierElement.ModifierExtension.Any(ext => _nonInheritableExtensions.Contains(ext.Url));
110+
111+
return false;
112+
}
113+
91114
/// <summary>
92115
/// This extension removes all non-inheritable extensions from the specified element definition and all it's child objects.
93116
/// Non-inheritable extensions are extensions that should not be inherited by derived profiles.
@@ -108,13 +131,10 @@ internal static void RemoveAllNonInheritableExtensions(this Element element)
108131
internal static void RemoveNonInheritableExtensions(this IExtendable element)
109132
{
110133
if (element == null) { throw Error.ArgumentNull(nameof(element)); }
111-
foreach (var ext in _nonInheritableExtensions)
112-
{
113-
element.RemoveExtension(ext);
114-
}
134+
element.RemoveExtensions(_nonInheritableExtensions);
115135
}
116136

117-
private static readonly List<string> _nonInheritableExtensions = [
137+
private static readonly HashSet<string> _nonInheritableExtensions = [
118138
ResourceIdentity.CORE_BASE_URL + "elementdefinition-isCommonBinding",
119139
ResourceIdentity.CORE_BASE_URL + "structuredefinition-fmm",
120140
ResourceIdentity.CORE_BASE_URL + "structuredefinition-fmm-no-warnings",

src/Hl7.Fhir.Conformance/Specification/Snapshot/SnapshotGenerator.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ public async Tasks.Task<IList<ElementDefinition>> ExpandElementAsync(IList<Eleme
233233
try
234234
{
235235
await expandElement(nav).ConfigureAwait(false);
236+
237+
foreach (var elem in nav.Elements)
238+
elem.RemoveAllNonInheritableExtensions();
236239
}
237240
finally
238241
{
@@ -260,7 +263,12 @@ public async Tasks.Task<bool> ExpandElementAsync(ElementDefinitionNavigator nav)
260263
_stack.OnStartRecursion();
261264
try
262265
{
263-
return await expandElement(nav).ConfigureAwait(false);
266+
var result = await expandElement(nav).ConfigureAwait(false);
267+
268+
foreach (var elem in nav.Elements)
269+
elem.RemoveAllNonInheritableExtensions();
270+
271+
return result;
264272
}
265273
finally
266274
{

src/Hl7.Fhir.STU3/Specification/Snapshot/SnapshotGenerator.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ public async Tasks.Task<IList<ElementDefinition>> ExpandElementAsync(IList<Eleme
228228
try
229229
{
230230
await expandElement(nav).ConfigureAwait(false);
231+
232+
foreach (var elem in nav.Elements)
233+
elem.RemoveAllNonInheritableExtensions();
231234
}
232235
finally
233236
{
@@ -255,7 +258,12 @@ public async Tasks.Task<bool> ExpandElementAsync(ElementDefinitionNavigator nav)
255258
_stack.OnStartRecursion();
256259
try
257260
{
258-
return await expandElement(nav).ConfigureAwait(false);
261+
var result = await expandElement(nav).ConfigureAwait(false);
262+
263+
foreach (var elem in nav.Elements)
264+
elem.RemoveAllNonInheritableExtensions();
265+
266+
return result;
259267
}
260268
finally
261269
{

src/Hl7.Fhir.Specification.STU3.Tests/Snapshot/SnapshotGeneratorTest.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,8 @@ private async Tasks.Task verifyExpandElement(ElementDefinition elem, IList<Eleme
14241424
{
14251425
var expandElemPath = elem.Path;
14261426

1427+
Assert.IsFalse(elem.HasAnyNonInheritableExtensions());
1428+
14271429
// Debug.WriteLine("\r\nOutput:");
14281430
// Debug.WriteLine(string.Join(Environment.NewLine, result.Where(e => e.Path.StartsWith(expandElemPath)).Select(e => e.Path)));
14291431

0 commit comments

Comments
 (0)