diff --git a/Datra.Generators/DataContextSourceGenerator.cs b/Datra.Generators/DataContextSourceGenerator.cs index 1498871..0c9be18 100644 --- a/Datra.Generators/DataContextSourceGenerator.cs +++ b/Datra.Generators/DataContextSourceGenerator.cs @@ -127,6 +127,10 @@ public void Execute(GeneratorExecutionContext context) bool enableDebugLogging = false; bool emitPhysicalFiles = false; string physicalFilesPath = null; + bool emitYamlSerializers = GetBoolBuildProperty( + context, + "DatraEmitYamlSerializers", + defaultValue: true); // Read optional named arguments foreach (var arg in configAttr.NamedArguments) @@ -177,7 +181,7 @@ public void Execute(GeneratorExecutionContext context) GeneratorLogger.AddDebugOutput(context); return; } - GeneratorLogger.Log($"Found DatraConfigurationAttribute: ContextName={contextName}, Namespace={generatedNamespace}, EnableLocalization={enableLocalization}, LocalizationKeyDataPath={localizationKeysPath}, LocalizationDataPath={localizationDataPath}, DefaultLanguage={defaultLanguage}, EnableDebugLogging={enableDebugLogging}, EmitPhysicalFiles={emitPhysicalFiles}, PhysicalFilesPath={physicalFilesPath}"); + GeneratorLogger.Log($"Found DatraConfigurationAttribute: ContextName={contextName}, Namespace={generatedNamespace}, EnableLocalization={enableLocalization}, LocalizationKeyDataPath={localizationKeysPath}, LocalizationDataPath={localizationDataPath}, DefaultLanguage={defaultLanguage}, EnableDebugLogging={enableDebugLogging}, EmitPhysicalFiles={emitPhysicalFiles}, PhysicalFilesPath={physicalFilesPath}, EmitYamlSerializers={emitYamlSerializers}"); // Filter out localization models var filteredModels = dataModels @@ -203,7 +207,7 @@ public void Execute(GeneratorExecutionContext context) GeneratorLogger.Log($"Generated {contextName}.g.cs"); // Generate DataModel files - var dataModelGenerator = new DataModelGenerator(context); + var dataModelGenerator = new DataModelGenerator(emitYamlSerializers); foreach (var model in dataModels) { var dataModelCode = dataModelGenerator.GenerateDataModelFile(model); @@ -249,6 +253,30 @@ public void Execute(GeneratorExecutionContext context) } } + /// + /// Read a bool MSBuild property exposed to analyzers as + /// build_property.PropertyName. + /// + private static bool GetBoolBuildProperty( + GeneratorExecutionContext context, + string propertyName, + bool defaultValue) + { + if (!context.AnalyzerConfigOptions.GlobalOptions.TryGetValue( + $"build_property.{propertyName}", + out var value)) + { + return defaultValue; + } + + if (bool.TryParse(value, out var parsed)) + { + return parsed; + } + + return defaultValue; + } + /// /// Emit a physical file for the DataContext to the project directory /// @@ -434,4 +462,4 @@ private static string SanitizeNamespace(string input) return string.IsNullOrEmpty(result) ? "Generated" : result; } } -} \ No newline at end of file +} diff --git a/Datra.Generators/Generators/DataModelGenerator.cs b/Datra.Generators/Generators/DataModelGenerator.cs index 6f47ee2..64a8a32 100644 --- a/Datra.Generators/Generators/DataModelGenerator.cs +++ b/Datra.Generators/Generators/DataModelGenerator.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; using Datra.Generators.Builders; using Datra.Generators.Models; @@ -10,11 +8,11 @@ namespace Datra.Generators.Generators { internal class DataModelGenerator { - private readonly GeneratorExecutionContext _context; + private readonly bool _emitYamlSerializers; - public DataModelGenerator(GeneratorExecutionContext context) + public DataModelGenerator(bool emitYamlSerializers = true) { - _context = context; + _emitYamlSerializers = emitYamlSerializers; } private static bool IsPrimitiveType(string typeName) @@ -253,7 +251,7 @@ private void GenerateTableSerializerMethods(CodeBuilder codeBuilder, DataModelIn // Generate YAML-specific methods without serializer parameter var isYamlFormat = CodeBuilder.IsYamlFormat(model.Format, model.FilePath); - if (isYamlFormat) + if (isYamlFormat && _emitYamlSerializers) { codeBuilder.AddBlankLine(); @@ -298,7 +296,7 @@ private void GenerateSingleSerializerMethods(CodeBuilder codeBuilder, DataModelI var jsonBuilder = new JsonSerializerBuilder(); jsonBuilder.GenerateSingleDeserializer(codeBuilder, model, simpleTypeName); break; - case "Yaml": + case "Yaml" when _emitYamlSerializers: var yamlBuilder = new YamlSerializerBuilder(); yamlBuilder.GenerateSingleDeserializer(codeBuilder, model, simpleTypeName); break; @@ -319,7 +317,7 @@ private void GenerateSingleSerializerMethods(CodeBuilder codeBuilder, DataModelI var jsonBuilder2 = new JsonSerializerBuilder(); jsonBuilder2.GenerateSingleSerializer(codeBuilder, model, simpleTypeName); break; - case "Yaml": + case "Yaml" when _emitYamlSerializers: var yamlBuilder2 = new YamlSerializerBuilder(); yamlBuilder2.GenerateSingleSerializer(codeBuilder, model, simpleTypeName); break; @@ -332,7 +330,7 @@ private void GenerateSingleSerializerMethods(CodeBuilder codeBuilder, DataModelI // Generate YAML-specific methods without serializer parameter var isYamlFormat = CodeBuilder.IsYamlFormat(model.Format, model.FilePath); - if (isYamlFormat) + if (isYamlFormat && _emitYamlSerializers) { codeBuilder.AddBlankLine(); @@ -352,4 +350,4 @@ private void GenerateSingleSerializerMethods(CodeBuilder codeBuilder, DataModelI } } } -} \ No newline at end of file +} diff --git a/Datra.Tests/DataModelGeneratorTests.cs b/Datra.Tests/DataModelGeneratorTests.cs new file mode 100644 index 0000000..c231333 --- /dev/null +++ b/Datra.Tests/DataModelGeneratorTests.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using Datra.Generators.Generators; +using Datra.Generators.Models; +using Xunit; + +namespace Datra.Tests +{ + public class DataModelGeneratorTests + { + [Fact] + public void GenerateDataModelFile_YamlTable_EmitsYamlHelpersByDefault() + { + var generator = new DataModelGenerator(); + + var code = generator.GenerateDataModelFile(CreateYamlTableModel()); + + Assert.Contains("DeserializeYaml", code); + Assert.Contains("SerializeYaml", code); + Assert.Contains("YamlDotNet", code); + } + + [Fact] + public void GenerateDataModelFile_YamlTable_CanSkipYamlHelpers() + { + var generator = new DataModelGenerator(emitYamlSerializers: false); + + var code = generator.GenerateDataModelFile(CreateYamlTableModel()); + + Assert.Contains("serializer.DeserializeTable(data);", code); + Assert.Contains("serializer.SerializeTable(table);", code); + Assert.DoesNotContain("DeserializeYaml", code); + Assert.DoesNotContain("SerializeYaml", code); + Assert.DoesNotContain("YamlDotNet", code); + } + + [Fact] + public void GenerateDataModelFile_YamlSingle_CanSkipDirectYamlDeserializer() + { + var generator = new DataModelGenerator(emitYamlSerializers: false); + + var code = generator.GenerateDataModelFile(CreateYamlSingleModel()); + + Assert.Contains("serializer.DeserializeSingle(data);", code); + Assert.Contains("serializer.SerializeSingle(data);", code); + Assert.DoesNotContain("DeserializeYaml", code); + Assert.DoesNotContain("SerializeYaml", code); + Assert.DoesNotContain("YamlDotNet", code); + } + + private static DataModelInfo CreateYamlTableModel() + { + return new DataModelInfo + { + TypeName = "Game.Data.MonsterData", + PropertyName = "Monsters", + IsTableData = true, + KeyType = "int", + Format = "Yaml", + FilePath = "monsters.yaml", + Properties = new List + { + new PropertyInfo { Name = "Id", Type = "int" }, + new PropertyInfo { Name = "Name", Type = "string" } + } + }; + } + + private static DataModelInfo CreateYamlSingleModel() + { + return new DataModelInfo + { + TypeName = "Game.Data.GameSettings", + PropertyName = "Settings", + IsTableData = false, + Format = "Yaml", + FilePath = "settings.yaml", + Properties = new List + { + new PropertyInfo { Name = "DisplayName", Type = "string" } + } + }; + } + } +}