diff --git a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs index c0e64a49a..40aeee233 100644 --- a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs +++ b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs @@ -143,26 +143,24 @@ private static string GetMethodBody(IEnumerable functions, b { var sb = new StringBuilder(); sb.Append( - $$""" + $""" var inputBindingFeature = context.Features.Get(); var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); var inputArguments = inputBindingResult.Values; - {{(anyDefaultExecutor ? $" _defaultExecutor = new Lazy(() => CreateDefaultExecutorInstance(context));{Environment.NewLine}" : string.Empty)}} + {(anyDefaultExecutor ? $" _defaultExecutor = new Lazy(() => CreateDefaultExecutorInstance(context));{Environment.NewLine}" : string.Empty)} """); - bool first = true; - foreach (ExecutableFunction function in functions) { var fast = function.Visibility == FunctionMethodVisibility.Public; sb.Append($$""" - {{(first ? string.Empty : "else ")}}if (string.Equals(context.FunctionDefinition.EntryPoint, "{{function.EntryPoint}}", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, "{{function.EntryPoint}}", StringComparison.Ordinal)) { {{(fast ? EmitFastPath(function) : EmitSlowPath())}} + return; } """); - first = false; } return sb.ToString(); @@ -171,51 +169,53 @@ private static string GetMethodBody(IEnumerable functions, b private static string EmitFastPath(ExecutableFunction function) { var sb = new StringBuilder(); - int functionParamCounter = 0; - var functionParamList = new List(); - foreach (var argumentTypeName in function.ParameterTypeNames) - { - functionParamList.Add($"({argumentTypeName})inputArguments[{functionParamCounter++}]"); - } - var methodParamsStr = string.Join(", ", functionParamList); - + if (!function.IsStatic) { - sb.Append($$""" - var instanceType = types["{{function.ParentFunctionClassName}}"]; - var i = _functionActivator.CreateInstance(instanceType, context) as {{function.ParentFunctionFullyQualifiedClassName}}; - """); + sb.Append($""" + var instanceType = types["{function.ParentFunctionClassName}"]; + var i = _functionActivator.CreateInstance(instanceType, context) as {function.ParentFunctionFullyQualifiedClassName}; + """); } - if (!function.IsStatic) - { - sb.Append(@" - "); - } - else - { - sb.Append(" "); - } + sb.Append(!function.IsStatic + ? """ + + + """ + : " "); if (function.IsReturnValueAssignable) { sb.Append("context.GetInvocationResult().Value = "); } + if (function.ShouldAwait) { sb.Append("await "); } + // Parameters + int functionParamCounter = 0; + var functionParamList = new List(); + + foreach (var argumentTypeName in function.ParameterTypeNames) + { + functionParamList.Add($"({argumentTypeName})inputArguments[{functionParamCounter++}]"); + } + + var methodParamsStr = string.Join(", ", functionParamList); + sb.Append(function.IsStatic ? $"{function.ParentFunctionFullyQualifiedClassName}.{function.MethodName}({methodParamsStr});" : $"i.{function.MethodName}({methodParamsStr});"); + return sb.ToString(); } private static string EmitSlowPath() { - return - " await _defaultExecutor.Value.ExecuteAsync(context);"; + return " await _defaultExecutor.Value.ExecuteAsync(context);"; } } } diff --git a/sdk/Sdk.Generators/Sdk.Generators.csproj b/sdk/Sdk.Generators/Sdk.Generators.csproj index fc001592e..d073479c5 100644 --- a/sdk/Sdk.Generators/Sdk.Generators.csproj +++ b/sdk/Sdk.Generators/Sdk.Generators.csproj @@ -10,7 +10,7 @@ false true 3 - 2 + 3 true diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 3927acaf3..1cc232248 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -2,7 +2,7 @@ 18 - 0 + 1 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk This package provides development time support for the Azure Functions .NET Worker. diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 8b2c498cc..3bf81d081 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,14 +4,12 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk 1.18.0 +### Microsoft.Azure.Functions.Worker.Sdk 1.18.1 -- Fix incorrect function version in build message (#2606) -- Fix inner build failures when central package management is enabled (#2689) -- Add support to publish a Function App (Flex Consumption) with `ZipDeploy` (#2712) - - Add `'UseBlobContainerDeploy'` property to identify when to use `OneDeploy` publish API endpoint (`"/api/publish"`) - - Enhance `ZipDeploy` deployment status logging by appending the `'status_message'` (when defined) to the output messages +- Updated `Microsoft.Azure.Functions.Worker.Sdk.Generators` reference to 1.3.3. -### Microsoft.Azure.Functions.Worker.Sdk.Generators +### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.3 + +- Changed `FunctionExecutorGenerator` to avoid generation of long `if`/`else` chains for apps with a large number of functions. - diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs index ed925683d..7d60c7e3c 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs @@ -101,38 +101,52 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction var instanceType = types["MyCompany.MyHttpTriggers"]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Foo((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + goto end; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.DependencyFunction.Run", StringComparison.Ordinal)) + + if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.DependencyFunction.Run", StringComparison.Ordinal)) { var instanceType = types["DependentAssemblyWithFunctions.DependencyFunction"]; var i = _functionActivator.CreateInstance(instanceType, context) as global::DependentAssemblyWithFunctions.DependencyFunction; context.GetInvocationResult().Value = i.Run((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + goto end; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.InternalFunction.Run", StringComparison.Ordinal)) + + if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.InternalFunction.Run", StringComparison.Ordinal)) { await _defaultExecutor.Value.ExecuteAsync(context); + goto end; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.StaticFunction.Run", StringComparison.Ordinal)) + + if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.StaticFunction.Run", StringComparison.Ordinal)) { context.GetInvocationResult().Value = global::DependentAssemblyWithFunctions.StaticFunction.Run((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + goto end; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "MyCompany.MyProduct.MyApp.HttpFunctions.Run", StringComparison.Ordinal)) + + if (string.Equals(context.FunctionDefinition.EntryPoint, "MyCompany.MyProduct.MyApp.HttpFunctions.Run", StringComparison.Ordinal)) { var instanceType = types["MyCompany.MyProduct.MyApp.HttpFunctions"]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyProduct.MyApp.HttpFunctions; context.GetInvocationResult().Value = i.Run((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + goto end; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "MyCompany.MyProduct.MyApp.Foo.Bar.Run", StringComparison.Ordinal)) + + if (string.Equals(context.FunctionDefinition.EntryPoint, "MyCompany.MyProduct.MyApp.Foo.Bar.Run", StringComparison.Ordinal)) { var instanceType = types["MyCompany.MyProduct.MyApp.Foo.Bar"]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyProduct.MyApp.Foo.Bar; context.GetInvocationResult().Value = i.Run((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + goto end; } + + end: + return; } private global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor CreateDefaultExecutorInstance(global::Microsoft.Azure.Functions.Worker.FunctionContext context) { - var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=1.18.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; + var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=1.19.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; var defaultExecutorType = global::System.Type.GetType(defaultExecutorFullName); return ActivatorUtilities.CreateInstance(context.InstanceServices, defaultExecutorType) as global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor; diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs index b9d5dcf50..a94d51fa4 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs @@ -144,28 +144,33 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Foo((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers2.Bar"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers2.Bar"", StringComparison.Ordinal)) {{ var instanceType = types[""MyCompany.MyHttpTriggers2""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers2; context.GetInvocationResult().Value = i.Bar((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.Foo.MyAsyncStaticMethod"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.Foo.MyAsyncStaticMethod"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = await global::MyCompany.Foo.MyAsyncStaticMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.QueueTriggers.Run"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.QueueTriggers.Run"", StringComparison.Ordinal)) {{ var instanceType = types[""MyCompany.QueueTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.QueueTriggers; i.Run((global::Azure.Storage.Queues.Models.QueueMessage)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.QueueTriggers.Run2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.QueueTriggers.Run2"", StringComparison.Ordinal)) {{ var instanceType = types[""MyCompany.QueueTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.QueueTriggers; i.Run2((string)inputArguments[0]); + return; }} }} }} @@ -259,12 +264,14 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Run1((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers.Run2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers.Run2"", StringComparison.Ordinal)) {{ var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Run2((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} }} }} @@ -400,46 +407,57 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyTaskStaticMethod"", StringComparison.Ordinal)) {{ await global::FunctionApp26.MyQTriggers.MyTaskStaticMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyAsyncStaticMethod"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyAsyncStaticMethod"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = await global::FunctionApp26.MyQTriggers.MyAsyncStaticMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyVoidStaticMethod"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyVoidStaticMethod"", StringComparison.Ordinal)) {{ global::FunctionApp26.MyQTriggers.MyVoidStaticMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyAsyncStaticMethodWithReturn"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyAsyncStaticMethodWithReturn"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = await global::FunctionApp26.MyQTriggers.MyAsyncStaticMethodWithReturn((string)inputArguments[0], (string)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyValueTaskOfTStaticAsyncMethod"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyValueTaskOfTStaticAsyncMethod"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = await global::FunctionApp26.MyQTriggers.MyValueTaskOfTStaticAsyncMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyValueTaskStaticAsyncMethod2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyValueTaskStaticAsyncMethod2"", StringComparison.Ordinal)) {{ await global::FunctionApp26.MyQTriggers.MyValueTaskStaticAsyncMethod2((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.BlobTriggers.Run"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.BlobTriggers.Run"", StringComparison.Ordinal)) {{ await global::FunctionApp26.BlobTriggers.Run((global::System.IO.Stream)inputArguments[0], (string)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.Run1"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.Run1"", StringComparison.Ordinal)) {{ global::FunctionApp26.EventHubTriggers.Run1((global::Azure.Messaging.EventHubs.EventData[])inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.Run2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.Run2"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = global::FunctionApp26.EventHubTriggers.Run2((global::Azure.Messaging.EventHubs.EventData)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.RunAsync1"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.RunAsync1"", StringComparison.Ordinal)) {{ await global::FunctionApp26.EventHubTriggers.RunAsync1((global::Azure.Messaging.EventHubs.EventData[])inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.RunAsync2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.RunAsync2"", StringComparison.Ordinal)) {{ await global::FunctionApp26.EventHubTriggers.RunAsync2((global::Azure.Messaging.EventHubs.EventData[])inputArguments[0]); + return; }} }} }} @@ -527,6 +545,7 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Run1((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + return; }} }} }} @@ -620,10 +639,12 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction var instanceType = types[""TestProject.TestProject""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::TestProject.TestProject; context.GetInvocationResult().Value = i.Foo((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""TestProject.TestProject.FooStatic"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""TestProject.TestProject.FooStatic"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = global::TestProject.TestProject.FooStatic((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} }} }} @@ -711,10 +732,12 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Hello((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers.HELLO"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers.HELLO"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = global::MyCompany.MyHttpTriggers.HELLO((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} }} }}