Skip to content

Commit

Permalink
- update the code generator to turn all of files into static and remo…
Browse files Browse the repository at this point in the history
…ve the required initialization
  • Loading branch information
DamienM419 committed Sep 17, 2024
1 parent 5ad85b3 commit adb1552
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 145 deletions.
142 changes: 5 additions & 137 deletions Cql/CodeGeneration.NET/CSharpSourceCodeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,35 +200,12 @@ private void writeClass(DefinitionDictionary<LambdaExpression> definitions,
if (PartialClass)
writer.WriteLine(indentLevel, $"partial class {className}");
else
writer.WriteLine(indentLevel, $"public class {className}");
writer.WriteLine(indentLevel, $"public static class {className}");
writer.WriteLine(indentLevel, "{");
writer.WriteLine();
indentLevel += 1;
// Class
{
writer.WriteLine();

writer.WriteLine(indentLevel, $"{AccessModifierString(ContextAccessModifier)} CqlContext context;");
writer.WriteLine();
writeCachedValues(definitions, libraryName, writer, indentLevel);

// Write constructor
writer.WriteLine(indentLevel, $"public {className}(CqlContext context)");
writer.WriteLine(indentLevel, "{");
{
indentLevel += 1;

writer.WriteLine(indentLevel, "this.context = context ?? throw new ArgumentNullException(\"context\");");
writer.WriteLine();

writeDependencies(dependencyGraph, libraryNameToClassName, libraryName, writer, indentLevel);
writer.WriteLine();
writeCachedValueNames(definitions, libraryName, writer, indentLevel);
indentLevel -= 1;
}
writer.WriteLine(indentLevel, "}");

WriteLibraryMembers(writer, dependencyGraph, libraryName, libraryNameToClassName!, indentLevel);
writeMemoizedInstanceMethods(definitions, libraryName, writer, indentLevel);
indentLevel -= 1;
writer.WriteLine(indentLevel, "}");
Expand All @@ -247,62 +224,7 @@ private void writeMemoizedInstanceMethods(DefinitionDictionary<LambdaExpression>
}
}
}

private void writeCachedValueNames(DefinitionDictionary<LambdaExpression> definitions, string libraryName, StreamWriter writer, int indentLevel)
{
foreach (var kvp in definitions.DefinitionsForLibrary(libraryName))
{
foreach (var overload in kvp.Value)
{
if (isDefinition(overload.Item2))
{
var methodName = VariableNameGenerator.NormalizeIdentifier(kvp.Key);
var cachedValueName = DefinitionCacheKeyForMethod(methodName!);
var returnType = ExpressionConverter.PrettyTypeName(overload.Item2.ReturnType);
var privateMethodName = PrivateMethodNameFor(methodName!);
writer.WriteLine(indentLevel, $"{cachedValueName} = new Lazy<{returnType}>(this.{privateMethodName});");
}
}
}
}

private static void writeDependencies(DirectedGraph dependencyGraph, Func<string?, string?> libraryNameToClassName, string libraryName, StreamWriter writer, int indentLevel)
{
var node = dependencyGraph.Nodes[libraryName];
var requiredLibraries = node.ForwardEdges?
.Select(edge => edge.ToId)
.Except(new[] { dependencyGraph.EndNode.NodeId })
.Distinct();
foreach (var dependentLibrary in requiredLibraries!)
{
var typeName = libraryNameToClassName!(dependentLibrary);
var memberName = typeName;
writer.WriteLine(indentLevel, $"{memberName} = new {typeName}(context);");
}
}

private void writeCachedValues(DefinitionDictionary<LambdaExpression> definitions, string libraryName, StreamWriter writer, int indentLevel)
{
writer.WriteLine(indentLevel, "#region Cached values");
writer.WriteLine();
var accessModifier = AccessModifierString(DefinesAccessModifier);
foreach (var kvp in definitions.DefinitionsForLibrary(libraryName))
{
foreach (var overload in kvp.Value)
{
if (isDefinition(overload.T))
{
var methodName = VariableNameGenerator.NormalizeIdentifier(kvp.Key);
var cachedValueName = DefinitionCacheKeyForMethod(methodName!);
var returnType = ExpressionConverter.PrettyTypeName(overload.T.ReturnType);
writer.WriteLine(indentLevel, $"{accessModifier} Lazy<{returnType}> {cachedValueName};");
}
}
}
writer.WriteLine();
writer.WriteLine(indentLevel, "#endregion");
}


private void writeTupleTypes(IEnumerable<Type> tupleTypes, Func<string, Stream> libraryNameToStream, bool closeStream)
{
if (tupleTypes.Any())
Expand Down Expand Up @@ -346,36 +268,6 @@ private static bool isDefinition(LambdaExpression overload) =>
overload.Parameters.Count == 1
&& overload.Parameters[0].Type == typeof(CqlContext);

private void WriteLibraryMembers(TextWriter writer,
DirectedGraph dependencyGraph,
string libraryName,
Func<string, string> libraryNameToClassName,
int indent)
{
var node = dependencyGraph.Nodes[libraryName];
var requiredLibraries = node.ForwardEdges?
.Select(edge => edge.ToId)
.Except(new[] { dependencyGraph.EndNode.NodeId })
.Distinct();
if (requiredLibraries != null)
{

writer.WriteLine(indent, "#region Dependencies");
writer.WriteLine();

foreach (var dependentLibrary in requiredLibraries)
{
var typeName = libraryNameToClassName(dependentLibrary);
var memberName = typeName;
writer.WriteLine(indent, $"public {typeName} {memberName} {{ get; }}");
}

writer.WriteLine();
writer.WriteLine(indent, "#endregion");
writer.WriteLine();
}
}

private IList<DirectedGraphNode> DetermineBuildOrder(DirectedGraph minimalGraph)
{
var sorted = minimalGraph.TopologicalSort()
Expand All @@ -385,14 +277,6 @@ private IList<DirectedGraphNode> DetermineBuildOrder(DirectedGraph minimalGraph)
return sorted;
}

private string DefinitionCacheKeyForMethod(string methodName)
{
if (methodName[0] == '@')
return "__" + methodName.Substring(1);
else return "__" + methodName;
}
private string PrivateMethodNameFor(string methodName) => methodName + "_Value";

private void WriteMemoizedInstanceMethod(string libraryName, TextWriter writer, int indentLevel,
string cqlName,
LambdaExpression overload,
Expand All @@ -419,16 +303,6 @@ private void WriteMemoizedInstanceMethod(string libraryName, TextWriter writer,

if (isDef)
{
// Definitions, which are CQL expressions without parameter, can be memoized,
// so we generate a "generator" function (name ending in _Value) and a
// getter function, which just calls triggers the lazy to invoke this
// first _Value method.
var cachedValueName = DefinitionCacheKeyForMethod(methodName!);
var privateMethodName = PrivateMethodNameFor(methodName!);

var func = expressionConverter.ConvertTopLevelFunctionDefinition(indentLevel, overload, privateMethodName, "private");
writer.Write(func);
writer.WriteLine();
writer.WriteLine(indentLevel, $"[CqlDeclaration(\"{cqlName}\")]");
WriteTags(writer, indentLevel, tags);

Expand All @@ -447,20 +321,14 @@ private void WriteMemoizedInstanceMethod(string libraryName, TextWriter writer,
}
}

var lazyType = typeof(Lazy<>).MakeGenericType(visitedBody.Type);
var valueFunc =
Expression.Lambda(
Expression.MakeMemberAccess(
Expression.Parameter(lazyType, cachedValueName),
lazyType.GetMember("Value").Single()));

writer.Write(expressionConverter.ConvertTopLevelFunctionDefinition(indentLevel, valueFunc, methodName!, "public"));
var func = expressionConverter.ConvertTopLevelFunctionDefinition(indentLevel, overload, methodName!, "public static");
writer.Write(func);
}
else
{
writer.WriteLine(indentLevel, $"[CqlDeclaration(\"{cqlName}\")]");
WriteTags(writer, indentLevel, tags);
writer.Write(expressionConverter.ConvertTopLevelFunctionDefinition(indentLevel, overload, methodName!, "public"));
writer.Write(expressionConverter.ConvertTopLevelFunctionDefinition(indentLevel, overload, methodName!, "public static"));
// writer.WriteLine();
}
}
Expand Down
19 changes: 11 additions & 8 deletions Cql/CodeGeneration.NET/ExpressionConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,11 @@ private string convertDefinitionCallExpression(int indent, string leadingIndentS
{
var sb = new StringBuilder();
sb.Append(leadingIndentString);

var target = dce.LibraryName == LibraryName ? "this" :
VariableNameGenerator.NormalizeIdentifier(dce.LibraryName);

var target = VariableNameGenerator.NormalizeIdentifier(dce.LibraryName);
var csFunctionName = VariableNameGenerator.NormalizeIdentifier(dce.DefinitionName);

sb.Append(CultureInfo.InvariantCulture, $"{target}.{csFunctionName}()");
sb.Append(CultureInfo.InvariantCulture, $"{target}.{csFunctionName}(context)");

return sb.ToString();
}
Expand All @@ -80,12 +79,11 @@ private string convertFunctionCallExpression(int indent, string leadingIndentStr
var sb = new StringBuilder();
sb.Append(leadingIndentString);

var target = fce.LibraryName == LibraryName ? "this" :
VariableNameGenerator.NormalizeIdentifier(fce.LibraryName);
var target = VariableNameGenerator.NormalizeIdentifier(fce.LibraryName);
var csFunctionName = VariableNameGenerator.NormalizeIdentifier(fce.FunctionName);

sb.Append(CultureInfo.InvariantCulture, $"{target}.{csFunctionName}");
sb.Append(convertArguments(indent, fce.Arguments.Skip(1))); // skip cqlContext
sb.Append(convertArguments(indent, fce.Arguments));

return sb.ToString();
}
Expand Down Expand Up @@ -417,7 +415,12 @@ private string convertLambdaExpression(int indent, string leadingIndentString, L
var lambdaSb = new StringBuilder();
lambdaSb.Append(leadingIndentString);

var lambdaParameters = $"({string.Join(", ", lambda.Parameters.Select(p => $"{PrettyTypeName(p.Type)} {escapeKeywords(p.Name!)}"))})";
var parameters = lambda.Parameters.Select(p => $"{PrettyTypeName(p.Type)} {escapeKeywords(p.Name!)}").ToList();
// inserts the context parameter in the start of the lambda expression
if (indent == 1)
parameters.Insert(0, "CqlContext context");

var lambdaParameters = $"({string.Join(", ", parameters)})";
lambdaSb.Append(lambdaParameters);

if (lambda.Body is BlockExpression)
Expand Down

0 comments on commit adb1552

Please sign in to comment.