Skip to content

Commit 9f76e84

Browse files
authored
Merge pull request #951 from FirelyTeam/949-load-a-resource-and-dependencies-instead-of-full-directory
949 load a resource and dependencies instead of full directory
2 parents c2074e0 + 88522bd commit 9f76e84

34 files changed

+578
-62
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using Hl7.Cql.Compiler.Infrastructure.Graphs;
2+
3+
namespace CoreTests.Infrastructure;
4+
5+
6+
[TestClass]
7+
public class TraversalTests
8+
{
9+
private static TraversalCallbacks<int> PreventRevisits = TraversalCallbacks<int>.CreatePreventRevisits();
10+
11+
private static TraversalCallbacks<int> PreventVisit4 = new(
12+
AllowEnter: t => t.Next != 4 // Also prevents continuing to its children
13+
);
14+
15+
[TestClass]
16+
public class Tree
17+
{
18+
private static IEnumerable<int> GetNext(int node) =>
19+
node switch
20+
{
21+
/*
22+
* 1
23+
* /|\
24+
* 2 3 4
25+
* | / \
26+
* 5 6 7
27+
* |
28+
* 8
29+
*/
30+
1 => [2, 3, 4],
31+
2 => [5],
32+
4 => [6, 7],
33+
7 => [8],
34+
_ => [],
35+
};
36+
37+
[TestMethod]
38+
public void PreOrder_VisitsNodesInPreOrder()
39+
{
40+
var result = string.Join(", ", Traversal.PreOrder(1, GetNext));
41+
Assert.AreEqual("1, 2, 5, 3, 4, 6, 7, 8", result);
42+
}
43+
44+
[TestMethod]
45+
public void PreOrderPreventVisit4_RespectsAllowEnterCallback()
46+
{
47+
var result = string.Join(", ", Traversal.PreOrder(1, GetNext, PreventVisit4));
48+
Assert.AreEqual("1, 2, 5, 3", result);
49+
}
50+
51+
[TestMethod]
52+
public void TopologicalSort_VisitsNodesTopologicallySorted()
53+
{
54+
var result = string.Join(", ", Enumerable.Range(1, 8).TopologicalSort(GetNext));
55+
Assert.AreEqual("5, 2, 3, 6, 8, 7, 4, 1", result);
56+
}
57+
}
58+
59+
[TestClass]
60+
public class DependencyGraph
61+
{
62+
private static IEnumerable<int> GetNext(int node) =>
63+
node switch
64+
{
65+
/*
66+
* 1
67+
* /|\
68+
* 2 3 4
69+
* | X |
70+
* | / \|
71+
* 5 6 7
72+
* \ |
73+
* \ |
74+
* 8
75+
*/
76+
1 => [2, 3, 4],
77+
2 => [5],
78+
3 => [7],
79+
4 => [6, 7],
80+
5 => [8],
81+
7 => [8],
82+
_ => [],
83+
};
84+
85+
[TestMethod]
86+
public void PreOrder_VisitsNodesInPreOrder()
87+
{
88+
var result = string.Join(", ", Traversal.PreOrder(1, GetNext));
89+
Assert.AreEqual("1, 2, 5, 8, 3, 7, 8, 4, 6, 7, 8", result);
90+
}
91+
92+
[TestMethod]
93+
public void PreOrderPreventRevisits_RespectsAllowEnterCallback()
94+
{
95+
var result = string.Join(", ", Traversal.PreOrder(1, GetNext, PreventRevisits));
96+
Assert.AreEqual("1, 2, 5, 8, 3, 7, 4, 6", result);
97+
}
98+
99+
[TestMethod]
100+
public void PreOrderPreventVisit4_RespectsAllowEnterCallback()
101+
{
102+
var result = string.Join(", ", Traversal.PreOrder(1, GetNext, PreventVisit4));
103+
Assert.AreEqual("1, 2, 5, 8, 3, 7, 8", result);
104+
}
105+
106+
[TestMethod]
107+
public void TopologicalSort_VisitsNodesTopologicallySorted()
108+
{
109+
var result = string.Join(", ", Enumerable.Range(1, 8).TopologicalSort(GetNext));
110+
Assert.AreEqual("8, 5, 2, 7, 3, 6, 4, 1", result);
111+
}
112+
}
113+
114+
}

Cql/Cql.Abstractions/Abstractions/Infrastructure/EnumerableExtensions.cs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,9 @@ public static bool TryPeek<T>(
218218
/// <param name="source">The source collection.</param>
219219
/// <param name="selector">A function to test each element for a condition and project the element into a new form.</param>
220220
/// <returns>An enumerable collection that contains the transformed elements that satisfy the condition.</returns>
221-
public static IEnumerable<TR> SelectWhere<T, TR>(this IEnumerable<T> source, Func<T, (bool include, TR resultOrDefault)> selector)
221+
public static IEnumerable<TR> SelectWhere<T, TR>(
222+
this IEnumerable<T> source,
223+
Func<T, (bool include, TR resultOrDefault)> selector)
222224
{
223225
foreach (var item in source)
224226
if (selector(item) is (include: true, { } resultOrDefault))
@@ -228,18 +230,6 @@ public static IEnumerable<TR> SelectWhere<T, TR>(this IEnumerable<T> source, Fun
228230
public static IEnumerable<TR> SelectWhereNotNull<T, TR>(
229231
this IEnumerable<T> enumerable,
230232
Func<T, TR?> selectNullable)
231-
where TR : class
232-
{
233-
return enumerable
234-
.Select(selectNullable)
235-
.WhereNotNull();
236-
}
237-
238-
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> enumerable)
239-
where T : class
240-
{
241-
return enumerable
242-
.Where(x => x is not null)
243-
.Select(x => x!);
244-
}
233+
where TR : notnull =>
234+
enumerable.SelectWhere(o => selectNullable(o) is { } r ? (true, r) : default);
245235
}

Cql/Cql.Compiler/Cql.Compiler.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<InternalsVisibleTo Include="Test.Measures.Demo" Key="$(LibraryPKHash)" />
2929
<InternalsVisibleTo Include="Hl7.Cql.Packaging" Key="$(LibraryPKHash)" />
3030
<InternalsVisibleTo Include="Hl7.Cql" Key="$(LibraryPKHash)" />
31+
<InternalsVisibleTo Include="Hl7.Cql.Invocation" Key="$(LibraryPKHash)" />
3132
<InternalsVisibleTo Include="CqlToElmTests" Key="$(LibraryPKHash)" />
3233
</ItemGroup>
3334

Cql/Cql.Compiler/Infrastructure/Graphs/Traversal.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,25 @@ namespace Hl7.Cql.Compiler.Infrastructure.Graphs;
1010

1111
internal static class Traversal
1212
{
13-
public static IEnumerable<T> DepthFirst<T>(
13+
/// <summary>
14+
/// Performs a pre-ordered traversal of a graph, starting from the specified node.
15+
/// </summary>
16+
/// <typeparam name="T">The type of the nodes in the graph.</typeparam>
17+
/// <param name="current">The starting node for the traversal.</param>
18+
/// <param name="getNextItems">
19+
/// A function that, given a node, returns the enumerable collection of its adjacent nodes.
20+
/// </param>
21+
/// <param name="callbacks">
22+
/// Optional callbacks to handle events during the traversal, such as entering or exiting a node,
23+
/// or determining whether to allow traversal to a specific node.
24+
/// </param>
25+
/// <param name="previous">
26+
/// The node that was visited immediately before the current node. This is used to track the traversal path.
27+
/// </param>
28+
/// <returns>
29+
/// An enumerable collection of nodes visited during the depth-first traversal, in the order they were visited.
30+
/// </returns>
31+
public static IEnumerable<T> PreOrder<T>(
1432
T current,
1533
Func<T, IEnumerable<T>> getNextItems,
1634
TraversalCallbacks<T> callbacks = default,
@@ -23,14 +41,15 @@ public static IEnumerable<T> DepthFirst<T>(
2341
{
2442
if (callbacks.AllowEnter?.Invoke((previous, current, next)) ?? true)
2543
{
26-
foreach (var grandChild in DepthFirst(next, getNextItems, callbacks, current))
44+
foreach (var grandChild in PreOrder(next, getNextItems, callbacks, current))
45+
{
2746
yield return grandChild;
47+
}
2848
}
2949
}
3050
callbacks.Exit?.Invoke((previous, current));
3151
}
3252

33-
3453
public static IEnumerable<T> GetRoots<T>(
3554
this IEnumerable<T> allItems,
3655
Func<T, IEnumerable<T>> getNextItems)
@@ -80,7 +99,7 @@ public static IEnumerable<T> TopologicalSort<T>(
8099

81100
while (unvisited.Count > 0)
82101
{
83-
foreach (var _ in DepthFirst(unvisited.First(), getNextItems, traversalCallbacks))
102+
foreach (var _ in PreOrder(unvisited.First(), getNextItems, traversalCallbacks))
84103
{
85104
// We have to enumerate, even though the resulting item is not used.
86105
}

Cql/Cql.Invocation/PublicAPI.Unshipped.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Hl7.Cql.Invocation.Toolkit.Extensions.LibraryInvokerExtensions
3434
Hl7.Cql.Invocation.Toolkit.Extensions.LibrarySetInvokerExtensions
3535
Hl7.Cql.Invocation.Toolkit.Extensions.PostInvokeDefinitionHandler
3636
Hl7.Cql.Invocation.Toolkit.Extensions.PreInvokeDefinitionHandler
37+
Hl7.Cql.Invocation.Toolkit.Extensions.ResourceFileInfoResolver
38+
Hl7.Cql.Invocation.Toolkit.Extensions.ResourceFileInfoResolvers
3739
Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions
3840
Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions.Deconstruct(out Hl7.Cql.Invocation.Toolkit.Extensions.DefinitionArgumentsProvider? ProviderArgumentsCallback, out Hl7.Cql.Invocation.Toolkit.Extensions.PreInvokeDefinitionHandler? PreInvokeDefinitionCallback, out Hl7.Cql.Invocation.Toolkit.Extensions.PostInvokeDefinitionHandler? PostInvokeDefinitionCallback, out Hl7.Cql.Runtime.BatchProcessExceptionHandler<Hl7.Cql.Invocation.Toolkit.DefinitionInvoker!>? InvocationExceptionCallback) -> void
3941
Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions.InvocationExceptionCallback.get -> Hl7.Cql.Runtime.BatchProcessExceptionHandler<Hl7.Cql.Invocation.Toolkit.DefinitionInvoker!>?
@@ -90,6 +92,7 @@ static Hl7.Cql.Invocation.Toolkit.Extensions.ElmToolkitInvocationExtensions.Crea
9092
static Hl7.Cql.Invocation.Toolkit.Extensions.ElmToolkitInvocationExtensions.CreateLibrarySetInvoker(this Hl7.Cql.CodeGeneration.NET.Toolkit.ElmToolkit! elmToolkit, string! name = "") -> Hl7.Cql.Invocation.Toolkit.LibrarySetInvoker!
9193
static Hl7.Cql.Invocation.Toolkit.Extensions.ElmToolkitInvocationExtensions.UseLibrarySetInvoker(this Hl7.Cql.CodeGeneration.NET.Toolkit.ElmToolkit! elmToolkit, System.Action<Hl7.Cql.Invocation.Toolkit.LibrarySetInvoker!>! useLibrarySetInvoker, string! librarySetName = "") -> void
9294
static Hl7.Cql.Invocation.Toolkit.Extensions.InvocationToolkitExtensions.AddAssemblyBinaries(this Hl7.Cql.Invocation.Toolkit.InvocationToolkit! invocationToolkit, params Hl7.Cql.CodeGeneration.NET.AssemblyBinary![]! assemblyBinary) -> Hl7.Cql.Invocation.Toolkit.InvocationToolkit!
95+
static Hl7.Cql.Invocation.Toolkit.Extensions.InvocationToolkitExtensions.AddAssemblyBinariesFromFhirLibraryAndDependencies(this Hl7.Cql.Invocation.Toolkit.InvocationToolkit! invocationToolkit, Hl7.Cql.Runtime.CqlVersionedLibraryIdentifier libraryIdentifier, Hl7.Cql.Invocation.Toolkit.Extensions.ResourceFileInfoResolver! fhirFileResolver, System.Func<System.IO.FileInfo!, bool>? filePredicate = null, Hl7.Cql.Abstractions.Mutator<System.Text.Json.JsonSerializerOptions!>? configureJsonSerializerOptions = null) -> Hl7.Cql.Invocation.Toolkit.InvocationToolkit!
9396
static Hl7.Cql.Invocation.Toolkit.Extensions.InvocationToolkitExtensions.AddAssemblyBinariesInFhirLibrariesFromDirectory(this Hl7.Cql.Invocation.Toolkit.InvocationToolkit! invocationToolkit, System.IO.DirectoryInfo! directory, System.IO.EnumerationOptions? options = null, System.Func<System.IO.FileInfo!, bool>? filePredicate = null, Hl7.Cql.Abstractions.Mutator<System.Text.Json.JsonSerializerOptions!>? configureJsonSerializerOptions = null) -> Hl7.Cql.Invocation.Toolkit.InvocationToolkit!
9497
static Hl7.Cql.Invocation.Toolkit.Extensions.InvocationToolkitExtensions.AddAssemblyBinaryFiles(this Hl7.Cql.Invocation.Toolkit.InvocationToolkit! invocationToolkit, System.Collections.Generic.IEnumerable<System.IO.FileInfo!>! files) -> Hl7.Cql.Invocation.Toolkit.InvocationToolkit!
9598
static Hl7.Cql.Invocation.Toolkit.Extensions.InvocationToolkitExtensions.AddAssemblyBinaryFilesFromDirectory(this Hl7.Cql.Invocation.Toolkit.InvocationToolkit! invocationToolkit, System.IO.DirectoryInfo! directory, System.IO.EnumerationOptions? options = null, System.Func<System.IO.FileInfo!, bool>? filePredicate = null) -> Hl7.Cql.Invocation.Toolkit.InvocationToolkit!
@@ -102,13 +105,15 @@ static Hl7.Cql.Invocation.Toolkit.Extensions.LibrarySetInvokerExtensions.InvokeL
102105
static Hl7.Cql.Invocation.Toolkit.Extensions.LibrarySetInvokerExtensions.SelectDefinitions(this Hl7.Cql.Invocation.Toolkit.LibrarySetInvoker! librarySetInvoker) -> System.Collections.Generic.IEnumerable<Hl7.Cql.Invocation.Toolkit.DefinitionInvoker!>!
103106
static Hl7.Cql.Invocation.Toolkit.Extensions.LibrarySetInvokerExtensions.SelectExpressions(this Hl7.Cql.Invocation.Toolkit.LibrarySetInvoker! librarySetInvoker, Hl7.Cql.Invocation.Toolkit.Extensions.DefinitionPredicate? filter = null) -> System.Collections.Generic.IEnumerable<Hl7.Cql.Invocation.Toolkit.DefinitionInvoker!>!
104107
static Hl7.Cql.Invocation.Toolkit.Extensions.LibrarySetInvokerExtensions.SelectExpressionsForLibrary(this Hl7.Cql.Invocation.Toolkit.LibrarySetInvoker! librarySetInvoker, Hl7.Cql.Runtime.CqlVersionedLibraryIdentifier libraryIdentifier, Hl7.Cql.Invocation.Toolkit.Extensions.DefinitionPredicate? filter = null) -> System.Collections.Generic.IEnumerable<Hl7.Cql.Invocation.Toolkit.DefinitionInvoker!>!
108+
static Hl7.Cql.Invocation.Toolkit.Extensions.ResourceFileInfoResolvers.FromDirectory(System.IO.DirectoryInfo! directory, string! resourceType = "Library") -> Hl7.Cql.Invocation.Toolkit.Extensions.ResourceFileInfoResolver!
105109
static Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions.Default.get -> Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions!
106110
static Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions.operator !=(Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions? left, Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions? right) -> bool
107111
static Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions.operator ==(Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions? left, Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions? right) -> bool
108112
virtual Hl7.Cql.Invocation.Toolkit.Extensions.DefinitionArgumentsProvider.Invoke(Hl7.Cql.Invocation.Toolkit.DefinitionInvoker! definitionInvoker, Hl7.Cql.Runtime.CqlContext! cqlContext) -> object?[]!
109113
virtual Hl7.Cql.Invocation.Toolkit.Extensions.DefinitionPredicate.Invoke(Hl7.Cql.Invocation.Toolkit.DefinitionInvoker! definitionInvoker) -> bool
110114
virtual Hl7.Cql.Invocation.Toolkit.Extensions.PostInvokeDefinitionHandler.Invoke(Hl7.Cql.Invocation.Toolkit.DefinitionInvoker! definitionInvoker, Hl7.Cql.Runtime.CqlContext! cqlContext, object?[]! definitionArguments, object? definitionResult) -> void
111115
virtual Hl7.Cql.Invocation.Toolkit.Extensions.PreInvokeDefinitionHandler.Invoke(Hl7.Cql.Invocation.Toolkit.DefinitionInvoker! definitionInvoker, Hl7.Cql.Runtime.CqlContext! cqlContext, object?[]! definitionArguments) -> void
116+
virtual Hl7.Cql.Invocation.Toolkit.Extensions.ResourceFileInfoResolver.Invoke(Hl7.Cql.Runtime.CqlVersionedLibraryIdentifier libraryIdentifier) -> System.IO.FileInfo!
112117
virtual Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions.<Clone>$() -> Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions!
113118
virtual Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions.EqualityContract.get -> System.Type!
114119
virtual Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions.Equals(Hl7.Cql.Invocation.Toolkit.Extensions.SelectResultsOptions? other) -> bool

Cql/Cql.Invocation/Toolkit/CqlParameterInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ namespace Hl7.Cql.Invocation.Toolkit;
1010
public readonly record struct CqlParameterInfo(string Name, Type Type)
1111
{
1212
/// <summary>
13-
/// Returns a string representation of the CQL parameter information,
13+
/// Returns a string representation of the CQL parameter information,
1414
/// including its type and name.
1515
/// </summary>
1616
/// <returns>
17-
/// A string in the format "<c>{Type}</c> '<c>{Name}</c>'", where <c>{Type}</c>
17+
/// A string in the format "<c>{Type}</c> '<c>{Name}</c>'", where <c>{Type}</c>
1818
/// is the C# representation of the parameter's type and <c>{Name}</c> is the parameter's name.
1919
/// </returns>
2020
public override string ToString() => $"{Type.ToCSharpString()} '{Name}'";

0 commit comments

Comments
 (0)