Enums runtime code generation done.

This commit is contained in:
Samuele Lorefice
2023-12-24 04:19:26 +01:00
parent d6f2362e9d
commit 6ded9230d4
3 changed files with 53 additions and 25 deletions

View File

@@ -6,6 +6,7 @@ namespace ComfySharp;
[DataContract, JsonSerializable(typeof(ConversionSettings))] [DataContract, JsonSerializable(typeof(ConversionSettings))]
public class ConversionSettings { public class ConversionSettings {
[DataMember(IsRequired = true)] public string CodeOutputFolderName = @"AutoGenerated";
[DataMember(IsRequired = true)] public List<string> BlacklistedNodes = new(); [DataMember(IsRequired = true)] public List<string> BlacklistedNodes = new();
[DataMember(IsRequired = true)] public List<string> EnumConvertAsString = new(); [DataMember(IsRequired = true)] public List<string> EnumConvertAsString = new();
[DataMember(IsRequired = true)] public List<string> EnumConvertAsBool = new(); [DataMember(IsRequired = true)] public List<string> EnumConvertAsBool = new();

View File

@@ -12,6 +12,7 @@ namespace ComfySharp;
public class NodeDBGenerator { public class NodeDBGenerator {
readonly private List<ExpandoObject> nodes; readonly private List<ExpandoObject> nodes;
#region Conversion
readonly private ConversionSettings settings; readonly private ConversionSettings settings;
readonly private List<string> knownTypes = new(); readonly private List<string> knownTypes = new();
@@ -27,6 +28,14 @@ public class NodeDBGenerator {
private int typeFields; private int typeFields;
private int enumFields; private int enumFields;
private int stringListFields; private int stringListFields;
#endregion
#region CodeGeneration
readonly private CSharpCodeProvider codeProvider = new();
readonly private CodeCompileUnit compileUnit = new();
readonly private CodeNamespace codeNamespace = new("ComfySharp.Types.Generated");
readonly private List<CodeTypeDeclaration> codeTypes = new();
#endregion
public NodeDBGenerator(ConversionSettings settings) { public NodeDBGenerator(ConversionSettings settings) {
nodes = new(); nodes = new();
@@ -124,32 +133,49 @@ public class NodeDBGenerator {
Logger.Info($"Total amount of stringLists detected\\iterated:\t {knownStringLists.Count}\t\\{knownStringLists.Count}"); Logger.Info($"Total amount of stringLists detected\\iterated:\t {knownStringLists.Count}\t\\{knownStringLists.Count}");
Logger.Info("NodeDB Scan phase 2: generating types"); Logger.Info("NodeDB Scan phase 2: generating types");
IndentedTextWriter provider = new(new StringWriter()); timer.Restart();
CSharpCodeProvider codeProvider = new(); Logger.Info("Enum Generation starting...");
CodeCompileUnit compileUnit = new(); CodeNamespace enumNs = new("ComfySharp.Types.Generated.Enums");
CodeNamespace ns = new("ComfySharp.Types.Generated"); compileUnit.Namespaces.Add(enumNs);
ns.Imports.AddRange(new CodeNamespaceImport[] { new ("System"), new ("System.Collections.Generics"), new ("ComfySharp") });
compileUnit.Namespaces.Add(ns);
foreach (var knownEnum in knownEnums) { foreach (var knownEnum in knownEnums) {
GenerateEnum(knownEnum.Key, knownEnum.Value, enumNs);
}
GenerateEnum("BaseTypes", knownTypes, enumNs);//TODO: make a proper method that handles the edge cases, like * and comma separated multi instances
Logger.Info($"Enum Generation finished. Took {timer.ElapsedMilliseconds} ms");
timer.Restart();
//compileUnit.Namespaces.Add(codeNamespace);
//ns.Imports.AddRange(new CodeNamespaceImport[] { new ("System"), new ("System.Collections.Generics"), new ("ComfySharp") });
}
private void GenerateEnum(string name, List<string> enumValues, CodeNamespace ns) {
string path = Path.Combine(Environment.CurrentDirectory, settings.CodeOutputFolderName, $"{name}.cs");
Logger.Debug($"Generating enum {name} w\\ {enumValues.Count} values.\n" +
$"\t\tPath: {path}");
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
IndentedTextWriter writer = new(File.CreateText(path));
CodeTypeDeclaration enumType = new() { CodeTypeDeclaration enumType = new() {
Name = knownEnum.Key, Name = name,
IsEnum = true, IsEnum = true,
IsPartial = false, IsPartial = false,
Attributes = MemberAttributes.Public Attributes = MemberAttributes.Public
}; };
foreach (var value in knownEnum.Value) {
enumType.Members.Add(new CodeMemberField(knownEnum.Key, value)); foreach (var value in enumValues)
} enumType.Members.Add(new CodeMemberField(name, value));
ns.Types.Add(enumType);
codeProvider.GenerateCodeFromCompileUnit(compileUnit, provider, new() { ns.Types.Add(enumType); //add the enum to the namespace
//generate the code
codeProvider.GenerateCodeFromCompileUnit(compileUnit, writer, new() {
BlankLinesBetweenMembers = false, BlankLinesBetweenMembers = false,
BracingStyle = "Block", BracingStyle = "Block",
VerbatimOrder = true, VerbatimOrder = true,
ElseOnClosing = false, ElseOnClosing = false,
IndentString = "\t" IndentString = "\t"
}); });
var enumcode = provider.InnerWriter.ToString(); ns.Types.Remove(enumType);//remove the enum from the namespace, so it doesn't get generated twice
} codeTypes.Add(enumType);//add the enum to the list of types, so we can generate the nodes later
writer.InnerWriter.Flush();//flush the writer
writer.Close();//close the writer and release the file lock
} }
/// <summary> /// <summary>

View File

@@ -1,4 +1,5 @@
{ {
"CodeOutputPath": "CodeOutputFolderName",
"BlacklistedNodes" : [ "BlacklistedNodes" : [
"CheckpointLoader|pysssss", "CheckpointLoader|pysssss",
"LoraLoader|pysssss", "LoraLoader|pysssss",