diff --git a/.gitignore b/.gitignore index 639feac6c..fa58a5919 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ codecover_merged.info # User-specific files .idea/ appsettings.Development.json +appsettings.development.json **/core @@ -62,4 +63,9 @@ appsettings.Development.json # remove HA integration test files from git tests/Integration/HA/config/* -!tests/Integration/HA/config/*.yaml \ No newline at end of file +!tests/Integration/HA/config/*.yaml + +# remove codegenerated files +HomeAssistantGenerated.cs +EntityMetaData.json +ServicesMetaData.json diff --git a/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/ExtensionMethodsGenerator.cs b/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/ExtensionMethodsGenerator.cs index 9c00449fc..a4e9af7a6 100644 --- a/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/ExtensionMethodsGenerator.cs +++ b/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/ExtensionMethodsGenerator.cs @@ -85,9 +85,9 @@ private static IEnumerable GenerateExtensionMethodsForS private static MemberDeclarationSyntax ExtensionMethodWithoutArguments(HassService service, string serviceName, string entityTypeName) { return ParseMemberDeclaration($$""" - public static void {{GetServiceMethodName(serviceName)}}(this {{entityTypeName}} target) + public static void {{GetServiceMethodName(serviceName)}}(this {{entityTypeName}} target, object? data = null) { - target.CallService("{{serviceName}}"); + target.CallService("{{serviceName}}", data); } """)! .WithSummaryComment(service.Description); diff --git a/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/Generator.cs b/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/Generator.cs index aada7a154..a422a0d06 100644 --- a/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/Generator.cs +++ b/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/Generator.cs @@ -53,7 +53,7 @@ private static SyntaxTrivia[] GetFileHeader() // In the template projects we provided a convenience powershell script that will update // the codegen and nugets to latest versions update_all_dependencies.ps1. // - // For more information: https://netdaemon.xyz/docs/v3/hass_model/hass_model_codegen + // For more information: https://netdaemon.xyz/docs/user/hass_model/hass_model_codegen // For more information about NetDaemon: https://netdaemon.xyz/ // //------------------------------------------------------------------------------"; diff --git a/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/ServicesGenerator.cs b/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/ServicesGenerator.cs index e0bb5cee4..73a75002a 100644 --- a/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/ServicesGenerator.cs +++ b/src/HassModel/NetDaemon.HassModel.CodeGenerator/CodeGeneration/ServicesGenerator.cs @@ -99,9 +99,9 @@ private static IEnumerable GenerateServiceMethod(string { // method without arguments yield return ParseMemberDeclaration($$""" - void {{serviceMethodName}}({{targetParam}}) + void {{serviceMethodName}}({{CommaSeparateNonEmpty(targetParam, "object? data = null")}}) { - {{haContextVariableName}}.CallService("{{domain}}", "{{serviceName}}", {{targetArg}}); + {{haContextVariableName}}.CallService("{{domain}}", "{{serviceName}}", {{CommaSeparateNonEmpty(targetArg, "data")}}); } """)! .ToPublic() @@ -112,7 +112,7 @@ private static IEnumerable GenerateServiceMethod(string { // method using arguments object yield return ParseMemberDeclaration($$""" - void {{serviceMethodName}}({{JoinList(targetParam, serviceArguments.TypeName)}} data) + void {{serviceMethodName}}({{CommaSeparateNonEmpty(targetParam, serviceArguments.TypeName)}} data) { {{haContextVariableName}}.CallService("{{domain}}", "{{serviceName}}", {{targetArg}}, data); } @@ -123,7 +123,7 @@ private static IEnumerable GenerateServiceMethod(string // method using arguments as separate parameters yield return ParseMemberDeclaration($$""" - void {{serviceMethodName}}({{JoinList(targetParam, serviceArguments.GetParametersList())}}) + void {{serviceMethodName}}({{CommaSeparateNonEmpty(targetParam, serviceArguments.GetParametersList())}}) { {{haContextVariableName}}.CallService("{{domain}}", "{{serviceName}}", {{targetArg}}, {{serviceArguments.GetNewServiceArgumentsTypeExpression()}}); } @@ -135,5 +135,5 @@ private static IEnumerable GenerateServiceMethod(string } } - private static string JoinList(params string?[] args) => string.Join(", ", args.Where(s => !string.IsNullOrEmpty(s))); + private static string CommaSeparateNonEmpty(params string?[] args) => string.Join(", ", args.Where(s => !string.IsNullOrEmpty(s))); } diff --git a/src/HassModel/NetDaemon.HassModel.Tests/CodeGenerator/ServicesGeneratorTest.cs b/src/HassModel/NetDaemon.HassModel.Tests/CodeGenerator/ServicesGeneratorTest.cs index 3daa35de8..75b8fa5c4 100644 --- a/src/HassModel/NetDaemon.HassModel.Tests/CodeGenerator/ServicesGeneratorTest.cs +++ b/src/HassModel/NetDaemon.HassModel.Tests/CodeGenerator/ServicesGeneratorTest.cs @@ -82,6 +82,67 @@ public void Run(IHaContext ha) CodeGenTestHelper.AssertCodeCompiles(code.ToString(), appCode); } + [Fact] + public void TestServicesGenerationWithAndWithoutProvidingDataForServicesWithoutTargetOrFields() + { + var readOnlyCollection = new HassState[] { + new() { EntityId = "script.script1" }, + }; + + var hassServiceDomains = new HassServiceDomain[] { + new() { + Domain = "script", + Services = [ + new() { + Service = "turn_off", + Target = new TargetSelector + { + Entity = [new EntitySelector { Domain = ["script"] }] + } + + }, + new() { + Service = "reload", + }, + ] + } + }; + + // Act: + var code = CodeGenTestHelper.GenerateCompilationUnit(_settings, readOnlyCollection, hassServiceDomains); + + var appCode = """ + using NetDaemon.HassModel; + using NetDaemon.HassModel.Entities; + using RootNameSpace; + + public class Root + { + public void Run(IHaContext ha) + { + var s = new RootNameSpace.Services(ha); + + s.Script.TurnOff(new ServiceTarget()); + s.Script.TurnOff(new ServiceTarget(), new { }); + + s.Script.Reload(); + s.Script.Reload(new { }); + + ScriptEntity script = new RootNameSpace.ScriptEntity(ha, "script.testScript"); + + script.TurnOff(new { }); + script.TurnOff(); + + IScriptEntityCore scriptCore = script; + scriptCore.TurnOff(); + scriptCore.TurnOff(new { }); + } + } + """; + + CodeGenTestHelper.AssertCodeCompiles(code.ToString(), appCode); + } + [Fact] public void TestServiceWithoutAnyTargetEntity_ExtensionMethodSkipped() {