diff --git a/src/ApiCodeGenerator.AsyncApi/Amqp/CSharp/CSharpAmqpServiceGeneratorSettings.cs b/src/ApiCodeGenerator.AsyncApi/Amqp/CSharp/CSharpAmqpServiceGeneratorSettings.cs index b16e120..ef8dc42 100644 --- a/src/ApiCodeGenerator.AsyncApi/Amqp/CSharp/CSharpAmqpServiceGeneratorSettings.cs +++ b/src/ApiCodeGenerator.AsyncApi/Amqp/CSharp/CSharpAmqpServiceGeneratorSettings.cs @@ -11,7 +11,7 @@ public CSharpAmqpServiceGeneratorSettings() CodeGeneratorSettings, [ new EmbededResourceTemplateProvider(GetType().Assembly, $"{asmName}.TemplatesAmqp"), - .. DefaultTemplateFactory.CreateProviders(CodeGeneratorSettings, + .. DefaultTemplateFactory.CreateProviders( [ typeof(CSharpClientGeneratorSettings).Assembly, typeof(NJsonSchema.CodeGeneration.CSharp.CSharpGenerator).Assembly diff --git a/src/ApiCodeGenerator.OpenApi/CSharpClientContentGenerator.cs b/src/ApiCodeGenerator.OpenApi/CSharpClientContentGenerator.cs index 5004d88..9861841 100644 --- a/src/ApiCodeGenerator.OpenApi/CSharpClientContentGenerator.cs +++ b/src/ApiCodeGenerator.OpenApi/CSharpClientContentGenerator.cs @@ -8,13 +8,5 @@ namespace ApiCodeGenerator.OpenApi internal sealed class CSharpClientContentGenerator : ContentGeneratorBase { - public override string Generate() - { - Generator.Settings.CodeGeneratorSettings.TemplateFactory = - new DefaultTemplateFactory( - Generator.Settings.CodeGeneratorSettings, - [typeof(CSharpClientGenerator).Assembly, typeof(NJsonSchema.CodeGeneration.CSharp.CSharpGenerator).Assembly]); - return base.Generate(); - } } } diff --git a/src/ApiCodeGenerator.OpenApi/CSharpClientGeneratorSettings.cs b/src/ApiCodeGenerator.OpenApi/CSharpClientGeneratorSettings.cs new file mode 100644 index 0000000..d9a386a --- /dev/null +++ b/src/ApiCodeGenerator.OpenApi/CSharpClientGeneratorSettings.cs @@ -0,0 +1,14 @@ +namespace ApiCodeGenerator.OpenApi; + +public class CSharpClientGeneratorSettings : NSwag.CodeGeneration.CSharp.CSharpClientGeneratorSettings +{ + public CSharpClientGeneratorSettings() + : base() + { + CSharpGeneratorSettings.TemplateFactory = new DefaultTemplateFactory( + CSharpGeneratorSettings, + [ + typeof(NSwag.CodeGeneration.CSharp.CSharpClientGenerator).Assembly, + typeof(NJsonSchema.CodeGeneration.CSharp.CSharpGenerator).Assembly]); + } +} diff --git a/src/ApiCodeGenerator.OpenApi/CSharpControllerContentGenerator.cs b/src/ApiCodeGenerator.OpenApi/CSharpControllerContentGenerator.cs index a866a35..7755a09 100644 --- a/src/ApiCodeGenerator.OpenApi/CSharpControllerContentGenerator.cs +++ b/src/ApiCodeGenerator.OpenApi/CSharpControllerContentGenerator.cs @@ -8,13 +8,5 @@ namespace ApiCodeGenerator.OpenApi internal sealed class CSharpControllerContentGenerator : ContentGeneratorBase { - public override string Generate() - { - Generator.Settings.CodeGeneratorSettings.TemplateFactory = - new DefaultTemplateFactory( - Generator.Settings.CodeGeneratorSettings, - [typeof(CSharpClientGenerator).Assembly, typeof(NJsonSchema.CodeGeneration.CSharp.CSharpGenerator).Assembly]); - return base.Generate(); - } } } diff --git a/src/ApiCodeGenerator.OpenApi/CSharpControllerGeneratorSettings.cs b/src/ApiCodeGenerator.OpenApi/CSharpControllerGeneratorSettings.cs new file mode 100644 index 0000000..ad3b539 --- /dev/null +++ b/src/ApiCodeGenerator.OpenApi/CSharpControllerGeneratorSettings.cs @@ -0,0 +1,15 @@ +namespace ApiCodeGenerator.OpenApi; + +public class CSharpControllerGeneratorSettings : NSwag.CodeGeneration.CSharp.CSharpControllerGeneratorSettings +{ + public CSharpControllerGeneratorSettings() + : base() + { + CSharpGeneratorSettings.TemplateFactory = new DefaultTemplateFactory( + CodeGeneratorSettings, + [ + typeof(NSwag.CodeGeneration.CSharp.CSharpClientGenerator).Assembly, + typeof(NJsonSchema.CodeGeneration.CSharp.CSharpGenerator).Assembly + ]); + } +} diff --git a/src/ApiCodeGenerator.OpenApi/DefaultTemplateFactory.cs b/src/ApiCodeGenerator.OpenApi/DefaultTemplateFactory.cs index 095203c..0782b26 100644 --- a/src/ApiCodeGenerator.OpenApi/DefaultTemplateFactory.cs +++ b/src/ApiCodeGenerator.OpenApi/DefaultTemplateFactory.cs @@ -22,38 +22,33 @@ namespace ApiCodeGenerator.OpenApi; public partial class DefaultTemplateFactory : ITemplateFactory { private const string BASE_TMPL_SUFFIX = ".base"; - + private readonly CodeGeneratorSettingsBase _settings; private readonly ITemplateProvider[] _providers; private readonly InternalTemplateFactory _internalTemplateFactory; public DefaultTemplateFactory(CodeGeneratorSettingsBase settings, params Assembly[] assemblies) - : this(settings, CreateProviders(settings, assemblies).ToArray()) + : this(settings, CreateProviders(assemblies).ToArray()) { } public DefaultTemplateFactory(CodeGeneratorSettingsBase settings, ITemplateProvider[] providers) { + _settings = settings; _providers = providers; _internalTemplateFactory = new(settings, GetLiquidTemplate, GetToolchainVersion); } + [Obsolete("Use CreateProviders(Assembly[] assemblies)")] public static IEnumerable CreateProviders(CodeGeneratorSettingsBase settings, Assembly[] assemblies) - { - if (!string.IsNullOrEmpty(settings.TemplateDirectory)) - { - yield return new DirectoryTemplateProvider(settings.TemplateDirectory!); - } + => CreateProviders(assemblies); - foreach (var assembly in assemblies) - { - yield return new EmbededResourceTemplateProvider(assembly, $"{assembly.GetName().Name}.Templates"); - } - } + public static IEnumerable CreateProviders(Assembly[] assemblies) + => assemblies.Select(a => new EmbededResourceTemplateProvider(a, $"{a.GetName().Name}.Templates")); public ITemplate CreateTemplate(string language, string template, object model) { - IEnumerable providers = _providers; + IEnumerable providers = GetProviders(); if (template.EndsWith(BASE_TMPL_SUFFIX)) { if (model is Fluid.TemplateContext templateContext) @@ -78,13 +73,24 @@ public ITemplate CreateTemplate(string language, string template, object model) private string GetLiquidTemplate(string language, string name) { - var text = _providers + var text = GetProviders() .Select(p => p.GetTemplateText(name.TrimEnd('!'), language)) .FirstOrDefault(t => t is not null); return text ?? string.Empty; } + private IEnumerable GetProviders() + { + var providers = _providers.AsEnumerable(); + if (!string.IsNullOrEmpty(_settings.TemplateDirectory)) + { + providers = providers.Prepend(new DirectoryTemplateProvider(_settings.TemplateDirectory!)); + } + + return providers; + } + private sealed class InternalTemplateFactory #if ASYNC_API : NJsonSchema.CodeGeneration.DefaultTemplateFactory diff --git a/test/ApiCodeGenerator.AsyncApi.Tests/ApiCodeGenerator.AsyncApi.Tests.csproj b/test/ApiCodeGenerator.AsyncApi.Tests/ApiCodeGenerator.AsyncApi.Tests.csproj index 98da215..90fd997 100644 --- a/test/ApiCodeGenerator.AsyncApi.Tests/ApiCodeGenerator.AsyncApi.Tests.csproj +++ b/test/ApiCodeGenerator.AsyncApi.Tests/ApiCodeGenerator.AsyncApi.Tests.csproj @@ -15,6 +15,9 @@ Always + + Always + diff --git a/test/ApiCodeGenerator.AsyncApi.Tests/FunctionalTests.cs b/test/ApiCodeGenerator.AsyncApi.Tests/FunctionalTests.cs index 4b34a70..2820364 100644 --- a/test/ApiCodeGenerator.AsyncApi.Tests/FunctionalTests.cs +++ b/test/ApiCodeGenerator.AsyncApi.Tests/FunctionalTests.cs @@ -169,6 +169,23 @@ public async Task GenerateMultipleClients() Assert.AreEqual(expected, actual); } + [TestCaseSource(nameof(TemplateDirectorySource))] + public void TemplateDirectory(T settings) + where T : CSharpGeneratorBaseSettings + { + settings.CodeGeneratorSettings.TemplateDirectory = "Templates"; + var template = settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate("CSharp", "File", new()); + var actual = template.Render(); + + Assert.That(actual, Is.EqualTo("overrided")); + } + + [SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:Static elements should appear before instance elements", Justification = "After tests")] + public static IEnumerable TemplateDirectorySource() + { + yield return new TestCaseData(new CSharpClientGeneratorSettings()).SetName($"{nameof(TemplateDirectory)}_Client"); + } + private static string[] GetExpectedOperationsCode(string[]? bodyLines) => [ TestHelpers.GetExpectedSummary("Inform about environmental lighting conditions of a particular streetlight.", 4 + 4) + GetExpectedPublisherCode("ReceiveLightMeasurement", "LightMeasuredPayload", 4 + 4, bodyLines), diff --git a/test/ApiCodeGenerator.AsyncApi.Tests/Templates/File.liquid b/test/ApiCodeGenerator.AsyncApi.Tests/Templates/File.liquid new file mode 100644 index 0000000..f61967f --- /dev/null +++ b/test/ApiCodeGenerator.AsyncApi.Tests/Templates/File.liquid @@ -0,0 +1 @@ +overrided diff --git a/test/ApiCodeGenerator.OpenApi.Tests/ApiCodeGenerator.OpenApi.Tests.csproj b/test/ApiCodeGenerator.OpenApi.Tests/ApiCodeGenerator.OpenApi.Tests.csproj index b3a9da6..7a5033c 100644 --- a/test/ApiCodeGenerator.OpenApi.Tests/ApiCodeGenerator.OpenApi.Tests.csproj +++ b/test/ApiCodeGenerator.OpenApi.Tests/ApiCodeGenerator.OpenApi.Tests.csproj @@ -16,6 +16,9 @@ Always + + Always + diff --git a/test/ApiCodeGenerator.OpenApi.Tests/DefaultTemplateFactoryTests.cs b/test/ApiCodeGenerator.OpenApi.Tests/DefaultTemplateFactoryTests.cs index 9acf6e6..af2c52a 100644 --- a/test/ApiCodeGenerator.OpenApi.Tests/DefaultTemplateFactoryTests.cs +++ b/test/ApiCodeGenerator.OpenApi.Tests/DefaultTemplateFactoryTests.cs @@ -39,6 +39,20 @@ public void CallBase() Assert.AreEqual("template1\ntemplate2\ntemplate3", actual); } + [Test] + public void TemplateDir() + { + var settings = new NJsonSchema.CodeGeneration.CSharp.CSharpGeneratorSettings(); + var src1 = new TestTemplateProvider("template1\n{% template Class.base %}"); + var factory = new DefaultTemplateFactory(settings, [src1]); + settings.TemplateFactory = factory; + settings.TemplateDirectory = "Templates"; + + var actual = factory.CreateTemplate("CSharp", "File", new object()).Render(); + + Assert.AreEqual("overrided", actual); + } + private class TestTemplateProvider : ITemplateProvider { private readonly string _providerKey = Guid.NewGuid().ToString(); diff --git a/test/ApiCodeGenerator.OpenApi.Tests/FunctionalTests.cs b/test/ApiCodeGenerator.OpenApi.Tests/FunctionalTests.cs index 5020cd3..78058bc 100644 --- a/test/ApiCodeGenerator.OpenApi.Tests/FunctionalTests.cs +++ b/test/ApiCodeGenerator.OpenApi.Tests/FunctionalTests.cs @@ -129,7 +129,18 @@ public async Task GenerateClientInterface_SingleClientFromLastSegmentOfOperation Assert.That(actual, Does.Contain(expectedClientDeclartion)); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:Static elements should appear before instance elements", Justification = "After tests")] + [TestCaseSource(nameof(TemplateDirectorySource))] + public void TemplateDirectory(T settings) + where T : CSharpGeneratorBaseSettings + { + settings.CodeGeneratorSettings.TemplateDirectory = "Templates"; + var template = settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate("CSharp", "File", new()); + var actual = template.Render(); + + Assert.That(actual, Is.EqualTo("overrided")); + } + + [SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1204:Static elements should appear before instance elements", Justification = "After tests")] public static IEnumerable TestCaseSource() { const string schemaName = "ReplaceChars.json"; @@ -196,6 +207,12 @@ public static IEnumerable TestCaseSource() .SetName($"{{m}}(\"{replaceParmas}\")"); } + public static IEnumerable TemplateDirectorySource() + { + yield return new TestCaseData(new CSharpClientGeneratorSettings()).SetName($"{nameof(TemplateDirectory)}_Client"); + yield return new TestCaseData(new CSharpControllerGeneratorSettings()).SetName($"{nameof(TemplateDirectory)}_Controller"); + } + private static GenerationTask CreateGenerator(Mock fileProviderMock, string settingsJson, string schema) { var settings = JObject.Parse(settingsJson); diff --git a/test/ApiCodeGenerator.OpenApi.Tests/Templates/File.liquid b/test/ApiCodeGenerator.OpenApi.Tests/Templates/File.liquid new file mode 100644 index 0000000..f61967f --- /dev/null +++ b/test/ApiCodeGenerator.OpenApi.Tests/Templates/File.liquid @@ -0,0 +1 @@ +overrided