Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

260 refactor pass tuple types as a result from expressionbuilder not via the typemanager #523

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8bf5fc5
Rename TypeManager to DynamicTupleCache
baseTwo Sep 10, 2024
d5b6bb7
DynamicTupleCache no longer needs dependency on TypeManager
baseTwo Sep 10, 2024
0ace49c
Rename DynamicTupleCache to TupleBuilderCache
baseTwo Sep 10, 2024
6d30e3f
Create the same pattern for services initializing in the PackagerCLI
baseTwo Sep 10, 2024
303dab7
Move packagercli configurator out of program
baseTwo Sep 10, 2024
1ff27d4
Move logging and commandline switch configuration to own files
baseTwo Sep 10, 2024
617aeb4
renames
baseTwo Sep 10, 2024
97d0c3a
Merge branch 'develop-2.0' into 260-refactor---pass-tuple-types-as-a-…
baseTwo Sep 10, 2024
b91665d
Don't leak out internal state from TupleBuilderCache
baseTwo Sep 10, 2024
1e2de14
Merge branch '260-refactor---pass-tuple-types-as-a-result-from-expres…
baseTwo Sep 10, 2024
0a35917
TEST - See if scoped services dispose - not yet
baseTwo Sep 10, 2024
5b3026f
Ensure scopes are used properly
baseTwo Sep 10, 2024
b9ca068
Update scopes and diagram
baseTwo Sep 10, 2024
5619ecc
Merge branch 'develop-2.0' into 260-refactor---pass-tuple-types-as-a-…
baseTwo Sep 10, 2024
9cc8905
Cleanup services and diagram
baseTwo Sep 10, 2024
f3b65ff
Merge branch '260-refactor---pass-tuple-types-as-a-result-from-expres…
baseTwo Sep 10, 2024
5e2047c
Update diagram
baseTwo Sep 10, 2024
161e506
Remove base interfaces for contexts
baseTwo Sep 10, 2024
27d8309
Use explicit fields
baseTwo Sep 10, 2024
5a10a1e
Make fields explicit
baseTwo Sep 10, 2024
945c06f
Correctly indicated scoped types on services
baseTwo Sep 10, 2024
b27579f
Fix string constants in MeasuresTest
baseTwo Sep 10, 2024
7d7892c
No tuple binary is needed anymore
baseTwo Sep 10, 2024
7162bb0
Update diagram
baseTwo Sep 10, 2024
788d498
Missed ResourcePackager in diagram
baseTwo Sep 10, 2024
504d26e
Color diagram
baseTwo Sep 11, 2024
7f9f64b
Dont cross lines in diagram
baseTwo Sep 11, 2024
5be45c3
Get diagram theme to be visible on dark or light background
baseTwo Sep 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions Cql/CodeGeneration.NET/AssemblyCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,19 @@ namespace Hl7.Cql.CodeGeneration.NET
{
internal class AssemblyCompiler
{
private readonly TypeManager _typeManager;
private readonly CSharpLibrarySetToStreamsWriter _cSharpLibrarySetToStreamsWriter;
private readonly CSharpCodeStreamPostProcessor? _cSharpCodeStreamPostProcessor;
private readonly Lazy<Assembly[]> _referencesLazy;
private readonly AssemblyDataPostProcessor? _assemblyDataPostProcessor;

public AssemblyCompiler(
CSharpLibrarySetToStreamsWriter cSharpLibrarySetToStreamsWriter,
TypeManager typeManager,
TypeResolver typeResolver,
CSharpCodeStreamPostProcessor? cSharpCodeStreamPostProcessor = null,
AssemblyDataPostProcessor? assemblyDataPostProcessor = null)
{
_assemblyDataPostProcessor = assemblyDataPostProcessor;
_cSharpLibrarySetToStreamsWriter = cSharpLibrarySetToStreamsWriter;
_typeManager = typeManager;
_cSharpCodeStreamPostProcessor = cSharpCodeStreamPostProcessor;
_referencesLazy = new Lazy<Assembly[]>(
() =>
Expand All @@ -62,7 +60,7 @@ public AssemblyCompiler(

} // @formatter on
.Select(type => type.Assembly)
.Concat(typeManager.Resolver.ModelAssemblies)
.Concat(typeResolver.ModelAssemblies)
.Distinct()
.ToArray();
return references;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,13 @@

namespace Hl7.Cql.CodeGeneration.NET.PostProcessors;

internal class WriteToFileCSharpCodeStreamPostProcessor : CSharpCodeStreamPostProcessor
internal class WriteToFileCSharpCodeStreamPostProcessor(
IOptions<CSharpCodeWriterOptions> csharpCodeWriterOptions,
ILogger<WriteToFileCSharpCodeStreamPostProcessor> logger)
: CSharpCodeStreamPostProcessor
{
private readonly CSharpCodeWriterOptions _csharpCodeWriterOptions;
private readonly ILogger<WriteToFileCSharpCodeStreamPostProcessor> _logger;

public WriteToFileCSharpCodeStreamPostProcessor(
IOptions<CSharpCodeWriterOptions> csharpCodeWriterOptions,
ILogger<WriteToFileCSharpCodeStreamPostProcessor> logger)
{
_logger = logger;
_csharpCodeWriterOptions = csharpCodeWriterOptions.Value;
}
private readonly CSharpCodeWriterOptions _csharpCodeWriterOptions = csharpCodeWriterOptions.Value;
private readonly ILogger<WriteToFileCSharpCodeStreamPostProcessor> _logger = logger;

public override void ProcessStream(string name, Stream stream)
{
Expand Down
10 changes: 5 additions & 5 deletions Cql/CoreTests/ExpressionBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void AggregateQueries_1_0_0()
var cqlCompilerServices = CqlServicesInitializer.CreateCqlCompilerServices(disposeContext.Token);
var elm = new FileInfo(@"Input\ELM\Test\Aggregates-1.0.0.json");
var elmPackage = Hl7.Cql.Elm.Library.LoadFromJson(elm);
var definitions = cqlCompilerServices.LibraryExpressionBuilder.ProcessLibrary(elmPackage);
var definitions = cqlCompilerServices.LibraryExpressionBuilderScoped().ProcessLibrary(elmPackage);
Assert.IsNotNull(definitions);
Assert.IsTrue(definitions.Libraries.Any());
}
Expand All @@ -30,7 +30,7 @@ public void FHIRConversionTest_1_0_0()
var cqlCompilerServices = CqlServicesInitializer.CreateCqlCompilerServices(disposeContext.Token);
var elm = new FileInfo(@"Input\ELM\HL7\FHIRConversionTest.json");
var elmPackage = Hl7.Cql.Elm.Library.LoadFromJson(elm);
var definitions = cqlCompilerServices.LibraryExpressionBuilder.ProcessLibrary(elmPackage);
var definitions = cqlCompilerServices.LibraryExpressionBuilderScoped().ProcessLibrary(elmPackage);
Assert.IsNotNull(definitions);
Assert.IsTrue(definitions.Libraries.Any());
}
Expand All @@ -42,7 +42,7 @@ public void QueriesTest_1_0_0()
var cqlCompilerServices = CqlServicesInitializer.CreateCqlCompilerServices(disposeContext.Token);
var elm = new FileInfo(@"Input\ELM\Test\QueriesTest-1.0.0.json");
var elmPackage = Hl7.Cql.Elm.Library.LoadFromJson(elm);
var definitions = cqlCompilerServices.LibraryExpressionBuilder.ProcessLibrary(elmPackage);
var definitions = cqlCompilerServices.LibraryExpressionBuilderScoped().ProcessLibrary(elmPackage);
Assert.IsNotNull(definitions);
Assert.IsTrue(definitions.Libraries.Any());
}
Expand All @@ -66,7 +66,7 @@ public void Medication_Request_Example_Test()
var fs = new FhirDateTime(fdts);
Assert.AreEqual(fdt, fs);

var definitions = cqlCompilerServices.LibrarySetExpressionBuilder.ProcessLibrarySet(librarySet);
var definitions = cqlCompilerServices.LibrarySetExpressionBuilderScoped().ProcessLibrarySet(librarySet);
Assert.IsNotNull(definitions);
Assert.IsTrue(definitions.Libraries.Any());
}
Expand All @@ -77,7 +77,7 @@ public void Get_Property_Uses_TypeResolver()
{
using var disposeContext = new DisposeContext();
var cqlCompilerServices = CqlServicesInitializer.CreateCqlCompilerServices(disposeContext.Token);
var property = ExpressionBuilder.GetProperty(typeof(MeasureReport.PopulationComponent), "id", cqlCompilerServices.TypeManager.Resolver)!;
var property = ExpressionBuilder.GetProperty(typeof(MeasureReport.PopulationComponent), "id", cqlCompilerServices.TypeResolver)!;
Assert.AreEqual(typeof(Element), property.DeclaringType);
Assert.AreEqual(nameof(Element.ElementId), property.Name);
}
Expand Down
2 changes: 1 addition & 1 deletion Cql/CoreTests/LibrarySetExpressionBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public void LoadLibraryAndDependencies_CrossLibraryCodeSystems()

LibrarySet librarySet = new();
librarySet.LoadLibraryAndDependencies(LibrarySetsDirs.Cms.ElmDir, "CumulativeMedicationDuration");
var definitionDictionary = cqlCompilerServices.LibrarySetExpressionBuilder.ProcessLibrarySet(librarySet);
var definitionDictionary = cqlCompilerServices.LibrarySetExpressionBuilderScoped().ProcessLibrarySet(librarySet);
var lambdaExpression = definitionDictionary["CumulativeMedicationDuration-4.0.000", "Every eight hours (qualifier value)"];
Assert.IsNotNull(lambdaExpression);

Expand Down
2 changes: 1 addition & 1 deletion Cql/CoreTests/PrimitiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3411,7 +3411,7 @@ public void Aggregate_Query_Test()
var librarySet = new LibrarySet();
librarySet.LoadLibraryAndDependencies(new DirectoryInfo("Input\\ELM\\Test"),"Aggregates", "1.0.0");
var elmPackage = librarySet.GetLibrary("Aggregates-1.0.0");
var definitions = cqlCodeGenerationServices.GetCqlCompilerServices().LibraryExpressionBuilder.ProcessLibrary(elmPackage);
var definitions = cqlCodeGenerationServices.GetCqlCompilerServices().LibraryExpressionBuilderScoped().ProcessLibrary(elmPackage);
var writer = cqlCodeGenerationServices.CSharpLibrarySetToStreamsWriter;
var isDone = false;
writer.ProcessDefinitions(
Expand Down
4 changes: 2 additions & 2 deletions Cql/CoreTests/QueriesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static void Initialize(TestContext context)

var elm = new FileInfo(@"Input\ELM\Test\QueriesTest-1.0.0.json");
var elmPackage = Hl7.Cql.Elm.Library.LoadFromJson(elm);
var definitions = cqlCompilerServices.LibraryExpressionBuilder.ProcessLibrary(elmPackage);
var definitions = cqlCompilerServices.LibraryExpressionBuilderScoped().ProcessLibrary(elmPackage);
QueriesDefinitions = definitions.CompileAll();
ValueSets = new HashValueSetDictionary();
ValueSets.Add("http://hl7.org/fhir/ValueSet/example-expansion",
Expand All @@ -32,7 +32,7 @@ public static void Initialize(TestContext context)

elm = new FileInfo(@"Input\ELM\Test\Aggregates-1.0.0.json");
elmPackage = Hl7.Cql.Elm.Library.LoadFromJson(elm);
cqlCompilerServices.LibraryExpressionBuilder.ProcessLibrary(elmPackage, libraryDefinitions: definitions);
cqlCompilerServices.LibraryExpressionBuilderScoped().ProcessLibrary(elmPackage, libraryDefinitions: definitions);
AggregatesDefinitions = definitions.CompileAll();
}

Expand Down
1 change: 0 additions & 1 deletion Cql/Cql.Compiler/AmbiguousOverloadCorrector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* available at https://raw.githubusercontent.com/FirelyTeam/firely-cql-sdk/main/LICENSE
*/

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Hl7.Cql.Elm;
Expand Down
51 changes: 20 additions & 31 deletions Cql/Cql.Compiler/CqlOperatorsBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,27 @@ namespace Hl7.Cql.Compiler
/// by converting the method name and <see cref="Expression"/> arguments
/// to the appropriate overload of the method.
/// </summary>
internal partial class CqlOperatorsBinder
/// <param name="logger">
/// The logger used.
/// </param>
/// <param name="typeResolver">
/// The type resolver used.
/// Note that if you provide a different instance of this class to <see cref="CqlOperators"/>, you will get errors at runtime.
/// </param>
/// <param name="typeConverter">
/// If provided, this binding will use the supplied instance to determine whether
/// a conversion is possible. Note that if you provide a different instance of this class to <see cref="CqlOperators"/>,
/// you may get errors at runtime, because this binding will think a conversion is possible when at runtime it is not.
/// If not provided, only conversions defined in <see cref="CqlOperators"/> will be used.
/// </param>
internal partial class CqlOperatorsBinder(
ILogger<CqlOperatorsBinder> logger,
TypeResolver typeResolver,
TypeConverter typeConverter)
{
private readonly ILogger<CqlOperatorsBinder> _logger;
private readonly TypeConverter _typeConverter;
private readonly TypeResolver _typeResolver;


/// <summary>
/// Creates an instance.
/// </summary>
/// <param name="logger">
/// The logger used.
/// </param>
/// <param name="typeResolver">
/// The type resolver used.
/// Note that if you provide a different instance of this class to <see cref="CqlOperators"/>, you will get errors at runtime.
/// </param>
/// <param name="typeConverter">
/// If provided, this binding will use the supplied instance to determine whether
/// a conversion is possible. Note that if you provide a different instance of this class to <see cref="CqlOperators"/>,
/// you may get errors at runtime, because this binding will think a conversion is possible when at runtime it is not.
/// If not provided, only conversions defined in <see cref="CqlOperators"/> will be used.
/// </param>
public CqlOperatorsBinder(
ILogger<CqlOperatorsBinder> logger,
TypeResolver typeResolver,
TypeConverter typeConverter)
{
_typeConverter = typeConverter;
_typeResolver = typeResolver;
_logger = logger;
}
private readonly ILogger<CqlOperatorsBinder> _logger = logger;
private readonly TypeResolver _typeResolver = typeResolver;
private readonly TypeConverter _typeConverter = typeConverter;

/// <summary>
/// Facilitates binding to <see cref="ICqlOperators"/> methods,
Expand Down
83 changes: 36 additions & 47 deletions Cql/Cql.Compiler/ExpressionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using Hl7.Cql.Abstractions;
using Hl7.Cql.Conversion;
using Hl7.Cql.Elm;
using Microsoft.Extensions.Logging;

Expand All @@ -20,71 +20,60 @@ internal class ExpressionBuilder(
ILogger<ExpressionBuilder> logger,
ExpressionBuilderSettings expressionBuilderSettings,
CqlOperatorsBinder cqlOperatorsBinder,
TypeManager typeManager,
TypeConverter typeConverter,
TupleBuilderCache tupleBuilderCache,
TypeResolver typeResolver,
CqlContextBinder cqlContextBinder)
{
internal readonly CqlOperatorsBinder _cqlOperatorsBinder = cqlOperatorsBinder;
internal readonly CqlContextBinder _cqlContextBinder = cqlContextBinder;
internal readonly TypeManager _typeManager = typeManager;
internal readonly ILogger<ExpressionBuilder> _logger = logger;
internal readonly TypeConverter _typeConverter = typeConverter;
internal readonly TypeResolver _typeResolver = typeResolver;
internal readonly ExpressionBuilderSettings _expressionBuilderSettings = expressionBuilderSettings;
private readonly ILogger<ExpressionBuilder> _logger = logger;
private readonly ExpressionBuilderSettings _expressionBuilderSettings = expressionBuilderSettings;
private readonly CqlOperatorsBinder _cqlOperatorsBinder = cqlOperatorsBinder;
private readonly TupleBuilderCache _tupleBuilderCache = tupleBuilderCache;
private readonly TypeResolver _typeResolver = typeResolver;
private readonly CqlContextBinder _cqlContextBinder = cqlContextBinder;

/*
* The ExpressionBuilderContext is created anew for each of the ProcessXXX methods.
* This works, because all but the ProcessExpressionDef methods only change state
* on the ILibraryExpressionBuilderContext.
* on the LibraryExpressionBuilderContext.
*
* Only ProcessExpressionDef changes state on the ExpressionBuilderContext.
*/

public void ProcessIncludes(ILibraryExpressionBuilderContext libCtx, IncludeDef includeDef)
{
ExpressionBuilderContext context = new ExpressionBuilderContext(this, libCtx);
context.ProcessIncludes(includeDef);
}
public void ProcessIncludes(LibraryExpressionBuilderContext libCtx, IncludeDef includeDef) =>
NewExpressionBuilderContext(libCtx)
.ProcessIncludes(includeDef);

public void ProcessValueSetDef(ILibraryExpressionBuilderContext libCtx, ValueSetDef valueSetDef)
{
ExpressionBuilderContext context = new ExpressionBuilderContext(this, libCtx);
context.ProcessValueSetDef(valueSetDef);
}
internal ExpressionBuilderContext NewExpressionBuilderContext(
LibraryExpressionBuilderContext libCtx,
Dictionary<string, ParameterExpression>? operands = null) =>
new(_logger, _expressionBuilderSettings, _cqlOperatorsBinder, _tupleBuilderCache, _typeResolver, _cqlContextBinder, libCtx, operands);

public void ProcessValueSetDef(LibraryExpressionBuilderContext libCtx, ValueSetDef valueSetDef) =>
NewExpressionBuilderContext(libCtx)
.ProcessValueSetDef(valueSetDef);

public void ProcessCodeDef(
ILibraryExpressionBuilderContext libCtx,
LibraryExpressionBuilderContext libCtx,
CodeDef codeDef,
HashSet<(string codeName, string codeSystemUrl)> foundCodeNameCodeSystemUrls)
{
ExpressionBuilderContext context = new ExpressionBuilderContext(this, libCtx);
context.ProcessCodeDef(codeDef, foundCodeNameCodeSystemUrls);
}
HashSet<(string codeName, string codeSystemUrl)> foundCodeNameCodeSystemUrls) =>
NewExpressionBuilderContext(libCtx)
.ProcessCodeDef(codeDef, foundCodeNameCodeSystemUrls);

public void ProcessCodeSystemDef(ILibraryExpressionBuilderContext libCtx, CodeSystemDef codeSystemDef)
{
ExpressionBuilderContext context = new ExpressionBuilderContext(this, libCtx);
context.ProcessCodeSystemDef(codeSystemDef);
}
public void ProcessCodeSystemDef(LibraryExpressionBuilderContext libCtx, CodeSystemDef codeSystemDef) =>
NewExpressionBuilderContext(libCtx)
.ProcessCodeSystemDef(codeSystemDef);

public void ProcessConceptDef(ILibraryExpressionBuilderContext libCtx, ConceptDef conceptDef)
{
ExpressionBuilderContext context = new ExpressionBuilderContext(this, libCtx);
context.ProcessConceptDef(conceptDef);
}
public void ProcessConceptDef(LibraryExpressionBuilderContext libCtx, ConceptDef conceptDef) =>
NewExpressionBuilderContext(libCtx)
.ProcessConceptDef(conceptDef);

public void ProcessParameterDef(ILibraryExpressionBuilderContext libCtx, ParameterDef parameterDef)
{
ExpressionBuilderContext context = new ExpressionBuilderContext(this, libCtx);
context.ProcessParameterDef(parameterDef);
}
public void ProcessParameterDef(LibraryExpressionBuilderContext libCtx, ParameterDef parameterDef) =>
NewExpressionBuilderContext(libCtx)
.ProcessParameterDef(parameterDef);

public void ProcessExpressionDef(ILibraryExpressionBuilderContext libCtx, ExpressionDef expressionDef)
{
ExpressionBuilderContext context = new ExpressionBuilderContext(this, libCtx, new());
context.ProcessExpressionDef(expressionDef);
}
public void ProcessExpressionDef(LibraryExpressionBuilderContext libCtx, ExpressionDef expressionDef) =>
NewExpressionBuilderContext(libCtx, new Dictionary<string, ParameterExpression>())
.ProcessExpressionDef(expressionDef);

internal static PropertyInfo? GetProperty(Type type, string name, TypeResolver typeResolver)
{
Expand Down
2 changes: 1 addition & 1 deletion Cql/Cql.Compiler/ExpressionBuilderContext.DebuggerView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ private IPopToken PushElement(Elm.Element element)

private readonly record struct ExpressionBuilderNode : IBuilderContext
{
public ILibraryExpressionBuilderContext LibraryExpressionBuilder { get; init; }
public LibraryExpressionBuilderContext LibraryExpressionBuilder { get; init; }
public IReadOnlyList<Elm.Element> ElementStackList { get; init; }
public int ElementStackPosition { get; init; }

Expand Down
6 changes: 4 additions & 2 deletions Cql/Cql.Compiler/ExpressionBuilderContext.LibraryDefs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using Hl7.Cql.Compiler.Infrastructure;
using Hl7.Cql.Elm;
using Hl7.Cql.Primitives;
using Hl7.Cql.Runtime;
using Microsoft.Extensions.Logging;
using Expression = System.Linq.Expressions.Expression;

Expand Down Expand Up @@ -131,6 +130,9 @@ public void ProcessExpressionDef(
ExpressionDef expressionDef) =>
this.CatchRethrowExpressionBuildingException(_ =>
{
if (_operands is null)
throw new InvalidOperationException("Operands dictionary is null.");

using (PushElement(expressionDef))
{
if (string.IsNullOrWhiteSpace(expressionDef.name))
Expand Down Expand Up @@ -260,7 +262,7 @@ public void ProcessParameterDef(
defaultValue = TranslateArg(parameter.@default).NewTypeAsExpression<object>();
else defaultValue = NullExpression.Object;

var resolveParam = _contextBinder.ResolveParameter(_libraryContext.LibraryKey, parameter.name, defaultValue);
var resolveParam = _cqlContextBinder.ResolveParameter(_libraryContext.LibraryKey, parameter.name, defaultValue);

var parameterType = TypeFor(parameter.parameterTypeSpecifier)!;
var cast = _cqlOperatorsBinder.CastToType(resolveParam, parameterType);
Expand Down
Loading