From 5c3927ce248232cdfaf652e3c94d9eb252d343dc Mon Sep 17 00:00:00 2001 From: jamesuk Date: Mon, 21 Aug 2023 18:46:37 +0100 Subject: [PATCH 01/27] #1571 Add annotations support for executable assemblies --- Libraries/Libraries.sln | 7 + ....Lambda.Annotations.SourceGenerator.csproj | 9 + .../Generator.cs | 15 +- .../Models/GeneratedMethodModelBuilder.cs | 3 +- .../Models/LambdaFunctionModel.cs | 5 + .../Models/LambdaFunctionModelBuilder.cs | 5 +- .../SyntaxReceiver.cs | 8 + .../Templates/ExecutableAssembly.cs | 541 ++++++++++++++++++ .../Templates/ExecutableAssembly.tt | 69 +++ .../Templates/ExecutableAssemblyCode.cs | 18 + .../Templates/FieldsAndConstructor.cs | 102 +++- .../Templates/FieldsAndConstructor.tt | 17 +- .../Templates/LambdaFunctionTemplate.cs | 77 ++- .../Templates/LambdaFunctionTemplate.tt | 5 +- .../LambdaOutputExecutableAttribute.cs | 13 + ....Annotations.SourceGenerators.Tests.csproj | 25 + ...nctions_AsyncStartupToUpper_Generated.g.cs | 56 ++ .../Functions_ToUpper_Generated.g.cs | 1 + .../Greeter_SayHelloAsync_Generated.g.cs | 25 +- .../Snapshots/Greeter_SayHello_Generated.g.cs | 25 +- .../Snapshots/Program.g.cs | 17 + .../Snapshots/ProgramMultiHandler.g.cs | 28 + .../SourceGeneratorTests.cs | 113 ++++ .../AssemblyAttributes.cs | 3 + .../ComplexQueryParameter.cs.error | 24 + .../CustomizeResponseExamples.cs | 70 +++ .../CustomizeResponseWithErrors.cs.error | 23 + .../TestExecutableServerlessApp/Dockerfile | 13 + .../DynamicExample.cs | 23 + .../TestExecutableServerlessApp/Greeter.cs | 47 ++ .../IntrinsicExample.cs | 14 + .../InvalidParameterAttributeNames.cs.error | 33 ++ .../MissingResourePathMapping.cs.error | 22 + .../NullableReferenceTypeExample.cs | 16 + .../PlaceholderClass.cs | 9 + .../Services/SimpleCalculatorService.cs | 42 ++ .../TestExecutableServerlessApp/Startup.cs | 20 + .../Sub1/Functions.cs | 14 + .../TaskExample.cs | 16 + .../test/TestExecutableServerlessApp/Temp.cs | 20 + .../TestExecutableServerlessApp.csproj | 31 + .../VoidExample.cs | 14 + .../aws-lambda-tools-defaults.json | 19 + .../serverless.template | 452 +++++++++++++++ .../TestServerlessApp/serverless.template | 20 + 45 files changed, 2043 insertions(+), 86 deletions(-) create mode 100644 Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs create mode 100644 Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt create mode 100644 Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssemblyCode.cs create mode 100644 Libraries/src/Amazon.Lambda.Annotations/LambdaOutputExecutableAttribute.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/ComplexQueryParameter.cs.error create mode 100644 Libraries/test/TestExecutableServerlessApp/CustomizeResponseExamples.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/CustomizeResponseWithErrors.cs.error create mode 100644 Libraries/test/TestExecutableServerlessApp/Dockerfile create mode 100644 Libraries/test/TestExecutableServerlessApp/DynamicExample.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/Greeter.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/IntrinsicExample.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/InvalidParameterAttributeNames.cs.error create mode 100644 Libraries/test/TestExecutableServerlessApp/MissingResourePathMapping.cs.error create mode 100644 Libraries/test/TestExecutableServerlessApp/NullableReferenceTypeExample.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/PlaceholderClass.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/Services/SimpleCalculatorService.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/Startup.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/TaskExample.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/Temp.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/TestExecutableServerlessApp.csproj create mode 100644 Libraries/test/TestExecutableServerlessApp/VoidExample.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/aws-lambda-tools-defaults.json create mode 100644 Libraries/test/TestExecutableServerlessApp/serverless.template diff --git a/Libraries/Libraries.sln b/Libraries/Libraries.sln index 80dcb552b..9879cb964 100644 --- a/Libraries/Libraries.sln +++ b/Libraries/Libraries.sln @@ -130,6 +130,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amazon.Lambda.LexV2Events", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomRuntimeAspNetCoreMinimalApiCustomSerializerTest", "test\Amazon.Lambda.RuntimeSupport.Tests\CustomRuntimeAspNetCoreMinimalApiCustomSerializerTest\CustomRuntimeAspNetCoreMinimalApiCustomSerializerTest.csproj", "{0BD83939-458C-4EF5-8663-7098AD1200F2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestExecutableServerlessApp", "test\TestExecutableServerlessApp\TestExecutableServerlessApp.csproj", "{DD378063-C54A-44C7-9A6F-32A6A1AE94B3}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution test\EventsTests.Shared\EventsTests.Shared.projitems*{44e9d925-b61d-4234-97b7-61424c963ba6}*SharedItemsImports = 5 @@ -353,6 +355,10 @@ Global {0BD83939-458C-4EF5-8663-7098AD1200F2}.Debug|Any CPU.Build.0 = Debug|Any CPU {0BD83939-458C-4EF5-8663-7098AD1200F2}.Release|Any CPU.ActiveCfg = Release|Any CPU {0BD83939-458C-4EF5-8663-7098AD1200F2}.Release|Any CPU.Build.0 = Release|Any CPU + {DD378063-C54A-44C7-9A6F-32A6A1AE94B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD378063-C54A-44C7-9A6F-32A6A1AE94B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD378063-C54A-44C7-9A6F-32A6A1AE94B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD378063-C54A-44C7-9A6F-32A6A1AE94B3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -415,6 +421,7 @@ Global {BF85932E-2DFF-41CD-8090-A672468B8FBB} = {AAB54E74-20B1-42ED-BC3D-CE9F7BC7FD12} {3C6AABF5-0372-41E0-874F-DF18ECCC7FB6} = {AAB54E74-20B1-42ED-BC3D-CE9F7BC7FD12} {0BD83939-458C-4EF5-8663-7098AD1200F2} = {B5BD0336-7D08-492C-8489-42C987E29B39} + {DD378063-C54A-44C7-9A6F-32A6A1AE94B3} = {1DE4EE60-45BA-4EF7-BE00-B9EB861E4C69} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {503678A4-B8D1-4486-8915-405A3E9CF0EB} diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Amazon.Lambda.Annotations.SourceGenerator.csproj b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Amazon.Lambda.Annotations.SourceGenerator.csproj index 0d8cf7798..1d306ad94 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Amazon.Lambda.Annotations.SourceGenerator.csproj +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Amazon.Lambda.Annotations.SourceGenerator.csproj @@ -56,6 +56,10 @@ TextTemplatingFilePreprocessor NoEventMethodBody.cs + + TextTemplatingFilePreprocessor + ExecutableAssembly.cs + @@ -84,6 +88,11 @@ True NoEventMethodBody.tt + + True + True + ExecutableAssembly.tt + diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs index 394eb2e37..6130d319b 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs @@ -15,6 +15,8 @@ namespace Amazon.Lambda.Annotations.SourceGenerator { + using System.Collections.Generic; + [Generator] public class Generator : ISourceGenerator { @@ -87,6 +89,9 @@ public void Execute(GeneratorExecutionContext context) var templateHandler = new CloudFormationTemplateHandler(_fileManager, _directoryManager); bool foundFatalError = false; + + var lambdaModels = new List(); + foreach (var lambdaMethod in receiver.LambdaMethods) { var lambdaMethodModel = semanticModelProvider.GetMethodSemanticModel(lambdaMethod); @@ -116,7 +121,7 @@ public void Execute(GeneratorExecutionContext context) } } - var model = LambdaFunctionModelBuilder.Build(lambdaMethodModel, configureMethodModel, context); + var model = LambdaFunctionModelBuilder.Build(lambdaMethodModel, configureMethodModel, context, receiver.IsExecutable); // If there are more than one event, report them as errors if (model.LambdaMethod.Events.Count > 1) @@ -175,9 +180,17 @@ public void Execute(GeneratorExecutionContext context) // report every generated file to build output diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.CodeGeneration, Location.None, $"{model.GeneratedMethod.ContainingType.Name}.g.cs", sourceText)); + lambdaModels.Add(model); annotationReport.LambdaFunctions.Add(model); } + if (receiver.IsExecutable) + { + var executableAssembly = new ExecutableAssembly(lambdaModels, lambdaModels[0].LambdaMethod.ContainingNamespace); + + context.AddSource("Program.g.cs", SourceText.From(executableAssembly.TransformText(), Encoding.UTF8, SourceHashAlgorithm.Sha256)); + } + // Run the CloudFormation sync if any LambdaMethods exists. Also run if no LambdaMethods exists but there is a // CloudFormation template in case orphaned functions in the template need to be removed. // Both checks are required because if there is no template but there are LambdaMethods the CF template the template will be created. diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/GeneratedMethodModelBuilder.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/GeneratedMethodModelBuilder.cs index 30efcadbf..35ba2fb0b 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/GeneratedMethodModelBuilder.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/GeneratedMethodModelBuilder.cs @@ -37,7 +37,8 @@ private static IList BuildUsings(LambdaMethodModel lambdaMethodModel, "System", "System.Linq", "System.Collections.Generic", - "System.Text" + "System.Text", + "System.Threading.Tasks" }; if (configureMethodSymbol != null) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs index f1dbd088e..3379140eb 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs @@ -30,6 +30,11 @@ public class LambdaFunctionModel : ILambdaFunctionSerializable /// Gets or sets fully qualified name of the serializer used for serialization or deserialization. /// public string Serializer { get; set; } + + /// + /// Gets or sets if the output is an executable. + /// + public bool IsExecutable { get; set; } /// public string Handler => $"{LambdaMethod.ContainingAssembly}::{GeneratedMethod.ContainingType.FullName}::{LambdaMethod.Name}"; diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs index b95fa34bc..5190ab159 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs @@ -8,7 +8,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Models /// public static class LambdaFunctionModelBuilder { - public static LambdaFunctionModel Build(IMethodSymbol lambdaMethodSymbol, IMethodSymbol configureMethodSymbol, GeneratorExecutionContext context) + public static LambdaFunctionModel Build(IMethodSymbol lambdaMethodSymbol, IMethodSymbol configureMethodSymbol, GeneratorExecutionContext context, bool isExecutable) { var lambdaMethod = LambdaMethodModelBuilder.Build(lambdaMethodSymbol, configureMethodSymbol, context); var generatedMethod = GeneratedMethodModelBuilder.Build(lambdaMethodSymbol, configureMethodSymbol, lambdaMethod, context); @@ -20,7 +20,8 @@ public static LambdaFunctionModel Build(IMethodSymbol lambdaMethodSymbol, IMetho StartupType = configureMethodSymbol != null ? TypeModelBuilder.Build(configureMethodSymbol.ContainingType, context) : null, SourceGeneratorVersion = context.Compilation .ReferencedAssemblyNames.FirstOrDefault(x => string.Equals(x.Name, "Amazon.Lambda.Annotations")) - ?.Version.ToString() + ?.Version.ToString(), + IsExecutable = isExecutable }; return model; diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs index 8e2802316..0631c139d 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs @@ -12,6 +12,8 @@ internal class SyntaxReceiver : ISyntaxContextReceiver public List LambdaMethods { get; } = new List(); public List StartupClasses { get; private set; } = new List(); + + public bool IsExecutable { get; set; } /// /// Path to the directory containing the .csproj file @@ -66,6 +68,12 @@ public void OnVisitSyntaxNode(GeneratorSyntaxContext context) { StartupClasses.Add(classDeclarationSyntax); } + + // If at least one class is annotated with the LambdaOutputExecutable annotations then set IsExecutable to be true. + if (methodSymbol.GetAttributes().Any(attr => attr.AttributeClass.Name == nameof(LambdaOutputExecutableAttribute))) + { + IsExecutable = true; + } } } } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs new file mode 100644 index 000000000..39cc577bf --- /dev/null +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs @@ -0,0 +1,541 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 16.0.0.0 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +namespace Amazon.Lambda.Annotations.SourceGenerator.Templates +{ + using System.Linq; + using System.Text; + using System.Collections.Generic; + using System.Threading.Tasks; + using Amazon.Lambda.Annotations.SourceGenerator.Extensions; + using Amazon.Lambda.Annotations.SourceGenerator.Validation; + using Amazon.Lambda.Annotations.SourceGenerator.Models; + using Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes; + using System; + + /// + /// Class to produce the template output + /// + + #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public partial class ExecutableAssembly : ExecutableAssemblyBase + { +#line hidden + /// + /// Create the template output + /// + public virtual string TransformText() + { + this.Write("using System;\r\nusing System.Linq;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\nusing Amazon.Lambda.Core;\r\n\r\nnamespace "); + + #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(this._containingNamespace)); + + #line default + #line hidden + this.Write(";\r\n\r\npublic class Program\r\n{\r\n private static async Task Main(string[] args)\r\n {\r\n"); + + #line 24 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + + if (this._lambdaFunctions.Count == 1) + { + + + #line default + #line hidden + this.Write(" Func<"); + + #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", this._lambdaFunctions[0].GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); + + #line default + #line hidden + this.Write(", "); + + #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].GeneratedMethod.ReturnType.FullName)); + + #line default + #line hidden + this.Write("> "); + + #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name.ToLower())); + + #line default + #line hidden + this.Write(" = "); + + #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.ContainingType.Name)); + + #line default + #line hidden + this.Write("_"); + + #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name)); + + #line default + #line hidden + this.Write("_Generated."); + + #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name)); + + #line default + #line hidden + this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + + #line 29 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name.ToLower())); + + #line default + #line hidden + this.Write(", new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync();\r\n"); + + #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + + } + else + { + + + #line default + #line hidden + this.Write("\r\n switch (Environment.GetEnvironmentVariable(\"HANDLER\"))\r\n {\r\n"); + + #line 38 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + + foreach (var model in this._lambdaFunctions) + { + + + #line default + #line hidden + this.Write(" case \""); + + #line 42 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); + + #line default + #line hidden + this.Write("\":\r\n"); + + #line 43 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + + if (model.GeneratedMethod.ReturnType.FullName == "void") + { + + + #line default + #line hidden + this.Write(" Action<"); + + #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); + + #line default + #line hidden + this.Write("> "); + + #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); + + #line default + #line hidden + this.Write(" = "); + + #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); + + #line default + #line hidden + this.Write("_"); + + #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); + + #line default + #line hidden + this.Write("_Generated."); + + #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); + + #line default + #line hidden + this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + + #line 48 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); + + #line default + #line hidden + this.Write(", new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync();\r\n break;\r\n"); + + #line 50 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" Func<"); + + #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); + + #line default + #line hidden + this.Write(", "); + + #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.ReturnType.FullName)); + + #line default + #line hidden + this.Write("> "); + + #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); + + #line default + #line hidden + this.Write(" = "); + + #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); + + #line default + #line hidden + this.Write("_"); + + #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); + + #line default + #line hidden + this.Write("_Generated."); + + #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); + + #line default + #line hidden + this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + + #line 56 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); + + #line default + #line hidden + this.Write(", new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync();\r\n break;\r\n"); + + #line 58 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + + } + } + + + #line default + #line hidden + this.Write("\r\n }\r\n"); + + #line 64 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + + + } + + + #line default + #line hidden + this.Write(" }\r\n}"); + return this.GenerationEnvironment.ToString(); + } + } + + #line default + #line hidden + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] + public class ExecutableAssemblyBase + { + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + protected System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); + } + return this.generationEnvironmentField; + } + set + { + this.generationEnvironmentField = value; + } + } + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + } + return this.errorsField; + } + } + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); + } + return this.indentLengthsField; + } + } + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; + } + } + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; + } + } + #endregion + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } + } + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); + this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; + } + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); + } + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; + } + } + } + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { + throw new global::System.ArgumentNullException("objectToConvert"); + } + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); + } + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); + } + } + } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion + } + #endregion +} diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt new file mode 100644 index 000000000..97f8a8364 --- /dev/null +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt @@ -0,0 +1,69 @@ +<#@ template language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="System.Threading.Tasks" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Extensions" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Validation" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes" #> +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Amazon.Lambda.Core; + +namespace <#= this._containingNamespace #>; + +public class Program +{ + private static async Task Main(string[] args) + { +<# + if (this._lambdaFunctions.Count == 1) + { +#> + Func<<#= string.Join(", ", this._lambdaFunctions[0].GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= this._lambdaFunctions[0].GeneratedMethod.ReturnType.FullName #>> <#=this._lambdaFunctions[0].LambdaMethod.Name.ToLower()#> = <#=this._lambdaFunctions[0].LambdaMethod.ContainingType.Name#>_<#=this._lambdaFunctions[0].LambdaMethod.Name#>_Generated.<#=this._lambdaFunctions[0].LambdaMethod.Name#>; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#=this._lambdaFunctions[0].LambdaMethod.Name.ToLower()#>, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); +<# + } + else + { + #> + + switch (Environment.GetEnvironmentVariable("HANDLER")) + { +<# + foreach (var model in this._lambdaFunctions) + { + #> + case "<#=model.LambdaMethod.Name#>": +<# + if (model.GeneratedMethod.ReturnType.FullName == "void") + { +#> + Action<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>> <#= model.LambdaMethod.Name.ToLower() #> = <#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated.<#= model.LambdaMethod.Name #>; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + break; +<# + } + else + { +#> + Func<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= model.GeneratedMethod.ReturnType.FullName #>> <#= model.LambdaMethod.Name.ToLower() #> = <#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated.<#= model.LambdaMethod.Name #>; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + break; +<# + } + } + #> + + } +<# + + } +#> + } +} \ No newline at end of file diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssemblyCode.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssemblyCode.cs new file mode 100644 index 000000000..4a2ef9a7f --- /dev/null +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssemblyCode.cs @@ -0,0 +1,18 @@ +namespace Amazon.Lambda.Annotations.SourceGenerator.Templates +{ + using System.Collections.Generic; + + using Amazon.Lambda.Annotations.SourceGenerator.Models; + + public partial class ExecutableAssembly + { + private List _lambdaFunctions; + private string _containingNamespace; + + public ExecutableAssembly(List lambdaFunctions, string containingNamespace) + { + this._lambdaFunctions = lambdaFunctions; + this._containingNamespace = containingNamespace; + } + } +} \ No newline at end of file diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs index b8d394cdb..2b530b268 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs @@ -1,7 +1,7 @@ // ------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version: 17.0.0.0 +// Runtime Version: 16.0.0.0 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -19,8 +19,8 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates /// Class to produce the template output /// - #line 1 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public partial class FieldsAndConstructor : FieldsAndConstructorBase { #line hidden @@ -30,7 +30,7 @@ public partial class FieldsAndConstructor : FieldsAndConstructorBase public virtual string TransformText() { - #line 7 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 7 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" if (_model.LambdaMethod.UsingDependencyInjection) { @@ -38,9 +38,16 @@ public virtual string TransformText() #line default #line hidden - this.Write(" private readonly ServiceProvider serviceProvider;\r\n"); + this.Write(" private "); - #line 12 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 11 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); + + #line default + #line hidden + this.Write("readonly ServiceProvider serviceProvider;\r\n"); + + #line 12 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } else @@ -49,68 +56,107 @@ public virtual string TransformText() #line default #line hidden - this.Write(" private readonly "); + this.Write(" private "); + + #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); + + #line default + #line hidden + this.Write("readonly "); - #line 17 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write(" "); - #line 17 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name.ToCamelCase())); #line default #line hidden this.Write(";\r\n"); - #line 18 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } #line default #line hidden - this.Write("\r\n public "); + this.Write("\r\n"); - #line 22 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 22 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + + if (_model.IsExecutable) + { + + + #line default + #line hidden + this.Write(" static "); + + #line 26 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.ContainingType.Name)); #line default #line hidden - this.Write("()\r\n {\r\n SetExecutionEnvironment();\r\n"); + this.Write("() \r\n"); - #line 25 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 27 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - if (_model.LambdaMethod.UsingDependencyInjection) + } + else { #line default #line hidden - this.Write(@" var services = new ServiceCollection(); + this.Write(" public "); + + #line 32 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.ContainingType.Name)); + + #line default + #line hidden + this.Write("()\r\n"); + + #line 33 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + + } + + + #line default + #line hidden + this.Write(" {\r\n SetExecutionEnvironment();\r\n"); + + #line 38 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - // By default, Lambda function class is added to the service container using the singleton lifetime - // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. - services.AddSingleton<"); + if (_model.LambdaMethod.UsingDependencyInjection) + { + + + #line default + #line hidden + this.Write(" var services = new ServiceCollection();\r\n\r\n // By default, Lambda function class is added to the service container using the singleton lifetime\r\n // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method.\r\n services.AddSingleton<"); - #line 33 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 46 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write(">();\r\n\r\n var startup = new "); - #line 35 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 48 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.StartupType.FullName)); #line default #line hidden - this.Write("();\r\n startup.ConfigureServices(services);\r\n serviceProvide" + - "r = services.BuildServiceProvider();\r\n"); + this.Write("();\r\n startup.ConfigureServices(services);\r\n serviceProvider = services.BuildServiceProvider();\r\n"); - #line 38 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 51 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } else @@ -121,21 +167,21 @@ public virtual string TransformText() #line hidden this.Write(" "); - #line 43 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 56 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name.ToCamelCase())); #line default #line hidden this.Write(" = new "); - #line 43 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 56 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("();\r\n"); - #line 44 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 57 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } @@ -153,7 +199,7 @@ public virtual string TransformText() /// /// Base class for this transformation /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public class FieldsAndConstructorBase { #region Fields diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt index 63c59da09..6afb7d31c 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt @@ -8,18 +8,31 @@ if (_model.LambdaMethod.UsingDependencyInjection) { #> - private readonly ServiceProvider serviceProvider; + private <#= _model.IsExecutable ? "static " : "" #>readonly ServiceProvider serviceProvider; <# } else { #> - private readonly <#= _model.LambdaMethod.ContainingType.Name #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>; + private <#= _model.IsExecutable ? "static " : "" #>readonly <#= _model.LambdaMethod.ContainingType.Name #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>; <# } #> +<# + if (_model.IsExecutable) + { +#> + static <#= _model.GeneratedMethod.ContainingType.Name #>() +<# + } + else + { +#> public <#= _model.GeneratedMethod.ContainingType.Name #>() +<# + } +#> { SetExecutionEnvironment(); <# diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs index 26fe0b02f..ad108aa98 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -1,7 +1,7 @@ // ------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version: 17.0.0.0 +// Runtime Version: 16.0.0.0 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -10,6 +10,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates { using System.Linq; + using System.Threading.Tasks; using System.Text; using System.Collections.Generic; using Amazon.Lambda.Annotations.SourceGenerator.Models; @@ -23,8 +24,8 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates /// Class to produce the template output /// - #line 1 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public partial class LambdaFunctionTemplate : LambdaFunctionTemplateBase { #line hidden @@ -34,7 +35,7 @@ public partial class LambdaFunctionTemplate : LambdaFunctionTemplateBase public virtual string TransformText() { - #line 11 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 12 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" foreach (var ns in _model.GeneratedMethod.Usings) { @@ -44,14 +45,14 @@ public virtual string TransformText() #line hidden this.Write("using "); - #line 15 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 16 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(ns)); #line default #line hidden this.Write(";\r\n"); - #line 16 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } @@ -60,21 +61,28 @@ public virtual string TransformText() #line hidden this.Write("\r\nnamespace "); - #line 20 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 21 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingNamespace)); #line default #line hidden - this.Write("\r\n{\r\n public class "); + this.Write("\r\n{\r\n public "); - #line 22 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 23 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); + + #line default + #line hidden + this.Write("class "); + + #line 23 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.ContainingType.Name)); #line default #line hidden this.Write("\r\n {\r\n"); - #line 24 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 25 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(new FieldsAndConstructor(_model).TransformText()); @@ -83,34 +91,40 @@ public virtual string TransformText() #line hidden this.Write("\r\n\r\n public "); - #line 29 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); + + #line default + #line hidden + + #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsVoidOrGenericTask ? "async " : "")); #line default #line hidden - #line 29 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.ReturnType.FullName)); #line default #line hidden this.Write(" "); - #line 29 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.Name)); #line default #line hidden this.Write("("); - #line 29 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", _model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName} {p.Name}")))); #line default #line hidden this.Write(")\r\n {\r\n"); - #line 31 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 32 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" if (_model.LambdaMethod.UsingDependencyInjection) { @@ -118,25 +132,23 @@ public virtual string TransformText() #line default #line hidden - this.Write(" // Create a scope for every request,\r\n // this allows crea" + - "ting scoped dependencies without creating a scope manually.\r\n using v" + - "ar scope = serviceProvider.CreateScope();\r\n var "); + this.Write(" // Create a scope for every request,\r\n // this allows creating scoped dependencies without creating a scope manually.\r\n using var scope = serviceProvider.CreateScope();\r\n var "); - #line 38 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 39 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name.ToCamelCase())); #line default #line hidden this.Write(" = scope.ServiceProvider.GetRequiredService<"); - #line 39 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 40 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write(">();\r\n\r\n"); - #line 41 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 42 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } @@ -154,29 +166,14 @@ public virtual string TransformText() #line default #line hidden - this.Write(@" } - - private static void SetExecutionEnvironment() - { - const string envName = ""AWS_EXECUTION_ENV""; - - var envValue = new StringBuilder(); - - // If there is an existing execution environment variable add the annotations package as a suffix. - if(!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName))) - { - envValue.Append($""{Environment.GetEnvironmentVariable(envName)}_""); - } - - envValue.Append(""amazon-lambda-annotations_"); + this.Write(" }\r\n\r\n private static void SetExecutionEnvironment()\r\n {\r\n const string envName = \"AWS_EXECUTION_ENV\";\r\n\r\n var envValue = new StringBuilder();\r\n\r\n // If there is an existing execution environment variable add the annotations package as a suffix.\r\n if(!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName)))\r\n {\r\n envValue.Append($\"{Environment.GetEnvironmentVariable(envName)}_\");\r\n }\r\n\r\n envValue.Append(\"amazon-lambda-annotations_"); - #line 69 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 70 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.SourceGeneratorVersion)); #line default #line hidden - this.Write("\");\r\n\r\n Environment.SetEnvironmentVariable(envName, envValue.ToString(" + - "));\r\n }\r\n }\r\n}"); + this.Write("\");\r\n\r\n Environment.SetEnvironmentVariable(envName, envValue.ToString());\r\n }\r\n }\r\n}"); return this.GenerationEnvironment.ToString(); } } @@ -187,7 +184,7 @@ private static void SetExecutionEnvironment() /// /// Base class for this transformation /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public class LambdaFunctionTemplateBase { #region Fields diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt index b7f088440..a0b7d91cc 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt @@ -1,6 +1,7 @@ <#@ template language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> +<#@ import namespace="System.Threading.Tasks" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models" #> @@ -19,14 +20,14 @@ using <#= ns #>; namespace <#= _model.LambdaMethod.ContainingNamespace #> { - public class <#= _model.GeneratedMethod.ContainingType.Name #> + public <#= _model.IsExecutable ? "static " : "" #>class <#= _model.GeneratedMethod.ContainingType.Name #> { <# this.Write(new FieldsAndConstructor(_model).TransformText()); #> - public <#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? "async " : "" #><#= _model.GeneratedMethod.ReturnType.FullName #> <#= _model.LambdaMethod.Name #>(<#= string.Join(", ", _model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName} {p.Name}")) #>) + public <#= _model.IsExecutable ? "static " : "" #><#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? "async " : "" #><#= _model.GeneratedMethod.ReturnType.FullName #> <#= _model.LambdaMethod.Name #>(<#= string.Join(", ", _model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName} {p.Name}")) #>) { <# if (_model.LambdaMethod.UsingDependencyInjection) diff --git a/Libraries/src/Amazon.Lambda.Annotations/LambdaOutputExecutableAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/LambdaOutputExecutableAttribute.cs new file mode 100644 index 000000000..94c4ccc21 --- /dev/null +++ b/Libraries/src/Amazon.Lambda.Annotations/LambdaOutputExecutableAttribute.cs @@ -0,0 +1,13 @@ + +using System; + +namespace Amazon.Lambda.Annotations +{ + /// + /// Indicates this the Lambda function is going to target an executable instead of a class based handler. + /// + [AttributeUsage(AttributeTargets.Class)] + public class LambdaOutputExecutableAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj index adbe62620..016457546 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj @@ -33,13 +33,37 @@ + + TestExecutableServerlessApp\%(RecursiveDir)/%(FileName)%(Extension) + Always + + + + NonCompilableCodeFile.cs Always + + + PreserveNewest + + + + PreserveNewest + + + + Amazon.Lambda.RuntimeSupport\%(RecursiveDir)/%(FileName)%(Extension) + Always + + + + + Amazon.Lambda.Annotations\%(RecursiveDir)/%(FileName)%(Extension) @@ -88,6 +112,7 @@ about using newer versions of System.Runtime then it can handle. This is not an issue in a end user scenario. --> + diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs new file mode 100644 index 000000000..12fd5d264 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs @@ -0,0 +1,56 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Amazon.Lambda.Core; + +namespace TestServerlessApp.Sub1 +{ + public static class Functions_ToUpper_Generated + { + private static readonly ServiceProvider serviceProvider; + + static Functions_ToUpper_Generated() + { + SetExecutionEnvironment(); + var services = new ServiceCollection(); + + // By default, Lambda function class is added to the service container using the singleton lifetime + // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. + services.AddSingleton(); + + var startup = new TestServerlessApp.Startup(); + startup.ConfigureServices(services); + serviceProvider = services.BuildServiceProvider(); + } + + public static string ToUpper(string text) + { + // Create a scope for every request, + // this allows creating scoped dependencies without creating a scope manually. + using var scope = serviceProvider.CreateScope(); + var functions = scope.ServiceProvider.GetRequiredService(); + + return functions.ToUpper(text); + } + + private static void SetExecutionEnvironment() + { + const string envName = "AWS_EXECUTION_ENV"; + + var envValue = new StringBuilder(); + + // If there is an existing execution environment variable add the annotations package as a suffix. + if(!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName))) + { + envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); + } + + envValue.Append("amazon-lambda-annotations_1.0.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_ToUpper_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_ToUpper_Generated.g.cs index d3b4e667a..b975a4ec4 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_ToUpper_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_ToUpper_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Amazon.Lambda.Core; namespace TestServerlessApp.Sub1 diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs index a53eefca6..65ed30d1a 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs @@ -2,22 +2,37 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; namespace TestServerlessApp { - public class Greeter_SayHelloAsync_Generated + public static class Greeter_SayHelloAsync_Generated { - private readonly Greeter greeter; + private static readonly ServiceProvider serviceProvider; - public Greeter_SayHelloAsync_Generated() + static Greeter_SayHelloAsync_Generated() { SetExecutionEnvironment(); - greeter = new Greeter(); + var services = new ServiceCollection(); + + // By default, Lambda function class is added to the service container using the singleton lifetime + // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. + services.AddSingleton(); + + var startup = new TestServerlessApp.Startup(); + startup.ConfigureServices(services); + serviceProvider = services.BuildServiceProvider(); } - public async System.Threading.Tasks.Task SayHelloAsync(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + public static async System.Threading.Tasks.Task SayHelloAsync(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) { + // Create a scope for every request, + // this allows creating scoped dependencies without creating a scope manually. + using var scope = serviceProvider.CreateScope(); + var greeter = scope.ServiceProvider.GetRequiredService(); + var validationErrors = new List(); var firstNames = default(System.Collections.Generic.IEnumerable); diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs index 4b5ae2745..ba9245093 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs @@ -2,22 +2,37 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; namespace TestServerlessApp { - public class Greeter_SayHello_Generated + public static class Greeter_SayHello_Generated { - private readonly Greeter greeter; + private static readonly ServiceProvider serviceProvider; - public Greeter_SayHello_Generated() + static Greeter_SayHello_Generated() { SetExecutionEnvironment(); - greeter = new Greeter(); + var services = new ServiceCollection(); + + // By default, Lambda function class is added to the service container using the singleton lifetime + // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. + services.AddSingleton(); + + var startup = new TestServerlessApp.Startup(); + startup.ConfigureServices(services); + serviceProvider = services.BuildServiceProvider(); } - public Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse SayHello(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + public static Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse SayHello(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) { + // Create a scope for every request, + // this allows creating scoped dependencies without creating a scope manually. + using var scope = serviceProvider.CreateScope(); + var greeter = scope.ServiceProvider.GetRequiredService(); + var validationErrors = new List(); var firstNames = default(System.Collections.Generic.IEnumerable); diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs new file mode 100644 index 000000000..6735ed796 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs @@ -0,0 +1,17 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Amazon.Lambda.Core; + +namespace TestServerlessApp.Sub1; + +public class Program +{ + private static async Task Main(string[] args) + { + Func toupper = Functions_ToUpper_Generated.ToUpper; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(toupper, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs new file mode 100644 index 000000000..0c5c74020 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs @@ -0,0 +1,28 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Amazon.Lambda.Core; + +namespace TestServerlessApp; + +public class Program +{ + private static async Task Main(string[] args) + { + + switch (Environment.GetEnvironmentVariable("HANDLER")) + { + case "SayHello": + Func sayhello = Greeter_SayHello_Generated.SayHello; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(sayhello, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + break; + case "SayHelloAsync": + Func> sayhelloasync = Greeter_SayHelloAsync_Generated.SayHelloAsync; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(sayhelloasync, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + break; + + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index 47cd2cc8b..a0ecef599 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -260,6 +260,119 @@ public async Task VerifyFunctionInSubNamespace() Assert.Equal(expectedTemplateContent, actualTemplateContent); } + [Fact] + public async Task VerifyExecutableAssembly() + { + var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace.template")).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = File.ReadAllText(Path.Combine("Snapshots", "Functions_AsyncStartupToUpper_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedProgramGenerated = File.ReadAllText(Path.Combine("Snapshots", "Program.g.cs")).ToEnvironmentLineEndings(); + + var test = new VerifyCS.Test + { + TestState = + { + Sources = + { + (Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaOutputExecutableAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaOutputExecutableAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "Functions_ToUpper_Generated.g.cs", + SourceText.From(expectedSubNamespaceGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ), + ( + typeof(SourceGenerator.Generator), + "Program.g.cs", + SourceText.From(expectedProgramGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("Functions_ToUpper_Generated.g.cs", expectedSubNamespaceGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestExecutableServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent), + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }; + + foreach (var file in Directory.GetFiles( + Path.Combine("Amazon.Lambda.RuntimeSupport"), + "*.cs", SearchOption.AllDirectories)) + { + test.TestState.Sources.Add((file, File.ReadAllText(file))); + } + + await test.RunAsync(); + } + + [Fact] + public async Task VerifyExecutableAssemblyWithMultipleHandler() + { + var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "greeter.template")).ToEnvironmentLineEndings(); + var expectedSayHello = File.ReadAllText(Path.Combine("Snapshots", "Greeter_SayHello_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedSayHelloAsync = File.ReadAllText(Path.Combine("Snapshots", "Greeter_SayHelloAsync_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedProgramGenerated = File.ReadAllText(Path.Combine("Snapshots", "ProgramMultiHandler.g.cs")).ToEnvironmentLineEndings(); + + var test = new VerifyCS.Test + { + TestState = + { + Sources = + { + (Path.Combine("TestExecutableServerlessApp", "Greeter.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Greeter.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaOutputExecutableAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaOutputExecutableAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "Greeter_SayHello_Generated.g.cs", + SourceText.From(expectedSayHello, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ), + ( + typeof(SourceGenerator.Generator), + "Greeter_SayHelloAsync_Generated.g.cs", + SourceText.From(expectedSayHelloAsync, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ), + ( + typeof(SourceGenerator.Generator), + "Program.g.cs", + SourceText.From(expectedProgramGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("Greeter_SayHello_Generated.g.cs", expectedSayHello), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("Greeter_SayHelloAsync_Generated.g.cs", expectedSayHelloAsync), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestExecutableServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent), + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }; + + foreach (var file in Directory.GetFiles( + Path.Combine("Amazon.Lambda.RuntimeSupport"), + "*.cs", SearchOption.AllDirectories)) + { + test.TestState.Sources.Add((file, File.ReadAllText(file))); + } + + await test.RunAsync(); + } + [Fact] public async Task VerifyFunctionReturnVoid() { diff --git a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs new file mode 100644 index 000000000..955e187fc --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs @@ -0,0 +1,3 @@ +using Amazon.Lambda.Core; + +[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/ComplexQueryParameter.cs.error b/Libraries/test/TestExecutableServerlessApp/ComplexQueryParameter.cs.error new file mode 100644 index 000000000..d862bdaf3 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/ComplexQueryParameter.cs.error @@ -0,0 +1,24 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class ComplexQueryParameter + { + + // This fails because the complex query parameter 'person' is not supported currently. + [LambdaFunction(ResourceName = "TestQueryParams", Policies = "AdministratorAccess")] + [RestApi(LambdaHttpMethod.Get, "/api/say-hello")] + public string SayHello([FromQuery] Person person, ILambdaContext context) + { + return $"Hello! {person.FirstName} {person.LastName}"; + } + } + + public class Person + { + public string FirstName { get; set; } + public string LastName { get; set; } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/CustomizeResponseExamples.cs b/Libraries/test/TestExecutableServerlessApp/CustomizeResponseExamples.cs new file mode 100644 index 000000000..708921d45 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/CustomizeResponseExamples.cs @@ -0,0 +1,70 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.Core; +using System.Threading.Tasks; + +namespace TestServerlessApp +{ + public class CustomizeResponseExamples + { + [LambdaFunction(PackageType = LambdaPackageType.Image)] + [RestApi(LambdaHttpMethod.Get, "/okresponsewithheader/{x}")] + public IHttpResult OkResponseWithHeader(int x, ILambdaContext context) + { + return HttpResults.Ok("All Good") + .AddHeader("Single-Header", "Value") + .AddHeader("Multi-Header", "Foo") + .AddHeader("Multi-Header", "Bar"); + } + + [LambdaFunction(PackageType = LambdaPackageType.Image)] + [RestApi(LambdaHttpMethod.Get, "/okresponsewithheaderasync/{x}")] + public Task OkResponseWithHeaderAsync(int x, ILambdaContext context) + { + return Task.FromResult(HttpResults.Ok("All Good") + .AddHeader("Single-Header", "Value") + .AddHeader("Multi-Header", "Foo") + .AddHeader("Multi-Header", "Bar")); + } + + [LambdaFunction(PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/notfoundwithheaderv2/{x}")] + public IHttpResult NotFoundResponseWithHeaderV2(int x, ILambdaContext context) + { + return HttpResults.NotFound("Not Found") + .AddHeader("Single-Header", "Value") + .AddHeader("Multi-Header", "Foo") + .AddHeader("Multi-Header", "Bar"); + } + + [LambdaFunction(PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/notfoundwithheaderv2async/{x}")] + public Task NotFoundResponseWithHeaderV2Async(int x, ILambdaContext context) + { + return Task.FromResult(HttpResults.NotFound("Not Found") + .AddHeader("Single-Header", "Value") + .AddHeader("Multi-Header", "Foo") + .AddHeader("Multi-Header", "Bar")); + } + + [LambdaFunction(PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/notfoundwithheaderv1/{x}", Version = HttpApiVersion.V1)] + public IHttpResult NotFoundResponseWithHeaderV1(int x, ILambdaContext context) + { + return HttpResults.NotFound("Not Found") + .AddHeader("Single-Header", "Value") + .AddHeader("Multi-Header", "Foo") + .AddHeader("Multi-Header", "Bar"); + } + + [LambdaFunction(PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/notfoundwithheaderv1async/{x}", Version = HttpApiVersion.V1)] + public Task NotFoundResponseWithHeaderV1Async(int x, ILambdaContext context) + { + return Task.FromResult(HttpResults.NotFound("Not Found") + .AddHeader("Single-Header", "Value") + .AddHeader("Multi-Header", "Foo") + .AddHeader("Multi-Header", "Bar")); + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/CustomizeResponseWithErrors.cs.error b/Libraries/test/TestExecutableServerlessApp/CustomizeResponseWithErrors.cs.error new file mode 100644 index 000000000..0792df382 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/CustomizeResponseWithErrors.cs.error @@ -0,0 +1,23 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.Core; +using System.Threading.Tasks; + +// This class has a "error" extension because it fails to compile. It is used to make in unit tests to make sure +// we get expected diagnostic error messages. + +namespace TestServerlessApp +{ + public class CustomizeResponseWithErrors + { + // Can not return IHttpResult for non API Gateway based function + [LambdaFunction(PackageType = LambdaPackageType.Image)] + public IHttpResult InvalidReturnTypeExample(int x, ILambdaContext context) + { + return HttpResults.Ok("All Good") + .AddHeader("Single-Header", "Value") + .AddHeader("Multi-Header", "Foo") + .AddHeader("Multi-Header", "Bar"); + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/Dockerfile b/Libraries/test/TestExecutableServerlessApp/Dockerfile new file mode 100644 index 000000000..3f1c870e6 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/Dockerfile @@ -0,0 +1,13 @@ +FROM public.ecr.aws/lambda/dotnet:6 + +WORKDIR /var/task + +# This COPY command copies the .NET Lambda project's build artifacts from the host machine into the image. +# The source of the COPY should match where the .NET Lambda project publishes its build artifacts. If the Lambda function is being built +# with the AWS .NET Lambda Tooling, the `--docker-host-build-output-dir` switch controls where the .NET Lambda project +# will be built. The .NET Lambda project templates default to having `--docker-host-build-output-dir` +# set in the aws-lambda-tools-defaults.json file to "bin/Release/lambda-publish". +# +# Alternatively Docker multi-stage build could be used to build the .NET Lambda project inside the image. +# For more information on this approach checkout the project's README.md file. +COPY "bin/Release/lambda-publish" . diff --git a/Libraries/test/TestExecutableServerlessApp/DynamicExample.cs b/Libraries/test/TestExecutableServerlessApp/DynamicExample.cs new file mode 100644 index 000000000..d2fc882c5 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/DynamicExample.cs @@ -0,0 +1,23 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Core; +using System.Threading.Tasks; + +namespace TestServerlessApp +{ + public class DynamicExample + { + [LambdaFunction(PackageType = LambdaPackageType.Image)] + public dynamic DynamicReturn(string text, ILambdaContext context) + { + context.Logger.LogLine(text); + return text; + } + + [LambdaFunction(PackageType = LambdaPackageType.Image)] + public string DynamicInput(dynamic text, ILambdaContext context) + { + context.Logger.LogLine(text); + return text; + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/Greeter.cs b/Libraries/test/TestExecutableServerlessApp/Greeter.cs new file mode 100644 index 000000000..f967e8a2a --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/Greeter.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.APIGatewayEvents; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class Greeter + { + [LambdaFunction(ResourceName = "GreeterSayHello", MemorySize = 1024, PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/Greeter/SayHello", Version = HttpApiVersion.V1)] + public void SayHello([FromQuery(Name = "names")]IEnumerable firstNames, APIGatewayProxyRequest request, ILambdaContext context) + { + context.Logger.LogLine($"Request {JsonSerializer.Serialize(request)}"); + + if (firstNames == null) + { + return; + } + + foreach (var firstName in firstNames) + { + Console.WriteLine($"Hello {firstName}"); + } + } + + [LambdaFunction(ResourceName = "GreeterSayHelloAsync", Timeout = 50, PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/Greeter/SayHelloAsync", Version = HttpApiVersion.V1)] + public async Task SayHelloAsync([FromHeader(Name = "names")]IEnumerable firstNames) + { + if (firstNames == null) + { + return; + } + + foreach (var firstName in firstNames) + { + Console.WriteLine($"Hello {firstName}"); + } + await Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/IntrinsicExample.cs b/Libraries/test/TestExecutableServerlessApp/IntrinsicExample.cs new file mode 100644 index 000000000..c1731b2dc --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/IntrinsicExample.cs @@ -0,0 +1,14 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class IntrinsicExample + { + [LambdaFunction(PackageType = LambdaPackageType.Image)] + public void HasIntrinsic(string text, ILambdaContext context) + { + context.Logger.LogLine(text); + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/InvalidParameterAttributeNames.cs.error b/Libraries/test/TestExecutableServerlessApp/InvalidParameterAttributeNames.cs.error new file mode 100644 index 000000000..17d977706 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/InvalidParameterAttributeNames.cs.error @@ -0,0 +1,33 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class InvalidParameterAttributeNames + { + // This fails because the FromQuery attribute name contains whitespaces + [LambdaFunction()] + [HttpApi(LambdaHttpMethod.Get, "/SayHello", Version = HttpApiVersion.V1)] + public string SayHello([FromQuery(Name = "This is a name")] string name, ILambdaContext context) + { + return $"Hello, {name}!"; + } + + // This fails because the FromHeader attribute name contains escape characters and ';' + [LambdaFunction()] + [HttpApi(LambdaHttpMethod.Get, "/inject")] + public int Injection([FromHeader(Name = "System.Diagnostics.Process.Start(\"CMD.exe\",\"whoami\");")] int test, ILambdaContext context) + { + return 1; + } + + // This fails because the FromRoute attribute name contains '@' + [LambdaFunction()] + [HttpApi(LambdaHttpMethod.Get, "/SayHello/{first@name}", Version = HttpApiVersion.V1)] + public string SayHelloFromRoute([FromRoute(Name = "first@name")] string firstName, ILambdaContext context) + { + return $"Hello, {firstName}!"; + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/MissingResourePathMapping.cs.error b/Libraries/test/TestExecutableServerlessApp/MissingResourePathMapping.cs.error new file mode 100644 index 000000000..43086c4c7 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/MissingResourePathMapping.cs.error @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Amazon.Lambda.Core; +using Amazon.Lambda.APIGatewayEvents; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; + +namespace TestServerlessApp +{ + public class MissingResourcePathMapping + { + // This fails because the "x" resource path has a different name then the FromRoute name + [LambdaFunction()] + [HttpApi(LambdaHttpMethod.Get, "/add/{x}/{y}")] + public int Add([FromRoute(Name = "x1")] int x1, [FromRoute(Name = "y")] int y1, ILambdaContext context) + { + return x1 + y1; + } + } +} \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/NullableReferenceTypeExample.cs b/Libraries/test/TestExecutableServerlessApp/NullableReferenceTypeExample.cs new file mode 100644 index 000000000..9b930176d --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/NullableReferenceTypeExample.cs @@ -0,0 +1,16 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class NullableReferenceTypeExample + { + [LambdaFunction(PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/nullableheaderhttpapi")] + public void NullableHeaderHttpApi([FromHeader(Name = "MyHeader")] string? text, ILambdaContext context) + { + context.Logger.LogLine(text); + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/PlaceholderClass.cs b/Libraries/test/TestExecutableServerlessApp/PlaceholderClass.cs new file mode 100644 index 000000000..c65ba7760 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/PlaceholderClass.cs @@ -0,0 +1,9 @@ +namespace TestServerlessApp +{ + internal class PlaceholderClass + { + // This type exists because some of the source generator tests use fake CS files to simulate errors. + // But there needs to be at least one real CS file in the test for the generator to determine the project + // directory. No logic should exist in this type. + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/Services/SimpleCalculatorService.cs b/Libraries/test/TestExecutableServerlessApp/Services/SimpleCalculatorService.cs new file mode 100644 index 000000000..a1293956e --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/Services/SimpleCalculatorService.cs @@ -0,0 +1,42 @@ +using System; +using System.Text.RegularExpressions; + +namespace TestServerlessApp.Services +{ + public interface ISimpleCalculatorService + { + int Add(int x, int y); + int Subtract(int x, int y); + int Multiply(int x, int y); + int Divide(int x, int y); + double PI(); + } + + public class SimpleCalculatorService : ISimpleCalculatorService + { + public int Divide(int x, int y) + { + return x / y; + } + + public double PI() + { + return Math.PI; + } + + public int Multiply(int x, int y) + { + return x * y; + } + + public int Add(int x, int y) + { + return x + y; + } + + public int Subtract(int x, int y) + { + return x - y; + } + } +} \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/Startup.cs b/Libraries/test/TestExecutableServerlessApp/Startup.cs new file mode 100644 index 000000000..22c4bdb57 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/Startup.cs @@ -0,0 +1,20 @@ +using Amazon.Lambda.Annotations; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using TestServerlessApp.Services; + +namespace TestServerlessApp +{ + [LambdaStartup] + [LambdaOutputExecutable] + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddScoped(); + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs b/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs new file mode 100644 index 000000000..023d71d53 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs @@ -0,0 +1,14 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Core; + +namespace TestServerlessApp.Sub1 +{ + public class Functions + { + [LambdaFunction(ResourceName = "ToUpper", PackageType = LambdaPackageType.Image)] + public string ToUpper(string text) + { + return text.ToUpper(); + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/TaskExample.cs b/Libraries/test/TestExecutableServerlessApp/TaskExample.cs new file mode 100644 index 000000000..a49535f9e --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/TaskExample.cs @@ -0,0 +1,16 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Core; +using System.Threading.Tasks; + +namespace TestServerlessApp +{ + public class TaskExample + { + [LambdaFunction(PackageType = LambdaPackageType.Image)] + public async Task TaskReturn(string text, ILambdaContext context) + { + context.Logger.LogLine(text); + await Task.CompletedTask; + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/Temp.cs b/Libraries/test/TestExecutableServerlessApp/Temp.cs new file mode 100644 index 000000000..94baa23d7 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/Temp.cs @@ -0,0 +1,20 @@ +namespace TestServerlessApp; + +using System; +using System.Threading.Tasks; + +using Amazon.Lambda.Core; + +public class Temp +{ + public static async Task Handle() + { + Action voidreturn = VoidExample_VoidReturn_Generated.VoidReturn; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(voidreturn, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + } + + public static void Handler(string message) + { + + } +} \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/TestExecutableServerlessApp.csproj b/Libraries/test/TestExecutableServerlessApp/TestExecutableServerlessApp.csproj new file mode 100644 index 000000000..f60c3c362 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/TestExecutableServerlessApp.csproj @@ -0,0 +1,31 @@ + + + net6.0 + true + Lambda + + true + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/VoidExample.cs b/Libraries/test/TestExecutableServerlessApp/VoidExample.cs new file mode 100644 index 000000000..59e02e74c --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/VoidExample.cs @@ -0,0 +1,14 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class VoidExample + { + [LambdaFunction(PackageType = LambdaPackageType.Image)] + public void VoidReturn(string text, ILambdaContext context) + { + context.Logger.LogLine(text); + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/aws-lambda-tools-defaults.json b/Libraries/test/TestExecutableServerlessApp/aws-lambda-tools-defaults.json new file mode 100644 index 000000000..a5f516588 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/aws-lambda-tools-defaults.json @@ -0,0 +1,19 @@ +{ + "Information": [ + "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.", + "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.", + "dotnet lambda help", + "All the command line options for the Lambda command can be specified in this file." + ], + "profile": "default", + "region": "us-west-2", + "configuration": "Release", + "framework": "net6.0", + "s3-prefix": "TestServerlessApp/", + "template": "serverless.template", + "template-parameters": "", + "docker-host-build-output-dir": "./bin/Release/lambda-publish", +"s3-bucket" : "test-serverless-app-81ae0673", +"stack-name" : "test-serverless-app-81ae0673", +"function-architecture" : "x86_64" +} diff --git a/Libraries/test/TestExecutableServerlessApp/serverless.template b/Libraries/test/TestExecutableServerlessApp/serverless.template new file mode 100644 index 000000000..588dadd5e --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/serverless.template @@ -0,0 +1,452 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "An AWS Serverless Application. This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).", + "Parameters": { + "ArchitectureTypeParameter": { + "Type": "String", + "Default": "x86_64", + "AllowedValues": [ + "x86_64", + "arm64" + ] + } + }, + "Globals": { + "Function": { + "Architectures": [ + { + "Ref": "ArchitectureTypeParameter" + } + ] + } + }, + "Resources": { + "TestServerlessAppDynamicExampleDynamicReturnGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicReturn_Generated::DynamicReturn" + ] + } + } + }, + "TestServerlessAppDynamicExampleDynamicInputGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicInput_Generated::DynamicInput" + ] + } + } + }, + "TestServerlessAppTaskExampleTaskReturnGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.TaskExample_TaskReturn_Generated::TaskReturn" + ] + } + } + }, + "TestServerlessAppVoidExampleVoidReturnGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.VoidExample_VoidReturn_Generated::VoidReturn" + ] + } + } + }, + "TestServerlessAppCustomizeResponseExamplesOkResponseWithHeaderGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeader_Generated::OkResponseWithHeader" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/okresponsewithheader/{x}", + "Method": "GET" + } + } + } + } + }, + "TestServerlessAppCustomizeResponseExamplesOkResponseWithHeaderAsyncGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated::OkResponseWithHeaderAsync" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/okresponsewithheaderasync/{x}", + "Method": "GET" + } + } + } + } + }, + "TestServerlessAppCustomizeResponseExamplesNotFoundResponseWithHeaderV2Generated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated::NotFoundResponseWithHeaderV2" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/notfoundwithheaderv2/{x}", + "Method": "GET" + } + } + } + } + }, + "TestServerlessAppCustomizeResponseExamplesNotFoundResponseWithHeaderV2AsyncGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated::NotFoundResponseWithHeaderV2Async" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/notfoundwithheaderv2async/{x}", + "Method": "GET" + } + } + } + } + }, + "TestServerlessAppCustomizeResponseExamplesNotFoundResponseWithHeaderV1Generated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated::NotFoundResponseWithHeaderV1" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/notfoundwithheaderv1/{x}", + "Method": "GET", + "PayloadFormatVersion": "1.0" + } + } + } + } + }, + "TestServerlessAppCustomizeResponseExamplesNotFoundResponseWithHeaderV1AsyncGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated::NotFoundResponseWithHeaderV1Async" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/notfoundwithheaderv1async/{x}", + "Method": "GET", + "PayloadFormatVersion": "1.0" + } + } + } + } + }, + "GreeterSayHello": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 1024, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHello_Generated::SayHello" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/Greeter/SayHello", + "Method": "GET", + "PayloadFormatVersion": "1.0" + } + } + } + } + }, + "GreeterSayHelloAsync": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 50, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/Greeter/SayHelloAsync", + "Method": "GET", + "PayloadFormatVersion": "1.0" + } + } + } + } + }, + "ToUpper": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.Sub1.Functions_ToUpper_Generated::ToUpper" + ] + } + } + }, + "TestServerlessAppNullableReferenceTypeExampleNullableHeaderHttpApiGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.NullableReferenceTypeExample_NullableHeaderHttpApi_Generated::NullableHeaderHttpApi" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/nullableheaderhttpapi", + "Method": "GET" + } + } + } + } + }, + "TestServerlessAppIntrinsicExampleHasIntrinsicGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestExecutableServerlessApp::TestServerlessApp.IntrinsicExample_HasIntrinsic_Generated::HasIntrinsic" + ] + } + } + } + }, + "Outputs": { + "RestApiURL": { + "Description": "Rest API endpoint URL for Prod environment", + "Value": { + "Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod" + } + }, + "HttpApiURL": { + "Description": "HTTP API endpoint URL for Prod environment", + "Value": { + "Fn::Sub": "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com" + } + } + } +} \ No newline at end of file diff --git a/Libraries/test/TestServerlessApp/serverless.template b/Libraries/test/TestServerlessApp/serverless.template index 2df85836e..b5f6ef178 100644 --- a/Libraries/test/TestServerlessApp/serverless.template +++ b/Libraries/test/TestServerlessApp/serverless.template @@ -718,6 +718,26 @@ ] } } + }, + "TestServerlessAppIntrinsicExampleHasIntrinsicGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.IntrinsicExample_HasIntrinsic_Generated::HasIntrinsic" + ] + } + } } }, "Outputs": { From fe69112f1cfbebf2b7941603256e90ed252be32f Mon Sep 17 00:00:00 2001 From: James Eastham Date: Mon, 21 Aug 2023 21:17:47 +0100 Subject: [PATCH 02/27] Add support for serialization --- .../Generator.cs | 17 ++- .../Models/LambdaFunctionModel.cs | 3 +- .../Models/LambdaFunctionModelBuilder.cs | 5 +- .../Templates/ExecutableAssembly.cs | 105 +++++++++++------- .../Templates/ExecutableAssembly.tt | 6 +- .../LambdaFunctionAttribute.cs | 5 + .../ComplexCalculator_Add_Generated.g.cs | 1 + ...s_OkResponseWithHeaderAsync_Generated.g.cs | 1 + ...amples_OkResponseWithHeader_Generated.g.cs | 1 + ...ynamicExample_DynamicReturn_Generated.g.cs | 1 + .../Snapshots/Greeter_SayHello_Generated.g.cs | 1 - ...trinsicExample_HasIntrinsic_Generated.g.cs | 1 + ...ample_NullableHeaderHttpApi_Generated.g.cs | 1 + .../SimpleCalculator_Add_Generated.g.cs | 1 + .../TaskExample_TaskReturn_Generated.g.cs | 1 + .../VoidExample_VoidReturn_Generated.g.cs | 1 + .../Sub1/Functions.cs | 2 +- .../test/TestServerlessApp/Sub1/Functions.cs | 2 +- .../TestServerlessApp/serverless.template | 40 +++---- 19 files changed, 123 insertions(+), 72 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs index 6130d319b..5790f5312 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Reflection; using System.Text; using System.Text.RegularExpressions; using Amazon.Lambda.Annotations.SourceGenerator.Diagnostics; @@ -120,8 +121,22 @@ public void Execute(GeneratorExecutionContext context) continue; } } + + var lambdaAttribute = lambdaMethodModel.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Name == nameof(LambdaFunctionAttribute)); + + string serializerString = "Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer"; + + if (lambdaAttribute != null) + { + var serializerValue = lambdaAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "Serializer").Value; + + if (serializerValue.Value != null) + { + serializerString = serializerValue.Value.ToString(); + } + } - var model = LambdaFunctionModelBuilder.Build(lambdaMethodModel, configureMethodModel, context, receiver.IsExecutable); + var model = LambdaFunctionModelBuilder.Build(lambdaMethodModel, configureMethodModel, context, receiver.IsExecutable, serializerString); // If there are more than one event, report them as errors if (model.LambdaMethod.Events.Count > 1) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs index 3379140eb..c4dc09d71 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs @@ -29,7 +29,8 @@ public class LambdaFunctionModel : ILambdaFunctionSerializable /// /// Gets or sets fully qualified name of the serializer used for serialization or deserialization. /// - public string Serializer { get; set; } + public string Serializer { get; set; } = + "Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer"; /// /// Gets or sets if the output is an executable. diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs index 5190ab159..bc5b7348d 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Reflection; using Microsoft.CodeAnalysis; namespace Amazon.Lambda.Annotations.SourceGenerator.Models @@ -8,7 +9,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Models /// public static class LambdaFunctionModelBuilder { - public static LambdaFunctionModel Build(IMethodSymbol lambdaMethodSymbol, IMethodSymbol configureMethodSymbol, GeneratorExecutionContext context, bool isExecutable) + public static LambdaFunctionModel Build(IMethodSymbol lambdaMethodSymbol, IMethodSymbol configureMethodSymbol, GeneratorExecutionContext context, bool isExecutable, string serializer) { var lambdaMethod = LambdaMethodModelBuilder.Build(lambdaMethodSymbol, configureMethodSymbol, context); var generatedMethod = GeneratedMethodModelBuilder.Build(lambdaMethodSymbol, configureMethodSymbol, lambdaMethod, context); @@ -16,7 +17,7 @@ public static LambdaFunctionModel Build(IMethodSymbol lambdaMethodSymbol, IMetho { GeneratedMethod = generatedMethod, LambdaMethod = lambdaMethod, - Serializer = "System.Text.Json.JsonSerializer", // TODO: replace serializer with assembly serializer + Serializer = serializer, StartupType = configureMethodSymbol != null ? TypeModelBuilder.Build(configureMethodSymbol.ContainingType, context) : null, SourceGeneratorVersion = context.Compilation .ReferencedAssemblyNames.FirstOrDefault(x => string.Equals(x.Name, "Amazon.Lambda.Annotations")) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs index 39cc577bf..67800a25f 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs @@ -23,7 +23,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates /// Class to produce the template output /// - #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 1 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public partial class ExecutableAssembly : ExecutableAssemblyBase { @@ -33,16 +33,16 @@ public partial class ExecutableAssembly : ExecutableAssemblyBase /// public virtual string TransformText() { - this.Write("using System;\r\nusing System.Linq;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\nusing Amazon.Lambda.Core;\r\n\r\nnamespace "); + this.Write("using System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Amazon.Lambda.Core;\n\nnamespace "); - #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 18 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._containingNamespace)); #line default #line hidden - this.Write(";\r\n\r\npublic class Program\r\n{\r\n private static async Task Main(string[] args)\r\n {\r\n"); + this.Write(";\n\npublic class Program\n{\n private static async Task Main(string[] args)\n {\n"); - #line 24 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 24 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" if (this._lambdaFunctions.Count == 1) { @@ -52,56 +52,63 @@ public virtual string TransformText() #line hidden this.Write(" Func<"); - #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", this._lambdaFunctions[0].GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); #line default #line hidden this.Write(", "); - #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].GeneratedMethod.ReturnType.FullName)); #line default #line hidden this.Write("> "); - #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name.ToLower())); #line default #line hidden this.Write(" = "); - #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name)); #line default #line hidden this.Write("_Generated."); - #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name)); #line default #line hidden - this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 29 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 29 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name.ToLower())); #line default #line hidden - this.Write(", new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync();\r\n"); + this.Write(", new "); - #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 29 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].Serializer)); + + #line default + #line hidden + this.Write("()).Build().RunAsync();\n"); + + #line 30 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" } else @@ -110,9 +117,9 @@ public virtual string TransformText() #line default #line hidden - this.Write("\r\n switch (Environment.GetEnvironmentVariable(\"HANDLER\"))\r\n {\r\n"); + this.Write("\n switch (Environment.GetEnvironmentVariable(\"HANDLER\"))\n {\n"); - #line 38 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 38 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" foreach (var model in this._lambdaFunctions) { @@ -122,14 +129,14 @@ public virtual string TransformText() #line hidden this.Write(" case \""); - #line 42 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 42 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write("\":\r\n"); + this.Write("\":\n"); - #line 43 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 43 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" if (model.GeneratedMethod.ReturnType.FullName == "void") { @@ -139,49 +146,56 @@ public virtual string TransformText() #line hidden this.Write(" Action<"); - #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); #line default #line hidden this.Write("> "); - #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); #line default #line hidden this.Write(" = "); - #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated."); - #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 48 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 48 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); #line default #line hidden - this.Write(", new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync();\r\n break;\r\n"); + this.Write(", new "); + + #line 48 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].Serializer)); + + #line default + #line hidden + this.Write("()).Build().RunAsync();\n break;\n"); - #line 50 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 50 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" } else @@ -192,56 +206,63 @@ public virtual string TransformText() #line hidden this.Write(" Func<"); - #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); #line default #line hidden this.Write(", "); - #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.ReturnType.FullName)); #line default #line hidden this.Write("> "); - #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); #line default #line hidden this.Write(" = "); - #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated."); - #line 55 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 56 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 56 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); #line default #line hidden - this.Write(", new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync();\r\n break;\r\n"); + this.Write(", new "); + + #line 56 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.Serializer)); + + #line default + #line hidden + this.Write("()).Build().RunAsync();\n break;\n"); - #line 58 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 58 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" } } @@ -249,9 +270,9 @@ public virtual string TransformText() #line default #line hidden - this.Write("\r\n }\r\n"); + this.Write("\n }\n"); - #line 64 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 64 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" } @@ -259,7 +280,7 @@ public virtual string TransformText() #line default #line hidden - this.Write(" }\r\n}"); + this.Write(" }\n}"); return this.GenerationEnvironment.ToString(); } } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt index 97f8a8364..46fa183a3 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt @@ -26,7 +26,7 @@ public class Program { #> Func<<#= string.Join(", ", this._lambdaFunctions[0].GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= this._lambdaFunctions[0].GeneratedMethod.ReturnType.FullName #>> <#=this._lambdaFunctions[0].LambdaMethod.Name.ToLower()#> = <#=this._lambdaFunctions[0].LambdaMethod.ContainingType.Name#>_<#=this._lambdaFunctions[0].LambdaMethod.Name#>_Generated.<#=this._lambdaFunctions[0].LambdaMethod.Name#>; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#=this._lambdaFunctions[0].LambdaMethod.Name.ToLower()#>, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#=this._lambdaFunctions[0].LambdaMethod.Name.ToLower()#>, new <#= this._lambdaFunctions[0].Serializer #>()).Build().RunAsync(); <# } else @@ -45,7 +45,7 @@ public class Program { #> Action<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>> <#= model.LambdaMethod.Name.ToLower() #> = <#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated.<#= model.LambdaMethod.Name #>; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new <#= this._lambdaFunctions[0].Serializer #>()).Build().RunAsync(); break; <# } @@ -53,7 +53,7 @@ public class Program { #> Func<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= model.GeneratedMethod.ReturnType.FullName #>> <#= model.LambdaMethod.Name.ToLower() #> = <#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated.<#= model.LambdaMethod.Name #>; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new <#= model.Serializer #>()).Build().RunAsync(); break; <# } diff --git a/Libraries/src/Amazon.Lambda.Annotations/LambdaFunctionAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/LambdaFunctionAttribute.cs index faf3b1062..20a8f93dc 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/LambdaFunctionAttribute.cs +++ b/Libraries/src/Amazon.Lambda.Annotations/LambdaFunctionAttribute.cs @@ -8,6 +8,11 @@ namespace Amazon.Lambda.Annotations [AttributeUsage(AttributeTargets.Method)] public class LambdaFunctionAttribute : Attribute { + /// + /// The serializer to use. + /// + public string Serializer { get; set; } + /// /// The name of the CloudFormation resource that is associated with the Lambda function. /// diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Add_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Add_Generated.g.cs index 456bac752..e764653e1 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Add_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Add_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Amazon.Lambda.Core; namespace TestServerlessApp diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs index 087f311b5..eee588b9e 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Amazon.Lambda.Core; using Amazon.Lambda.Annotations.APIGateway; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs index f45d39aa8..fe6e40d1b 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Amazon.Lambda.Core; using Amazon.Lambda.Annotations.APIGateway; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicReturn_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicReturn_Generated.g.cs index 34dc44076..87adda1a1 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicReturn_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicReturn_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Amazon.Lambda.Core; namespace TestServerlessApp diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs index ba9245093..53a507160 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; namespace TestServerlessApp diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/IntrinsicExample_HasIntrinsic_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/IntrinsicExample_HasIntrinsic_Generated.g.cs index ed842d808..b1ffa7d7c 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/IntrinsicExample_HasIntrinsic_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/IntrinsicExample_HasIntrinsic_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Amazon.Lambda.Core; namespace TestServerlessApp diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs index b34383395..a77488c92 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Amazon.Lambda.Core; namespace TestServerlessApp diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Add_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Add_Generated.g.cs index acfbb76e4..32d1f843c 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Add_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Add_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/TaskExample_TaskReturn_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/TaskExample_TaskReturn_Generated.g.cs index bb26afb73..d5b7658d6 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/TaskExample_TaskReturn_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/TaskExample_TaskReturn_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Amazon.Lambda.Core; namespace TestServerlessApp diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/VoidExample_VoidReturn_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/VoidExample_VoidReturn_Generated.g.cs index 06c92f9a4..f52417b87 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/VoidExample_VoidReturn_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/VoidExample_VoidReturn_Generated.g.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using Amazon.Lambda.Core; namespace TestServerlessApp diff --git a/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs b/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs index 023d71d53..eb5b13ed7 100644 --- a/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs +++ b/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs @@ -5,7 +5,7 @@ namespace TestServerlessApp.Sub1 { public class Functions { - [LambdaFunction(ResourceName = "ToUpper", PackageType = LambdaPackageType.Image)] + [LambdaFunction(ResourceName = "ToUpper", PackageType = LambdaPackageType.Image, Serializer = "Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer")] public string ToUpper(string text) { return text.ToUpper(); diff --git a/Libraries/test/TestServerlessApp/Sub1/Functions.cs b/Libraries/test/TestServerlessApp/Sub1/Functions.cs index 023d71d53..00b4bd280 100644 --- a/Libraries/test/TestServerlessApp/Sub1/Functions.cs +++ b/Libraries/test/TestServerlessApp/Sub1/Functions.cs @@ -5,7 +5,7 @@ namespace TestServerlessApp.Sub1 { public class Functions { - [LambdaFunction(ResourceName = "ToUpper", PackageType = LambdaPackageType.Image)] + [LambdaFunction(ResourceName = "ToUpper", PackageType = LambdaPackageType.Image, Serializer = "System.Text.Json.JsonSerializer")] public string ToUpper(string text) { return text.ToUpper(); diff --git a/Libraries/test/TestServerlessApp/serverless.template b/Libraries/test/TestServerlessApp/serverless.template index b5f6ef178..bfbf1a50a 100644 --- a/Libraries/test/TestServerlessApp/serverless.template +++ b/Libraries/test/TestServerlessApp/serverless.template @@ -614,26 +614,6 @@ } } }, - "ToUpper": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations" - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.Sub1.Functions_ToUpper_Generated::ToUpper" - ] - } - } - }, "TestServerlessAppNullableReferenceTypeExampleNullableHeaderHttpApiGenerated": { "Type": "AWS::Serverless::Function", "Metadata": { @@ -738,6 +718,26 @@ ] } } + }, + "ToUpper": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.Sub1.Functions_ToUpper_Generated::ToUpper" + ] + } + } } }, "Outputs": { From 5ebbf64f7ace836c58c81f3e3cb9cdf4fe242f67 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Tue, 22 Aug 2023 11:44:38 +0100 Subject: [PATCH 03/27] Add support for serialization and update annotation name --- .../Diagnostics/DiagnosticDescriptors.cs | 7 + .../Generator.cs | 125 ++++++++++++--- .../Models/ILambdaFunctionSerializable.cs | 12 ++ .../Models/LambdaFunctionModel.cs | 7 +- .../SyntaxReceiver.cs | 24 ++- .../Templates/ExecutableAssembly.cs | 143 ++++-------------- .../Templates/ExecutableAssembly.tt | 17 +-- .../Templates/LambdaFunctionTemplate.cs | 9 +- .../Templates/LambdaFunctionTemplate.tt | 2 +- .../TypeFullNames.cs | 2 + .../Writers/CloudFormationWriter.cs | 5 + .../LambdaFunctionAttribute.cs | 5 - ...bute.cs => LambdaGenerateMainAttribute.cs} | 4 +- ....Annotations.SourceGenerators.Tests.csproj | 16 ++ .../CSharpSourceGeneratorVerifier.cs | 8 +- ...nctions_AsyncStartupToLower_Generated.g.cs | 56 +++++++ ...nctions_AsyncStartupToUpper_Generated.g.cs | 2 +- .../Greeter_SayHelloAsync_Generated.g.cs | 2 +- .../Snapshots/Greeter_SayHello_Generated.g.cs | 3 +- .../Snapshots/Program.g.cs | 13 +- .../Snapshots/ProgramMultiHandler.g.cs | 4 +- .../Snapshots/ProgramZipOutput.g.cs | 24 +++ .../ServerlessTemplates/greeter.template | 14 +- .../subnamespace_executable.template | 29 ++++ .../subnamespace_executableimage.template | 32 ++++ .../SourceGeneratorTests.cs | 61 +++++++- .../WriterTests/CloudFormationWriterTests.cs | 2 + .../AssemblyAttributes.cs | 6 +- .../TestExecutableServerlessApp/Startup.cs | 1 - .../Sub1/Functions.cs | 12 +- .../Sub1/FunctionsZipOutput.cs | 14 ++ .../test/TestExecutableServerlessApp/Temp.cs | 20 --- .../serverless.template | 126 +++++++++++++-- .../test/TestServerlessApp/Sub1/Functions.cs | 2 +- 34 files changed, 581 insertions(+), 228 deletions(-) rename Libraries/src/Amazon.Lambda.Annotations/{LambdaOutputExecutableAttribute.cs => LambdaGenerateMainAttribute.cs} (67%) create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToLower_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executable.template create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executableimage.template create mode 100644 Libraries/test/TestExecutableServerlessApp/Sub1/FunctionsZipOutput.cs delete mode 100644 Libraries/test/TestExecutableServerlessApp/Temp.cs diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs index 17bef57a3..7eb5eeff3 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs @@ -45,6 +45,13 @@ public static class DiagnosticDescriptors DiagnosticSeverity.Error, isEnabledByDefault: true); + public static readonly DiagnosticDescriptor MainMethodExists = new DiagnosticDescriptor(id: "AWSLambda0104", + title: "static Main method exists", + messageFormat: "Your project already defines a static Main method.", + category: "AWSLambdaCSharpGenerator", + DiagnosticSeverity.Error, + isEnabledByDefault: true); + public static readonly DiagnosticDescriptor HttpResultsOnNonApiFunction = new DiagnosticDescriptor(id: "AWSLambda0105", title: $"Invalid return type {nameof(IHttpResult)}", messageFormat: $"{nameof(IHttpResult)} is not a valid return type for LambdaFunctions without {nameof(HttpApiAttribute)} or {nameof(RestApiAttribute)} attributes", diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs index 5790f5312..ca319e1ed 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs @@ -21,6 +21,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator [Generator] public class Generator : ISourceGenerator { + private const string DEFAULT_LAMBDA_SERIALIZER = "Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer"; private readonly IFileManager _fileManager = new FileManager(); private readonly IDirectoryManager _directoryManager = new DirectoryManager(); @@ -83,6 +84,19 @@ public void Execute(GeneratorExecutionContext context) } } + var isExecutable = false; + + var assemblyAttributes = context.Compilation.Assembly.GetAttributes(); + + // Let's find the AssemblyTitleAttribute + var generateMainAttribute = assemblyAttributes + .FirstOrDefault(attr => attr.AttributeClass.Name == nameof(LambdaGenerateMainAttribute)); + + if (generateMainAttribute != null) + { + isExecutable = true; + } + var configureMethodModel = semanticModelProvider.GetConfigureMethodModel(receiver.StartupClasses.FirstOrDefault()); var annotationReport = new AnnotationReport(); @@ -122,21 +136,9 @@ public void Execute(GeneratorExecutionContext context) } } - var lambdaAttribute = lambdaMethodModel.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Name == nameof(LambdaFunctionAttribute)); - - string serializerString = "Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer"; - - if (lambdaAttribute != null) - { - var serializerValue = lambdaAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "Serializer").Value; - - if (serializerValue.Value != null) - { - serializerString = serializerValue.Value.ToString(); - } - } + var serializerString = GetSerializerAttribute(context, lambdaMethodModel); - var model = LambdaFunctionModelBuilder.Build(lambdaMethodModel, configureMethodModel, context, receiver.IsExecutable, serializerString); + var model = LambdaFunctionModelBuilder.Build(lambdaMethodModel, configureMethodModel, context, isExecutable, serializerString); // If there are more than one event, report them as errors if (model.LambdaMethod.Events.Count > 1) @@ -199,11 +201,21 @@ public void Execute(GeneratorExecutionContext context) annotationReport.LambdaFunctions.Add(model); } - if (receiver.IsExecutable) + if (isExecutable) { - var executableAssembly = new ExecutableAssembly(lambdaModels, lambdaModels[0].LambdaMethod.ContainingNamespace); - - context.AddSource("Program.g.cs", SourceText.From(executableAssembly.TransformText(), Encoding.UTF8, SourceHashAlgorithm.Sha256)); + var executableAssembly = GenerateExecutableAssemblySource( + context, + diagnosticReporter, + receiver, + lambdaModels); + + if (executableAssembly == null) + { + foundFatalError = true; + return; + } + + context.AddSource("Program.g.cs", SourceText.From(executableAssembly.TransformText().ToEnvironmentLineEndings(), Encoding.UTF8, SourceHashAlgorithm.Sha256)); } // Run the CloudFormation sync if any LambdaMethods exists. Also run if no LambdaMethods exists but there is a @@ -240,11 +252,88 @@ public void Execute(GeneratorExecutionContext context) } } + private static ExecutableAssembly GenerateExecutableAssemblySource( + GeneratorExecutionContext context, + DiagnosticReporter diagnosticReporter, + SyntaxReceiver receiver, + List lambdaModels) + { + // Check 'Amazon.Lambda.RuntimeSupport' is referenced + if (context.Compilation.ReferencedAssemblyNames.FirstOrDefault(x => x.Name == "Amazon.Lambda.RuntimeSupport") == null) + { + diagnosticReporter.Report( + Diagnostic.Create( + DiagnosticDescriptors.MissingDependencies, + Location.None, + "Amazon.Lambda.RuntimeSupport")); + + return null; + } + + foreach (var methodDeclaration in receiver.MethodDeclarations) + { + var model = context.Compilation.GetSemanticModel(methodDeclaration.SyntaxTree); + var symbol = model.GetDeclaredSymbol(methodDeclaration); + + if (symbol.Name == "Main" && symbol.IsStatic && symbol.ContainingNamespace.Name == lambdaModels[0].LambdaMethod.ContainingAssembly) + { + diagnosticReporter.Report( + Diagnostic.Create( + DiagnosticDescriptors.MainMethodExists, + Location.None)); + + return null; + } + } + + return new ExecutableAssembly( + lambdaModels, + lambdaModels[0].LambdaMethod.ContainingNamespace); + } + private bool HasSerializerAttribute(GeneratorExecutionContext context, IMethodSymbol methodModel) { return methodModel.ContainingAssembly.HasAttribute(context, TypeFullNames.LambdaSerializerAttribute); } + private string GetSerializerAttribute(GeneratorExecutionContext context, IMethodSymbol methodModel) + { + var serializerString = DEFAULT_LAMBDA_SERIALIZER; + + ISymbol symbol = null; + + // First check if method has the Lambda Serializer. + if (methodModel.HasAttribute( + context, + TypeFullNames.LambdaSerializerAttribute)) + { + symbol = methodModel; + } + // Then check assembly + else if (methodModel.ContainingAssembly.HasAttribute( + context, + TypeFullNames.LambdaSerializerAttribute)) + { + symbol = methodModel.ContainingAssembly; + } + // Else return the default serializer. + else + { + return serializerString; + } + + var attribute = symbol.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Name == TypeFullNames.LambdaSerializerAttributeWithoutNamespace); + + var serializerValue = attribute.ConstructorArguments.FirstOrDefault(kvp => kvp.Type.Name == nameof(Type)).Value; + + if (serializerValue != null) + { + serializerString = serializerValue.ToString(); + } + + return serializerString; + } + public void Initialize(GeneratorInitializationContext context) { // Register a syntax receiver that will be created for each generation pass diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/ILambdaFunctionSerializable.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/ILambdaFunctionSerializable.cs index fcca6c65e..171bff03d 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/ILambdaFunctionSerializable.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/ILambdaFunctionSerializable.cs @@ -14,6 +14,13 @@ public interface ILambdaFunctionSerializable /// /// string Handler { get; } + + /// + /// + /// The original method name. + /// + /// + string MethodName { get; } /// /// The name of the CloudFormation resource that is associated with the Lambda function. @@ -34,6 +41,11 @@ public interface ILambdaFunctionSerializable /// The IAM Role assumed by the Lambda function during its execution. /// string Role { get; } + + /// + /// Gets or sets if the output is an executable. + /// + bool IsExecutable { get; } /// /// Resource based policies that grants permissions to access other AWS resources. diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs index c4dc09d71..38921bd93 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs @@ -26,6 +26,11 @@ public class LambdaFunctionModel : ILambdaFunctionSerializable /// public TypeModel StartupType { get; set; } + /// + /// The original method name. + /// + public string MethodName => LambdaMethod.Name; + /// /// Gets or sets fully qualified name of the serializer used for serialization or deserialization. /// @@ -38,7 +43,7 @@ public class LambdaFunctionModel : ILambdaFunctionSerializable public bool IsExecutable { get; set; } /// - public string Handler => $"{LambdaMethod.ContainingAssembly}::{GeneratedMethod.ContainingType.FullName}::{LambdaMethod.Name}"; + public string Handler => IsExecutable ? LambdaMethod.ContainingAssembly : $"{LambdaMethod.ContainingAssembly}::{GeneratedMethod.ContainingType.FullName}::{LambdaMethod.Name}"; /// public string ResourceName => LambdaMethod.LambdaFunctionAttribute.Data.ResourceName ?? diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs index 0631c139d..0c34c2fde 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs @@ -7,13 +7,15 @@ namespace Amazon.Lambda.Annotations.SourceGenerator { + using Microsoft.CodeAnalysis.CSharp; + internal class SyntaxReceiver : ISyntaxContextReceiver { public List LambdaMethods { get; } = new List(); public List StartupClasses { get; private set; } = new List(); - public bool IsExecutable { get; set; } + public List MethodDeclarations { get; } = new List(); /// /// Path to the directory containing the .csproj file @@ -52,7 +54,9 @@ public void OnVisitSyntaxNode(GeneratorSyntaxContext context) if (context.Node is MethodDeclarationSyntax methodDeclarationSyntax && methodDeclarationSyntax.AttributeLists.Count > 0) { // Get the symbol being declared by the method, and keep it if its annotated - var methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclarationSyntax); + var methodSymbol = ModelExtensions.GetDeclaredSymbol( + context.SemanticModel, + methodDeclarationSyntax); if (methodSymbol.GetAttributes().Any(attr => attr.AttributeClass.Name == nameof(LambdaFunctionAttribute))) { LambdaMethods.Add(methodDeclarationSyntax); @@ -63,16 +67,24 @@ public void OnVisitSyntaxNode(GeneratorSyntaxContext context) if (context.Node is ClassDeclarationSyntax classDeclarationSyntax && classDeclarationSyntax.AttributeLists.Count > 0) { // Get the symbol being declared by the class, and keep it if its annotated - var methodSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclarationSyntax); + var methodSymbol = ModelExtensions.GetDeclaredSymbol( + context.SemanticModel, + classDeclarationSyntax); if (methodSymbol.GetAttributes().Any(attr => attr.AttributeClass.Name == nameof(LambdaStartupAttribute))) { StartupClasses.Add(classDeclarationSyntax); } + } + + if (context.Node is MethodDeclarationSyntax methodDeclaration) + { + var model = ModelExtensions.GetDeclaredSymbol( + context.SemanticModel, + methodDeclaration); - // If at least one class is annotated with the LambdaOutputExecutable annotations then set IsExecutable to be true. - if (methodSymbol.GetAttributes().Any(attr => attr.AttributeClass.Name == nameof(LambdaOutputExecutableAttribute))) + if (model.Name == "Main" && model.IsStatic) { - IsExecutable = true; + MethodDeclarations.Add(methodDeclaration); } } } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs index 67800a25f..a6d341856 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs @@ -23,7 +23,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates /// Class to produce the template output /// - #line 1 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public partial class ExecutableAssembly : ExecutableAssemblyBase { @@ -33,93 +33,16 @@ public partial class ExecutableAssembly : ExecutableAssemblyBase /// public virtual string TransformText() { - this.Write("using System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Amazon.Lambda.Core;\n\nnamespace "); + this.Write("using System;\r\nusing System.Linq;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\nusing Amazon.Lambda.Core;\r\n\r\nnamespace "); - #line 18 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._containingNamespace)); #line default #line hidden - this.Write(";\n\npublic class Program\n{\n private static async Task Main(string[] args)\n {\n"); + this.Write(";\r\n\r\npublic class GeneratedProgram\r\n{\r\n private static async Task Main(string[] args)\r\n {\r\n\r\n switch (Environment.GetEnvironmentVariable(\"ANNOTATIONS_HANDLER\"))\r\n {\r\n"); - #line 24 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - - if (this._lambdaFunctions.Count == 1) - { - - - #line default - #line hidden - this.Write(" Func<"); - - #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", this._lambdaFunctions[0].GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); - - #line default - #line hidden - this.Write(", "); - - #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].GeneratedMethod.ReturnType.FullName)); - - #line default - #line hidden - this.Write("> "); - - #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name.ToLower())); - - #line default - #line hidden - this.Write(" = "); - - #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.ContainingType.Name)); - - #line default - #line hidden - this.Write("_"); - - #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name)); - - #line default - #line hidden - this.Write("_Generated."); - - #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name)); - - #line default - #line hidden - this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - - #line 29 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].LambdaMethod.Name.ToLower())); - - #line default - #line hidden - this.Write(", new "); - - #line 29 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].Serializer)); - - #line default - #line hidden - this.Write("()).Build().RunAsync();\n"); - - #line 30 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - - } - else - { - - - #line default - #line hidden - this.Write("\n switch (Environment.GetEnvironmentVariable(\"HANDLER\"))\n {\n"); - - #line 38 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 27 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" foreach (var model in this._lambdaFunctions) { @@ -129,14 +52,14 @@ public virtual string TransformText() #line hidden this.Write(" case \""); - #line 42 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 31 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write("\":\n"); + this.Write("\":\r\n"); - #line 43 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 32 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" if (model.GeneratedMethod.ReturnType.FullName == "void") { @@ -146,56 +69,56 @@ public virtual string TransformText() #line hidden this.Write(" Action<"); - #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); #line default #line hidden this.Write("> "); - #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); #line default #line hidden this.Write(" = "); - #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated."); - #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 48 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); #line default #line hidden this.Write(", new "); - #line 48 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].Serializer)); #line default #line hidden - this.Write("()).Build().RunAsync();\n break;\n"); + this.Write("()).Build().RunAsync();\r\n break;\r\n"); - #line 50 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 39 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" } else @@ -206,63 +129,63 @@ public virtual string TransformText() #line hidden this.Write(" Func<"); - #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); #line default #line hidden this.Write(", "); - #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.ReturnType.FullName)); #line default #line hidden this.Write("> "); - #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); #line default #line hidden this.Write(" = "); - #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated."); - #line 55 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 56 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); #line default #line hidden this.Write(", new "); - #line 56 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.Serializer)); #line default #line hidden - this.Write("()).Build().RunAsync();\n break;\n"); + this.Write("()).Build().RunAsync();\r\n break;\r\n"); - #line 58 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" } } @@ -270,17 +193,15 @@ public virtual string TransformText() #line default #line hidden - this.Write("\n }\n"); + this.Write("\r\n }\r\n"); - #line 64 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - + #line 53 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" - } #line default #line hidden - this.Write(" }\n}"); + this.Write(" }\r\n}"); return this.GenerationEnvironment.ToString(); } } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt index 46fa183a3..efdafd1ac 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt @@ -17,23 +17,12 @@ using Amazon.Lambda.Core; namespace <#= this._containingNamespace #>; -public class Program +public class GeneratedProgram { private static async Task Main(string[] args) { -<# - if (this._lambdaFunctions.Count == 1) - { -#> - Func<<#= string.Join(", ", this._lambdaFunctions[0].GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= this._lambdaFunctions[0].GeneratedMethod.ReturnType.FullName #>> <#=this._lambdaFunctions[0].LambdaMethod.Name.ToLower()#> = <#=this._lambdaFunctions[0].LambdaMethod.ContainingType.Name#>_<#=this._lambdaFunctions[0].LambdaMethod.Name#>_Generated.<#=this._lambdaFunctions[0].LambdaMethod.Name#>; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#=this._lambdaFunctions[0].LambdaMethod.Name.ToLower()#>, new <#= this._lambdaFunctions[0].Serializer #>()).Build().RunAsync(); -<# - } - else - { - #> - switch (Environment.GetEnvironmentVariable("HANDLER")) + switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) { <# foreach (var model in this._lambdaFunctions) @@ -62,8 +51,6 @@ public class Program } <# - - } #> } } \ No newline at end of file diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs index ad108aa98..b9a4d497e 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -66,14 +66,7 @@ public virtual string TransformText() #line default #line hidden - this.Write("\r\n{\r\n public "); - - #line 23 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); - - #line default - #line hidden - this.Write("class "); + this.Write("\r\n{\r\n public class "); #line 23 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.ContainingType.Name)); diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt index a0b7d91cc..550afeafe 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt @@ -20,7 +20,7 @@ using <#= ns #>; namespace <#= _model.LambdaMethod.ContainingNamespace #> { - public <#= _model.IsExecutable ? "static " : "" #>class <#= _model.GeneratedMethod.ContainingType.Name #> + public class <#= _model.GeneratedMethod.ContainingType.Name #> { <# this.Write(new FieldsAndConstructor(_model).TransformText()); diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs index 6026b2969..6450a31b9 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs @@ -33,6 +33,8 @@ public static class TypeFullNames public const string FromRouteAttribute = "Amazon.Lambda.Annotations.APIGateway.FromRouteAttribute"; public const string LambdaSerializerAttribute = "Amazon.Lambda.Core.LambdaSerializerAttribute"; + + public const string LambdaSerializerAttributeWithoutNamespace = "LambdaSerializerAttribute"; public static HashSet Requests = new HashSet { diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs index b26cc665c..3717d4d82 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs @@ -167,6 +167,11 @@ private void ProcessPackageTypeProperty(ILambdaFunctionSerializable lambdaFuncti default: throw new InvalidEnumArgumentException($"The {nameof(lambdaFunction.PackageType)} does not match any supported enums of type {nameof(LambdaPackageType)}"); } + + if (lambdaFunction.IsExecutable) + { + this._templateWriter.SetToken($"{propertiesPath}.Environment.Variables.ANNOTATIONS_HANDLER", lambdaFunction.MethodName); + } } /// diff --git a/Libraries/src/Amazon.Lambda.Annotations/LambdaFunctionAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/LambdaFunctionAttribute.cs index 20a8f93dc..faf3b1062 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/LambdaFunctionAttribute.cs +++ b/Libraries/src/Amazon.Lambda.Annotations/LambdaFunctionAttribute.cs @@ -8,11 +8,6 @@ namespace Amazon.Lambda.Annotations [AttributeUsage(AttributeTargets.Method)] public class LambdaFunctionAttribute : Attribute { - /// - /// The serializer to use. - /// - public string Serializer { get; set; } - /// /// The name of the CloudFormation resource that is associated with the Lambda function. /// diff --git a/Libraries/src/Amazon.Lambda.Annotations/LambdaOutputExecutableAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs similarity index 67% rename from Libraries/src/Amazon.Lambda.Annotations/LambdaOutputExecutableAttribute.cs rename to Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs index 94c4ccc21..804a2b069 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/LambdaOutputExecutableAttribute.cs +++ b/Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs @@ -6,8 +6,8 @@ namespace Amazon.Lambda.Annotations /// /// Indicates this the Lambda function is going to target an executable instead of a class based handler. /// - [AttributeUsage(AttributeTargets.Class)] - public class LambdaOutputExecutableAttribute : Attribute + [AttributeUsage( AttributeTargets.Assembly)] + public class LambdaGenerateMainAttribute : Attribute { } } \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj index 016457546..4163d6a78 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj @@ -53,6 +53,22 @@ PreserveNewest + + + PreserveNewest + + + + PreserveNewest + + + + PreserveNewest + + + + PreserveNewest + diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/CSharpSourceGeneratorVerifier.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/CSharpSourceGeneratorVerifier.cs index 8ff45f391..960e6fcdc 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/CSharpSourceGeneratorVerifier.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/CSharpSourceGeneratorVerifier.cs @@ -12,6 +12,8 @@ namespace Amazon.Lambda.Annotations.SourceGenerators.Tests { + using Amazon.Lambda.RuntimeSupport; + /// /// Source: https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.cookbook.md /// @@ -31,7 +33,8 @@ public Test(ReferencesMode referencesMode = ReferencesMode.All) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(IServiceCollection).Assembly.Location)) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(ServiceProvider).Assembly.Location)) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(RestApiAttribute).Assembly.Location)) - .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(DefaultLambdaJsonSerializer).Assembly.Location)); + .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(DefaultLambdaJsonSerializer).Assembly.Location)) + .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(LambdaBootstrapBuilder).Assembly.Location)); }); } @@ -44,7 +47,8 @@ public Test(ReferencesMode referencesMode = ReferencesMode.All) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(IServiceCollection).Assembly.Location)) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(ServiceProvider).Assembly.Location)) .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(RestApiAttribute).Assembly.Location)) - .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(DefaultLambdaJsonSerializer).Assembly.Location)); + .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(DefaultLambdaJsonSerializer).Assembly.Location)) + .AddMetadataReference(projectId, MetadataReference.CreateFromFile(typeof(LambdaBootstrapBuilder).Assembly.Location)); }); } } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToLower_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToLower_Generated.g.cs new file mode 100644 index 000000000..04cd4d249 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToLower_Generated.g.cs @@ -0,0 +1,56 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Amazon.Lambda.Core; + +namespace TestServerlessApp.Sub1 +{ + public class FunctionsZipOutput_ToLower_Generated + { + private static readonly ServiceProvider serviceProvider; + + static FunctionsZipOutput_ToLower_Generated() + { + SetExecutionEnvironment(); + var services = new ServiceCollection(); + + // By default, Lambda function class is added to the service container using the singleton lifetime + // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. + services.AddSingleton(); + + var startup = new TestServerlessApp.Startup(); + startup.ConfigureServices(services); + serviceProvider = services.BuildServiceProvider(); + } + + public static string ToLower(string text) + { + // Create a scope for every request, + // this allows creating scoped dependencies without creating a scope manually. + using var scope = serviceProvider.CreateScope(); + var functionsZipOutput = scope.ServiceProvider.GetRequiredService(); + + return functionsZipOutput.ToLower(text); + } + + private static void SetExecutionEnvironment() + { + const string envName = "AWS_EXECUTION_ENV"; + + var envValue = new StringBuilder(); + + // If there is an existing execution environment variable add the annotations package as a suffix. + if(!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName))) + { + envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); + } + + envValue.Append("amazon-lambda-annotations_1.0.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs index 12fd5d264..dd05e0915 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs @@ -8,7 +8,7 @@ namespace TestServerlessApp.Sub1 { - public static class Functions_ToUpper_Generated + public class Functions_ToUpper_Generated { private static readonly ServiceProvider serviceProvider; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs index 65ed30d1a..85093c6d0 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs @@ -8,7 +8,7 @@ namespace TestServerlessApp { - public static class Greeter_SayHelloAsync_Generated + public class Greeter_SayHelloAsync_Generated { private static readonly ServiceProvider serviceProvider; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs index 53a507160..47c64659d 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs @@ -3,11 +3,12 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; namespace TestServerlessApp { - public static class Greeter_SayHello_Generated + public class Greeter_SayHello_Generated { private static readonly ServiceProvider serviceProvider; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs index 6735ed796..6b589f408 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs @@ -7,11 +7,18 @@ namespace TestServerlessApp.Sub1; -public class Program +public class GeneratedProgram { private static async Task Main(string[] args) { - Func toupper = Functions_ToUpper_Generated.ToUpper; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(toupper, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + + switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) + { + case "ToUpper": + Func toupper = Functions_ToUpper_Generated.ToUpper; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(toupper, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + break; + + } } } \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs index 0c5c74020..ec3a05bc8 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs @@ -7,12 +7,12 @@ namespace TestServerlessApp; -public class Program +public class GeneratedProgram { private static async Task Main(string[] args) { - switch (Environment.GetEnvironmentVariable("HANDLER")) + switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) { case "SayHello": Func sayhello = Greeter_SayHello_Generated.SayHello; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs new file mode 100644 index 000000000..db403da31 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs @@ -0,0 +1,24 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Amazon.Lambda.Core; + +namespace TestServerlessApp.Sub1; + +public class GeneratedProgram +{ + private static async Task Main(string[] args) + { + + switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) + { + case "ToLower": + Func tolower = FunctionsZipOutput_ToLower_Generated.ToLower; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(tolower, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + break; + + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter.template index 63e20c35f..cd99fc094 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter.template +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter.template @@ -21,9 +21,14 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestProject::TestServerlessApp.Greeter_SayHello_Generated::SayHello" + "TestProject" ] }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "SayHello" + } + }, "Events": { "RootGet": { "Type": "HttpApi", @@ -54,9 +59,14 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestProject::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" + "TestProject" ] }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "SayHelloAsync" + } + }, "Events": { "RootGet": { "Type": "HttpApi", diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executable.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executable.template new file mode 100644 index 000000000..90d108993 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executable.template @@ -0,0 +1,29 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).", + "Resources": { + "ToLower": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "Runtime": "dotnet6", + "CodeUri": ".", + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Zip", + "Handler": "TestProject", + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "ToLower" + } + } + } + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executableimage.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executableimage.template new file mode 100644 index 000000000..c402557ec --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executableimage.template @@ -0,0 +1,32 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).", + "Resources": { + "ToUpper": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestProject" + ] + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "ToUpper" + } + } + } + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index a0ecef599..40d5170db 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -250,7 +250,7 @@ public async Task VerifyFunctionInSubNamespace() ExpectedDiagnostics = { new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("Functions_ToUpper_Generated.g.cs", expectedSubNamespaceGenerated), - new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent) + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent), }, ReferenceAssemblies = ReferenceAssemblies.Net.Net60 } @@ -260,10 +260,63 @@ public async Task VerifyFunctionInSubNamespace() Assert.Equal(expectedTemplateContent, actualTemplateContent); } + [Fact] + public async Task VerifyExecutableAssemblyWithZipAndHandler() + { + var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace_executable.template")).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = File.ReadAllText(Path.Combine("Snapshots", "Functions_AsyncStartupToLower_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedProgramGenerated = File.ReadAllText(Path.Combine("Snapshots", "ProgramZipOutput.g.cs")).ToEnvironmentLineEndings(); + + var test = new VerifyCS.Test + { + TestState = + { + Sources = + { + (Path.Combine("TestExecutableServerlessApp", "Sub1", "FunctionsZipOutput.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Sub1", "FunctionsZipOutput.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "FunctionsZipOutput_ToLower_Generated.g.cs", + SourceText.From(expectedSubNamespaceGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ), + ( + typeof(SourceGenerator.Generator), + "Program.g.cs", + SourceText.From(expectedProgramGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("FunctionsZipOutput_ToLower_Generated.g.cs", expectedSubNamespaceGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestExecutableServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent), + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }; + + foreach (var file in Directory.GetFiles( + Path.Combine("Amazon.Lambda.RuntimeSupport"), + "*.cs", SearchOption.AllDirectories)) + { + test.TestState.Sources.Add((file, File.ReadAllText(file))); + } + + await test.RunAsync(); + } + [Fact] public async Task VerifyExecutableAssembly() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace.template")).ToEnvironmentLineEndings(); + var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace_executableimage.template")).ToEnvironmentLineEndings(); var expectedSubNamespaceGenerated = File.ReadAllText(Path.Combine("Snapshots", "Functions_AsyncStartupToUpper_Generated.g.cs")).ToEnvironmentLineEndings(); var expectedProgramGenerated = File.ReadAllText(Path.Combine("Snapshots", "Program.g.cs")).ToEnvironmentLineEndings(); @@ -278,7 +331,7 @@ public async Task VerifyExecutableAssembly() (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaOutputExecutableAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaOutputExecutableAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = @@ -332,7 +385,7 @@ public async Task VerifyExecutableAssemblyWithMultipleHandler() (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaOutputExecutableAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaOutputExecutableAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/WriterTests/CloudFormationWriterTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/WriterTests/CloudFormationWriterTests.cs index f9616c5de..d973350f9 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/WriterTests/CloudFormationWriterTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/WriterTests/CloudFormationWriterTests.cs @@ -822,7 +822,9 @@ private CloudFormationWriter GetCloudFormationWriter(IFileManager fileManager, I public class LambdaFunctionModelTest : ILambdaFunctionSerializable { + public string MethodName { get; set; } public string Handler { get; set; } + public bool IsExecutable { get; set; } public string ResourceName { get; set; } public uint? Timeout { get; set; } public uint? MemorySize { get; set; } diff --git a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs index 955e187fc..8a8a683a7 100644 --- a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs +++ b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs @@ -1,3 +1,5 @@ -using Amazon.Lambda.Core; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Core; -[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] \ No newline at end of file +[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] +[assembly: LambdaGenerateMain] \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/Startup.cs b/Libraries/test/TestExecutableServerlessApp/Startup.cs index 22c4bdb57..eb9362992 100644 --- a/Libraries/test/TestExecutableServerlessApp/Startup.cs +++ b/Libraries/test/TestExecutableServerlessApp/Startup.cs @@ -9,7 +9,6 @@ namespace TestServerlessApp { [LambdaStartup] - [LambdaOutputExecutable] public class Startup { public void ConfigureServices(IServiceCollection services) diff --git a/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs b/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs index eb5b13ed7..fcaddf827 100644 --- a/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs +++ b/Libraries/test/TestExecutableServerlessApp/Sub1/Functions.cs @@ -1,14 +1,14 @@ -using Amazon.Lambda.Annotations; -using Amazon.Lambda.Core; - -namespace TestServerlessApp.Sub1 +namespace TestServerlessApp.Sub1 { + using Amazon.Lambda.Annotations; + using Amazon.Lambda.Core; + public class Functions { - [LambdaFunction(ResourceName = "ToUpper", PackageType = LambdaPackageType.Image, Serializer = "Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer")] + [LambdaFunction(ResourceName = "ToUpper", PackageType = LambdaPackageType.Image)] public string ToUpper(string text) { return text.ToUpper(); } } -} +} \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/Sub1/FunctionsZipOutput.cs b/Libraries/test/TestExecutableServerlessApp/Sub1/FunctionsZipOutput.cs new file mode 100644 index 000000000..194883818 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/Sub1/FunctionsZipOutput.cs @@ -0,0 +1,14 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Core; + +namespace TestServerlessApp.Sub1 +{ + public class FunctionsZipOutput + { + [LambdaFunction(ResourceName = "ToLower")] + public string ToLower(string text) + { + return text.ToUpper(); + } + } +} diff --git a/Libraries/test/TestExecutableServerlessApp/Temp.cs b/Libraries/test/TestExecutableServerlessApp/Temp.cs deleted file mode 100644 index 94baa23d7..000000000 --- a/Libraries/test/TestExecutableServerlessApp/Temp.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace TestServerlessApp; - -using System; -using System.Threading.Tasks; - -using Amazon.Lambda.Core; - -public class Temp -{ - public static async Task Handle() - { - Action voidreturn = VoidExample_VoidReturn_Generated.VoidReturn; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(voidreturn, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); - } - - public static void Handler(string message) - { - - } -} \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/serverless.template b/Libraries/test/TestExecutableServerlessApp/serverless.template index 588dadd5e..b1d9c89ec 100644 --- a/Libraries/test/TestExecutableServerlessApp/serverless.template +++ b/Libraries/test/TestExecutableServerlessApp/serverless.template @@ -37,8 +37,13 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicReturn_Generated::DynamicReturn" + "TestExecutableServerlessApp" ] + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "DynamicReturn" + } } } }, @@ -57,8 +62,13 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicInput_Generated::DynamicInput" + "TestExecutableServerlessApp" ] + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "DynamicInput" + } } } }, @@ -77,8 +87,13 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.TaskExample_TaskReturn_Generated::TaskReturn" + "TestExecutableServerlessApp" ] + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "TaskReturn" + } } } }, @@ -97,8 +112,13 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.VoidExample_VoidReturn_Generated::VoidReturn" + "TestExecutableServerlessApp" ] + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "VoidReturn" + } } } }, @@ -120,7 +140,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeader_Generated::OkResponseWithHeader" + "TestExecutableServerlessApp" ] }, "Events": { @@ -131,6 +151,11 @@ "Method": "GET" } } + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "OkResponseWithHeader" + } } } }, @@ -152,7 +177,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated::OkResponseWithHeaderAsync" + "TestExecutableServerlessApp" ] }, "Events": { @@ -163,6 +188,11 @@ "Method": "GET" } } + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "OkResponseWithHeaderAsync" + } } } }, @@ -184,7 +214,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated::NotFoundResponseWithHeaderV2" + "TestExecutableServerlessApp" ] }, "Events": { @@ -195,6 +225,11 @@ "Method": "GET" } } + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "NotFoundResponseWithHeaderV2" + } } } }, @@ -216,7 +251,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated::NotFoundResponseWithHeaderV2Async" + "TestExecutableServerlessApp" ] }, "Events": { @@ -227,6 +262,11 @@ "Method": "GET" } } + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "NotFoundResponseWithHeaderV2Async" + } } } }, @@ -248,7 +288,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated::NotFoundResponseWithHeaderV1" + "TestExecutableServerlessApp" ] }, "Events": { @@ -260,6 +300,11 @@ "PayloadFormatVersion": "1.0" } } + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "NotFoundResponseWithHeaderV1" + } } } }, @@ -281,7 +326,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated::NotFoundResponseWithHeaderV1Async" + "TestExecutableServerlessApp" ] }, "Events": { @@ -293,6 +338,11 @@ "PayloadFormatVersion": "1.0" } } + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "NotFoundResponseWithHeaderV1Async" + } } } }, @@ -314,7 +364,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHello_Generated::SayHello" + "TestExecutableServerlessApp" ] }, "Events": { @@ -326,6 +376,11 @@ "PayloadFormatVersion": "1.0" } } + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "SayHello" + } } } }, @@ -347,7 +402,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" + "TestExecutableServerlessApp" ] }, "Events": { @@ -359,6 +414,11 @@ "PayloadFormatVersion": "1.0" } } + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "SayHelloAsync" + } } } }, @@ -377,8 +437,13 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Sub1.Functions_ToUpper_Generated::ToUpper" + "TestExecutableServerlessApp" ] + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "ToUpper" + } } } }, @@ -400,7 +465,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.NullableReferenceTypeExample_NullableHeaderHttpApi_Generated::NullableHeaderHttpApi" + "TestExecutableServerlessApp" ] }, "Events": { @@ -411,6 +476,11 @@ "Method": "GET" } } + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "NullableHeaderHttpApi" + } } } }, @@ -429,8 +499,34 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.IntrinsicExample_HasIntrinsic_Generated::HasIntrinsic" + "TestExecutableServerlessApp" ] + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "HasIntrinsic" + } + } + } + }, + "ToLower": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Zip", + "CodeUri": ".", + "Handler": "TestExecutableServerlessApp", + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "ToLower" + } } } } diff --git a/Libraries/test/TestServerlessApp/Sub1/Functions.cs b/Libraries/test/TestServerlessApp/Sub1/Functions.cs index 00b4bd280..023d71d53 100644 --- a/Libraries/test/TestServerlessApp/Sub1/Functions.cs +++ b/Libraries/test/TestServerlessApp/Sub1/Functions.cs @@ -5,7 +5,7 @@ namespace TestServerlessApp.Sub1 { public class Functions { - [LambdaFunction(ResourceName = "ToUpper", PackageType = LambdaPackageType.Image, Serializer = "System.Text.Json.JsonSerializer")] + [LambdaFunction(ResourceName = "ToUpper", PackageType = LambdaPackageType.Image)] public string ToUpper(string text) { return text.ToUpper(); From c73b61c8f18efa728f19176419ed623dcc9c0528 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Tue, 22 Aug 2023 16:42:30 +0100 Subject: [PATCH 04/27] Move serialization to constructor --- .../Models/GeneratedMethodModelBuilder.cs | 3 +- .../Templates/APIGatewayInvoke.cs | 90 +++--- .../Templates/APIGatewayInvoke.tt | 7 +- .../Templates/APIGatewaySetupParameters.cs | 264 +++++++----------- .../Templates/APIGatewaySetupParameters.tt | 5 +- .../Templates/FieldsAndConstructor.cs | 54 +++- .../Templates/FieldsAndConstructor.tt | 3 + .../Templates/LambdaFunctionTemplate.cs | 11 +- .../Templates/LambdaFunctionTemplate.tt | 1 + .../ComplexCalculator_Add_Generated.g.cs | 10 +- .../ComplexCalculator_Subtract_Generated.g.cs | 16 +- ...ndResponseWithHeaderV1Async_Generated.g.cs | 4 + ...otFoundResponseWithHeaderV1_Generated.g.cs | 4 + ...ndResponseWithHeaderV2Async_Generated.g.cs | 4 + ...otFoundResponseWithHeaderV2_Generated.g.cs | 4 + ...s_OkResponseWithHeaderAsync_Generated.g.cs | 3 + ...amples_OkResponseWithHeader_Generated.g.cs | 3 + .../Greeter_SayHelloAsync_Generated.g.cs | 25 +- .../Snapshots/Greeter_SayHello_Generated.g.cs | 25 +- 19 files changed, 269 insertions(+), 267 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/GeneratedMethodModelBuilder.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/GeneratedMethodModelBuilder.cs index 35ba2fb0b..5a0460beb 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/GeneratedMethodModelBuilder.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/GeneratedMethodModelBuilder.cs @@ -38,7 +38,8 @@ private static IList BuildUsings(LambdaMethodModel lambdaMethodModel, "System.Linq", "System.Collections.Generic", "System.Text", - "System.Threading.Tasks" + "System.Threading.Tasks", + "System.IO" }; if (configureMethodSymbol != null) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewayInvoke.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewayInvoke.cs index b955538be..f2435c571 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewayInvoke.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewayInvoke.cs @@ -1,7 +1,7 @@ // ------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version: 17.0.0.0 +// Runtime Version: 16.0.0.0 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -22,8 +22,8 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates /// Class to produce the template output /// - #line 1 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public partial class APIGatewayInvoke : APIGatewayInvokeBase { #line hidden @@ -33,7 +33,7 @@ public partial class APIGatewayInvoke : APIGatewayInvokeBase public virtual string TransformText() { - #line 10 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 10 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" var restApiAttribute = _model.LambdaMethod.Attributes.FirstOrDefault(att => att.Type.FullName == TypeFullNames.RestApiAttribute) as AttributeModel; var httpApiAttribute = _model.LambdaMethod.Attributes.FirstOrDefault(att => att.Type.FullName == TypeFullNames.HttpApiAttribute) as AttributeModel; @@ -46,52 +46,48 @@ public virtual string TransformText() #line hidden this.Write(" var httpResults = "); - #line 17 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); #line default #line hidden - #line 17 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name.ToCamelCase())); #line default #line hidden this.Write("."); - #line 17 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.Name)); #line default #line hidden this.Write("("); - #line 17 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_parameterSignature)); #line default #line hidden - this.Write(");\r\n HttpResultSerializationOptions.ProtocolFormat serializationFormat" + - " = "); + this.Write(");\r\n HttpResultSerializationOptions.ProtocolFormat serializationFormat = "); - #line 18 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(restApiAttribute != null ? "HttpResultSerializationOptions.ProtocolFormat.RestApi" : "HttpResultSerializationOptions.ProtocolFormat.HttpApi")); #line default #line hidden - this.Write(";\r\n HttpResultSerializationOptions.ProtocolVersion serializationVersio" + - "n = "); + this.Write(";\r\n HttpResultSerializationOptions.ProtocolVersion serializationVersion = "); - #line 19 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 19 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "HttpResultSerializationOptions.ProtocolVersion.V1" : "HttpResultSerializationOptions.ProtocolVersion.V2")); #line default #line hidden - this.Write(";\r\n var serializationOptions = new HttpResultSerializationOptions { Fo" + - "rmat = serializationFormat, Version = serializationVersion };\r\n var r" + - "esponse = httpResults.Serialize(serializationOptions);\r\n"); + this.Write(";\r\n var serializationOptions = new HttpResultSerializationOptions { Format = serializationFormat, Version = serializationVersion };\r\n var response = httpResults.Serialize(serializationOptions);\r\n"); - #line 22 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 22 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" } else if (_model.LambdaMethod.ReturnsVoid) @@ -102,28 +98,28 @@ public virtual string TransformText() #line hidden this.Write(" "); - #line 27 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 27 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name.ToCamelCase())); #line default #line hidden this.Write("."); - #line 27 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 27 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.Name)); #line default #line hidden this.Write("("); - #line 27 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 27 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_parameterSignature)); #line default #line hidden this.Write(");\r\n"); - #line 28 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" } else if (_model.LambdaMethod.ReturnsVoidTask) @@ -134,28 +130,28 @@ public virtual string TransformText() #line hidden this.Write(" await "); - #line 33 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 33 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name.ToCamelCase())); #line default #line hidden this.Write("."); - #line 33 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 33 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.Name)); #line default #line hidden this.Write("("); - #line 33 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 33 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_parameterSignature)); #line default #line hidden this.Write(");\r\n"); - #line 34 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 34 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" } else @@ -166,34 +162,34 @@ public virtual string TransformText() #line hidden this.Write(" var response = "); - #line 39 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 39 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); #line default #line hidden - #line 39 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 39 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name.ToCamelCase())); #line default #line hidden this.Write("."); - #line 39 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 39 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.Name)); #line default #line hidden this.Write("("); - #line 39 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 39 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_parameterSignature)); #line default #line hidden this.Write(");\r\n"); - #line 40 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 40 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" } @@ -205,7 +201,7 @@ public virtual string TransformText() #line hidden this.Write(" return response;\r\n"); - #line 47 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" } else @@ -220,7 +216,7 @@ public virtual string TransformText() #line hidden this.Write("\r\n var body = response.ToString();\r\n"); - #line 58 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 58 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" } else if (_model.LambdaMethod.ReturnType.IsString()) @@ -233,16 +229,9 @@ public virtual string TransformText() #line default #line hidden - this.Write("\r\n var body = "); + this.Write(" var memoryStream = new MemoryStream();\r\n serializer.Serialize(response, memoryStream);\r\n memoryStream.Position = 0;\r\n\r\n // convert stream to string\r\n StreamReader reader = new StreamReader( memoryStream );\r\n var body = reader.ReadToEnd();\r\n"); - #line 68 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.Serializer)); - - #line default - #line hidden - this.Write(".Serialize(response);\r\n"); - - #line 69 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 74 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" } } @@ -252,14 +241,14 @@ public virtual string TransformText() #line hidden this.Write("\r\n return new "); - #line 74 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 79 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsVoidOrGenericTask ? _model.GeneratedMethod.ReturnType.TaskTypeArgument : _model.GeneratedMethod.ReturnType.FullName)); #line default #line hidden this.Write("\r\n {\r\n"); - #line 76 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 81 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) { @@ -269,22 +258,21 @@ public virtual string TransformText() #line hidden this.Write(" Body = "); - #line 80 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 85 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnType.IsString() ? "response" : "body")); #line default #line hidden - this.Write(",\r\n Headers = new Dictionary\r\n {\r\n " + - " {\"Content-Type\", "); + this.Write(",\r\n Headers = new Dictionary\r\n {\r\n {\"Content-Type\", "); - #line 83 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 88 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnType.IsString() ? "\"text/plain\"" : "\"application/json\"")); #line default #line hidden this.Write("}\r\n },\r\n"); - #line 85 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 90 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" } @@ -293,7 +281,7 @@ public virtual string TransformText() #line hidden this.Write(" StatusCode = 200\r\n };\r\n"); - #line 90 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" + #line 95 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewayInvoke.tt" } @@ -310,7 +298,7 @@ public virtual string TransformText() /// /// Base class for this transformation /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public class APIGatewayInvokeBase { #region Fields diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewayInvoke.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewayInvoke.tt index 75ce3a75c..577284842 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewayInvoke.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewayInvoke.tt @@ -64,8 +64,13 @@ else { #> + var memoryStream = new MemoryStream(); + serializer.Serialize(response, memoryStream); + memoryStream.Position = 0; - var body = <#= _model.Serializer #>.Serialize(response); + // convert stream to string + StreamReader reader = new StreamReader( memoryStream ); + var body = reader.ReadToEnd(); <# } } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs index f00263815..812254443 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs @@ -1,7 +1,7 @@ // ------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version: 17.0.0.0 +// Runtime Version: 16.0.0.0 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -22,8 +22,8 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates /// Class to produce the template output /// - #line 1 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public partial class APIGatewaySetupParameters : APIGatewaySetupParametersBase { #line hidden @@ -33,7 +33,7 @@ public partial class APIGatewaySetupParameters : APIGatewaySetupParametersBase public virtual string TransformText() { - #line 10 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 10 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" ParameterSignature = string.Join(", ", _model.LambdaMethod.Parameters .Select(p => @@ -77,7 +77,7 @@ public virtual string TransformText() #line hidden this.Write(" var validationErrors = new List();\r\n\r\n"); - #line 50 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 50 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } @@ -95,21 +95,21 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 62 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 62 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = scope.ServiceProvider.GetRequiredService<"); - #line 62 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 62 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(">();\r\n"); - #line 63 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 63 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromQueryAttribute)) @@ -127,21 +127,21 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 75 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 75 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = default("); - #line 75 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 75 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(");\r\n"); - #line 76 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 76 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) @@ -175,77 +175,70 @@ public virtual string TransformText() #line hidden this.Write(" if (__request__."); - #line 104 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 104 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); #line default #line hidden this.Write("?.ContainsKey(\""); - #line 104 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 104 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); #line default #line hidden this.Write("\") == true)\r\n {\r\n "); - #line 106 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 106 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = __request__."); - #line 106 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 106 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); #line default #line hidden this.Write("[\""); - #line 106 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 106 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); #line default #line hidden this.Write("\"]"); - #line 106 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 106 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(commaSplit)); #line default #line hidden - this.Write("\r\n .Select(q =>\r\n {\r\n " + - " try\r\n {\r\n return ("); + this.Write("\r\n .Select(q =>\r\n {\r\n try\r\n {\r\n return ("); - #line 111 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 111 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); #line default #line hidden this.Write(")Convert.ChangeType(q, typeof("); - #line 111 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 111 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullNameWithoutAnnotations)); #line default #line hidden - this.Write(@")); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($""Value {q} at '"); + this.Write("));\r\n }\r\n catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException)\r\n {\r\n validationErrors.Add($\"Value {q} at '"); - #line 115 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 115 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); #line default #line hidden - this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n retur" + - "n default;\r\n }\r\n })\r\n " + - " .ToList();\r\n }\r\n\r\n"); + this.Write("' failed to satisfy constraint: {e.Message}\");\r\n return default;\r\n }\r\n })\r\n .ToList();\r\n }\r\n\r\n"); - #line 122 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 122 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -257,82 +250,77 @@ public virtual string TransformText() #line hidden this.Write(" if (__request__."); - #line 128 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 128 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); #line default #line hidden this.Write("?.ContainsKey(\""); - #line 128 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 128 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); #line default #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n "); - #line 132 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 132 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = ("); - #line 132 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 132 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(")Convert.ChangeType(__request__."); - #line 132 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 132 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); #line default #line hidden this.Write("[\""); - #line 132 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 132 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); #line default #line hidden this.Write("\"], typeof("); - #line 132 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 132 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); #line default #line hidden - this.Write("));\r\n }\r\n catch (Exception e) when (e is InvalidCas" + - "tException || e is FormatException || e is OverflowException || e is ArgumentExc" + - "eption)\r\n {\r\n validationErrors.Add($\"Value {__" + - "request__."); + this.Write("));\r\n }\r\n catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException)\r\n {\r\n validationErrors.Add($\"Value {__request__."); - #line 136 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 136 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); #line default #line hidden this.Write("[\""); - #line 136 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 136 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); #line default #line hidden - this.Write("\"]} at \'"); + this.Write("\"]} at '"); - #line 136 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 136 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); #line default #line hidden - this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + - "\n\r\n"); + this.Write("' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r\n\r\n"); - #line 140 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 140 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } @@ -354,21 +342,21 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 156 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 156 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = default("); - #line 156 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 156 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(");\r\n"); - #line 157 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 157 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) @@ -402,78 +390,70 @@ public virtual string TransformText() #line hidden this.Write(" if (__request__."); - #line 185 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 185 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headers)); #line default #line hidden this.Write("?.Any(x => string.Equals(x.Key, \""); - #line 185 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 185 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\", StringComparison.OrdinalIgnoreCase)) == true)\r\n {\r\n " + - ""); + this.Write("\", StringComparison.OrdinalIgnoreCase)) == true)\r\n {\r\n "); - #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 187 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = __request__."); - #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 187 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headers)); #line default #line hidden this.Write(".First(x => string.Equals(x.Key, \""); - #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 187 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden this.Write("\", StringComparison.OrdinalIgnoreCase)).Value"); - #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 187 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(commaSplit)); #line default #line hidden - this.Write("\r\n .Select(q =>\r\n {\r\n " + - " try\r\n {\r\n return ("); + this.Write("\r\n .Select(q =>\r\n {\r\n try\r\n {\r\n return ("); - #line 192 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 192 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); #line default #line hidden this.Write(")Convert.ChangeType(q, typeof("); - #line 192 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 192 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullNameWithoutAnnotations)); #line default #line hidden - this.Write(@")); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($""Value {q} at '"); + this.Write("));\r\n }\r\n catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException)\r\n {\r\n validationErrors.Add($\"Value {q} at '"); - #line 196 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 196 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n retur" + - "n default;\r\n }\r\n })\r\n " + - " .ToList();\r\n }\r\n\r\n"); + this.Write("' failed to satisfy constraint: {e.Message}\");\r\n return default;\r\n }\r\n })\r\n .ToList();\r\n }\r\n\r\n"); - #line 203 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 203 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -485,82 +465,77 @@ public virtual string TransformText() #line hidden this.Write(" if (__request__."); - #line 209 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 209 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headers)); #line default #line hidden this.Write("?.Any(x => string.Equals(x.Key, \""); - #line 209 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 209 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\", StringComparison.OrdinalIgnoreCase)) == true)\r\n {\r\n " + - "try\r\n {\r\n "); + this.Write("\", StringComparison.OrdinalIgnoreCase)) == true)\r\n {\r\n try\r\n {\r\n "); - #line 213 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 213 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = ("); - #line 213 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 213 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(")Convert.ChangeType(__request__."); - #line 213 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 213 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headers)); #line default #line hidden this.Write(".First(x => string.Equals(x.Key, \""); - #line 213 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 213 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden this.Write("\", StringComparison.OrdinalIgnoreCase)).Value, typeof("); - #line 213 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 213 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); #line default #line hidden - this.Write("));\r\n }\r\n catch (Exception e) when (e is InvalidCas" + - "tException || e is FormatException || e is OverflowException || e is ArgumentExc" + - "eption)\r\n {\r\n validationErrors.Add($\"Value {__" + - "request__."); + this.Write("));\r\n }\r\n catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException)\r\n {\r\n validationErrors.Add($\"Value {__request__."); - #line 217 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 217 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headers)); #line default #line hidden this.Write(".First(x => string.Equals(x.Key, \""); - #line 217 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 217 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\", StringComparison.OrdinalIgnoreCase)).Value} at \'"); + this.Write("\", StringComparison.OrdinalIgnoreCase)).Value} at '"); - #line 217 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 217 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + - "\n\r\n"); + this.Write("' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r\n\r\n"); - #line 221 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 221 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } } @@ -575,14 +550,14 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 230 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 230 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = __request__.Body;\r\n\r\n"); - #line 232 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 232 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -593,44 +568,35 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 237 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 237 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = default("); - #line 237 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 237 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden - this.Write(");\r\n try\r\n {\r\n "); + this.Write(");\r\n try\r\n {\r\n // convert string to stream\r\n var byteArray = Encoding.ASCII.GetBytes(__request__.Body);\r\n var stream = new MemoryStream(byteArray);\r\n "); - #line 240 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 243 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden - this.Write(" = "); + this.Write(" = serializer.Deserialize<"); - #line 240 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.Serializer)); - - #line default - #line hidden - this.Write(".Deserialize<"); - - #line 240 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 243 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden - this.Write(">(__request__.Body);\r\n }\r\n catch (Exception e)\r\n " + - " {\r\n validationErrors.Add($\"Value {__request__.Body} at \'body\' fa" + - "iled to satisfy constraint: {e.Message}\");\r\n }\r\n\r\n"); + this.Write(">(stream);\r\n }\r\n catch (Exception e)\r\n {\r\n validationErrors.Add($\"Value {__request__.Body} at 'body' failed to satisfy constraint: {e.Message}\");\r\n }\r\n\r\n"); - #line 247 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 250 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } } @@ -646,76 +612,70 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 260 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = default("); - #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 260 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(");\r\n if (__request__.PathParameters?.ContainsKey(\""); - #line 258 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 261 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n "); - #line 262 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 265 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = ("); - #line 262 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 265 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(")Convert.ChangeType(__request__.PathParameters[\""); - #line 262 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 265 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default #line hidden this.Write("\"], typeof("); - #line 262 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 265 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); #line default #line hidden - this.Write(@")); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($""Value {__request__.PathParameters["""); + this.Write("));\r\n }\r\n catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException)\r\n {\r\n validationErrors.Add($\"Value {__request__.PathParameters[\""); - #line 266 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 269 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default #line hidden - this.Write("\"]} at \'"); + this.Write("\"]} at '"); - #line 266 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 269 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default #line hidden - this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + - "\n\r\n"); + this.Write("' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r\n\r\n"); - #line 270 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 273 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -730,28 +690,16 @@ public virtual string TransformText() #line default #line hidden - this.Write(" // return 400 Bad Request if there exists a validation error\r\n " + - " if (validationErrors.Any())\r\n {\r\n var errorResult" + - " = new "); + this.Write(" // return 400 Bad Request if there exists a validation error\r\n if (validationErrors.Any())\r\n {\r\n var errorResult = new "); - #line 284 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 287 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse" : "Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse")); #line default #line hidden - this.Write(@" - { - Body = @$""{{""""message"""": """"{validationErrors.Count} validation error(s) detected: {string.Join("","", validationErrors)}""""}}"", - Headers = new Dictionary - { - {""Content-Type"", ""application/json""}, - {""x-amzn-ErrorType"", ""ValidationException""} - }, - StatusCode = 400 - }; -"); - - #line 294 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + this.Write("\r\n {\r\n Body = @$\"{{\"\"message\"\": \"\"{validationErrors.Count} validation error(s) detected: {string.Join(\",\", validationErrors)}\"\"}}\",\r\n Headers = new Dictionary\r\n {\r\n {\"Content-Type\", \"application/json\"},\r\n {\"x-amzn-ErrorType\", \"ValidationException\"}\r\n },\r\n StatusCode = 400\r\n };\r\n"); + + #line 297 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" if(_model.LambdaMethod.ReturnsIHttpResults) { @@ -759,11 +707,9 @@ public virtual string TransformText() #line default #line hidden - this.Write(" var errorStream = new System.IO.MemoryStream();\r\n " + - "System.Text.Json.JsonSerializer.Serialize(errorStream, errorResult);\r\n " + - " return errorStream;\r\n"); + this.Write(" var errorStream = new System.IO.MemoryStream();\r\n System.Text.Json.JsonSerializer.Serialize(errorStream, errorResult);\r\n return errorStream;\r\n"); - #line 301 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 304 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -774,7 +720,7 @@ public virtual string TransformText() #line hidden this.Write(" return errorResult;\r\n"); - #line 307 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 310 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } @@ -783,7 +729,7 @@ public virtual string TransformText() #line hidden this.Write(" }\r\n\r\n"); - #line 312 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 315 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } @@ -800,7 +746,7 @@ public virtual string TransformText() /// /// Base class for this transformation /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public class APIGatewaySetupParametersBase { #region Fields diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt index 321a3fc46..ad9f01f93 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt @@ -237,7 +237,10 @@ var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); try { - <#= parameter.Name #> = <#= _model.Serializer #>.Deserialize<<#= parameter.Type.FullName #>>(__request__.Body); + // convert string to stream + var byteArray = Encoding.ASCII.GetBytes(__request__.Body); + var stream = new MemoryStream(byteArray); + <#= parameter.Name #> = serializer.Deserialize<<#= parameter.Type.FullName #>>(stream); } catch (Exception e) { diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs index 2b530b268..b5e2d6ab6 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs @@ -77,9 +77,23 @@ public virtual string TransformText() #line default #line hidden - this.Write(";\r\n"); + this.Write(";\r\n private "); #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); + + #line default + #line hidden + this.Write("readonly "); + + #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.Serializer)); + + #line default + #line hidden + this.Write(" serializer;\r\n"); + + #line 19 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } @@ -88,7 +102,7 @@ public virtual string TransformText() #line hidden this.Write("\r\n"); - #line 22 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 23 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" if (_model.IsExecutable) { @@ -98,14 +112,14 @@ public virtual string TransformText() #line hidden this.Write(" static "); - #line 26 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 27 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.ContainingType.Name)); #line default #line hidden this.Write("() \r\n"); - #line 27 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } else @@ -116,14 +130,14 @@ public virtual string TransformText() #line hidden this.Write(" public "); - #line 32 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 33 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.ContainingType.Name)); #line default #line hidden this.Write("()\r\n"); - #line 33 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 34 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } @@ -132,7 +146,7 @@ public virtual string TransformText() #line hidden this.Write(" {\r\n SetExecutionEnvironment();\r\n"); - #line 38 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 39 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" if (_model.LambdaMethod.UsingDependencyInjection) { @@ -142,21 +156,28 @@ public virtual string TransformText() #line hidden this.Write(" var services = new ServiceCollection();\r\n\r\n // By default, Lambda function class is added to the service container using the singleton lifetime\r\n // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method.\r\n services.AddSingleton<"); - #line 46 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); #line default #line hidden - this.Write(">();\r\n\r\n var startup = new "); + this.Write(">();\r\n services.AddSingleton<"); #line 48 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.Serializer)); + + #line default + #line hidden + this.Write(">();\r\n\r\n var startup = new "); + + #line 50 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.StartupType.FullName)); #line default #line hidden this.Write("();\r\n startup.ConfigureServices(services);\r\n serviceProvider = services.BuildServiceProvider();\r\n"); - #line 51 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 53 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } else @@ -167,21 +188,28 @@ public virtual string TransformText() #line hidden this.Write(" "); - #line 56 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 58 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name.ToCamelCase())); #line default #line hidden this.Write(" = new "); - #line 56 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 58 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); + #line default + #line hidden + this.Write("();\r\n serializer = new "); + + #line 59 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.Serializer)); + #line default #line hidden this.Write("();\r\n"); - #line 57 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 60 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt index 6afb7d31c..2aa43bd42 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt @@ -15,6 +15,7 @@ { #> private <#= _model.IsExecutable ? "static " : "" #>readonly <#= _model.LambdaMethod.ContainingType.Name #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>; + private <#= _model.IsExecutable ? "static " : "" #>readonly <#= _model.Serializer #> serializer; <# } #> @@ -44,6 +45,7 @@ // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton<<#= _model.LambdaMethod.ContainingType.Name #>>(); + services.AddSingleton<<#= _model.Serializer #>>(); var startup = new <#= _model.StartupType.FullName #>(); startup.ConfigureServices(services); @@ -54,6 +56,7 @@ { #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = new <#= _model.LambdaMethod.ContainingType.Name #>(); + serializer = new <#= _model.Serializer #>(); <# } #> diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs index b9a4d497e..da58c1065 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -137,11 +137,18 @@ public virtual string TransformText() #line 40 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); + #line default + #line hidden + this.Write(">();\r\n var serializer = scope.ServiceProvider.GetRequiredService<"); + + #line 41 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.Serializer)); + #line default #line hidden this.Write(">();\r\n\r\n"); - #line 42 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 43 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } @@ -161,7 +168,7 @@ public virtual string TransformText() #line hidden this.Write(" }\r\n\r\n private static void SetExecutionEnvironment()\r\n {\r\n const string envName = \"AWS_EXECUTION_ENV\";\r\n\r\n var envValue = new StringBuilder();\r\n\r\n // If there is an existing execution environment variable add the annotations package as a suffix.\r\n if(!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName)))\r\n {\r\n envValue.Append($\"{Environment.GetEnvironmentVariable(envName)}_\");\r\n }\r\n\r\n envValue.Append(\"amazon-lambda-annotations_"); - #line 70 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 71 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.SourceGeneratorVersion)); #line default diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt index 550afeafe..d371cd808 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt @@ -38,6 +38,7 @@ this.Write(new FieldsAndConstructor(_model).TransformText()); using var scope = serviceProvider.CreateScope(); var <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = scope.ServiceProvider.GetRequiredService<<#= _model.LambdaMethod.ContainingType.Name #>>(); + var serializer = scope.ServiceProvider.GetRequiredService<<#= _model.Serializer #>>(); <# } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Add_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Add_Generated.g.cs index e764653e1..a5e6d453c 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Add_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Add_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp @@ -10,11 +11,13 @@ namespace TestServerlessApp public class ComplexCalculator_Add_Generated { private readonly ComplexCalculator complexCalculator; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public ComplexCalculator_Add_Generated() { SetExecutionEnvironment(); complexCalculator = new ComplexCalculator(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse Add(Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) @@ -22,8 +25,13 @@ public Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse Add(Amazo var complexNumbers = __request__.Body; var response = complexCalculator.Add(complexNumbers, __context__, __request__); + var memoryStream = new MemoryStream(); + serializer.Serialize(response, memoryStream); + memoryStream.Position = 0; - var body = System.Text.Json.JsonSerializer.Serialize(response); + // convert stream to string + StreamReader reader = new StreamReader( memoryStream ); + var body = reader.ReadToEnd(); return new Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse { diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Subtract_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Subtract_Generated.g.cs index 8f7db3a8d..7db78f473 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Subtract_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ComplexCalculator_Subtract_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp @@ -9,11 +11,13 @@ namespace TestServerlessApp public class ComplexCalculator_Subtract_Generated { private readonly ComplexCalculator complexCalculator; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public ComplexCalculator_Subtract_Generated() { SetExecutionEnvironment(); complexCalculator = new ComplexCalculator(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse Subtract(Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) @@ -23,7 +27,10 @@ public Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse Subtract( var complexNumbers = default(System.Collections.Generic.IList>); try { - complexNumbers = System.Text.Json.JsonSerializer.Deserialize>>(__request__.Body); + // convert string to stream + var byteArray = Encoding.ASCII.GetBytes(__request__.Body); + var stream = new MemoryStream(byteArray); + complexNumbers = serializer.Deserialize>>(stream); } catch (Exception e) { @@ -47,8 +54,13 @@ public Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse Subtract( } var response = complexCalculator.Subtract(complexNumbers); + var memoryStream = new MemoryStream(); + serializer.Serialize(response, memoryStream); + memoryStream.Position = 0; - var body = System.Text.Json.JsonSerializer.Serialize(response); + // convert stream to string + StreamReader reader = new StreamReader( memoryStream ); + var body = reader.ReadToEnd(); return new Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse { diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated.g.cs index c37ab5ac4..72723fe4e 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; using Amazon.Lambda.Annotations.APIGateway; @@ -10,11 +12,13 @@ namespace TestServerlessApp public class CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated { private readonly CustomizeResponseExamples customizeResponseExamples; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated() { SetExecutionEnvironment(); customizeResponseExamples = new CustomizeResponseExamples(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public async System.Threading.Tasks.Task NotFoundResponseWithHeaderV1Async(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated.g.cs index 7c7bc11ae..202380b2c 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; using Amazon.Lambda.Annotations.APIGateway; @@ -10,11 +12,13 @@ namespace TestServerlessApp public class CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated { private readonly CustomizeResponseExamples customizeResponseExamples; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated() { SetExecutionEnvironment(); customizeResponseExamples = new CustomizeResponseExamples(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public System.IO.Stream NotFoundResponseWithHeaderV1(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated.g.cs index 3e517e068..11ccf50ea 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; using Amazon.Lambda.Annotations.APIGateway; @@ -10,11 +12,13 @@ namespace TestServerlessApp public class CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated { private readonly CustomizeResponseExamples customizeResponseExamples; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated() { SetExecutionEnvironment(); customizeResponseExamples = new CustomizeResponseExamples(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public async System.Threading.Tasks.Task NotFoundResponseWithHeaderV2Async(Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated.g.cs index f2d18fad7..d1a524b7a 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; using Amazon.Lambda.Annotations.APIGateway; @@ -10,11 +12,13 @@ namespace TestServerlessApp public class CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated { private readonly CustomizeResponseExamples customizeResponseExamples; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated() { SetExecutionEnvironment(); customizeResponseExamples = new CustomizeResponseExamples(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public System.IO.Stream NotFoundResponseWithHeaderV2(Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs index eee588b9e..d8f7906da 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; using Amazon.Lambda.Annotations.APIGateway; @@ -11,11 +12,13 @@ namespace TestServerlessApp public class CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated { private readonly CustomizeResponseExamples customizeResponseExamples; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated() { SetExecutionEnvironment(); customizeResponseExamples = new CustomizeResponseExamples(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public async System.Threading.Tasks.Task OkResponseWithHeaderAsync(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs index fe6e40d1b..798110d7c 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; using Amazon.Lambda.Annotations.APIGateway; @@ -11,11 +12,13 @@ namespace TestServerlessApp public class CustomizeResponseExamples_OkResponseWithHeader_Generated { private readonly CustomizeResponseExamples customizeResponseExamples; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public CustomizeResponseExamples_OkResponseWithHeader_Generated() { SetExecutionEnvironment(); customizeResponseExamples = new CustomizeResponseExamples(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public System.IO.Stream OkResponseWithHeader(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs index 85093c6d0..29da3f459 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHelloAsync_Generated.g.cs @@ -3,36 +3,25 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp { public class Greeter_SayHelloAsync_Generated { - private static readonly ServiceProvider serviceProvider; + private readonly Greeter greeter; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; - static Greeter_SayHelloAsync_Generated() + public Greeter_SayHelloAsync_Generated() { SetExecutionEnvironment(); - var services = new ServiceCollection(); - - // By default, Lambda function class is added to the service container using the singleton lifetime - // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. - services.AddSingleton(); - - var startup = new TestServerlessApp.Startup(); - startup.ConfigureServices(services); - serviceProvider = services.BuildServiceProvider(); + greeter = new Greeter(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } - public static async System.Threading.Tasks.Task SayHelloAsync(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + public async System.Threading.Tasks.Task SayHelloAsync(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) { - // Create a scope for every request, - // this allows creating scoped dependencies without creating a scope manually. - using var scope = serviceProvider.CreateScope(); - var greeter = scope.ServiceProvider.GetRequiredService(); - var validationErrors = new List(); var firstNames = default(System.Collections.Generic.IEnumerable); diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs index 47c64659d..2d8c4f14a 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Greeter_SayHello_Generated.g.cs @@ -3,36 +3,25 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp { public class Greeter_SayHello_Generated { - private static readonly ServiceProvider serviceProvider; + private readonly Greeter greeter; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; - static Greeter_SayHello_Generated() + public Greeter_SayHello_Generated() { SetExecutionEnvironment(); - var services = new ServiceCollection(); - - // By default, Lambda function class is added to the service container using the singleton lifetime - // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. - services.AddSingleton(); - - var startup = new TestServerlessApp.Startup(); - startup.ConfigureServices(services); - serviceProvider = services.BuildServiceProvider(); + greeter = new Greeter(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } - public static Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse SayHello(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + public Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse SayHello(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) { - // Create a scope for every request, - // this allows creating scoped dependencies without creating a scope manually. - using var scope = serviceProvider.CreateScope(); - var greeter = scope.ServiceProvider.GetRequiredService(); - var validationErrors = new List(); var firstNames = default(System.Collections.Generic.IEnumerable); From 0093d5340982fa011dec9a46230d76000d35f696 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Wed, 30 Aug 2023 09:27:33 +0100 Subject: [PATCH 05/27] Update existing static main error --- .../Diagnostics/DiagnosticDescriptors.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs index 7eb5eeff3..89295690d 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs @@ -47,7 +47,7 @@ public static class DiagnosticDescriptors public static readonly DiagnosticDescriptor MainMethodExists = new DiagnosticDescriptor(id: "AWSLambda0104", title: "static Main method exists", - messageFormat: "Your project already defines a static Main method.", + messageFormat: "Failed to generate Main method for LambdaGenerateMainAttribute because project already contains Main method. Existing Main methods must be removed when using LambdaGenerateMainAttribute attribute.", category: "AWSLambdaCSharpGenerator", DiagnosticSeverity.Error, isEnabledByDefault: true); From e54ea0d1c4e633d65be973f85cb2e56625e36939 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Wed, 30 Aug 2023 09:31:56 +0100 Subject: [PATCH 06/27] Use syntax receiver get declared symbol --- .../SyntaxReceiver.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs index 0c34c2fde..973175499 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs @@ -67,9 +67,8 @@ public void OnVisitSyntaxNode(GeneratorSyntaxContext context) if (context.Node is ClassDeclarationSyntax classDeclarationSyntax && classDeclarationSyntax.AttributeLists.Count > 0) { // Get the symbol being declared by the class, and keep it if its annotated - var methodSymbol = ModelExtensions.GetDeclaredSymbol( - context.SemanticModel, - classDeclarationSyntax); + var methodSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclarationSyntax); + if (methodSymbol.GetAttributes().Any(attr => attr.AttributeClass.Name == nameof(LambdaStartupAttribute))) { StartupClasses.Add(classDeclarationSyntax); From 9484ac1d118709972314eb385ec012e2ff5263d9 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Wed, 30 Aug 2023 09:32:18 +0100 Subject: [PATCH 07/27] Add check for method parameter count --- .../Generator.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs index ca319e1ed..21e347966 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs @@ -273,17 +273,18 @@ private static ExecutableAssembly GenerateExecutableAssemblySource( foreach (var methodDeclaration in receiver.MethodDeclarations) { var model = context.Compilation.GetSemanticModel(methodDeclaration.SyntaxTree); - var symbol = model.GetDeclaredSymbol(methodDeclaration); + var symbol = model.GetDeclaredSymbol(methodDeclaration) as IMethodSymbol; - if (symbol.Name == "Main" && symbol.IsStatic && symbol.ContainingNamespace.Name == lambdaModels[0].LambdaMethod.ContainingAssembly) - { - diagnosticReporter.Report( - Diagnostic.Create( - DiagnosticDescriptors.MainMethodExists, - Location.None)); + // Check to see if a static main method exists in the same namespace that has 0 or 1 parameters + if (symbol.Name != "Main" || !symbol.IsStatic || symbol.ContainingNamespace.Name != lambdaModels[0].LambdaMethod.ContainingAssembly || (symbol.Parameters.Length > 1)) + continue; + + diagnosticReporter.Report( + Diagnostic.Create( + DiagnosticDescriptors.MainMethodExists, + Location.None)); - return null; - } + return null; } return new ExecutableAssembly( From 68bebac2215e4be652ef90988be7c7898a16d251 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Wed, 30 Aug 2023 09:32:57 +0100 Subject: [PATCH 08/27] Update to use extension method --- .../SyntaxReceiver.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs index 973175499..ddc167b1e 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs @@ -77,8 +77,7 @@ public void OnVisitSyntaxNode(GeneratorSyntaxContext context) if (context.Node is MethodDeclarationSyntax methodDeclaration) { - var model = ModelExtensions.GetDeclaredSymbol( - context.SemanticModel, + var model = context.SemanticModel.GetDeclaredSymbol( methodDeclaration); if (model.Name == "Main" && model.IsStatic) From a90b6ce18b593d836baa41e2db8fa372c0dc8e98 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Wed, 30 Aug 2023 15:25:21 +0100 Subject: [PATCH 09/27] Fix test unit tests --- .../Templates/ExecutableAssembly.cs | 22 +- .../Templates/ExecutableAssembly.tt | 4 +- .../Templates/FieldsAndConstructor.cs | 86 +---- .../Templates/FieldsAndConstructor.tt | 19 +- .../Templates/LambdaFunctionTemplate.cs | 6 - .../Templates/LambdaFunctionTemplate.tt | 2 +- .../LambdaGenerateMainAttribute.cs | 4 +- ....Annotations.SourceGenerators.Tests.csproj | 12 + ...DynamicExample_DynamicInput_Generated.g.cs | 4 + ...ynamicExample_DynamicReturn_Generated.g.cs | 3 + ...nctions_AsyncStartupToLower_Generated.g.cs | 9 +- ...nctions_AsyncStartupToUpper_Generated.g.cs | 9 +- .../Functions_ToUpper_Generated.g.cs | 3 + ...terExecutable_SayHelloAsync_Generated.g.cs | 101 +++++ .../GreeterExecutable_SayHello_Generated.g.cs | 101 +++++ ...trinsicExample_HasIntrinsic_Generated.g.cs | 3 + ...ample_NullableHeaderHttpApi_Generated.g.cs | 3 + .../Snapshots/Program.g.cs | 2 +- .../Snapshots/ProgramMultiHandler.g.cs | 4 +- .../Snapshots/ProgramZipOutput.g.cs | 2 +- .../ServerlessTemplates/greeter.template | 14 +- .../greeter_executable.template | 83 +++++ .../SimpleCalculator_Add_Generated.g.cs | 3 + ...impleCalculator_DivideAsync_Generated.g.cs | 11 +- .../SimpleCalculator_Multiply_Generated.g.cs | 4 + .../SimpleCalculator_Pi_Generated.g.cs | 4 + .../SimpleCalculator_Random_Generated.g.cs | 4 + .../SimpleCalculator_Randoms_Generated.g.cs | 4 + .../SimpleCalculator_Subtract_Generated.g.cs | 4 + .../TaskExample_TaskReturn_Generated.g.cs | 3 + .../VoidExample_VoidReturn_Generated.g.cs | 3 + .../SourceGeneratorTests.cs | 344 +++++++++--------- 32 files changed, 583 insertions(+), 297 deletions(-) create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/GreeterExecutable_SayHelloAsync_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/GreeterExecutable_SayHello_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter_executable.template diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs index a6d341856..bd0eff9c8 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs @@ -81,7 +81,14 @@ public virtual string TransformText() #line default #line hidden - this.Write(" = "); + this.Write(" = new "); + + #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingNamespace)); + + #line default + #line hidden + this.Write("."); #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); @@ -95,7 +102,7 @@ public virtual string TransformText() #line default #line hidden - this.Write("_Generated."); + this.Write("_Generated()."); #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); @@ -148,7 +155,14 @@ public virtual string TransformText() #line default #line hidden - this.Write(" = "); + this.Write(" = new "); + + #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingNamespace)); + + #line default + #line hidden + this.Write("."); #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); @@ -162,7 +176,7 @@ public virtual string TransformText() #line default #line hidden - this.Write("_Generated."); + this.Write("_Generated()."); #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt index efdafd1ac..5e1a35bf7 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt @@ -33,7 +33,7 @@ public class GeneratedProgram if (model.GeneratedMethod.ReturnType.FullName == "void") { #> - Action<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>> <#= model.LambdaMethod.Name.ToLower() #> = <#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated.<#= model.LambdaMethod.Name #>; + Action<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>> <#= model.LambdaMethod.Name.ToLower() #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new <#= this._lambdaFunctions[0].Serializer #>()).Build().RunAsync(); break; <# @@ -41,7 +41,7 @@ public class GeneratedProgram else { #> - Func<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= model.GeneratedMethod.ReturnType.FullName #>> <#= model.LambdaMethod.Name.ToLower() #> = <#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated.<#= model.LambdaMethod.Name #>; + Func<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= model.GeneratedMethod.ReturnType.FullName #>> <#= model.LambdaMethod.Name.ToLower() #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new <#= model.Serializer #>()).Build().RunAsync(); break; <# diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs index b5e2d6ab6..76f304bf7 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.cs @@ -38,14 +38,7 @@ public virtual string TransformText() #line default #line hidden - this.Write(" private "); - - #line 11 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); - - #line default - #line hidden - this.Write("readonly ServiceProvider serviceProvider;\r\n"); + this.Write(" private readonly ServiceProvider serviceProvider;\r\n"); #line 12 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" @@ -56,14 +49,7 @@ public virtual string TransformText() #line default #line hidden - this.Write(" private "); - - #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); - - #line default - #line hidden - this.Write("readonly "); + this.Write(" private readonly "); #line 17 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); @@ -77,14 +63,7 @@ public virtual string TransformText() #line default #line hidden - this.Write(";\r\n private "); - - #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); - - #line default - #line hidden - this.Write("readonly "); + this.Write(";\r\n private readonly "); #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.Serializer)); @@ -100,53 +79,16 @@ public virtual string TransformText() #line default #line hidden - this.Write("\r\n"); + this.Write("\r\n public "); #line 23 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - - if (_model.IsExecutable) - { - - - #line default - #line hidden - this.Write(" static "); - - #line 27 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.ContainingType.Name)); - - #line default - #line hidden - this.Write("() \r\n"); - - #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" public "); - - #line 33 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.ContainingType.Name)); #line default #line hidden - this.Write("()\r\n"); + this.Write("()\r\n {\r\n SetExecutionEnvironment();\r\n"); - #line 34 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" - - } - - - #line default - #line hidden - this.Write(" {\r\n SetExecutionEnvironment();\r\n"); - - #line 39 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 26 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" if (_model.LambdaMethod.UsingDependencyInjection) { @@ -156,28 +98,28 @@ public virtual string TransformText() #line hidden this.Write(" var services = new ServiceCollection();\r\n\r\n // By default, Lambda function class is added to the service container using the singleton lifetime\r\n // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method.\r\n services.AddSingleton<"); - #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 34 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write(">();\r\n services.AddSingleton<"); - #line 48 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 35 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.Serializer)); #line default #line hidden this.Write(">();\r\n\r\n var startup = new "); - #line 50 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.StartupType.FullName)); #line default #line hidden this.Write("();\r\n startup.ConfigureServices(services);\r\n serviceProvider = services.BuildServiceProvider();\r\n"); - #line 53 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 40 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } else @@ -188,28 +130,28 @@ public virtual string TransformText() #line hidden this.Write(" "); - #line 58 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name.ToCamelCase())); #line default #line hidden this.Write(" = new "); - #line 58 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("();\r\n serializer = new "); - #line 59 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 46 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.Serializer)); #line default #line hidden this.Write("();\r\n"); - #line 60 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" + #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\FieldsAndConstructor.tt" } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt index 2aa43bd42..5b9f6b7a5 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/FieldsAndConstructor.tt @@ -8,32 +8,19 @@ if (_model.LambdaMethod.UsingDependencyInjection) { #> - private <#= _model.IsExecutable ? "static " : "" #>readonly ServiceProvider serviceProvider; + private readonly ServiceProvider serviceProvider; <# } else { #> - private <#= _model.IsExecutable ? "static " : "" #>readonly <#= _model.LambdaMethod.ContainingType.Name #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>; - private <#= _model.IsExecutable ? "static " : "" #>readonly <#= _model.Serializer #> serializer; + private readonly <#= _model.LambdaMethod.ContainingType.Name #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>; + private readonly <#= _model.Serializer #> serializer; <# } #> -<# - if (_model.IsExecutable) - { -#> - static <#= _model.GeneratedMethod.ContainingType.Name #>() -<# - } - else - { -#> public <#= _model.GeneratedMethod.ContainingType.Name #>() -<# - } -#> { SetExecutionEnvironment(); <# diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs index da58c1065..e8d3d56ba 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -84,12 +84,6 @@ public virtual string TransformText() #line hidden this.Write("\r\n\r\n public "); - #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.IsExecutable ? "static " : "")); - - #line default - #line hidden - #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsVoidOrGenericTask ? "async " : "")); diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt index d371cd808..ac8ac1682 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt @@ -27,7 +27,7 @@ this.Write(new FieldsAndConstructor(_model).TransformText()); #> - public <#= _model.IsExecutable ? "static " : "" #><#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? "async " : "" #><#= _model.GeneratedMethod.ReturnType.FullName #> <#= _model.LambdaMethod.Name #>(<#= string.Join(", ", _model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName} {p.Name}")) #>) + public <#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? "async " : "" #><#= _model.GeneratedMethod.ReturnType.FullName #> <#= _model.LambdaMethod.Name #>(<#= string.Join(", ", _model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName} {p.Name}")) #>) { <# if (_model.LambdaMethod.UsingDependencyInjection) diff --git a/Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs index 804a2b069..785aaeb99 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs +++ b/Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs @@ -4,7 +4,9 @@ namespace Amazon.Lambda.Annotations { /// - /// Indicates this the Lambda function is going to target an executable instead of a class based handler. + /// Used when deploying Lambda functions as a .NET executable instead of a class library. Ensure the .NET project's output type is configured for `Console Application`. In the project file the `OutputType` property will be set to `Exe`. + /// + /// Deploying as an executable versus a class library is required when compiling functions with Native AOT. It can also be useful to deploy as an executable to include specific versions of `Amazon.Lambda.RuntimeSupport` the .NET Lambda runtime client. /// [AttributeUsage( AttributeTargets.Assembly)] public class LambdaGenerateMainAttribute : Attribute diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj index 4163d6a78..e2ad84dc2 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj @@ -69,6 +69,18 @@ PreserveNewest + + + PreserveNewest + + + + PreserveNewest + + + + PreserveNewest + diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicInput_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicInput_Generated.g.cs index 61733f2d8..f5f731ed8 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicInput_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicInput_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp @@ -9,11 +11,13 @@ namespace TestServerlessApp public class DynamicExample_DynamicInput_Generated { private readonly DynamicExample dynamicExample; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public DynamicExample_DynamicInput_Generated() { SetExecutionEnvironment(); dynamicExample = new DynamicExample(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public string DynamicInput(dynamic text, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicReturn_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicReturn_Generated.g.cs index 87adda1a1..274abb063 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicReturn_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/DynamicExample_DynamicReturn_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp @@ -10,11 +11,13 @@ namespace TestServerlessApp public class DynamicExample_DynamicReturn_Generated { private readonly DynamicExample dynamicExample; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public DynamicExample_DynamicReturn_Generated() { SetExecutionEnvironment(); dynamicExample = new DynamicExample(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public dynamic DynamicReturn(string text, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToLower_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToLower_Generated.g.cs index 04cd4d249..6c39fc6d6 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToLower_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToLower_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; @@ -10,9 +11,9 @@ namespace TestServerlessApp.Sub1 { public class FunctionsZipOutput_ToLower_Generated { - private static readonly ServiceProvider serviceProvider; + private readonly ServiceProvider serviceProvider; - static FunctionsZipOutput_ToLower_Generated() + public FunctionsZipOutput_ToLower_Generated() { SetExecutionEnvironment(); var services = new ServiceCollection(); @@ -20,18 +21,20 @@ static FunctionsZipOutput_ToLower_Generated() // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton(); + services.AddSingleton(); var startup = new TestServerlessApp.Startup(); startup.ConfigureServices(services); serviceProvider = services.BuildServiceProvider(); } - public static string ToLower(string text) + public string ToLower(string text) { // Create a scope for every request, // this allows creating scoped dependencies without creating a scope manually. using var scope = serviceProvider.CreateScope(); var functionsZipOutput = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); return functionsZipOutput.ToLower(text); } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs index dd05e0915..5dce441b3 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_AsyncStartupToUpper_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; @@ -10,9 +11,9 @@ namespace TestServerlessApp.Sub1 { public class Functions_ToUpper_Generated { - private static readonly ServiceProvider serviceProvider; + private readonly ServiceProvider serviceProvider; - static Functions_ToUpper_Generated() + public Functions_ToUpper_Generated() { SetExecutionEnvironment(); var services = new ServiceCollection(); @@ -20,18 +21,20 @@ static Functions_ToUpper_Generated() // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton(); + services.AddSingleton(); var startup = new TestServerlessApp.Startup(); startup.ConfigureServices(services); serviceProvider = services.BuildServiceProvider(); } - public static string ToUpper(string text) + public string ToUpper(string text) { // Create a scope for every request, // this allows creating scoped dependencies without creating a scope manually. using var scope = serviceProvider.CreateScope(); var functions = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); return functions.ToUpper(text); } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_ToUpper_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_ToUpper_Generated.g.cs index b975a4ec4..f5a32b25b 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_ToUpper_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Functions_ToUpper_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp.Sub1 @@ -10,11 +11,13 @@ namespace TestServerlessApp.Sub1 public class Functions_ToUpper_Generated { private readonly Functions functions; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public Functions_ToUpper_Generated() { SetExecutionEnvironment(); functions = new Functions(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public string ToUpper(string text) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/GreeterExecutable_SayHelloAsync_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/GreeterExecutable_SayHelloAsync_Generated.g.cs new file mode 100644 index 000000000..b0f4a67dc --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/GreeterExecutable_SayHelloAsync_Generated.g.cs @@ -0,0 +1,101 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Microsoft.Extensions.DependencyInjection; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class Greeter_SayHelloAsync_Generated + { + private readonly ServiceProvider serviceProvider; + + public Greeter_SayHelloAsync_Generated() + { + SetExecutionEnvironment(); + var services = new ServiceCollection(); + + // By default, Lambda function class is added to the service container using the singleton lifetime + // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. + services.AddSingleton(); + services.AddSingleton(); + + var startup = new TestServerlessApp.Startup(); + startup.ConfigureServices(services); + serviceProvider = services.BuildServiceProvider(); + } + + public async System.Threading.Tasks.Task SayHelloAsync(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + { + // Create a scope for every request, + // this allows creating scoped dependencies without creating a scope manually. + using var scope = serviceProvider.CreateScope(); + var greeter = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); + + var validationErrors = new List(); + + var firstNames = default(System.Collections.Generic.IEnumerable); + if (__request__.MultiValueHeaders?.Any(x => string.Equals(x.Key, "names", StringComparison.OrdinalIgnoreCase)) == true) + { + firstNames = __request__.MultiValueHeaders.First(x => string.Equals(x.Key, "names", StringComparison.OrdinalIgnoreCase)).Value + .Select(q => + { + try + { + return (string)Convert.ChangeType(q, typeof(string)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {q} at 'names' failed to satisfy constraint: {e.Message}"); + return default; + } + }) + .ToList(); + } + + // return 400 Bad Request if there exists a validation error + if (validationErrors.Any()) + { + var errorResult = new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse + { + Body = @$"{{""message"": ""{validationErrors.Count} validation error(s) detected: {string.Join(",", validationErrors)}""}}", + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "ValidationException"} + }, + StatusCode = 400 + }; + return errorResult; + } + + await greeter.SayHelloAsync(firstNames); + + return new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse + { + StatusCode = 200 + }; + } + + private static void SetExecutionEnvironment() + { + const string envName = "AWS_EXECUTION_ENV"; + + var envValue = new StringBuilder(); + + // If there is an existing execution environment variable add the annotations package as a suffix. + if(!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName))) + { + envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); + } + + envValue.Append("amazon-lambda-annotations_1.0.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/GreeterExecutable_SayHello_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/GreeterExecutable_SayHello_Generated.g.cs new file mode 100644 index 000000000..c10fcca0e --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/GreeterExecutable_SayHello_Generated.g.cs @@ -0,0 +1,101 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Microsoft.Extensions.DependencyInjection; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class Greeter_SayHello_Generated + { + private readonly ServiceProvider serviceProvider; + + public Greeter_SayHello_Generated() + { + SetExecutionEnvironment(); + var services = new ServiceCollection(); + + // By default, Lambda function class is added to the service container using the singleton lifetime + // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. + services.AddSingleton(); + services.AddSingleton(); + + var startup = new TestServerlessApp.Startup(); + startup.ConfigureServices(services); + serviceProvider = services.BuildServiceProvider(); + } + + public Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse SayHello(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + { + // Create a scope for every request, + // this allows creating scoped dependencies without creating a scope manually. + using var scope = serviceProvider.CreateScope(); + var greeter = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); + + var validationErrors = new List(); + + var firstNames = default(System.Collections.Generic.IEnumerable); + if (__request__.MultiValueQueryStringParameters?.ContainsKey("names") == true) + { + firstNames = __request__.MultiValueQueryStringParameters["names"] + .Select(q => + { + try + { + return (string)Convert.ChangeType(q, typeof(string)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {q} at 'names' failed to satisfy constraint: {e.Message}"); + return default; + } + }) + .ToList(); + } + + // return 400 Bad Request if there exists a validation error + if (validationErrors.Any()) + { + var errorResult = new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse + { + Body = @$"{{""message"": ""{validationErrors.Count} validation error(s) detected: {string.Join(",", validationErrors)}""}}", + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "ValidationException"} + }, + StatusCode = 400 + }; + return errorResult; + } + + greeter.SayHello(firstNames, __request__, __context__); + + return new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse + { + StatusCode = 200 + }; + } + + private static void SetExecutionEnvironment() + { + const string envName = "AWS_EXECUTION_ENV"; + + var envValue = new StringBuilder(); + + // If there is an existing execution environment variable add the annotations package as a suffix. + if(!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName))) + { + envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); + } + + envValue.Append("amazon-lambda-annotations_1.0.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/IntrinsicExample_HasIntrinsic_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/IntrinsicExample_HasIntrinsic_Generated.g.cs index b1ffa7d7c..9e0b1a4af 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/IntrinsicExample_HasIntrinsic_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/IntrinsicExample_HasIntrinsic_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp @@ -10,11 +11,13 @@ namespace TestServerlessApp public class IntrinsicExample_HasIntrinsic_Generated { private readonly IntrinsicExample intrinsicExample; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public IntrinsicExample_HasIntrinsic_Generated() { SetExecutionEnvironment(); intrinsicExample = new IntrinsicExample(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public void HasIntrinsic(string text, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs index a77488c92..88c96fef2 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp @@ -10,11 +11,13 @@ namespace TestServerlessApp public class NullableReferenceTypeExample_NullableHeaderHttpApi_Generated { private readonly NullableReferenceTypeExample nullableReferenceTypeExample; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public NullableReferenceTypeExample_NullableHeaderHttpApi_Generated() { SetExecutionEnvironment(); nullableReferenceTypeExample = new NullableReferenceTypeExample(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse NullableHeaderHttpApi(Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs index 6b589f408..942b82d8a 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs @@ -15,7 +15,7 @@ private static async Task Main(string[] args) switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) { case "ToUpper": - Func toupper = Functions_ToUpper_Generated.ToUpper; + Func toupper = new TestServerlessApp.Sub1.Functions_ToUpper_Generated().ToUpper; await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(toupper, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); break; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs index ec3a05bc8..c3052e7fc 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs @@ -15,11 +15,11 @@ private static async Task Main(string[] args) switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) { case "SayHello": - Func sayhello = Greeter_SayHello_Generated.SayHello; + Func sayhello = new TestServerlessApp.Greeter_SayHello_Generated().SayHello; await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(sayhello, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); break; case "SayHelloAsync": - Func> sayhelloasync = Greeter_SayHelloAsync_Generated.SayHelloAsync; + Func> sayhelloasync = new TestServerlessApp.Greeter_SayHelloAsync_Generated().SayHelloAsync; await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(sayhelloasync, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); break; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs index db403da31..5b3c922aa 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs @@ -15,7 +15,7 @@ private static async Task Main(string[] args) switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) { case "ToLower": - Func tolower = FunctionsZipOutput_ToLower_Generated.ToLower; + Func tolower = new TestServerlessApp.Sub1.FunctionsZipOutput_ToLower_Generated().ToLower; await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(tolower, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); break; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter.template index cd99fc094..63e20c35f 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter.template +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter.template @@ -21,14 +21,9 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestProject" + "TestProject::TestServerlessApp.Greeter_SayHello_Generated::SayHello" ] }, - "Environment": { - "Variables": { - "ANNOTATIONS_HANDLER": "SayHello" - } - }, "Events": { "RootGet": { "Type": "HttpApi", @@ -59,14 +54,9 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestProject" + "TestProject::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" ] }, - "Environment": { - "Variables": { - "ANNOTATIONS_HANDLER": "SayHelloAsync" - } - }, "Events": { "RootGet": { "Type": "HttpApi", diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter_executable.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter_executable.template new file mode 100644 index 000000000..cd99fc094 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/greeter_executable.template @@ -0,0 +1,83 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).", + "Resources": { + "GreeterSayHello": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 1024, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestProject" + ] + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "SayHello" + } + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/Greeter/SayHello", + "Method": "GET", + "PayloadFormatVersion": "1.0" + } + } + } + } + }, + "GreeterSayHelloAsync": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 50, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestProject" + ] + }, + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "SayHelloAsync" + } + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/Greeter/SayHelloAsync", + "Method": "GET", + "PayloadFormatVersion": "1.0" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Add_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Add_Generated.g.cs index 32d1f843c..fda9870f7 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Add_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Add_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; @@ -20,6 +21,7 @@ public SimpleCalculator_Add_Generated() // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton(); + services.AddSingleton(); var startup = new TestServerlessApp.Startup(); startup.ConfigureServices(services); @@ -32,6 +34,7 @@ public Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse Add(Amazon.Lambda. // this allows creating scoped dependencies without creating a scope manually. using var scope = serviceProvider.CreateScope(); var simpleCalculator = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); var validationErrors = new List(); diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_DivideAsync_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_DivideAsync_Generated.g.cs index da6c99445..8b17c1c99 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_DivideAsync_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_DivideAsync_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; @@ -19,6 +21,7 @@ public SimpleCalculator_DivideAsync_Generated() // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton(); + services.AddSingleton(); var startup = new TestServerlessApp.Startup(); startup.ConfigureServices(services); @@ -31,6 +34,7 @@ public SimpleCalculator_DivideAsync_Generated() // this allows creating scoped dependencies without creating a scope manually. using var scope = serviceProvider.CreateScope(); var simpleCalculator = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); var validationErrors = new List(); @@ -77,8 +81,13 @@ public SimpleCalculator_DivideAsync_Generated() } var response = await simpleCalculator.DivideAsync(first, second); + var memoryStream = new MemoryStream(); + serializer.Serialize(response, memoryStream); + memoryStream.Position = 0; - var body = System.Text.Json.JsonSerializer.Serialize(response); + // convert stream to string + StreamReader reader = new StreamReader( memoryStream ); + var body = reader.ReadToEnd(); return new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse { diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Multiply_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Multiply_Generated.g.cs index 90613c33a..221d060ec 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Multiply_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Multiply_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; @@ -19,6 +21,7 @@ public SimpleCalculator_Multiply_Generated() // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton(); + services.AddSingleton(); var startup = new TestServerlessApp.Startup(); startup.ConfigureServices(services); @@ -31,6 +34,7 @@ public Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse Multiply(Amazon.La // this allows creating scoped dependencies without creating a scope manually. using var scope = serviceProvider.CreateScope(); var simpleCalculator = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); var validationErrors = new List(); diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Pi_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Pi_Generated.g.cs index 36450b6e5..5797fa689 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Pi_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Pi_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; @@ -19,6 +21,7 @@ public SimpleCalculator_Pi_Generated() // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton(); + services.AddSingleton(); var startup = new TestServerlessApp.Startup(); startup.ConfigureServices(services); @@ -31,6 +34,7 @@ public double Pi() // this allows creating scoped dependencies without creating a scope manually. using var scope = serviceProvider.CreateScope(); var simpleCalculator = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); var simpleCalculatorService = scope.ServiceProvider.GetRequiredService(); return simpleCalculator.Pi(simpleCalculatorService); diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Random_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Random_Generated.g.cs index 40b979292..c72450f62 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Random_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Random_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; @@ -19,6 +21,7 @@ public SimpleCalculator_Random_Generated() // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton(); + services.AddSingleton(); var startup = new TestServerlessApp.Startup(); startup.ConfigureServices(services); @@ -31,6 +34,7 @@ public async System.Threading.Tasks.Task Random(int maxValue, Amazon.Lambda // this allows creating scoped dependencies without creating a scope manually. using var scope = serviceProvider.CreateScope(); var simpleCalculator = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); return await simpleCalculator.Random(maxValue, __context__); } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Randoms_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Randoms_Generated.g.cs index 4e66af57a..ce468df60 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Randoms_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Randoms_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; @@ -19,6 +21,7 @@ public SimpleCalculator_Randoms_Generated() // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton(); + services.AddSingleton(); var startup = new TestServerlessApp.Startup(); startup.ConfigureServices(services); @@ -31,6 +34,7 @@ public System.Collections.Generic.IList Randoms(TestServerlessApp.SimpleCal // this allows creating scoped dependencies without creating a scope manually. using var scope = serviceProvider.CreateScope(); var simpleCalculator = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); return simpleCalculator.Randoms(input, __context__); } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Subtract_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Subtract_Generated.g.cs index ee78ed3e2..b2b76fb56 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Subtract_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Subtract_Generated.g.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; +using System.IO; using Microsoft.Extensions.DependencyInjection; using Amazon.Lambda.Core; @@ -19,6 +21,7 @@ public SimpleCalculator_Subtract_Generated() // By default, Lambda function class is added to the service container using the singleton lifetime // To use a different lifetime, specify the lifetime in Startup.ConfigureServices(IServiceCollection) method. services.AddSingleton(); + services.AddSingleton(); var startup = new TestServerlessApp.Startup(); startup.ConfigureServices(services); @@ -31,6 +34,7 @@ public Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse Subtract(Amazon.La // this allows creating scoped dependencies without creating a scope manually. using var scope = serviceProvider.CreateScope(); var simpleCalculator = scope.ServiceProvider.GetRequiredService(); + var serializer = scope.ServiceProvider.GetRequiredService(); var validationErrors = new List(); diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/TaskExample_TaskReturn_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/TaskExample_TaskReturn_Generated.g.cs index d5b7658d6..c852469ba 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/TaskExample_TaskReturn_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/TaskExample_TaskReturn_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp @@ -10,11 +11,13 @@ namespace TestServerlessApp public class TaskExample_TaskReturn_Generated { private readonly TaskExample taskExample; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public TaskExample_TaskReturn_Generated() { SetExecutionEnvironment(); taskExample = new TaskExample(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public async System.Threading.Tasks.Task TaskReturn(string text, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/VoidExample_VoidReturn_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/VoidExample_VoidReturn_Generated.g.cs index f52417b87..0f94957d5 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/VoidExample_VoidReturn_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/VoidExample_VoidReturn_Generated.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp @@ -10,11 +11,13 @@ namespace TestServerlessApp public class VoidExample_VoidReturn_Generated { private readonly VoidExample voidExample; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; public VoidExample_VoidReturn_Generated() { SetExecutionEnvironment(); voidExample = new VoidExample(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } public void VoidReturn(string text, Amazon.Lambda.Core.ILambdaContext __context__) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index 40d5170db..1e8c231b8 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -16,9 +16,9 @@ public class SourceGeneratorTests : IDisposable [Fact] public async Task Greeter() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "greeter.template")).ToEnvironmentLineEndings(); - var expectedSayHelloGenerated = File.ReadAllText(Path.Combine("Snapshots", "Greeter_SayHello_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedSayHelloAsyncGenerated = File.ReadAllText(Path.Combine("Snapshots", "Greeter_SayHelloAsync_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "greeter.template"))).ToEnvironmentLineEndings(); + var expectedSayHelloGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Greeter_SayHello_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedSayHelloAsyncGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Greeter_SayHelloAsync_Generated.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -26,10 +26,10 @@ public async Task Greeter() { Sources = { - (Path.Combine("TestServerlessApp", "Greeter.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "Greeter.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "Greeter.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "Greeter.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -54,16 +54,16 @@ public async Task Greeter() } }.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } [Fact] public async Task GeneratorDoesNotRunDueToCompileError() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "greeter.template")).ToEnvironmentLineEndings(); - var expectedSayHelloGenerated = File.ReadAllText(Path.Combine("Snapshots", "Greeter_SayHello_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedSayHelloAsyncGenerated = File.ReadAllText(Path.Combine("Snapshots", "Greeter_SayHelloAsync_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "greeter.template"))).ToEnvironmentLineEndings(); + var expectedSayHelloGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Greeter_SayHello_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedSayHelloAsyncGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Greeter_SayHelloAsync_Generated.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -71,11 +71,11 @@ public async Task GeneratorDoesNotRunDueToCompileError() { Sources = { - (Path.Combine("TestServerlessApp", "Greeter.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "Greeter.cs"))), - ("NonCompilableCodeFile.cs", File.ReadAllText("NonCompilableCodeFile.cs")), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "Greeter.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "Greeter.cs"))), + ("NonCompilableCodeFile.cs", await File.ReadAllTextAsync("NonCompilableCodeFile.cs")), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -94,14 +94,14 @@ public async Task GeneratorDoesNotRunDueToCompileError() [Fact] public async Task SimpleCalculator() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "simpleCalculator.template")).ToEnvironmentLineEndings(); - var expectedAddGenerated = File.ReadAllText(Path.Combine("Snapshots", "SimpleCalculator_Add_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedSubtractGenerated = File.ReadAllText(Path.Combine("Snapshots", "SimpleCalculator_Subtract_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedMultiplyGenerated = File.ReadAllText(Path.Combine("Snapshots", "SimpleCalculator_Multiply_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedDivideAsyncGenerated = File.ReadAllText(Path.Combine("Snapshots", "SimpleCalculator_DivideAsync_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedPiGenerated = File.ReadAllText(Path.Combine("Snapshots", "SimpleCalculator_Pi_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedRandomGenerated = File.ReadAllText(Path.Combine("Snapshots", "SimpleCalculator_Random_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedRandomsGenerated = File.ReadAllText(Path.Combine("Snapshots", "SimpleCalculator_Randoms_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "simpleCalculator.template"))).ToEnvironmentLineEndings(); + var expectedAddGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "SimpleCalculator_Add_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedSubtractGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "SimpleCalculator_Subtract_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedMultiplyGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "SimpleCalculator_Multiply_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedDivideAsyncGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "SimpleCalculator_DivideAsync_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedPiGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "SimpleCalculator_Pi_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedRandomGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "SimpleCalculator_Random_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedRandomsGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "SimpleCalculator_Randoms_Generated.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -110,15 +110,15 @@ public async Task SimpleCalculator() Sources = { - (Path.Combine("TestServerlessApp", "SimpleCalculator.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "SimpleCalculator.cs"))), - (Path.Combine("TestServerlessApp", "Startup.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "Startup.cs"))), - (Path.Combine("TestServerlessApp", "Services", "SimpleCalculatorService.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "Services", "SimpleCalculatorService.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "FromServicesAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "FromServicesAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "SimpleCalculator.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "SimpleCalculator.cs"))), + (Path.Combine("TestServerlessApp", "Startup.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "Startup.cs"))), + (Path.Combine("TestServerlessApp", "Services", "SimpleCalculatorService.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "Services", "SimpleCalculatorService.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "FromServicesAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "FromServicesAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -173,16 +173,16 @@ public async Task SimpleCalculator() } }.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } [Fact] public async Task ComplexCalculator() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "complexCalculator.template")).ToEnvironmentLineEndings(); - var expectedAddGenerated = File.ReadAllText(Path.Combine("Snapshots", "ComplexCalculator_Add_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedSubtractGenerated = File.ReadAllText(Path.Combine("Snapshots", "ComplexCalculator_Subtract_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "complexCalculator.template"))).ToEnvironmentLineEndings(); + var expectedAddGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ComplexCalculator_Add_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedSubtractGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ComplexCalculator_Subtract_Generated.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -190,10 +190,10 @@ public async Task ComplexCalculator() { Sources = { - (Path.Combine("TestServerlessApp", "ComplexCalculator.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "ComplexCalculator.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "ComplexCalculator.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "ComplexCalculator.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -218,15 +218,15 @@ public async Task ComplexCalculator() } }.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } [Fact] public async Task VerifyFunctionInSubNamespace() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace.template")).ToEnvironmentLineEndings(); - var expectedSubNamespaceGenerated = File.ReadAllText(Path.Combine("Snapshots", "Functions_ToUpper_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Functions_ToUpper_Generated.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -234,10 +234,10 @@ public async Task VerifyFunctionInSubNamespace() { Sources = { - (Path.Combine("TestServerlessApp", "Sub1", "Functions.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "Sub1", "Functions.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "Sub1", "Functions.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "Sub1", "Functions.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -256,16 +256,16 @@ public async Task VerifyFunctionInSubNamespace() } }.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } [Fact] public async Task VerifyExecutableAssemblyWithZipAndHandler() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace_executable.template")).ToEnvironmentLineEndings(); - var expectedSubNamespaceGenerated = File.ReadAllText(Path.Combine("Snapshots", "Functions_AsyncStartupToLower_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedProgramGenerated = File.ReadAllText(Path.Combine("Snapshots", "ProgramZipOutput.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace_executable.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Functions_AsyncStartupToLower_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedProgramGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ProgramZipOutput.g.cs"))).ToEnvironmentLineEndings(); var test = new VerifyCS.Test { @@ -273,13 +273,13 @@ public async Task VerifyExecutableAssemblyWithZipAndHandler() { Sources = { - (Path.Combine("TestExecutableServerlessApp", "Sub1", "FunctionsZipOutput.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Sub1", "FunctionsZipOutput.cs"))), - (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), - (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), - (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Sub1", "FunctionsZipOutput.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Sub1", "FunctionsZipOutput.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -307,7 +307,7 @@ public async Task VerifyExecutableAssemblyWithZipAndHandler() Path.Combine("Amazon.Lambda.RuntimeSupport"), "*.cs", SearchOption.AllDirectories)) { - test.TestState.Sources.Add((file, File.ReadAllText(file))); + test.TestState.Sources.Add((file, await File.ReadAllTextAsync(file))); } await test.RunAsync(); @@ -316,9 +316,9 @@ public async Task VerifyExecutableAssemblyWithZipAndHandler() [Fact] public async Task VerifyExecutableAssembly() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace_executableimage.template")).ToEnvironmentLineEndings(); - var expectedSubNamespaceGenerated = File.ReadAllText(Path.Combine("Snapshots", "Functions_AsyncStartupToUpper_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedProgramGenerated = File.ReadAllText(Path.Combine("Snapshots", "Program.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace_executableimage.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Functions_AsyncStartupToUpper_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedProgramGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Program.g.cs"))).ToEnvironmentLineEndings(); var test = new VerifyCS.Test { @@ -326,13 +326,13 @@ public async Task VerifyExecutableAssembly() { Sources = { - (Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"))), - (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), - (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), - (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -360,7 +360,7 @@ public async Task VerifyExecutableAssembly() Path.Combine("Amazon.Lambda.RuntimeSupport"), "*.cs", SearchOption.AllDirectories)) { - test.TestState.Sources.Add((file, File.ReadAllText(file))); + test.TestState.Sources.Add((file, await File.ReadAllTextAsync(file))); } await test.RunAsync(); @@ -369,10 +369,10 @@ public async Task VerifyExecutableAssembly() [Fact] public async Task VerifyExecutableAssemblyWithMultipleHandler() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "greeter.template")).ToEnvironmentLineEndings(); - var expectedSayHello = File.ReadAllText(Path.Combine("Snapshots", "Greeter_SayHello_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedSayHelloAsync = File.ReadAllText(Path.Combine("Snapshots", "Greeter_SayHelloAsync_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedProgramGenerated = File.ReadAllText(Path.Combine("Snapshots", "ProgramMultiHandler.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "greeter_executable.template"))).ToEnvironmentLineEndings(); + var expectedSayHello = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "GreeterExecutable_SayHello_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedSayHelloAsync = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "GreeterExecutable_SayHelloAsync_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedProgramGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ProgramMultiHandler.g.cs"))).ToEnvironmentLineEndings(); var test = new VerifyCS.Test { @@ -380,13 +380,13 @@ public async Task VerifyExecutableAssemblyWithMultipleHandler() { Sources = { - (Path.Combine("TestExecutableServerlessApp", "Greeter.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Greeter.cs"))), - (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), - (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), - (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Greeter.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Greeter.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -420,7 +420,7 @@ public async Task VerifyExecutableAssemblyWithMultipleHandler() Path.Combine("Amazon.Lambda.RuntimeSupport"), "*.cs", SearchOption.AllDirectories)) { - test.TestState.Sources.Add((file, File.ReadAllText(file))); + test.TestState.Sources.Add((file, await File.ReadAllTextAsync(file))); } await test.RunAsync(); @@ -429,8 +429,8 @@ public async Task VerifyExecutableAssemblyWithMultipleHandler() [Fact] public async Task VerifyFunctionReturnVoid() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "voidexample.template")).ToEnvironmentLineEndings(); - var expectedSubNamespaceGenerated = File.ReadAllText(Path.Combine("Snapshots", "VoidExample_VoidReturn_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "voidexample.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "VoidExample_VoidReturn_Generated.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -438,10 +438,10 @@ public async Task VerifyFunctionReturnVoid() { Sources = { - (Path.Combine("TestServerlessApp", "VoidExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "VoidExample.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "VoidExample.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "VoidExample.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -460,16 +460,16 @@ public async Task VerifyFunctionReturnVoid() } }.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } [Fact] public async Task VerifyNoErrorWithIntrinsicInTemplate() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "intrinsicexample.template")).ToEnvironmentLineEndings(); - var expectedSubNamespaceGenerated = File.ReadAllText(Path.Combine("Snapshots", "IntrinsicExample_HasIntrinsic_Generated.g.cs")).ToEnvironmentLineEndings(); - File.WriteAllText(Path.Combine("TestServerlessApp", "serverless.template"), expectedTemplateContent); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "intrinsicexample.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "IntrinsicExample_HasIntrinsic_Generated.g.cs"))).ToEnvironmentLineEndings(); + await File.WriteAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template"), expectedTemplateContent); await new VerifyCS.Test { @@ -477,10 +477,10 @@ public async Task VerifyNoErrorWithIntrinsicInTemplate() { Sources = { - (Path.Combine("TestServerlessApp", "IntrinsicExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "IntrinsicExample.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "IntrinsicExample.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "IntrinsicExample.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -499,15 +499,15 @@ public async Task VerifyNoErrorWithIntrinsicInTemplate() } }.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } [Fact] public async Task VerifyFunctionReturnTask() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "taskexample.template")).ToEnvironmentLineEndings(); - var expectedSubNamespaceGenerated = File.ReadAllText(Path.Combine("Snapshots", "TaskExample_TaskReturn_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "taskexample.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "TaskExample_TaskReturn_Generated.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -515,10 +515,10 @@ public async Task VerifyFunctionReturnTask() { Sources = { - (Path.Combine("TestServerlessApp", "TaskExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "TaskExample.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "TaskExample.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "TaskExample.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -537,16 +537,16 @@ public async Task VerifyFunctionReturnTask() } }.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } [Fact] public async Task VerifyFunctionDynamic() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "dynamicexample.template")).ToEnvironmentLineEndings(); - var expectedSubNamespaceGenerated_DynamicReturn = File.ReadAllText(Path.Combine("Snapshots", "DynamicExample_DynamicReturn_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedSubNamespaceGenerated_DynamicInput = File.ReadAllText(Path.Combine("Snapshots", "DynamicExample_DynamicInput_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "dynamicexample.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated_DynamicReturn = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "DynamicExample_DynamicReturn_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated_DynamicInput = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "DynamicExample_DynamicInput_Generated.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -554,10 +554,10 @@ public async Task VerifyFunctionDynamic() { Sources = { - (Path.Combine("TestServerlessApp", "DynamicExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "DynamicExample.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "DynamicExample.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "DynamicExample.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -582,21 +582,21 @@ public async Task VerifyFunctionDynamic() } }.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } [Fact] public async Task CustomizeResponses() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "customizeResponse.template")).ToEnvironmentLineEndings(); - var expectedOkResponseWithHeaderGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedNotFoundResponseWithHeaderV2Generated = File.ReadAllText(Path.Combine("Snapshots", "CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedNotFoundResponseWithHeaderV1Generated = File.ReadAllText(Path.Combine("Snapshots", "CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "customizeResponse.template"))).ToEnvironmentLineEndings(); + var expectedOkResponseWithHeaderGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "CustomizeResponseExamples_OkResponseWithHeader_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedNotFoundResponseWithHeaderV2Generated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedNotFoundResponseWithHeaderV1Generated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated.g.cs"))).ToEnvironmentLineEndings(); - var expectedOkResponseWithHeaderAsyncGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedNotFoundResponseWithHeaderV2AsyncGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated.g.cs")).ToEnvironmentLineEndings(); - var expectedNotFoundResponseWithHeaderV1AsyncGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedOkResponseWithHeaderAsyncGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedNotFoundResponseWithHeaderV2AsyncGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedNotFoundResponseWithHeaderV1AsyncGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -604,12 +604,12 @@ public async Task CustomizeResponses() { Sources = { - (Path.Combine("TestServerlessApp", "CustomizeResponseExamples.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "CustomizeResponseExamples.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "CustomizeResponseExamples.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "CustomizeResponseExamples.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -662,7 +662,7 @@ public async Task CustomizeResponses() }.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } @@ -677,13 +677,13 @@ public async Task InvalidReturnTypeIHttpResult() { Sources = { - (Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))), - (Path.Combine("TestServerlessApp", "CustomizeResponseWithErrors.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "CustomizeResponseWithErrors.cs.error"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))), + (Path.Combine("TestServerlessApp", "CustomizeResponseWithErrors.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "CustomizeResponseWithErrors.cs.error"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, ExpectedDiagnostics = { @@ -704,13 +704,13 @@ public async Task MissingResourePathMapping() { Sources = { - (Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))), - (Path.Combine("TestServerlessApp", "MissingResourePathMapping.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "MissingResourePathMapping.cs.error"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))), + (Path.Combine("TestServerlessApp", "MissingResourePathMapping.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "MissingResourePathMapping.cs.error"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, ExpectedDiagnostics = { @@ -726,8 +726,8 @@ public async Task MissingResourePathMapping() [Fact] public async Task VerifyApiFunctionUsingNullableParameters() { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "nullreferenceexample.template")).ToEnvironmentLineEndings(); - var expectedCSharpContent = File.ReadAllText(Path.Combine("Snapshots", "NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs")).ToEnvironmentLineEndings(); + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "nullreferenceexample.template"))).ToEnvironmentLineEndings(); + var expectedCSharpContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "NullableReferenceTypeExample_NullableHeaderHttpApi_Generated.g.cs"))).ToEnvironmentLineEndings(); var test = new VerifyCS.Test { @@ -735,12 +735,12 @@ public async Task VerifyApiFunctionUsingNullableParameters() { Sources = { - (Path.Combine("TestServerlessApp", "NullableReferenceTypeExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "NullableReferenceTypeExample.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "NullableReferenceTypeExample.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "NullableReferenceTypeExample.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -761,7 +761,7 @@ public async Task VerifyApiFunctionUsingNullableParameters() await test.RunAsync(); - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } @@ -774,11 +774,11 @@ public async Task VerifyNoApiGatewayEventsReference() { Sources = { - (Path.Combine("TestServerlessApp", "FromScratch", "NoApiGatewayEventsReference.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "FromScratch", "NoApiGatewayEventsReference.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "FromScratch", "NoApiGatewayEventsReference.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "FromScratch", "NoApiGatewayEventsReference.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -805,9 +805,9 @@ public async Task VerifyNoSerializerAttributeReference() { Sources = { - (Path.Combine("TestServerlessApp", "FromScratch", "NoSerializerAttributeReference.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "FromScratch", "NoSerializerAttributeReference.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestServerlessApp", "FromScratch", "NoSerializerAttributeReference.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "FromScratch", "NoSerializerAttributeReference.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), }, GeneratedSources = { @@ -833,13 +833,13 @@ public async Task ComplexQueryParameters_AreNotSupported() { Sources = { - (Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))), - (Path.Combine("TestServerlessApp", "ComplexQueryParameter.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "ComplexQueryParameter.cs.error"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))), + (Path.Combine("TestServerlessApp", "ComplexQueryParameter.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "ComplexQueryParameter.cs.error"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, ExpectedDiagnostics = { @@ -861,13 +861,13 @@ public async Task InvalidParameterAttributeNames_ThrowsDiagnosticErrors() { Sources = { - (Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))), - (Path.Combine("TestServerlessApp", "InvalidParameterAttributeNames.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "InvalidParameterAttributeNames.cs.error"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), - (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), + (Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))), + (Path.Combine("TestServerlessApp", "InvalidParameterAttributeNames.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "InvalidParameterAttributeNames.cs.error"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))), + (Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, ExpectedDiagnostics = { From 0b577585a52d25b8b6b3ceea6083ef98f26eb69a Mon Sep 17 00:00:00 2001 From: James Eastham Date: Sat, 9 Sep 2023 18:19:54 +0100 Subject: [PATCH 10/27] Update attribute name and add Runtime option --- Libraries/Amazon.Lambda.Annotations.slnf | 27 ++++++- .../Diagnostics/DiagnosticDescriptors.cs | 18 ++++- .../Generator.cs | 36 +++++++-- .../Models/ILambdaFunctionSerializable.cs | 5 ++ .../Models/LambdaFunctionModel.cs | 5 ++ .../Models/LambdaFunctionModelBuilder.cs | 5 +- .../Models/LambdaMethodModel.cs | 5 ++ .../Templates/ExecutableAssembly.cs | 76 +++++++++---------- .../Templates/ExecutableAssembly.tt | 8 +- .../Writers/CloudFormationWriter.cs | 6 +- ....cs => LambdaGlobalPropertiesAttribute.cs} | 5 +- .../Snapshots/Program.g.cs | 4 +- .../Snapshots/ProgramMultiHandler.g.cs | 8 +- .../Snapshots/ProgramZipOutput.g.cs | 4 +- .../subnamespace_executable.template | 2 +- .../SourceGeneratorTests.cs | 6 +- .../WriterTests/CloudFormationWriterTests.cs | 1 + .../AssemblyAttributes.cs | 2 +- .../IntegrationTestContextFixture.cs | 2 +- 19 files changed, 156 insertions(+), 69 deletions(-) rename Libraries/src/Amazon.Lambda.Annotations/{LambdaGenerateMainAttribute.cs => LambdaGlobalPropertiesAttribute.cs} (80%) diff --git a/Libraries/Amazon.Lambda.Annotations.slnf b/Libraries/Amazon.Lambda.Annotations.slnf index edfc6fbe8..bb87c663c 100644 --- a/Libraries/Amazon.Lambda.Annotations.slnf +++ b/Libraries/Amazon.Lambda.Annotations.slnf @@ -2,11 +2,36 @@ "solution": { "path": "Libraries.sln", "projects": [ - "src\\Amazon.Lambda.APIGatewayEvents\\Amazon.Lambda.APIGatewayEvents.csproj", "src\\Amazon.Lambda.Annotations.SourceGenerator\\Amazon.Lambda.Annotations.SourceGenerator.csproj", "src\\Amazon.Lambda.Annotations\\Amazon.Lambda.Annotations.csproj", + "src\\Amazon.Lambda.APIGatewayEvents\\Amazon.Lambda.APIGatewayEvents.csproj", + "src\\Amazon.Lambda.ApplicationLoadBalancerEvents\\Amazon.Lambda.ApplicationLoadBalancerEvents.csproj", + "src\\Amazon.Lambda.AspNetCoreServer.Hosting\\Amazon.Lambda.AspNetCoreServer.Hosting.csproj", + "src\\Amazon.Lambda.AspNetCoreServer\\Amazon.Lambda.AspNetCoreServer.csproj", + "src\\Amazon.Lambda.CloudWatchEvents\\Amazon.Lambda.CloudWatchEvents.csproj", + "src\\Amazon.Lambda.CloudWatchLogsEvents\\Amazon.Lambda.CloudWatchLogsEvents.csproj", + "src\\Amazon.Lambda.CognitoEvents\\Amazon.Lambda.CognitoEvents.csproj", + "src\\Amazon.Lambda.ConfigEvents\\Amazon.Lambda.ConfigEvents.csproj", + "src\\Amazon.Lambda.ConnectEvents\\Amazon.Lambda.ConnectEvents.csproj", "src\\Amazon.Lambda.Core\\Amazon.Lambda.Core.csproj", + "src\\Amazon.Lambda.DynamoDBEvents\\Amazon.Lambda.DynamoDBEvents.csproj", + "src\\Amazon.Lambda.KafkaEvents\\Amazon.Lambda.KafkaEvents.csproj", + "src\\Amazon.Lambda.KinesisAnalyticsEvents\\Amazon.Lambda.KinesisAnalyticsEvents.csproj", + "src\\Amazon.Lambda.KinesisEvents\\Amazon.Lambda.KinesisEvents.csproj", + "src\\Amazon.Lambda.KinesisFirehoseEvents\\Amazon.Lambda.KinesisFirehoseEvents.csproj", + "src\\Amazon.Lambda.LexEvents\\Amazon.Lambda.LexEvents.csproj", + "src\\Amazon.Lambda.LexV2Events\\Amazon.Lambda.LexV2Events.csproj", + "src\\Amazon.Lambda.Logging.AspNetCore\\Amazon.Lambda.Logging.AspNetCore.csproj", + "src\\Amazon.Lambda.MQEvents\\Amazon.Lambda.MQEvents.csproj", + "src\\Amazon.Lambda.PowerShellHost\\Amazon.Lambda.PowerShellHost.csproj", + "src\\Amazon.Lambda.RuntimeSupport\\Amazon.Lambda.RuntimeSupport.csproj", + "src\\Amazon.Lambda.S3Events\\Amazon.Lambda.S3Events.csproj", + "src\\Amazon.Lambda.Serialization.Json\\Amazon.Lambda.Serialization.Json.csproj", "src\\Amazon.Lambda.Serialization.SystemTextJson\\Amazon.Lambda.Serialization.SystemTextJson.csproj", + "src\\Amazon.Lambda.SimpleEmailEvents\\Amazon.Lambda.SimpleEmailEvents.csproj", + "src\\Amazon.Lambda.SNSEvents\\Amazon.Lambda.SNSEvents.csproj", + "src\\Amazon.Lambda.SQSEvents\\Amazon.Lambda.SQSEvents.csproj", + "src\\Amazon.Lambda.TestUtilities\\Amazon.Lambda.TestUtilities.csproj", "test\\Amazon.Lambda.Annotations.SourceGenerators.Tests\\Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj", "test\\TestServerlessApp.IntegrationTests\\TestServerlessApp.IntegrationTests.csproj", "test\\TestServerlessApp\\TestServerlessApp.csproj" diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs index 89295690d..f7498df62 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs @@ -47,7 +47,7 @@ public static class DiagnosticDescriptors public static readonly DiagnosticDescriptor MainMethodExists = new DiagnosticDescriptor(id: "AWSLambda0104", title: "static Main method exists", - messageFormat: "Failed to generate Main method for LambdaGenerateMainAttribute because project already contains Main method. Existing Main methods must be removed when using LambdaGenerateMainAttribute attribute.", + messageFormat: "Failed to generate Main method for LambdaGenerateMainAttribute because project already contains Main method. Existing Main methods must be removed when using LambdaGenerateMainAttribute attribute.", category: "AWSLambdaCSharpGenerator", DiagnosticSeverity.Error, isEnabledByDefault: true); @@ -94,5 +94,21 @@ public static class DiagnosticDescriptors category: "AWSLambdaCSharpGenerator", DiagnosticSeverity.Error, isEnabledByDefault: true); + + public static readonly DiagnosticDescriptor SetOutputTypeExecutable = new DiagnosticDescriptor(id: "AWSLambda0111", + title: "Output Type is not an executable", + messageFormat: "AssemblyAttribute Amazon.Lambda.Annotations.LambdaGlobalPropertiesAttribute is configured to generate a static main method " + + "but the assembly itself is not configured to output an executable. Set the 'OutputType' property in the .csproj file to be 'exe'.", + category: "AWSLambdaCSharpGenerator", + DiagnosticSeverity.Error, + isEnabledByDefault: true); + + public static readonly DiagnosticDescriptor InvalidRuntimeSelection = new DiagnosticDescriptor(id: "AWSLambda0112", + title: "Invalid runtime selection", + messageFormat: "The runtime selected in the Amazon.Lambda.Annotations.LambdaGlobalPropertiesAttribute is not a supported value " + + "It should be set to either 'dotnet6' or 'provided.al2'.", + category: "AWSLambdaCSharpGenerator", + DiagnosticSeverity.Error, + isEnabledByDefault: true); } } \ No newline at end of file diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs index 21e347966..c5340ebc0 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs @@ -25,6 +25,12 @@ public class Generator : ISourceGenerator private readonly IFileManager _fileManager = new FileManager(); private readonly IDirectoryManager _directoryManager = new DirectoryManager(); + private readonly List _allowdRuntimeValues = new List(2) + { + "dotnet6", + "provided.al2" + }; + // Only allow alphanumeric characters private readonly Regex _resourceNameRegex = new Regex("^[a-zA-Z0-9]+$"); @@ -85,16 +91,38 @@ public void Execute(GeneratorExecutionContext context) } var isExecutable = false; + + bool foundFatalError = false; var assemblyAttributes = context.Compilation.Assembly.GetAttributes(); // Let's find the AssemblyTitleAttribute var generateMainAttribute = assemblyAttributes - .FirstOrDefault(attr => attr.AttributeClass.Name == nameof(LambdaGenerateMainAttribute)); + .FirstOrDefault(attr => attr.AttributeClass.Name == nameof(LambdaGlobalPropertiesAttribute)); + + var defaultRuntime = "dotnet6"; if (generateMainAttribute != null) { - isExecutable = true; + var generateMain = generateMainAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "GenerateMain").Value; + var runtime = generateMainAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "Runtime") + .Value.Value.ToString(); + + if (!_allowdRuntimeValues.Contains(runtime)) + { + diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.InvalidRuntimeSelection, Location.None)); + return; + } + + defaultRuntime = runtime; + + isExecutable = bool.Parse(generateMain.Value.ToString()); + + // if (isExecutable && context.Compilation.Options.OutputKind != OutputKind.ConsoleApplication) + // { + // diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.SetOutputTypeExecutable, Location.None)); + // return; + // } } var configureMethodModel = semanticModelProvider.GetConfigureMethodModel(receiver.StartupClasses.FirstOrDefault()); @@ -103,8 +131,6 @@ public void Execute(GeneratorExecutionContext context) var templateHandler = new CloudFormationTemplateHandler(_fileManager, _directoryManager); - bool foundFatalError = false; - var lambdaModels = new List(); foreach (var lambdaMethod in receiver.LambdaMethods) @@ -138,7 +164,7 @@ public void Execute(GeneratorExecutionContext context) var serializerString = GetSerializerAttribute(context, lambdaMethodModel); - var model = LambdaFunctionModelBuilder.Build(lambdaMethodModel, configureMethodModel, context, isExecutable, serializerString); + var model = LambdaFunctionModelBuilder.Build(lambdaMethodModel, configureMethodModel, context, isExecutable, serializerString, defaultRuntime); // If there are more than one event, report them as errors if (model.LambdaMethod.Events.Count > 1) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/ILambdaFunctionSerializable.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/ILambdaFunctionSerializable.cs index 171bff03d..9ed23c88f 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/ILambdaFunctionSerializable.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/ILambdaFunctionSerializable.cs @@ -47,6 +47,11 @@ public interface ILambdaFunctionSerializable /// bool IsExecutable { get; } + /// + /// Gets or sets the Lambda runtime to use.. + /// + string Runtime { get; } + /// /// Resource based policies that grants permissions to access other AWS resources. /// diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs index 38921bd93..ddaf50b6e 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModel.cs @@ -41,6 +41,11 @@ public class LambdaFunctionModel : ILambdaFunctionSerializable /// Gets or sets if the output is an executable. /// public bool IsExecutable { get; set; } + + /// + /// Gets or sets the Lambda runtime to use. + /// + public string Runtime { get; set; } /// public string Handler => IsExecutable ? LambdaMethod.ContainingAssembly : $"{LambdaMethod.ContainingAssembly}::{GeneratedMethod.ContainingType.FullName}::{LambdaMethod.Name}"; diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs index bc5b7348d..88300dcc6 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaFunctionModelBuilder.cs @@ -9,7 +9,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Models /// public static class LambdaFunctionModelBuilder { - public static LambdaFunctionModel Build(IMethodSymbol lambdaMethodSymbol, IMethodSymbol configureMethodSymbol, GeneratorExecutionContext context, bool isExecutable, string serializer) + public static LambdaFunctionModel Build(IMethodSymbol lambdaMethodSymbol, IMethodSymbol configureMethodSymbol, GeneratorExecutionContext context, bool isExecutable, string serializer, string runtime) { var lambdaMethod = LambdaMethodModelBuilder.Build(lambdaMethodSymbol, configureMethodSymbol, context); var generatedMethod = GeneratedMethodModelBuilder.Build(lambdaMethodSymbol, configureMethodSymbol, lambdaMethod, context); @@ -22,7 +22,8 @@ public static LambdaFunctionModel Build(IMethodSymbol lambdaMethodSymbol, IMetho SourceGeneratorVersion = context.Compilation .ReferencedAssemblyNames.FirstOrDefault(x => string.Equals(x.Name, "Amazon.Lambda.Annotations")) ?.Version.ToString(), - IsExecutable = isExecutable + IsExecutable = isExecutable, + Runtime = runtime }; return model; diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaMethodModel.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaMethodModel.cs index d3a414bb8..9a81ee95c 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaMethodModel.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/LambdaMethodModel.cs @@ -75,6 +75,11 @@ public bool ReturnsIHttpResults /// public string Name { get; set; } + /// + /// Gets or sets name of the original method. + /// + public string ExecutableAssemblyHandlerName => $"{this.Name.ToLower()}_handler"; + /// /// Returns true if original method uses dependency injection. /// diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs index bd0eff9c8..e11a1c91c 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs @@ -23,7 +23,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates /// Class to produce the template output /// - #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 1 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public partial class ExecutableAssembly : ExecutableAssemblyBase { @@ -33,16 +33,16 @@ public partial class ExecutableAssembly : ExecutableAssemblyBase /// public virtual string TransformText() { - this.Write("using System;\r\nusing System.Linq;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\nusing Amazon.Lambda.Core;\r\n\r\nnamespace "); + this.Write("using System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Amazon.Lambda.Core;\n\nnamespace "); - #line 18 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 18 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._containingNamespace)); #line default #line hidden - this.Write(";\r\n\r\npublic class GeneratedProgram\r\n{\r\n private static async Task Main(string[] args)\r\n {\r\n\r\n switch (Environment.GetEnvironmentVariable(\"ANNOTATIONS_HANDLER\"))\r\n {\r\n"); + this.Write(";\n\npublic class GeneratedProgram\n{\n private static async Task Main(string[] args)\n {\n\n switch (Environment.GetEnvironmentVariable(\"ANNOTATIONS_HANDLER\"))\n {\n"); - #line 27 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 27 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" foreach (var model in this._lambdaFunctions) { @@ -52,14 +52,14 @@ public virtual string TransformText() #line hidden this.Write(" case \""); - #line 31 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 31 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write("\":\r\n"); + this.Write("\":\n"); - #line 32 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 32 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" if (model.GeneratedMethod.ReturnType.FullName == "void") { @@ -69,63 +69,63 @@ public virtual string TransformText() #line hidden this.Write(" Action<"); - #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); #line default #line hidden this.Write("> "); - #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); + #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(" = new "); - #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingNamespace)); #line default #line hidden this.Write("."); - #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated()."); - #line 36 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); + #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(", new "); - #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].Serializer)); #line default #line hidden - this.Write("()).Build().RunAsync();\r\n break;\r\n"); + this.Write("()).Build().RunAsync();\n break;\n"); - #line 39 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 39 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" } else @@ -136,70 +136,70 @@ public virtual string TransformText() #line hidden this.Write(" Func<"); - #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); #line default #line hidden this.Write(", "); - #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.ReturnType.FullName)); #line default #line hidden this.Write("> "); - #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); + #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(" = new "); - #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingNamespace)); #line default #line hidden this.Write("."); - #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated()."); - #line 44 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name.ToLower())); + #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(", new "); - #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.Serializer)); #line default #line hidden - this.Write("()).Build().RunAsync();\r\n break;\r\n"); + this.Write("()).Build().RunAsync();\n break;\n"); - #line 47 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" } } @@ -207,15 +207,15 @@ public virtual string TransformText() #line default #line hidden - this.Write("\r\n }\r\n"); + this.Write("\n }\n"); - #line 53 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 53 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" #line default #line hidden - this.Write(" }\r\n}"); + this.Write(" }\n}"); return this.GenerationEnvironment.ToString(); } } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt index 5e1a35bf7..29e88d2d2 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt @@ -33,16 +33,16 @@ public class GeneratedProgram if (model.GeneratedMethod.ReturnType.FullName == "void") { #> - Action<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>> <#= model.LambdaMethod.Name.ToLower() #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new <#= this._lambdaFunctions[0].Serializer #>()).Build().RunAsync(); + Action<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>> <#= model.LambdaMethod.ExecutableAssemblyHandlerName #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.ExecutableAssemblyHandlerName #>, new <#= this._lambdaFunctions[0].Serializer #>()).Build().RunAsync(); break; <# } else { #> - Func<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= model.GeneratedMethod.ReturnType.FullName #>> <#= model.LambdaMethod.Name.ToLower() #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.Name.ToLower() #>, new <#= model.Serializer #>()).Build().RunAsync(); + Func<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= model.GeneratedMethod.ReturnType.FullName #>> <#= model.LambdaMethod.ExecutableAssemblyHandlerName #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.ExecutableAssemblyHandlerName #>, new <#= model.Serializer #>()).Build().RunAsync(); break; <# } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs index 3717d4d82..f131b4631 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs @@ -104,7 +104,7 @@ private void ProcessLambdaFunction(ILambdaFunctionSerializable lambdaFunction, s var propertiesPath = $"{lambdaFunctionPath}.Properties"; if (!_templateWriter.Exists(lambdaFunctionPath)) - ApplyLambdaFunctionDefaults(lambdaFunctionPath, propertiesPath); + ApplyLambdaFunctionDefaults(lambdaFunctionPath, propertiesPath, lambdaFunction.Runtime); ProcessLambdaFunctionProperties(lambdaFunction, propertiesPath, relativeProjectUri); ProcessLambdaFunctionEventAttributes(lambdaFunction); @@ -256,12 +256,12 @@ private string ProcessHttpApiAttribute(ILambdaFunctionSerializable lambdaFunctio /// /// Writes the default values for the Lambda function's metadata and properties. /// - private void ApplyLambdaFunctionDefaults(string lambdaFunctionPath, string propertiesPath) + private void ApplyLambdaFunctionDefaults(string lambdaFunctionPath, string propertiesPath, string runtime) { _templateWriter.SetToken($"{lambdaFunctionPath}.Type", "AWS::Serverless::Function"); _templateWriter.SetToken($"{lambdaFunctionPath}.Metadata.Tool", CREATION_TOOL); - _templateWriter.SetToken($"{propertiesPath}.Runtime", "dotnet6"); + _templateWriter.SetToken($"{propertiesPath}.Runtime", runtime); _templateWriter.SetToken($"{propertiesPath}.CodeUri", ""); _templateWriter.SetToken($"{propertiesPath}.MemorySize", 256); _templateWriter.SetToken($"{propertiesPath}.Timeout", 30); diff --git a/Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs similarity index 80% rename from Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs rename to Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs index 785aaeb99..3a10d6455 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/LambdaGenerateMainAttribute.cs +++ b/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs @@ -9,7 +9,10 @@ namespace Amazon.Lambda.Annotations /// Deploying as an executable versus a class library is required when compiling functions with Native AOT. It can also be useful to deploy as an executable to include specific versions of `Amazon.Lambda.RuntimeSupport` the .NET Lambda runtime client. /// [AttributeUsage( AttributeTargets.Assembly)] - public class LambdaGenerateMainAttribute : Attribute + public class LambdaGlobalPropertiesAttribute : Attribute { + public bool GenerateMain { get; set; } + + public string Runtime { get; set; } } } \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs index 942b82d8a..1c5734cee 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs @@ -15,8 +15,8 @@ private static async Task Main(string[] args) switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) { case "ToUpper": - Func toupper = new TestServerlessApp.Sub1.Functions_ToUpper_Generated().ToUpper; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(toupper, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + Func toupper_handler = new TestServerlessApp.Sub1.Functions_ToUpper_Generated().ToUpper; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(toupper_handler, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); break; } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs index c3052e7fc..1923b42d3 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs @@ -15,12 +15,12 @@ private static async Task Main(string[] args) switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) { case "SayHello": - Func sayhello = new TestServerlessApp.Greeter_SayHello_Generated().SayHello; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(sayhello, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + Func sayhello_handler = new TestServerlessApp.Greeter_SayHello_Generated().SayHello; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(sayhello_handler, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); break; case "SayHelloAsync": - Func> sayhelloasync = new TestServerlessApp.Greeter_SayHelloAsync_Generated().SayHelloAsync; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(sayhelloasync, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + Func> sayhelloasync_handler = new TestServerlessApp.Greeter_SayHelloAsync_Generated().SayHelloAsync; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(sayhelloasync_handler, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); break; } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs index 5b3c922aa..66a02964e 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs @@ -15,8 +15,8 @@ private static async Task Main(string[] args) switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) { case "ToLower": - Func tolower = new TestServerlessApp.Sub1.FunctionsZipOutput_ToLower_Generated().ToLower; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(tolower, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + Func tolower_handler = new TestServerlessApp.Sub1.FunctionsZipOutput_ToLower_Generated().ToLower; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(tolower_handler, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); break; } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executable.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executable.template index 90d108993..28fbac2df 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executable.template +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/subnamespace_executable.template @@ -9,7 +9,7 @@ "Tool": "Amazon.Lambda.Annotations" }, "Properties": { - "Runtime": "dotnet6", + "Runtime": "provided.al2", "CodeUri": ".", "MemorySize": 256, "Timeout": 30, diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index 1e8c231b8..149352a91 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -278,7 +278,7 @@ public async Task VerifyExecutableAssemblyWithZipAndHandler() (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"))), (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = @@ -331,7 +331,7 @@ public async Task VerifyExecutableAssembly() (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"))), (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = @@ -385,7 +385,7 @@ public async Task VerifyExecutableAssemblyWithMultipleHandler() (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGenerateMainAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"))), (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/WriterTests/CloudFormationWriterTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/WriterTests/CloudFormationWriterTests.cs index d973350f9..e2c4abaf2 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/WriterTests/CloudFormationWriterTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/WriterTests/CloudFormationWriterTests.cs @@ -830,6 +830,7 @@ public class LambdaFunctionModelTest : ILambdaFunctionSerializable public uint? MemorySize { get; set; } public string Role { get; set; } public string Policies { get; set; } + public string Runtime { get; set; } public IList Attributes { get; set; } = new List(); public string SourceGeneratorVersion { get; set; } public LambdaPackageType PackageType { get; set; } = LambdaPackageType.Zip; diff --git a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs index 8a8a683a7..33962fb9f 100644 --- a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs +++ b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributes.cs @@ -2,4 +2,4 @@ using Amazon.Lambda.Core; [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] -[assembly: LambdaGenerateMain] \ No newline at end of file +[assembly: LambdaGlobalProperties(GenerateMain = true, Runtime = "provided.al2")] \ No newline at end of file diff --git a/Libraries/test/TestServerlessApp.IntegrationTests/IntegrationTestContextFixture.cs b/Libraries/test/TestServerlessApp.IntegrationTests/IntegrationTestContextFixture.cs index 5c4ac6672..211abab5b 100644 --- a/Libraries/test/TestServerlessApp.IntegrationTests/IntegrationTestContextFixture.cs +++ b/Libraries/test/TestServerlessApp.IntegrationTests/IntegrationTestContextFixture.cs @@ -55,7 +55,7 @@ public async Task InitializeAsync() Assert.Equal(StackStatus.CREATE_COMPLETE, await _cloudFormationHelper.GetStackStatusAsync(_stackName)); Assert.True(await _s3Helper.BucketExistsAsync(_bucketName)); - Assert.Equal(25, LambdaFunctions.Count); + Assert.Equal(26, LambdaFunctions.Count); Assert.False(string.IsNullOrEmpty(RestApiUrlPrefix)); Assert.False(string.IsNullOrEmpty(RestApiUrlPrefix)); From 0207130270838bf42a6ccdf014c4e3de8607be5f Mon Sep 17 00:00:00 2001 From: jamesuk Date: Mon, 11 Sep 2023 13:54:19 +0100 Subject: [PATCH 11/27] Update unit tests and documentation --- .../Generator.cs | 17 ++--- .../LambdaGlobalPropertiesAttribute.cs | 6 ++ .../SourceGeneratorTests.cs | 73 +++++++++++++++++++ .../AssemblyAttributeNullValues.cs | 5 ++ .../AssemblyAttributesInvalidRuntime.cs | 5 ++ .../serverless.template | 32 ++++---- 6 files changed, 113 insertions(+), 25 deletions(-) create mode 100644 Libraries/test/TestExecutableServerlessApp/AssemblyAttributeNullValues.cs create mode 100644 Libraries/test/TestExecutableServerlessApp/AssemblyAttributesInvalidRuntime.cs diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs index c5340ebc0..f503e91a7 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs @@ -96,17 +96,16 @@ public void Execute(GeneratorExecutionContext context) var assemblyAttributes = context.Compilation.Assembly.GetAttributes(); - // Let's find the AssemblyTitleAttribute - var generateMainAttribute = assemblyAttributes + var globalPropertiesAttribute = assemblyAttributes .FirstOrDefault(attr => attr.AttributeClass.Name == nameof(LambdaGlobalPropertiesAttribute)); var defaultRuntime = "dotnet6"; - if (generateMainAttribute != null) + if (globalPropertiesAttribute != null) { - var generateMain = generateMainAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "GenerateMain").Value; - var runtime = generateMainAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "Runtime") - .Value.Value.ToString(); + var generateMain = globalPropertiesAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "GenerateMain").Value; + var runtimeAttributeValue = globalPropertiesAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "Runtime").Value; + var runtime = runtimeAttributeValue.Value == null ? defaultRuntime : runtimeAttributeValue.Value.ToString(); if (!_allowdRuntimeValues.Contains(runtime)) { @@ -115,9 +114,9 @@ public void Execute(GeneratorExecutionContext context) } defaultRuntime = runtime; - - isExecutable = bool.Parse(generateMain.Value.ToString()); - + + isExecutable = generateMain.Value != null && bool.Parse(generateMain.Value.ToString()); + // if (isExecutable && context.Compilation.Options.OutputKind != OutputKind.ConsoleApplication) // { // diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.SetOutputTypeExecutable, Location.None)); diff --git a/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs index 3a10d6455..f710ec086 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs +++ b/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs @@ -11,8 +11,14 @@ namespace Amazon.Lambda.Annotations [AttributeUsage( AttributeTargets.Assembly)] public class LambdaGlobalPropertiesAttribute : Attribute { + /// + /// Indicates whether the Lambda Annotations Framework will generate a static main method and the code to bootstrap the Lambda runtime. + /// public bool GenerateMain { get; set; } + /// + /// The runtime to set in the generated CloudFormation template. Either 'dotnet6' or 'provided.al2'. + /// public string Runtime { get; set; } } } \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index 149352a91..f2af8aa80 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -222,6 +222,41 @@ public async Task ComplexCalculator() Assert.Equal(expectedTemplateContent, actualTemplateContent); } + [Fact] + public async Task TestInvalidGlobalRuntime_ShouldError() + { + var test = new VerifyCS.Test + { + TestState = + { + Sources = + { + (Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Startup.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Startup.cs"))), + (Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Services", "SimpleCalculatorService.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributesInvalidRuntime.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributesInvalidRuntime.cs"))), + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0112", DiagnosticSeverity.Error).WithMessage("The runtime selected in the Amazon.Lambda.Annotations.LambdaGlobalPropertiesAttribute is not a supported value It should be set to either 'dotnet6' or 'provided.al2'."), + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }; + + foreach (var file in Directory.GetFiles( + Path.Combine("Amazon.Lambda.RuntimeSupport"), + "*.cs", SearchOption.AllDirectories)) + { + test.TestState.Sources.Add((file, await File.ReadAllTextAsync(file))); + } + + await test.RunAsync(); + } + [Fact] public async Task VerifyFunctionInSubNamespace() { @@ -366,6 +401,44 @@ public async Task VerifyExecutableAssembly() await test.RunAsync(); } + [Fact] + public async Task VerifyExecutableAssembly_WithNullAttributeValues_ShouldComplete() + { + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Functions_ToUpper_Generated.g.cs"))).ToEnvironmentLineEndings(); + + await new VerifyCS.Test + { + TestState = + { + Sources = + { + (Path.Combine("TestServerlessApp", "Sub1", "Functions.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "Sub1", "Functions.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributeNullValues.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributeNullValues.cs"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "Functions_ToUpper_Generated.g.cs", + SourceText.From(expectedSubNamespaceGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("Functions_ToUpper_Generated.g.cs", expectedSubNamespaceGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent), + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }.RunAsync(); + + var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); + Assert.Equal(expectedTemplateContent, actualTemplateContent); + } + [Fact] public async Task VerifyExecutableAssemblyWithMultipleHandler() { diff --git a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributeNullValues.cs b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributeNullValues.cs new file mode 100644 index 000000000..35be8676d --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributeNullValues.cs @@ -0,0 +1,5 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Core; + +[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] +[assembly: LambdaGlobalProperties(Runtime = null)] \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributesInvalidRuntime.cs b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributesInvalidRuntime.cs new file mode 100644 index 000000000..d44771dee --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributesInvalidRuntime.cs @@ -0,0 +1,5 @@ +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Core; + +[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] +[assembly: LambdaGlobalProperties(GenerateMain = true, Runtime = "notavalidruntime")] \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/serverless.template b/Libraries/test/TestExecutableServerlessApp/serverless.template index b1d9c89ec..b8d6794f3 100644 --- a/Libraries/test/TestExecutableServerlessApp/serverless.template +++ b/Libraries/test/TestExecutableServerlessApp/serverless.template @@ -37,7 +37,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicReturn_Generated::DynamicReturn" ] }, "Environment": { @@ -62,7 +62,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicInput_Generated::DynamicInput" ] }, "Environment": { @@ -87,7 +87,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.TaskExample_TaskReturn_Generated::TaskReturn" ] }, "Environment": { @@ -112,7 +112,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.VoidExample_VoidReturn_Generated::VoidReturn" ] }, "Environment": { @@ -140,7 +140,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeader_Generated::OkResponseWithHeader" ] }, "Events": { @@ -177,7 +177,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated::OkResponseWithHeaderAsync" ] }, "Events": { @@ -214,7 +214,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated::NotFoundResponseWithHeaderV2" ] }, "Events": { @@ -251,7 +251,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated::NotFoundResponseWithHeaderV2Async" ] }, "Events": { @@ -288,7 +288,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated::NotFoundResponseWithHeaderV1" ] }, "Events": { @@ -326,7 +326,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated::NotFoundResponseWithHeaderV1Async" ] }, "Events": { @@ -364,7 +364,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHello_Generated::SayHello" ] }, "Events": { @@ -402,7 +402,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" ] }, "Events": { @@ -437,7 +437,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.Sub1.Functions_ToUpper_Generated::ToUpper" ] }, "Environment": { @@ -465,7 +465,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.NullableReferenceTypeExample_NullableHeaderHttpApi_Generated::NullableHeaderHttpApi" ] }, "Events": { @@ -499,7 +499,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.IntrinsicExample_HasIntrinsic_Generated::HasIntrinsic" ] }, "Environment": { @@ -522,7 +522,7 @@ ], "PackageType": "Zip", "CodeUri": ".", - "Handler": "TestExecutableServerlessApp", + "Handler": "TestExecutableServerlessApp::TestServerlessApp.Sub1.FunctionsZipOutput_ToLower_Generated::ToLower", "Environment": { "Variables": { "ANNOTATIONS_HANDLER": "ToLower" From d695a6cc1f08705a8e16817e35a4f861c87c44d7 Mon Sep 17 00:00:00 2001 From: James Eastham Date: Sun, 1 Oct 2023 13:19:30 +0100 Subject: [PATCH 12/27] Update tests and comments --- .../Generator.cs | 10 +++--- .../LambdaGlobalPropertiesAttribute.cs | 8 ++--- .../SourceGeneratorTests.cs | 21 ++++++++++++ .../serverless.template | 32 +++++++++---------- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs index f503e91a7..d3b11b0be 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs @@ -117,11 +117,11 @@ public void Execute(GeneratorExecutionContext context) isExecutable = generateMain.Value != null && bool.Parse(generateMain.Value.ToString()); - // if (isExecutable && context.Compilation.Options.OutputKind != OutputKind.ConsoleApplication) - // { - // diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.SetOutputTypeExecutable, Location.None)); - // return; - // } + if (isExecutable && context.Compilation.Options.OutputKind != OutputKind.ConsoleApplication) + { + diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.SetOutputTypeExecutable, Location.None)); + return; + } } var configureMethodModel = semanticModelProvider.GetConfigureMethodModel(receiver.StartupClasses.FirstOrDefault()); diff --git a/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs index f710ec086..392761432 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs +++ b/Libraries/src/Amazon.Lambda.Annotations/LambdaGlobalPropertiesAttribute.cs @@ -4,15 +4,15 @@ namespace Amazon.Lambda.Annotations { /// - /// Used when deploying Lambda functions as a .NET executable instead of a class library. Ensure the .NET project's output type is configured for `Console Application`. In the project file the `OutputType` property will be set to `Exe`. - /// - /// Deploying as an executable versus a class library is required when compiling functions with Native AOT. It can also be useful to deploy as an executable to include specific versions of `Amazon.Lambda.RuntimeSupport` the .NET Lambda runtime client. + /// Used to add global configuration to the Lambda Source Generators. /// [AttributeUsage( AttributeTargets.Assembly)] public class LambdaGlobalPropertiesAttribute : Attribute { /// - /// Indicates whether the Lambda Annotations Framework will generate a static main method and the code to bootstrap the Lambda runtime. + /// Indicates whether the Lambda Annotations Framework will generate a static main method and the code to bootstrap the Lambda runtime. + /// Ensure the .NET project's output type is configured for `Console Application`. In the project file the `OutputType` property will be set to `Exe`. + /// Deploying as an executable versus a class library is required when compiling functions with Native AOT. It can also be useful to deploy as an executable to include specific versions of `Amazon.Lambda.RuntimeSupport` the .NET Lambda runtime client. /// public bool GenerateMain { get; set; } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index f2af8aa80..c202e2e4a 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -306,6 +306,7 @@ public async Task VerifyExecutableAssemblyWithZipAndHandler() { TestState = { + OutputKind = OutputKind.ConsoleApplication, Sources = { (Path.Combine("TestExecutableServerlessApp", "Sub1", "FunctionsZipOutput.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Sub1", "FunctionsZipOutput.cs"))), @@ -342,6 +343,12 @@ public async Task VerifyExecutableAssemblyWithZipAndHandler() Path.Combine("Amazon.Lambda.RuntimeSupport"), "*.cs", SearchOption.AllDirectories)) { + var content = await File.ReadAllTextAsync(file); + + // Don't include RuntimeSupport's entry point. + if (file.EndsWith("Program.cs") && content.Contains("Task Main(string[] args)")) + continue; + test.TestState.Sources.Add((file, await File.ReadAllTextAsync(file))); } @@ -359,6 +366,7 @@ public async Task VerifyExecutableAssembly() { TestState = { + OutputKind = OutputKind.ConsoleApplication, Sources = { (Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Sub1", "Functions.cs"))), @@ -395,6 +403,12 @@ public async Task VerifyExecutableAssembly() Path.Combine("Amazon.Lambda.RuntimeSupport"), "*.cs", SearchOption.AllDirectories)) { + var content = await File.ReadAllTextAsync(file); + + // Don't include RuntimeSupport's entry point. + if (file.EndsWith("Program.cs") && content.Contains("Task Main(string[] args)")) + continue; + test.TestState.Sources.Add((file, await File.ReadAllTextAsync(file))); } @@ -451,6 +465,7 @@ public async Task VerifyExecutableAssemblyWithMultipleHandler() { TestState = { + OutputKind = OutputKind.ConsoleApplication, Sources = { (Path.Combine("TestExecutableServerlessApp", "Greeter.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "Greeter.cs"))), @@ -493,6 +508,12 @@ public async Task VerifyExecutableAssemblyWithMultipleHandler() Path.Combine("Amazon.Lambda.RuntimeSupport"), "*.cs", SearchOption.AllDirectories)) { + var content = await File.ReadAllTextAsync(file); + + // Don't include RuntimeSupport's entry point. + if (file.EndsWith("Program.cs") && content.Contains("Task Main(string[] args)")) + continue; + test.TestState.Sources.Add((file, await File.ReadAllTextAsync(file))); } diff --git a/Libraries/test/TestExecutableServerlessApp/serverless.template b/Libraries/test/TestExecutableServerlessApp/serverless.template index b8d6794f3..b1d9c89ec 100644 --- a/Libraries/test/TestExecutableServerlessApp/serverless.template +++ b/Libraries/test/TestExecutableServerlessApp/serverless.template @@ -37,7 +37,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicReturn_Generated::DynamicReturn" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -62,7 +62,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicInput_Generated::DynamicInput" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -87,7 +87,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.TaskExample_TaskReturn_Generated::TaskReturn" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -112,7 +112,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.VoidExample_VoidReturn_Generated::VoidReturn" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -140,7 +140,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeader_Generated::OkResponseWithHeader" + "TestExecutableServerlessApp" ] }, "Events": { @@ -177,7 +177,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated::OkResponseWithHeaderAsync" + "TestExecutableServerlessApp" ] }, "Events": { @@ -214,7 +214,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated::NotFoundResponseWithHeaderV2" + "TestExecutableServerlessApp" ] }, "Events": { @@ -251,7 +251,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated::NotFoundResponseWithHeaderV2Async" + "TestExecutableServerlessApp" ] }, "Events": { @@ -288,7 +288,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated::NotFoundResponseWithHeaderV1" + "TestExecutableServerlessApp" ] }, "Events": { @@ -326,7 +326,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated::NotFoundResponseWithHeaderV1Async" + "TestExecutableServerlessApp" ] }, "Events": { @@ -364,7 +364,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHello_Generated::SayHello" + "TestExecutableServerlessApp" ] }, "Events": { @@ -402,7 +402,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" + "TestExecutableServerlessApp" ] }, "Events": { @@ -437,7 +437,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Sub1.Functions_ToUpper_Generated::ToUpper" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -465,7 +465,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.NullableReferenceTypeExample_NullableHeaderHttpApi_Generated::NullableHeaderHttpApi" + "TestExecutableServerlessApp" ] }, "Events": { @@ -499,7 +499,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.IntrinsicExample_HasIntrinsic_Generated::HasIntrinsic" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -522,7 +522,7 @@ ], "PackageType": "Zip", "CodeUri": ".", - "Handler": "TestExecutableServerlessApp::TestServerlessApp.Sub1.FunctionsZipOutput_ToLower_Generated::ToLower", + "Handler": "TestExecutableServerlessApp", "Environment": { "Variables": { "ANNOTATIONS_HANDLER": "ToLower" From 5604358562235233e45a6eedf5d3368406c0d33e Mon Sep 17 00:00:00 2001 From: James Eastham Date: Sun, 1 Oct 2023 13:31:28 +0100 Subject: [PATCH 13/27] Update CfN writer to always set runtime --- .../Writers/CloudFormationWriter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs index f131b4631..ba6906a19 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Writers/CloudFormationWriter.cs @@ -152,6 +152,7 @@ private void ProcessPackageTypeProperty(ILambdaFunctionSerializable lambdaFuncti case LambdaPackageType.Zip: _templateWriter.SetToken($"{propertiesPath}.CodeUri", relativeProjectUri); _templateWriter.SetToken($"{propertiesPath}.Handler", lambdaFunction.Handler); + _templateWriter.SetToken($"{propertiesPath}.Runtime", lambdaFunction.Runtime); _templateWriter.RemoveToken($"{propertiesPath}.ImageUri"); _templateWriter.RemoveToken($"{propertiesPath}.ImageConfig"); break; From 47d87f986cf7755a5ef4347b59ba8675f235e210 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Thu, 26 Oct 2023 11:43:58 +0100 Subject: [PATCH 14/27] Update serverless template --- .../serverless.template | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Libraries/test/TestExecutableServerlessApp/serverless.template b/Libraries/test/TestExecutableServerlessApp/serverless.template index b8d6794f3..b1d9c89ec 100644 --- a/Libraries/test/TestExecutableServerlessApp/serverless.template +++ b/Libraries/test/TestExecutableServerlessApp/serverless.template @@ -37,7 +37,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicReturn_Generated::DynamicReturn" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -62,7 +62,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicInput_Generated::DynamicInput" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -87,7 +87,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.TaskExample_TaskReturn_Generated::TaskReturn" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -112,7 +112,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.VoidExample_VoidReturn_Generated::VoidReturn" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -140,7 +140,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeader_Generated::OkResponseWithHeader" + "TestExecutableServerlessApp" ] }, "Events": { @@ -177,7 +177,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated::OkResponseWithHeaderAsync" + "TestExecutableServerlessApp" ] }, "Events": { @@ -214,7 +214,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated::NotFoundResponseWithHeaderV2" + "TestExecutableServerlessApp" ] }, "Events": { @@ -251,7 +251,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated::NotFoundResponseWithHeaderV2Async" + "TestExecutableServerlessApp" ] }, "Events": { @@ -288,7 +288,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated::NotFoundResponseWithHeaderV1" + "TestExecutableServerlessApp" ] }, "Events": { @@ -326,7 +326,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated::NotFoundResponseWithHeaderV1Async" + "TestExecutableServerlessApp" ] }, "Events": { @@ -364,7 +364,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHello_Generated::SayHello" + "TestExecutableServerlessApp" ] }, "Events": { @@ -402,7 +402,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" + "TestExecutableServerlessApp" ] }, "Events": { @@ -437,7 +437,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Sub1.Functions_ToUpper_Generated::ToUpper" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -465,7 +465,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.NullableReferenceTypeExample_NullableHeaderHttpApi_Generated::NullableHeaderHttpApi" + "TestExecutableServerlessApp" ] }, "Events": { @@ -499,7 +499,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.IntrinsicExample_HasIntrinsic_Generated::HasIntrinsic" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -522,7 +522,7 @@ ], "PackageType": "Zip", "CodeUri": ".", - "Handler": "TestExecutableServerlessApp::TestServerlessApp.Sub1.FunctionsZipOutput_ToLower_Generated::ToLower", + "Handler": "TestExecutableServerlessApp", "Environment": { "Variables": { "ANNOTATIONS_HANDLER": "ToLower" From 1ae33d359eee9225141834ccf5f61913a50dac3a Mon Sep 17 00:00:00 2001 From: jamesuk Date: Thu, 26 Oct 2023 11:44:56 +0100 Subject: [PATCH 15/27] Add diaganostic error and update SLN --- Libraries/Amazon.Lambda.Annotations.slnf.bak | 40 +++++++++++++++++++ .../Diagnostics/DiagnosticDescriptors.cs | 7 ++++ .../ExecutableNoAttributes.cs | 29 ++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 Libraries/Amazon.Lambda.Annotations.slnf.bak create mode 100644 Libraries/test/TestExecutableServerlessApp/ExecutableNoAttributes.cs diff --git a/Libraries/Amazon.Lambda.Annotations.slnf.bak b/Libraries/Amazon.Lambda.Annotations.slnf.bak new file mode 100644 index 000000000..bb87c663c --- /dev/null +++ b/Libraries/Amazon.Lambda.Annotations.slnf.bak @@ -0,0 +1,40 @@ +{ + "solution": { + "path": "Libraries.sln", + "projects": [ + "src\\Amazon.Lambda.Annotations.SourceGenerator\\Amazon.Lambda.Annotations.SourceGenerator.csproj", + "src\\Amazon.Lambda.Annotations\\Amazon.Lambda.Annotations.csproj", + "src\\Amazon.Lambda.APIGatewayEvents\\Amazon.Lambda.APIGatewayEvents.csproj", + "src\\Amazon.Lambda.ApplicationLoadBalancerEvents\\Amazon.Lambda.ApplicationLoadBalancerEvents.csproj", + "src\\Amazon.Lambda.AspNetCoreServer.Hosting\\Amazon.Lambda.AspNetCoreServer.Hosting.csproj", + "src\\Amazon.Lambda.AspNetCoreServer\\Amazon.Lambda.AspNetCoreServer.csproj", + "src\\Amazon.Lambda.CloudWatchEvents\\Amazon.Lambda.CloudWatchEvents.csproj", + "src\\Amazon.Lambda.CloudWatchLogsEvents\\Amazon.Lambda.CloudWatchLogsEvents.csproj", + "src\\Amazon.Lambda.CognitoEvents\\Amazon.Lambda.CognitoEvents.csproj", + "src\\Amazon.Lambda.ConfigEvents\\Amazon.Lambda.ConfigEvents.csproj", + "src\\Amazon.Lambda.ConnectEvents\\Amazon.Lambda.ConnectEvents.csproj", + "src\\Amazon.Lambda.Core\\Amazon.Lambda.Core.csproj", + "src\\Amazon.Lambda.DynamoDBEvents\\Amazon.Lambda.DynamoDBEvents.csproj", + "src\\Amazon.Lambda.KafkaEvents\\Amazon.Lambda.KafkaEvents.csproj", + "src\\Amazon.Lambda.KinesisAnalyticsEvents\\Amazon.Lambda.KinesisAnalyticsEvents.csproj", + "src\\Amazon.Lambda.KinesisEvents\\Amazon.Lambda.KinesisEvents.csproj", + "src\\Amazon.Lambda.KinesisFirehoseEvents\\Amazon.Lambda.KinesisFirehoseEvents.csproj", + "src\\Amazon.Lambda.LexEvents\\Amazon.Lambda.LexEvents.csproj", + "src\\Amazon.Lambda.LexV2Events\\Amazon.Lambda.LexV2Events.csproj", + "src\\Amazon.Lambda.Logging.AspNetCore\\Amazon.Lambda.Logging.AspNetCore.csproj", + "src\\Amazon.Lambda.MQEvents\\Amazon.Lambda.MQEvents.csproj", + "src\\Amazon.Lambda.PowerShellHost\\Amazon.Lambda.PowerShellHost.csproj", + "src\\Amazon.Lambda.RuntimeSupport\\Amazon.Lambda.RuntimeSupport.csproj", + "src\\Amazon.Lambda.S3Events\\Amazon.Lambda.S3Events.csproj", + "src\\Amazon.Lambda.Serialization.Json\\Amazon.Lambda.Serialization.Json.csproj", + "src\\Amazon.Lambda.Serialization.SystemTextJson\\Amazon.Lambda.Serialization.SystemTextJson.csproj", + "src\\Amazon.Lambda.SimpleEmailEvents\\Amazon.Lambda.SimpleEmailEvents.csproj", + "src\\Amazon.Lambda.SNSEvents\\Amazon.Lambda.SNSEvents.csproj", + "src\\Amazon.Lambda.SQSEvents\\Amazon.Lambda.SQSEvents.csproj", + "src\\Amazon.Lambda.TestUtilities\\Amazon.Lambda.TestUtilities.csproj", + "test\\Amazon.Lambda.Annotations.SourceGenerators.Tests\\Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj", + "test\\TestServerlessApp.IntegrationTests\\TestServerlessApp.IntegrationTests.csproj", + "test\\TestServerlessApp\\TestServerlessApp.csproj" + ] + } +} \ No newline at end of file diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs index f7498df62..3dcb234bc 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs @@ -44,6 +44,13 @@ public static class DiagnosticDescriptors category: "AWSLambdaCSharpGenerator", DiagnosticSeverity.Error, isEnabledByDefault: true); + + public static readonly DiagnosticDescriptor ExecutableWithNoFunctions = new DiagnosticDescriptor(id: "AWSLambda0104", + title: "Executable output with no LambdaFunction annotations", + messageFormat: "Your project is configured to output an executable and generate a static Main method, but you have not configured any methods with the 'LambdaFunction' attribute.", + category: "AWSLambdaCSharpGenerator", + DiagnosticSeverity.Error, + isEnabledByDefault: true); public static readonly DiagnosticDescriptor MainMethodExists = new DiagnosticDescriptor(id: "AWSLambda0104", title: "static Main method exists", diff --git a/Libraries/test/TestExecutableServerlessApp/ExecutableNoAttributes.cs b/Libraries/test/TestExecutableServerlessApp/ExecutableNoAttributes.cs new file mode 100644 index 000000000..8f77fb323 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/ExecutableNoAttributes.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.APIGatewayEvents; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class ExecutableNoAttributes + { + public void SayHello([FromQuery(Name = "names")]IEnumerable firstNames, APIGatewayProxyRequest request, ILambdaContext context) + { + context.Logger.LogLine($"Request {JsonSerializer.Serialize(request)}"); + + if (firstNames == null) + { + return; + } + + foreach (var firstName in firstNames) + { + Console.WriteLine($"Hello {firstName}"); + } + } + } +} \ No newline at end of file From ae09362a86cf6820d9d8b188808aa7a777b1825d Mon Sep 17 00:00:00 2001 From: jamesuk Date: Sun, 29 Oct 2023 12:19:13 +0000 Subject: [PATCH 16/27] Fix issue with parameterless response --- .../Generator.cs | 11 +++ .../Templates/ExecutableAssembly.cs | 70 +++++++------- .../Templates/ExecutableAssembly.tt | 3 +- .../Templates/LambdaFunctionTemplate.cs | 2 +- .../Templates/LambdaFunctionTemplate.tt | 2 +- ....Annotations.SourceGenerators.Tests.csproj | 12 +++ ...arameterlessMethods_ToUpper_Generated.g.cs | 45 +++++++++ .../Snapshots/Program.g.cs | 1 + .../Snapshots/ProgramMultiHandler.g.cs | 1 + .../Snapshots/ProgramParameterless.g.cs | 25 +++++ .../Snapshots/ProgramZipOutput.g.cs | 1 + .../parameterless.template | 29 ++++++ .../SimpleCalculator_Pi_Generated.g.cs | 2 +- .../SourceGeneratorTests.cs | 93 ++++++++++++++++++- .../ParameterlessMethods.cs | 20 ++++ 15 files changed, 275 insertions(+), 42 deletions(-) create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethods_ToUpper_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterless.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterless.template create mode 100644 Libraries/test/TestExecutableServerlessApp/ParameterlessMethods.cs diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs index d3b11b0be..b63d18cd4 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs @@ -312,6 +312,17 @@ private static ExecutableAssembly GenerateExecutableAssemblySource( return null; } + if (lambdaModels.Count == 0) + { + diagnosticReporter.Report( + Diagnostic.Create( + DiagnosticDescriptors.ExecutableWithNoFunctions, + Location.None, + "Amazon.Lambda.Annotations")); + + return null; + } + return new ExecutableAssembly( lambdaModels, lambdaModels[0].LambdaMethod.ContainingNamespace); diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs index e11a1c91c..7bb55a915 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs @@ -23,7 +23,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates /// Class to produce the template output /// - #line 1 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public partial class ExecutableAssembly : ExecutableAssemblyBase { @@ -33,16 +33,16 @@ public partial class ExecutableAssembly : ExecutableAssemblyBase /// public virtual string TransformText() { - this.Write("using System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Amazon.Lambda.Core;\n\nnamespace "); + this.Write("using System;\r\nusing System.Linq;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\nusing System.IO;\r\nusing Amazon.Lambda.Core;\r\n\r\nnamespace "); - #line 18 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 19 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._containingNamespace)); #line default #line hidden - this.Write(";\n\npublic class GeneratedProgram\n{\n private static async Task Main(string[] args)\n {\n\n switch (Environment.GetEnvironmentVariable(\"ANNOTATIONS_HANDLER\"))\n {\n"); + this.Write(";\r\n\r\npublic class GeneratedProgram\r\n{\r\n private static async Task Main(string[] args)\r\n {\r\n\r\n switch (Environment.GetEnvironmentVariable(\"ANNOTATIONS_HANDLER\"))\r\n {\r\n"); - #line 27 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" foreach (var model in this._lambdaFunctions) { @@ -52,14 +52,14 @@ public virtual string TransformText() #line hidden this.Write(" case \""); - #line 31 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 32 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write("\":\n"); + this.Write("\":\r\n"); - #line 32 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 33 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" if (model.GeneratedMethod.ReturnType.FullName == "void") { @@ -69,63 +69,63 @@ public virtual string TransformText() #line hidden this.Write(" Action<"); - #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); + #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.Parameters.Any() ? string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) : "Stream")); #line default #line hidden this.Write("> "); - #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(" = new "); - #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingNamespace)); #line default #line hidden this.Write("."); - #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated()."); - #line 36 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 38 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(", new "); - #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 38 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].Serializer)); #line default #line hidden - this.Write("()).Build().RunAsync();\n break;\n"); + this.Write("()).Build().RunAsync();\r\n break;\r\n"); - #line 39 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 40 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" } else @@ -136,70 +136,70 @@ public virtual string TransformText() #line hidden this.Write(" Func<"); - #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); #line default #line hidden this.Write(", "); - #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.ReturnType.FullName)); #line default #line hidden this.Write("> "); - #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(" = new "); - #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingNamespace)); #line default #line hidden this.Write("."); - #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated()."); - #line 44 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 46 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(", new "); - #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 46 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.Serializer)); #line default #line hidden - this.Write("()).Build().RunAsync();\n break;\n"); + this.Write("()).Build().RunAsync();\r\n break;\r\n"); - #line 47 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 48 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" } } @@ -207,15 +207,15 @@ public virtual string TransformText() #line default #line hidden - this.Write("\n }\n"); + this.Write("\r\n }\r\n"); - #line 53 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" + #line 54 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" #line default #line hidden - this.Write(" }\n}"); + this.Write(" }\r\n}"); return this.GenerationEnvironment.ToString(); } } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt index 29e88d2d2..964dd2b43 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt @@ -13,6 +13,7 @@ using System.Linq; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace <#= this._containingNamespace #>; @@ -33,7 +34,7 @@ public class GeneratedProgram if (model.GeneratedMethod.ReturnType.FullName == "void") { #> - Action<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>> <#= model.LambdaMethod.ExecutableAssemblyHandlerName #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; + Action<<#= model.GeneratedMethod.Parameters.Any() ? string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) : "Stream" #>> <#= model.LambdaMethod.ExecutableAssemblyHandlerName #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.ExecutableAssemblyHandlerName #>, new <#= this._lambdaFunctions[0].Serializer #>()).Build().RunAsync(); break; <# diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs index e8d3d56ba..54c369bb3 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -105,7 +105,7 @@ public virtual string TransformText() this.Write("("); #line 30 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", _model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName} {p.Name}")))); + this.Write(this.ToStringHelper.ToStringWithCulture(_model.GeneratedMethod.Parameters.Any() ? string.Join(", ", _model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName} {p.Name}")) : "Stream stream")); #line default #line hidden diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt index ac8ac1682..050364e79 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt @@ -27,7 +27,7 @@ this.Write(new FieldsAndConstructor(_model).TransformText()); #> - public <#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? "async " : "" #><#= _model.GeneratedMethod.ReturnType.FullName #> <#= _model.LambdaMethod.Name #>(<#= string.Join(", ", _model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName} {p.Name}")) #>) + public <#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? "async " : "" #><#= _model.GeneratedMethod.ReturnType.FullName #> <#= _model.LambdaMethod.Name #>(<#= _model.GeneratedMethod.Parameters.Any() ? string.Join(", ", _model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName} {p.Name}")) : "Stream stream" #>) { <# if (_model.LambdaMethod.UsingDependencyInjection) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj index e2ad84dc2..22982ddd1 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj @@ -81,6 +81,18 @@ PreserveNewest + + + PreserveNewest + + + + PreserveNewest + + + + PreserveNewest + diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethods_ToUpper_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethods_ToUpper_Generated.g.cs new file mode 100644 index 000000000..80590454c --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethods_ToUpper_Generated.g.cs @@ -0,0 +1,45 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class ParameterlessMethods_NoParameter_Generated + { + private readonly ParameterlessMethods parameterlessMethods; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; + + public ParameterlessMethods_NoParameter_Generated() + { + SetExecutionEnvironment(); + parameterlessMethods = new ParameterlessMethods(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); + } + + public void NoParameter(Stream stream) + { + parameterlessMethods.NoParameter(); + } + + private static void SetExecutionEnvironment() + { + const string envName = "AWS_EXECUTION_ENV"; + + var envValue = new StringBuilder(); + + // If there is an existing execution environment variable add the annotations package as a suffix. + if(!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName))) + { + envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); + } + + envValue.Append("amazon-lambda-annotations_1.0.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs index 1c5734cee..c2faa209f 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp.Sub1; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs index 1923b42d3..de74c4b69 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterless.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterless.g.cs new file mode 100644 index 000000000..fce003bae --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterless.g.cs @@ -0,0 +1,25 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Amazon.Lambda.Core; + +namespace TestServerlessApp; + +public class GeneratedProgram +{ + private static async Task Main(string[] args) + { + + switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) + { + case "NoParameter": + Action noparameter_handler = new TestServerlessApp.ParameterlessMethods_NoParameter_Generated().NoParameter; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(noparameter_handler, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + break; + + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs index 66a02964e..9db1ccbca 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; +using System.IO; using Amazon.Lambda.Core; namespace TestServerlessApp.Sub1; diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterless.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterless.template new file mode 100644 index 000000000..c7c158e28 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterless.template @@ -0,0 +1,29 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).", + "Resources": { + "TestServerlessAppParameterlessMethodsNoParameterGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "Runtime": "provided.al2", + "CodeUri": ".", + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Zip", + "Handler": "TestProject", + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "NoParameter" + } + } + } + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Pi_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Pi_Generated.g.cs index 5797fa689..1aa4604e9 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Pi_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/SimpleCalculator_Pi_Generated.g.cs @@ -28,7 +28,7 @@ public SimpleCalculator_Pi_Generated() serviceProvider = services.BuildServiceProvider(); } - public double Pi() + public double Pi(Stream stream) { // Create a scope for every request, // this allows creating scoped dependencies without creating a scope manually. diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index c202e2e4a..cb33bf13f 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -57,6 +57,34 @@ public async Task Greeter() var actualTemplateContent = await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } + + [Fact] + public async Task TestExecutableOutputWithNoAnnotations() + { + + await new VerifyCS.Test + { + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + Sources = + { + (Path.Combine("TestExecutableServerlessApp", "ExecutableNoAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "ExecutableNoAttributes.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributesWithRouting.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), + }, + ExpectedDiagnostics = + { + DiagnosticResult.CompilerError("AWSLambda0104") + .WithMessage("Your project is configured to output an executable and generate a static Main method, but you have not configured any methods with the 'LambdaFunction' attribute."), + DiagnosticResult.CompilerError("CS5001") + .WithMessage("Program does not contain a static 'Main' method suitable for an entry point"), + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }.RunAsync(); + } [Fact] public async Task GeneratorDoesNotRunDueToCompileError() @@ -262,6 +290,7 @@ public async Task VerifyFunctionInSubNamespace() { var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace.template"))).ToEnvironmentLineEndings(); var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Functions_ToUpper_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedProgramGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Program.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { @@ -300,8 +329,8 @@ public async Task VerifyExecutableAssemblyWithZipAndHandler() { var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace_executable.template"))).ToEnvironmentLineEndings(); var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Functions_AsyncStartupToLower_Generated.g.cs"))).ToEnvironmentLineEndings(); - var expectedProgramGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ProgramZipOutput.g.cs"))).ToEnvironmentLineEndings(); - + var expectedProgram = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ProgramZipOutput.g.cs"))).ToEnvironmentLineEndings(); + var test = new VerifyCS.Test { TestState = @@ -327,7 +356,7 @@ public async Task VerifyExecutableAssemblyWithZipAndHandler() ( typeof(SourceGenerator.Generator), "Program.g.cs", - SourceText.From(expectedProgramGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + SourceText.From(expectedProgram, Encoding.UTF8, SourceHashAlgorithm.Sha256) ) }, ExpectedDiagnostics = @@ -415,11 +444,69 @@ public async Task VerifyExecutableAssembly() await test.RunAsync(); } + [Fact] + public async Task VerifyExecutableAssemblyWithParameterlessConstructor() + { + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "parameterless.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ParameterlessMethods_ToUpper_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedProgramGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ProgramParameterless.g.cs"))).ToEnvironmentLineEndings(); + + var test = new VerifyCS.Test + { + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + Sources = + { + (Path.Combine("TestExecutableServerlessApp", "ParameterlessMethods.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "ParameterlessMethods.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "ParameterlessMethods_NoParameter_Generated.g.cs", + SourceText.From(expectedSubNamespaceGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ), + ( + typeof(SourceGenerator.Generator), + "Program.g.cs", + SourceText.From(expectedProgramGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("ParameterlessMethods_NoParameter_Generated.g.cs", expectedSubNamespaceGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestExecutableServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent), + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }; + + foreach (var file in Directory.GetFiles( + Path.Combine("Amazon.Lambda.RuntimeSupport"), + "*.cs", SearchOption.AllDirectories)) + { + var content = await File.ReadAllTextAsync(file); + + // Don't include RuntimeSupport's entry point. + if (file.EndsWith("Program.cs") && content.Contains("Task Main(string[] args)")) + continue; + + test.TestState.Sources.Add((file, await File.ReadAllTextAsync(file))); + } + + await test.RunAsync(); + } + [Fact] public async Task VerifyExecutableAssembly_WithNullAttributeValues_ShouldComplete() { var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "subnamespace.template"))).ToEnvironmentLineEndings(); var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Functions_ToUpper_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedProgramGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "Program.g.cs"))).ToEnvironmentLineEndings(); await new VerifyCS.Test { diff --git a/Libraries/test/TestExecutableServerlessApp/ParameterlessMethods.cs b/Libraries/test/TestExecutableServerlessApp/ParameterlessMethods.cs new file mode 100644 index 000000000..184711f91 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/ParameterlessMethods.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.APIGatewayEvents; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class ParameterlessMethods + { + [LambdaFunction] + public void NoParameter() + { + return; + } + } +} \ No newline at end of file From 5034c3088c01d264f7fa1d3dbebf2fd1defeff88 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Sun, 29 Oct 2023 12:31:28 +0000 Subject: [PATCH 17/27] Updates to handle responses with no parameters --- .../Templates/ExecutableAssembly.cs | 2 +- .../Templates/ExecutableAssembly.tt | 2 +- ....Annotations.SourceGenerators.Tests.csproj | 12 ++++ ...sMethodWithResponse_ToUpper_Generated.g.cs | 45 +++++++++++++++ .../ProgramParameterlessWithResponse.g.cs | 25 ++++++++ .../parameterlesswithresponse.template | 29 ++++++++++ .../SourceGeneratorTests.cs | 57 +++++++++++++++++++ .../ParameterlessMethodWithResponse.cs | 20 +++++++ 8 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethodWithResponse_ToUpper_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterlessWithResponse.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterlesswithresponse.template create mode 100644 Libraries/test/TestExecutableServerlessApp/ParameterlessMethodWithResponse.cs diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs index 7bb55a915..01586ca66 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs @@ -137,7 +137,7 @@ public virtual string TransformText() this.Write(" Func<"); #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")))); + this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.Parameters.Any() ? string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) : "Stream")); #line default #line hidden diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt index 964dd2b43..e7ef5e082 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt @@ -42,7 +42,7 @@ public class GeneratedProgram else { #> - Func<<#= string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) #>, <#= model.GeneratedMethod.ReturnType.FullName #>> <#= model.LambdaMethod.ExecutableAssemblyHandlerName #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; + Func<<#= model.GeneratedMethod.Parameters.Any() ? string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) : "Stream" #>, <#= model.GeneratedMethod.ReturnType.FullName #>> <#= model.LambdaMethod.ExecutableAssemblyHandlerName #> = new <#= model.LambdaMethod.ContainingNamespace #>.<#= model.LambdaMethod.ContainingType.Name #>_<#= model.LambdaMethod.Name #>_Generated().<#= model.LambdaMethod.Name #>; await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(<#= model.LambdaMethod.ExecutableAssemblyHandlerName #>, new <#= model.Serializer #>()).Build().RunAsync(); break; <# diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj index 22982ddd1..884b6c857 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj @@ -93,6 +93,18 @@ PreserveNewest + + + PreserveNewest + + + + PreserveNewest + + + + PreserveNewest + diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethodWithResponse_ToUpper_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethodWithResponse_ToUpper_Generated.g.cs new file mode 100644 index 000000000..ba97679db --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethodWithResponse_ToUpper_Generated.g.cs @@ -0,0 +1,45 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class ParameterlessMethodWithResponse_NoParameter_Generated + { + private readonly ParameterlessMethodWithResponse parameterlessMethodWithResponse; + private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; + + public ParameterlessMethodWithResponse_NoParameter_Generated() + { + SetExecutionEnvironment(); + parameterlessMethodWithResponse = new ParameterlessMethodWithResponse(); + serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); + } + + public string NoParameter(Stream stream) + { + return parameterlessMethodWithResponse.NoParameter(); + } + + private static void SetExecutionEnvironment() + { + const string envName = "AWS_EXECUTION_ENV"; + + var envValue = new StringBuilder(); + + // If there is an existing execution environment variable add the annotations package as a suffix. + if(!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(envName))) + { + envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); + } + + envValue.Append("amazon-lambda-annotations_1.0.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterlessWithResponse.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterlessWithResponse.g.cs new file mode 100644 index 000000000..5623e704f --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterlessWithResponse.g.cs @@ -0,0 +1,25 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Amazon.Lambda.Core; + +namespace TestServerlessApp; + +public class GeneratedProgram +{ + private static async Task Main(string[] args) + { + + switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) + { + case "NoParameter": + Func noparameter_handler = new TestServerlessApp.ParameterlessMethodWithResponse_NoParameter_Generated().NoParameter; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(noparameter_handler, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + break; + + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterlesswithresponse.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterlesswithresponse.template new file mode 100644 index 000000000..992104395 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterlesswithresponse.template @@ -0,0 +1,29 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).", + "Resources": { + "TestServerlessAppParameterlessMethodWithResponseNoParameterGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "Runtime": "provided.al2", + "CodeUri": ".", + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Zip", + "Handler": "TestProject", + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "NoParameter" + } + } + } + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index cb33bf13f..5b16aa1bd 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -501,6 +501,63 @@ public async Task VerifyExecutableAssemblyWithParameterlessConstructor() await test.RunAsync(); } + [Fact] + public async Task VerifyExecutableAssemblyWithParameterlessConstructorAndResponse() + { + var expectedTemplateContent = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ServerlessTemplates", "parameterlesswithresponse.template"))).ToEnvironmentLineEndings(); + var expectedSubNamespaceGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ParameterlessMethodWithResponse_ToUpper_Generated.g.cs"))).ToEnvironmentLineEndings(); + var expectedProgramGenerated = (await File.ReadAllTextAsync(Path.Combine("Snapshots", "ProgramParameterlessWithResponse.g.cs"))).ToEnvironmentLineEndings(); + + var test = new VerifyCS.Test + { + TestState = + { + OutputKind = OutputKind.ConsoleApplication, + Sources = + { + (Path.Combine("TestExecutableServerlessApp", "ParameterlessMethodWithResponse.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "ParameterlessMethodWithResponse.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), + (Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"))), + (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributes.cs"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "ParameterlessMethodWithResponse_NoParameter_Generated.g.cs", + SourceText.From(expectedSubNamespaceGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ), + ( + typeof(SourceGenerator.Generator), + "Program.g.cs", + SourceText.From(expectedProgramGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("ParameterlessMethodWithResponse_NoParameter_Generated.g.cs", expectedSubNamespaceGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestExecutableServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent), + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }; + + foreach (var file in Directory.GetFiles( + Path.Combine("Amazon.Lambda.RuntimeSupport"), + "*.cs", SearchOption.AllDirectories)) + { + var content = await File.ReadAllTextAsync(file); + + // Don't include RuntimeSupport's entry point. + if (file.EndsWith("Program.cs") && content.Contains("Task Main(string[] args)")) + continue; + + test.TestState.Sources.Add((file, await File.ReadAllTextAsync(file))); + } + + await test.RunAsync(); + } + [Fact] public async Task VerifyExecutableAssembly_WithNullAttributeValues_ShouldComplete() { diff --git a/Libraries/test/TestExecutableServerlessApp/ParameterlessMethodWithResponse.cs b/Libraries/test/TestExecutableServerlessApp/ParameterlessMethodWithResponse.cs new file mode 100644 index 000000000..6294fbe25 --- /dev/null +++ b/Libraries/test/TestExecutableServerlessApp/ParameterlessMethodWithResponse.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.APIGatewayEvents; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class ParameterlessMethodWithResponse + { + [LambdaFunction] + public string NoParameter() + { + return "OK"; + } + } +} \ No newline at end of file From 974753618b05e88e14761f8602ee503e54f9a3f7 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Thu, 2 Nov 2023 09:32:26 +0000 Subject: [PATCH 18/27] Remove BAK file and update referenced libraries --- Libraries/Amazon.Lambda.Annotations.slnf | 26 +------------ Libraries/Amazon.Lambda.Annotations.slnf.bak | 40 -------------------- 2 files changed, 1 insertion(+), 65 deletions(-) delete mode 100644 Libraries/Amazon.Lambda.Annotations.slnf.bak diff --git a/Libraries/Amazon.Lambda.Annotations.slnf b/Libraries/Amazon.Lambda.Annotations.slnf index bb87c663c..94441257b 100644 --- a/Libraries/Amazon.Lambda.Annotations.slnf +++ b/Libraries/Amazon.Lambda.Annotations.slnf @@ -5,35 +5,11 @@ "src\\Amazon.Lambda.Annotations.SourceGenerator\\Amazon.Lambda.Annotations.SourceGenerator.csproj", "src\\Amazon.Lambda.Annotations\\Amazon.Lambda.Annotations.csproj", "src\\Amazon.Lambda.APIGatewayEvents\\Amazon.Lambda.APIGatewayEvents.csproj", - "src\\Amazon.Lambda.ApplicationLoadBalancerEvents\\Amazon.Lambda.ApplicationLoadBalancerEvents.csproj", - "src\\Amazon.Lambda.AspNetCoreServer.Hosting\\Amazon.Lambda.AspNetCoreServer.Hosting.csproj", - "src\\Amazon.Lambda.AspNetCoreServer\\Amazon.Lambda.AspNetCoreServer.csproj", - "src\\Amazon.Lambda.CloudWatchEvents\\Amazon.Lambda.CloudWatchEvents.csproj", - "src\\Amazon.Lambda.CloudWatchLogsEvents\\Amazon.Lambda.CloudWatchLogsEvents.csproj", - "src\\Amazon.Lambda.CognitoEvents\\Amazon.Lambda.CognitoEvents.csproj", - "src\\Amazon.Lambda.ConfigEvents\\Amazon.Lambda.ConfigEvents.csproj", - "src\\Amazon.Lambda.ConnectEvents\\Amazon.Lambda.ConnectEvents.csproj", "src\\Amazon.Lambda.Core\\Amazon.Lambda.Core.csproj", - "src\\Amazon.Lambda.DynamoDBEvents\\Amazon.Lambda.DynamoDBEvents.csproj", - "src\\Amazon.Lambda.KafkaEvents\\Amazon.Lambda.KafkaEvents.csproj", - "src\\Amazon.Lambda.KinesisAnalyticsEvents\\Amazon.Lambda.KinesisAnalyticsEvents.csproj", - "src\\Amazon.Lambda.KinesisEvents\\Amazon.Lambda.KinesisEvents.csproj", - "src\\Amazon.Lambda.KinesisFirehoseEvents\\Amazon.Lambda.KinesisFirehoseEvents.csproj", - "src\\Amazon.Lambda.LexEvents\\Amazon.Lambda.LexEvents.csproj", - "src\\Amazon.Lambda.LexV2Events\\Amazon.Lambda.LexV2Events.csproj", - "src\\Amazon.Lambda.Logging.AspNetCore\\Amazon.Lambda.Logging.AspNetCore.csproj", - "src\\Amazon.Lambda.MQEvents\\Amazon.Lambda.MQEvents.csproj", - "src\\Amazon.Lambda.PowerShellHost\\Amazon.Lambda.PowerShellHost.csproj", - "src\\Amazon.Lambda.RuntimeSupport\\Amazon.Lambda.RuntimeSupport.csproj", - "src\\Amazon.Lambda.S3Events\\Amazon.Lambda.S3Events.csproj", - "src\\Amazon.Lambda.Serialization.Json\\Amazon.Lambda.Serialization.Json.csproj", "src\\Amazon.Lambda.Serialization.SystemTextJson\\Amazon.Lambda.Serialization.SystemTextJson.csproj", - "src\\Amazon.Lambda.SimpleEmailEvents\\Amazon.Lambda.SimpleEmailEvents.csproj", - "src\\Amazon.Lambda.SNSEvents\\Amazon.Lambda.SNSEvents.csproj", - "src\\Amazon.Lambda.SQSEvents\\Amazon.Lambda.SQSEvents.csproj", - "src\\Amazon.Lambda.TestUtilities\\Amazon.Lambda.TestUtilities.csproj", "test\\Amazon.Lambda.Annotations.SourceGenerators.Tests\\Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj", "test\\TestServerlessApp.IntegrationTests\\TestServerlessApp.IntegrationTests.csproj", + "test\\TestExecutableServerlessApp\\TestExecutableServerlessApp.csproj", "test\\TestServerlessApp\\TestServerlessApp.csproj" ] } diff --git a/Libraries/Amazon.Lambda.Annotations.slnf.bak b/Libraries/Amazon.Lambda.Annotations.slnf.bak deleted file mode 100644 index bb87c663c..000000000 --- a/Libraries/Amazon.Lambda.Annotations.slnf.bak +++ /dev/null @@ -1,40 +0,0 @@ -{ - "solution": { - "path": "Libraries.sln", - "projects": [ - "src\\Amazon.Lambda.Annotations.SourceGenerator\\Amazon.Lambda.Annotations.SourceGenerator.csproj", - "src\\Amazon.Lambda.Annotations\\Amazon.Lambda.Annotations.csproj", - "src\\Amazon.Lambda.APIGatewayEvents\\Amazon.Lambda.APIGatewayEvents.csproj", - "src\\Amazon.Lambda.ApplicationLoadBalancerEvents\\Amazon.Lambda.ApplicationLoadBalancerEvents.csproj", - "src\\Amazon.Lambda.AspNetCoreServer.Hosting\\Amazon.Lambda.AspNetCoreServer.Hosting.csproj", - "src\\Amazon.Lambda.AspNetCoreServer\\Amazon.Lambda.AspNetCoreServer.csproj", - "src\\Amazon.Lambda.CloudWatchEvents\\Amazon.Lambda.CloudWatchEvents.csproj", - "src\\Amazon.Lambda.CloudWatchLogsEvents\\Amazon.Lambda.CloudWatchLogsEvents.csproj", - "src\\Amazon.Lambda.CognitoEvents\\Amazon.Lambda.CognitoEvents.csproj", - "src\\Amazon.Lambda.ConfigEvents\\Amazon.Lambda.ConfigEvents.csproj", - "src\\Amazon.Lambda.ConnectEvents\\Amazon.Lambda.ConnectEvents.csproj", - "src\\Amazon.Lambda.Core\\Amazon.Lambda.Core.csproj", - "src\\Amazon.Lambda.DynamoDBEvents\\Amazon.Lambda.DynamoDBEvents.csproj", - "src\\Amazon.Lambda.KafkaEvents\\Amazon.Lambda.KafkaEvents.csproj", - "src\\Amazon.Lambda.KinesisAnalyticsEvents\\Amazon.Lambda.KinesisAnalyticsEvents.csproj", - "src\\Amazon.Lambda.KinesisEvents\\Amazon.Lambda.KinesisEvents.csproj", - "src\\Amazon.Lambda.KinesisFirehoseEvents\\Amazon.Lambda.KinesisFirehoseEvents.csproj", - "src\\Amazon.Lambda.LexEvents\\Amazon.Lambda.LexEvents.csproj", - "src\\Amazon.Lambda.LexV2Events\\Amazon.Lambda.LexV2Events.csproj", - "src\\Amazon.Lambda.Logging.AspNetCore\\Amazon.Lambda.Logging.AspNetCore.csproj", - "src\\Amazon.Lambda.MQEvents\\Amazon.Lambda.MQEvents.csproj", - "src\\Amazon.Lambda.PowerShellHost\\Amazon.Lambda.PowerShellHost.csproj", - "src\\Amazon.Lambda.RuntimeSupport\\Amazon.Lambda.RuntimeSupport.csproj", - "src\\Amazon.Lambda.S3Events\\Amazon.Lambda.S3Events.csproj", - "src\\Amazon.Lambda.Serialization.Json\\Amazon.Lambda.Serialization.Json.csproj", - "src\\Amazon.Lambda.Serialization.SystemTextJson\\Amazon.Lambda.Serialization.SystemTextJson.csproj", - "src\\Amazon.Lambda.SimpleEmailEvents\\Amazon.Lambda.SimpleEmailEvents.csproj", - "src\\Amazon.Lambda.SNSEvents\\Amazon.Lambda.SNSEvents.csproj", - "src\\Amazon.Lambda.SQSEvents\\Amazon.Lambda.SQSEvents.csproj", - "src\\Amazon.Lambda.TestUtilities\\Amazon.Lambda.TestUtilities.csproj", - "test\\Amazon.Lambda.Annotations.SourceGenerators.Tests\\Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj", - "test\\TestServerlessApp.IntegrationTests\\TestServerlessApp.IntegrationTests.csproj", - "test\\TestServerlessApp\\TestServerlessApp.csproj" - ] - } -} \ No newline at end of file From 2c710993bef4eff3e3cc3aac90b64e4526ebfadd Mon Sep 17 00:00:00 2001 From: jamesuk Date: Thu, 2 Nov 2023 17:04:42 +0000 Subject: [PATCH 19/27] Add RuntimeSupport to solution filter --- Libraries/Amazon.Lambda.Annotations.slnf | 1 + 1 file changed, 1 insertion(+) diff --git a/Libraries/Amazon.Lambda.Annotations.slnf b/Libraries/Amazon.Lambda.Annotations.slnf index 94441257b..48c0cd6e0 100644 --- a/Libraries/Amazon.Lambda.Annotations.slnf +++ b/Libraries/Amazon.Lambda.Annotations.slnf @@ -5,6 +5,7 @@ "src\\Amazon.Lambda.Annotations.SourceGenerator\\Amazon.Lambda.Annotations.SourceGenerator.csproj", "src\\Amazon.Lambda.Annotations\\Amazon.Lambda.Annotations.csproj", "src\\Amazon.Lambda.APIGatewayEvents\\Amazon.Lambda.APIGatewayEvents.csproj", + "src\\Amazon.Lambda.RuntimeSupport\\Amazon.Lambda.RuntimeSupport.csproj", "src\\Amazon.Lambda.Core\\Amazon.Lambda.Core.csproj", "src\\Amazon.Lambda.Serialization.SystemTextJson\\Amazon.Lambda.Serialization.SystemTextJson.csproj", "test\\Amazon.Lambda.Annotations.SourceGenerators.Tests\\Amazon.Lambda.Annotations.SourceGenerators.Tests.csproj", From 5692d985eeb7e8e3636f9d02e992ab142c78ee3c Mon Sep 17 00:00:00 2001 From: Thomas Carlier Date: Tue, 7 Nov 2023 10:17:12 +1000 Subject: [PATCH 20/27] Update HttpResults.cs (#1602) Fix typo 'consided' --> 'considered'. --- .../src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs b/Libraries/src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs index 54ff1e7ea..66a7be116 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs +++ b/Libraries/src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs @@ -112,7 +112,7 @@ public interface IHttpResult /// For string then returned as is. /// /// - /// For Stream, byte[] or IList<byte> the data is consided binary and base 64 encoded. + /// For Stream, byte[] or IList<byte> the data is considered binary and base 64 encoded. /// /// /// Anything other type is serialized to JSON. @@ -504,4 +504,4 @@ private class APIGatewayV2Response #endif #endregion } -} \ No newline at end of file +} From c4a08bac9747857b62a9f10827bd1ef58af4bf73 Mon Sep 17 00:00:00 2001 From: Thomas Carlier Date: Tue, 7 Nov 2023 10:21:44 +1000 Subject: [PATCH 21/27] Update HttpResults.cs (#1603) Fix typo 'inteface' --> 'interface' --- .../src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs b/Libraries/src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs index 66a7be116..9662da61d 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs +++ b/Libraries/src/Amazon.Lambda.Annotations/APIGateway/HttpResults.cs @@ -68,7 +68,7 @@ public enum ProtocolVersion { } /// - /// If this inteface is returned for an API Gateway Lambda function it will serialize itself to the correct JSON format for the + /// If this interface is returned for an API Gateway Lambda function it will serialize itself to the correct JSON format for the /// configured event source's protocol format and version. /// /// Users should use the implementation class HttpResults to construct an instance of IHttpResult with the configured, status code, response body and headers. From 4092dbfcacd830bdb0814227dae026c2906fa79e Mon Sep 17 00:00:00 2001 From: jamesuk Date: Wed, 8 Nov 2023 14:42:17 +0000 Subject: [PATCH 22/27] Update README --- Docs/lambda-annotations-design.md | 68 +++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/Docs/lambda-annotations-design.md b/Docs/lambda-annotations-design.md index 6d6a4b6a2..f3a33d724 100644 --- a/Docs/lambda-annotations-design.md +++ b/Docs/lambda-annotations-design.md @@ -330,7 +330,69 @@ public class LambdaFunctions } ``` +## Auto Generate Main +A `LambdaGlobalProperties` attribute is available to set global settings that annotations framework uses when generated code at compile time. This simplifies the programming model when using custom runtimes or native ahead of time (AOT) compilation. It removes the need to manually bootstrap the Lambda runtime. + +To auto-generate the `static Main` method, first ensure the `OutputType` in your `csproj` file is set to `exe`. +```xml + + + exe + +``` + +Once the output type is set to executable, add the `LambdaGlobalProperties` assembly attribute and set the `GenerateMain` property to true. You can also configure the `Runtime` in the generated CloudFormation template. + +```c# +[assembly: LambdaGlobalProperties(GenerateMain = true, Runtime = "provided.al2")] +``` + +### Behind The Scenes + +Assuming the below Lambda function handler: + +```c# +public class Greeter +{ + [LambdaFunction(ResourceName = "GreeterSayHello", MemorySize = 1024, PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/Greeter/SayHello", Version = HttpApiVersion.V1)] + public void SayHello([FromQuery(Name = "names")]IEnumerable firstNames, APIGatewayProxyRequest request, ILambdaContext context) + { + context.Logger.LogLine($"Request {JsonSerializer.Serialize(request)}"); + + if (firstNames == null) + { + return; + } + + foreach (var firstName in firstNames) + { + Console.WriteLine($"Hello {firstName}"); + } + } +} +``` + +The generated `static Main` method would look like the below. To allow for multiple Lambda functions in the same executable an Environment variable is used to determine which handler is executed. When using the `GenerateMain` attribute, ensure you also set the `ANNOTATIONS_HANDLER` environment variable on the deployed resource. + +The auto-generated CloudFormation template will include this as a default. + +```c# +public class GeneratedProgram +{ + private static async Task Main(string[] args) + { + switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) + { + case "ToUpper": + Func toupper_handler = new TestServerlessApp.Sub1.Functions_ToUpper_Generated().ToUpper; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(toupper_handler, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + break; + } + } +} +``` ## Lambda .NET Attributes @@ -368,3 +430,9 @@ Here is a preliminary list of .NET attributes that will tell the source generato * Map method parameter to HTTP request body. If parameter is a complex type then request body will be assumed to be JSON and deserialized into the type. * FromServices * Map method parameter to registered service in IServiceProvider + +### Global Attributes +* GenerateMain + * Generates a `static Program` class and a `static Main` method that bootstraps the Lambda runtime. Simplifies the programming model when building on a custom runtime or using native ahead of time (AOT) compilation. +* Runtime + * Set the runtime in the generated CloudFormation template. Set to either `dotnet6` or `provided.al2` From 62e11c1f48519d236d84b73a1e9bf185a560403e Mon Sep 17 00:00:00 2001 From: jamesuk Date: Thu, 9 Nov 2023 08:55:40 +0000 Subject: [PATCH 23/27] Add new diagnostics --- .../Diagnostics/AnalyzerReleases.Unshipped.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/AnalyzerReleases.Unshipped.md b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/AnalyzerReleases.Unshipped.md index 77c3c454f..8c9d1d493 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/AnalyzerReleases.Unshipped.md +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/AnalyzerReleases.Unshipped.md @@ -5,3 +5,7 @@ Rule ID | Category | Severity | Notes --------|----------|----------|------- +AWSLambda0111|AWSLambdaCSharpGenerator|Error|If the GenerateMain global property is set to true but the project OutputType is not set to 'exe' +AWSLambda0112|AWSLambdaCSharpGenerator|Error|An invalid runtime is selected in the LambdaGlobalProperties attribute +AWSLambda0113|AWSLambdaCSharpGenerator|Error|The GenerateMain global property is set to true and the OutputType is set to 'exe', but no Lambda Function attributes are used +AWSLambda0114|AWSLambdaCSharpGenerator|Error|The GenerateMain global property is set to true, but the project already contains a static Main method \ No newline at end of file From 1132f97a1b22787e0a9aeac48060677c6fb25ce2 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Thu, 9 Nov 2023 08:56:05 +0000 Subject: [PATCH 24/27] Update SourceGen tests to use static strings instead of files --- .../SourceGeneratorTests.cs | 18 ++++++++++++++---- .../AssemblyAttributesInvalidRuntime.cs | 5 ----- 2 files changed, 14 insertions(+), 9 deletions(-) delete mode 100644 Libraries/test/TestExecutableServerlessApp/AssemblyAttributesInvalidRuntime.cs diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index 5b16aa1bd..cc04c9509 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -76,7 +76,7 @@ public async Task TestExecutableOutputWithNoAnnotations() }, ExpectedDiagnostics = { - DiagnosticResult.CompilerError("AWSLambda0104") + DiagnosticResult.CompilerError("AWSLambda0113") .WithMessage("Your project is configured to output an executable and generate a static Main method, but you have not configured any methods with the 'LambdaFunction' attribute."), DiagnosticResult.CompilerError("CS5001") .WithMessage("Program does not contain a static 'Main' method suitable for an entry point"), @@ -265,11 +265,11 @@ public async Task TestInvalidGlobalRuntime_ShouldError() (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaGlobalPropertiesAttribute.cs"))), - (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributesInvalidRuntime.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributesInvalidRuntime.cs"))), + SourceText.From(InvalidAssemblyAttributeString), }, ExpectedDiagnostics = { - new DiagnosticResult("AWSLambda0112", DiagnosticSeverity.Error).WithMessage("The runtime selected in the Amazon.Lambda.Annotations.LambdaGlobalPropertiesAttribute is not a supported value It should be set to either 'dotnet6' or 'provided.al2'."), + new DiagnosticResult("AWSLambda0112", DiagnosticSeverity.Error).WithMessage("The runtime selected in the Amazon.Lambda.Annotations.LambdaGlobalPropertiesAttribute is not a supported value. It should be set to one of dotnet6 or provided.al2."), }, ReferenceAssemblies = ReferenceAssemblies.Net.Net60 } @@ -574,7 +574,7 @@ public async Task VerifyExecutableAssembly_WithNullAttributeValues_ShouldComplet (Path.Combine("TestServerlessApp", "Sub1", "Functions.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "Sub1", "Functions.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))), (Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))), - (Path.Combine("TestExecutableServerlessApp", "AssemblyAttributeNullValues.cs"), await File.ReadAllTextAsync(Path.Combine("TestExecutableServerlessApp", "AssemblyAttributeNullValues.cs"))), + SourceText.From(NullAssemblyAttributeString) }, GeneratedSources = { @@ -1128,5 +1128,15 @@ public void Dispose() { File.Delete(Path.Combine("TestServerlessApp", "serverless.template")); } + + private static string InvalidAssemblyAttributeString = "using Amazon.Lambda.Annotations;" + + "using Amazon.Lambda.Core;" + + "[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]" + + "[assembly: LambdaGlobalProperties(GenerateMain = true, Runtime = \"notavalidruntime\")]"; + + private static string NullAssemblyAttributeString = "using Amazon.Lambda.Annotations;" + + "using Amazon.Lambda.Core;" + + "[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]" + + "[assembly: LambdaGlobalProperties(Runtime = null)]"; } } \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributesInvalidRuntime.cs b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributesInvalidRuntime.cs deleted file mode 100644 index d44771dee..000000000 --- a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributesInvalidRuntime.cs +++ /dev/null @@ -1,5 +0,0 @@ -using Amazon.Lambda.Annotations; -using Amazon.Lambda.Core; - -[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] -[assembly: LambdaGlobalProperties(GenerateMain = true, Runtime = "notavalidruntime")] \ No newline at end of file From d9d5b96bf0c6101cbdf844da99c6ad24afea8879 Mon Sep 17 00:00:00 2001 From: jamesuk Date: Thu, 9 Nov 2023 08:56:19 +0000 Subject: [PATCH 25/27] Update error messages --- .../Diagnostics/DiagnosticDescriptors.cs | 32 ++++----- .../Generator.cs | 2 +- .../src/Amazon.Lambda.Annotations/README.md | 18 +++++ .../serverless.template | 69 ++++++++++++++----- 4 files changed, 87 insertions(+), 34 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs index 3dcb234bc..2cf88f5f5 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs @@ -44,20 +44,6 @@ public static class DiagnosticDescriptors category: "AWSLambdaCSharpGenerator", DiagnosticSeverity.Error, isEnabledByDefault: true); - - public static readonly DiagnosticDescriptor ExecutableWithNoFunctions = new DiagnosticDescriptor(id: "AWSLambda0104", - title: "Executable output with no LambdaFunction annotations", - messageFormat: "Your project is configured to output an executable and generate a static Main method, but you have not configured any methods with the 'LambdaFunction' attribute.", - category: "AWSLambdaCSharpGenerator", - DiagnosticSeverity.Error, - isEnabledByDefault: true); - - public static readonly DiagnosticDescriptor MainMethodExists = new DiagnosticDescriptor(id: "AWSLambda0104", - title: "static Main method exists", - messageFormat: "Failed to generate Main method for LambdaGenerateMainAttribute because project already contains Main method. Existing Main methods must be removed when using LambdaGenerateMainAttribute attribute.", - category: "AWSLambdaCSharpGenerator", - DiagnosticSeverity.Error, - isEnabledByDefault: true); public static readonly DiagnosticDescriptor HttpResultsOnNonApiFunction = new DiagnosticDescriptor(id: "AWSLambda0105", title: $"Invalid return type {nameof(IHttpResult)}", @@ -112,8 +98,22 @@ public static class DiagnosticDescriptors public static readonly DiagnosticDescriptor InvalidRuntimeSelection = new DiagnosticDescriptor(id: "AWSLambda0112", title: "Invalid runtime selection", - messageFormat: "The runtime selected in the Amazon.Lambda.Annotations.LambdaGlobalPropertiesAttribute is not a supported value " + - "It should be set to either 'dotnet6' or 'provided.al2'.", + messageFormat: "The runtime selected in the Amazon.Lambda.Annotations.LambdaGlobalPropertiesAttribute is not a supported value. " + + $"It should be set to one of {string.Join(" or ", Generator._allowdRuntimeValues.ToArray())}.", + category: "AWSLambdaCSharpGenerator", + DiagnosticSeverity.Error, + isEnabledByDefault: true); + + public static readonly DiagnosticDescriptor ExecutableWithNoFunctions = new DiagnosticDescriptor(id: "AWSLambda0113", + title: "Executable output with no LambdaFunction annotations", + messageFormat: "Your project is configured to output an executable and generate a static Main method, but you have not configured any methods with the 'LambdaFunction' attribute.", + category: "AWSLambdaCSharpGenerator", + DiagnosticSeverity.Error, + isEnabledByDefault: true); + + public static readonly DiagnosticDescriptor MainMethodExists = new DiagnosticDescriptor(id: "AWSLambda0114", + title: "static Main method exists", + messageFormat: "Failed to generate Main method for LambdaGenerateMainAttribute because project already contains Main method. Existing Main methods must be removed when using LambdaGenerateMainAttribute attribute.", category: "AWSLambdaCSharpGenerator", DiagnosticSeverity.Error, isEnabledByDefault: true); diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs index b63d18cd4..0436eac8b 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs @@ -25,7 +25,7 @@ public class Generator : ISourceGenerator private readonly IFileManager _fileManager = new FileManager(); private readonly IDirectoryManager _directoryManager = new DirectoryManager(); - private readonly List _allowdRuntimeValues = new List(2) + internal static readonly List _allowdRuntimeValues = new List(2) { "dotnet6", "provided.al2" diff --git a/Libraries/src/Amazon.Lambda.Annotations/README.md b/Libraries/src/Amazon.Lambda.Annotations/README.md index 9d8841d63..290f6fa98 100644 --- a/Libraries/src/Amazon.Lambda.Annotations/README.md +++ b/Libraries/src/Amazon.Lambda.Annotations/README.md @@ -303,6 +303,24 @@ If you do not want AWS to track the usage of the library, please set the followi ``` +## Lambda Global Properties + +A `LambdaGlobalProperties` attribute is available to set global settings that the annotations framework uses when generating code at compile time. This simplifies the programming model when using custom runtimes or native ahead of time (AOT) compilation. It removes the need to manually bootstrap the Lambda runtime. + +To auto-generate the `static Main` method, first ensure the `OutputType` in your `csproj` file is set to `exe`. +```xml + + + exe + +``` + +Once the output type is set to executable, add the `LambdaGlobalProperties` assembly attribute and set the `GenerateMain` property to true. You can also configure the `Runtime` in the generated CloudFormation template. + +To allow for multiple Lambda functions in the same executable an Environment Variable is used to determine which handler is executed. When using the `GenerateMain` attribute, ensure you also set the `ANNOTATIONS_HANDLER` environment variable on the deployed Lambda function. + +The auto-generated CloudFormation template will include this as a default. + ## Amazon API Gateway example This example creates a REST API through Amazon API Gateway that exposes the common arithmetic operations. diff --git a/Libraries/test/TestExecutableServerlessApp/serverless.template b/Libraries/test/TestExecutableServerlessApp/serverless.template index b1d9c89ec..96b50247e 100644 --- a/Libraries/test/TestExecutableServerlessApp/serverless.template +++ b/Libraries/test/TestExecutableServerlessApp/serverless.template @@ -37,7 +37,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicReturn_Generated::DynamicReturn" ] }, "Environment": { @@ -62,7 +62,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicInput_Generated::DynamicInput" ] }, "Environment": { @@ -87,7 +87,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.TaskExample_TaskReturn_Generated::TaskReturn" ] }, "Environment": { @@ -112,7 +112,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.VoidExample_VoidReturn_Generated::VoidReturn" ] }, "Environment": { @@ -140,7 +140,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeader_Generated::OkResponseWithHeader" ] }, "Events": { @@ -177,7 +177,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated::OkResponseWithHeaderAsync" ] }, "Events": { @@ -214,7 +214,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated::NotFoundResponseWithHeaderV2" ] }, "Events": { @@ -251,7 +251,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated::NotFoundResponseWithHeaderV2Async" ] }, "Events": { @@ -288,7 +288,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated::NotFoundResponseWithHeaderV1" ] }, "Events": { @@ -326,7 +326,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated::NotFoundResponseWithHeaderV1Async" ] }, "Events": { @@ -364,7 +364,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHello_Generated::SayHello" ] }, "Events": { @@ -402,7 +402,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" ] }, "Events": { @@ -437,7 +437,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.Sub1.Functions_ToUpper_Generated::ToUpper" ] }, "Environment": { @@ -465,7 +465,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.NullableReferenceTypeExample_NullableHeaderHttpApi_Generated::NullableHeaderHttpApi" ] }, "Events": { @@ -499,7 +499,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp" + "TestExecutableServerlessApp::TestServerlessApp.IntrinsicExample_HasIntrinsic_Generated::HasIntrinsic" ] }, "Environment": { @@ -522,12 +522,47 @@ ], "PackageType": "Zip", "CodeUri": ".", - "Handler": "TestExecutableServerlessApp", + "Handler": "TestExecutableServerlessApp::TestServerlessApp.Sub1.FunctionsZipOutput_ToLower_Generated::ToLower", "Environment": { "Variables": { "ANNOTATIONS_HANDLER": "ToLower" } - } + }, + "Runtime": "dotnet6" + } + }, + "TestServerlessAppParameterlessMethodsNoParameterGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "Runtime": "dotnet6", + "CodeUri": ".", + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Zip", + "Handler": "TestExecutableServerlessApp::TestServerlessApp.ParameterlessMethods_NoParameter_Generated::NoParameter" + } + }, + "TestServerlessAppParameterlessMethodWithResponseNoParameterGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "Runtime": "dotnet6", + "CodeUri": ".", + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Zip", + "Handler": "TestExecutableServerlessApp::TestServerlessApp.ParameterlessMethodWithResponse_NoParameter_Generated::NoParameter" } } }, From aaaa5a8fdeffb69d31417b944105c1536269e44a Mon Sep 17 00:00:00 2001 From: jamesuk Date: Thu, 9 Nov 2023 08:57:46 +0000 Subject: [PATCH 26/27] Update annotations design --- Docs/lambda-annotations-design.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/lambda-annotations-design.md b/Docs/lambda-annotations-design.md index f3a33d724..fdeb2fc6b 100644 --- a/Docs/lambda-annotations-design.md +++ b/Docs/lambda-annotations-design.md @@ -332,7 +332,7 @@ public class LambdaFunctions ## Auto Generate Main -A `LambdaGlobalProperties` attribute is available to set global settings that annotations framework uses when generated code at compile time. This simplifies the programming model when using custom runtimes or native ahead of time (AOT) compilation. It removes the need to manually bootstrap the Lambda runtime. +A `LambdaGlobalProperties` attribute is available to set global settings that the annotations framework uses when generating code at compile time. This simplifies the programming model when using custom runtimes or native ahead of time (AOT) compilation. It removes the need to manually bootstrap the Lambda runtime. To auto-generate the `static Main` method, first ensure the `OutputType` in your `csproj` file is set to `exe`. ```xml From c78c6d28921cc5b85cd8933528b65b17a67c95c9 Mon Sep 17 00:00:00 2001 From: James Eastham Date: Sat, 11 Nov 2023 09:52:19 +0000 Subject: [PATCH 27/27] Resolve build issues --- .../Templates/ExecutableAssembly.cs | 68 +++++++++---------- .../Templates/ExecutableAssembly.tt | 2 +- ...sMethodWithResponse_ToUpper_Generated.g.cs | 8 +-- .../Snapshots/Program.g.cs | 2 +- .../Snapshots/ProgramMultiHandler.g.cs | 2 +- .../Snapshots/ProgramParameterless.g.cs | 2 +- .../ProgramParameterlessWithResponse.g.cs | 8 +-- .../Snapshots/ProgramZipOutput.g.cs | 2 +- .../parameterlesswithresponse.template | 4 +- .../SourceGeneratorTests.cs | 4 +- .../AssemblyAttributeNullValues.cs | 5 -- .../ParameterlessMethodWithResponse.cs | 2 +- .../TestExecutableServerlessApp.csproj | 1 + .../serverless.template | 54 +++++++++------ .../aws-lambda-tools-defaults.json | 8 +-- 15 files changed, 89 insertions(+), 83 deletions(-) delete mode 100644 Libraries/test/TestExecutableServerlessApp/AssemblyAttributeNullValues.cs diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs index 01586ca66..304db3e8b 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.cs @@ -23,7 +23,7 @@ namespace Amazon.Lambda.Annotations.SourceGenerator.Templates /// Class to produce the template output /// - #line 1 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 1 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")] public partial class ExecutableAssembly : ExecutableAssemblyBase { @@ -33,16 +33,16 @@ public partial class ExecutableAssembly : ExecutableAssemblyBase /// public virtual string TransformText() { - this.Write("using System;\r\nusing System.Linq;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\nusing System.IO;\r\nusing Amazon.Lambda.Core;\r\n\r\nnamespace "); + this.Write("using System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.IO;\nusing Amazon.Lambda.Core;\n\nnamespace "); - #line 19 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 19 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._containingNamespace)); #line default #line hidden - this.Write(";\r\n\r\npublic class GeneratedProgram\r\n{\r\n private static async Task Main(string[] args)\r\n {\r\n\r\n switch (Environment.GetEnvironmentVariable(\"ANNOTATIONS_HANDLER\"))\r\n {\r\n"); + this.Write(";\n\npublic class GeneratedProgram\n{\n public static async Task Main(string[] args)\n {\n\n switch (Environment.GetEnvironmentVariable(\"ANNOTATIONS_HANDLER\"))\n {\n"); - #line 28 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 28 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" foreach (var model in this._lambdaFunctions) { @@ -52,14 +52,14 @@ public virtual string TransformText() #line hidden this.Write(" case \""); - #line 32 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 32 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write("\":\r\n"); + this.Write("\":\n"); - #line 33 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 33 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" if (model.GeneratedMethod.ReturnType.FullName == "void") { @@ -69,63 +69,63 @@ public virtual string TransformText() #line hidden this.Write(" Action<"); - #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.Parameters.Any() ? string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) : "Stream")); #line default #line hidden this.Write("> "); - #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(" = new "); - #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingNamespace)); #line default #line hidden this.Write("."); - #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated()."); - #line 37 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 37 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 38 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 38 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(", new "); - #line 38 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 38 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(this._lambdaFunctions[0].Serializer)); #line default #line hidden - this.Write("()).Build().RunAsync();\r\n break;\r\n"); + this.Write("()).Build().RunAsync();\n break;\n"); - #line 40 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 40 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" } else @@ -136,70 +136,70 @@ public virtual string TransformText() #line hidden this.Write(" Func<"); - #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.Parameters.Any() ? string.Join(", ", model.GeneratedMethod.Parameters.Select(p => $"{p.Type.FullName}")) : "Stream")); #line default #line hidden this.Write(", "); - #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.GeneratedMethod.ReturnType.FullName)); #line default #line hidden this.Write("> "); - #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(" = new "); - #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingNamespace)); #line default #line hidden this.Write("."); - #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ContainingType.Name)); #line default #line hidden this.Write("_"); - #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden this.Write("_Generated()."); - #line 45 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 45 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.Name)); #line default #line hidden - this.Write(";\r\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); + this.Write(";\n await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create("); - #line 46 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 46 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.LambdaMethod.ExecutableAssemblyHandlerName)); #line default #line hidden this.Write(", new "); - #line 46 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 46 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" this.Write(this.ToStringHelper.ToStringWithCulture(model.Serializer)); #line default #line hidden - this.Write("()).Build().RunAsync();\r\n break;\r\n"); + this.Write("()).Build().RunAsync();\n break;\n"); - #line 48 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 48 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" } } @@ -207,15 +207,15 @@ public virtual string TransformText() #line default #line hidden - this.Write("\r\n }\r\n"); + this.Write("\n }\n"); - #line 54 "C:\Users\jamesuk\source\github\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\ExecutableAssembly.tt" + #line 54 "/Users/jameseastham/source/github/aws-lambda-dotnet/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt" #line default #line hidden - this.Write(" }\r\n}"); + this.Write(" }\n}"); return this.GenerationEnvironment.ToString(); } } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt index e7ef5e082..179e396e7 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/ExecutableAssembly.tt @@ -20,7 +20,7 @@ namespace <#= this._containingNamespace #>; public class GeneratedProgram { - private static async Task Main(string[] args) + public static async Task Main(string[] args) { switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethodWithResponse_ToUpper_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethodWithResponse_ToUpper_Generated.g.cs index ba97679db..642f5cb07 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethodWithResponse_ToUpper_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ParameterlessMethodWithResponse_ToUpper_Generated.g.cs @@ -8,21 +8,21 @@ namespace TestServerlessApp { - public class ParameterlessMethodWithResponse_NoParameter_Generated + public class ParameterlessMethodWithResponse_NoParameterWithResponse_Generated { private readonly ParameterlessMethodWithResponse parameterlessMethodWithResponse; private readonly Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer serializer; - public ParameterlessMethodWithResponse_NoParameter_Generated() + public ParameterlessMethodWithResponse_NoParameterWithResponse_Generated() { SetExecutionEnvironment(); parameterlessMethodWithResponse = new ParameterlessMethodWithResponse(); serializer = new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer(); } - public string NoParameter(Stream stream) + public string NoParameterWithResponse(Stream stream) { - return parameterlessMethodWithResponse.NoParameter(); + return parameterlessMethodWithResponse.NoParameterWithResponse(); } private static void SetExecutionEnvironment() diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs index c2faa209f..594bd7af9 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/Program.g.cs @@ -10,7 +10,7 @@ namespace TestServerlessApp.Sub1; public class GeneratedProgram { - private static async Task Main(string[] args) + public static async Task Main(string[] args) { switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs index de74c4b69..d3b7728d5 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramMultiHandler.g.cs @@ -10,7 +10,7 @@ namespace TestServerlessApp; public class GeneratedProgram { - private static async Task Main(string[] args) + public static async Task Main(string[] args) { switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterless.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterless.g.cs index fce003bae..dcf6c591a 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterless.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterless.g.cs @@ -10,7 +10,7 @@ namespace TestServerlessApp; public class GeneratedProgram { - private static async Task Main(string[] args) + public static async Task Main(string[] args) { switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterlessWithResponse.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterlessWithResponse.g.cs index 5623e704f..b60ed0e85 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterlessWithResponse.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramParameterlessWithResponse.g.cs @@ -10,14 +10,14 @@ namespace TestServerlessApp; public class GeneratedProgram { - private static async Task Main(string[] args) + public static async Task Main(string[] args) { switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) { - case "NoParameter": - Func noparameter_handler = new TestServerlessApp.ParameterlessMethodWithResponse_NoParameter_Generated().NoParameter; - await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(noparameter_handler, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); + case "NoParameterWithResponse": + Func noparameterwithresponse_handler = new TestServerlessApp.ParameterlessMethodWithResponse_NoParameterWithResponse_Generated().NoParameterWithResponse; + await Amazon.Lambda.RuntimeSupport.LambdaBootstrapBuilder.Create(noparameterwithresponse_handler, new Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer()).Build().RunAsync(); break; } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs index 9db1ccbca..337fc01f7 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ProgramZipOutput.g.cs @@ -10,7 +10,7 @@ namespace TestServerlessApp.Sub1; public class GeneratedProgram { - private static async Task Main(string[] args) + public static async Task Main(string[] args) { switch (Environment.GetEnvironmentVariable("ANNOTATIONS_HANDLER")) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterlesswithresponse.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterlesswithresponse.template index 992104395..c84071255 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterlesswithresponse.template +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/parameterlesswithresponse.template @@ -3,7 +3,7 @@ "Transform": "AWS::Serverless-2016-10-31", "Description": "This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).", "Resources": { - "TestServerlessAppParameterlessMethodWithResponseNoParameterGenerated": { + "TestServerlessAppParameterlessMethodWithResponseNoParameterWithResponseGenerated": { "Type": "AWS::Serverless::Function", "Metadata": { "Tool": "Amazon.Lambda.Annotations" @@ -20,7 +20,7 @@ "Handler": "TestProject", "Environment": { "Variables": { - "ANNOTATIONS_HANDLER": "NoParameter" + "ANNOTATIONS_HANDLER": "NoParameterWithResponse" } } } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index cc04c9509..769cf5990 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -524,7 +524,7 @@ public async Task VerifyExecutableAssemblyWithParameterlessConstructorAndRespons { ( typeof(SourceGenerator.Generator), - "ParameterlessMethodWithResponse_NoParameter_Generated.g.cs", + "ParameterlessMethodWithResponse_NoParameterWithResponse_Generated.g.cs", SourceText.From(expectedSubNamespaceGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) ), ( @@ -535,7 +535,7 @@ public async Task VerifyExecutableAssemblyWithParameterlessConstructorAndRespons }, ExpectedDiagnostics = { - new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("ParameterlessMethodWithResponse_NoParameter_Generated.g.cs", expectedSubNamespaceGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("ParameterlessMethodWithResponse_NoParameterWithResponse_Generated.g.cs", expectedSubNamespaceGenerated), new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestExecutableServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent), }, ReferenceAssemblies = ReferenceAssemblies.Net.Net60 diff --git a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributeNullValues.cs b/Libraries/test/TestExecutableServerlessApp/AssemblyAttributeNullValues.cs deleted file mode 100644 index 35be8676d..000000000 --- a/Libraries/test/TestExecutableServerlessApp/AssemblyAttributeNullValues.cs +++ /dev/null @@ -1,5 +0,0 @@ -using Amazon.Lambda.Annotations; -using Amazon.Lambda.Core; - -[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] -[assembly: LambdaGlobalProperties(Runtime = null)] \ No newline at end of file diff --git a/Libraries/test/TestExecutableServerlessApp/ParameterlessMethodWithResponse.cs b/Libraries/test/TestExecutableServerlessApp/ParameterlessMethodWithResponse.cs index 6294fbe25..1ec83eab6 100644 --- a/Libraries/test/TestExecutableServerlessApp/ParameterlessMethodWithResponse.cs +++ b/Libraries/test/TestExecutableServerlessApp/ParameterlessMethodWithResponse.cs @@ -12,7 +12,7 @@ namespace TestServerlessApp public class ParameterlessMethodWithResponse { [LambdaFunction] - public string NoParameter() + public string NoParameterWithResponse() { return "OK"; } diff --git a/Libraries/test/TestExecutableServerlessApp/TestExecutableServerlessApp.csproj b/Libraries/test/TestExecutableServerlessApp/TestExecutableServerlessApp.csproj index f60c3c362..0fa9708b4 100644 --- a/Libraries/test/TestExecutableServerlessApp/TestExecutableServerlessApp.csproj +++ b/Libraries/test/TestExecutableServerlessApp/TestExecutableServerlessApp.csproj @@ -1,5 +1,6 @@  + exe net6.0 true Lambda diff --git a/Libraries/test/TestExecutableServerlessApp/serverless.template b/Libraries/test/TestExecutableServerlessApp/serverless.template index 96b50247e..9584ef590 100644 --- a/Libraries/test/TestExecutableServerlessApp/serverless.template +++ b/Libraries/test/TestExecutableServerlessApp/serverless.template @@ -37,7 +37,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicReturn_Generated::DynamicReturn" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -62,7 +62,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.DynamicExample_DynamicInput_Generated::DynamicInput" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -87,7 +87,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.TaskExample_TaskReturn_Generated::TaskReturn" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -112,7 +112,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.VoidExample_VoidReturn_Generated::VoidReturn" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -140,7 +140,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeader_Generated::OkResponseWithHeader" + "TestExecutableServerlessApp" ] }, "Events": { @@ -177,7 +177,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_OkResponseWithHeaderAsync_Generated::OkResponseWithHeaderAsync" + "TestExecutableServerlessApp" ] }, "Events": { @@ -214,7 +214,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated::NotFoundResponseWithHeaderV2" + "TestExecutableServerlessApp" ] }, "Events": { @@ -251,7 +251,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated::NotFoundResponseWithHeaderV2Async" + "TestExecutableServerlessApp" ] }, "Events": { @@ -288,7 +288,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated::NotFoundResponseWithHeaderV1" + "TestExecutableServerlessApp" ] }, "Events": { @@ -326,7 +326,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated::NotFoundResponseWithHeaderV1Async" + "TestExecutableServerlessApp" ] }, "Events": { @@ -364,7 +364,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHello_Generated::SayHello" + "TestExecutableServerlessApp" ] }, "Events": { @@ -402,7 +402,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" + "TestExecutableServerlessApp" ] }, "Events": { @@ -437,7 +437,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.Sub1.Functions_ToUpper_Generated::ToUpper" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -465,7 +465,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.NullableReferenceTypeExample_NullableHeaderHttpApi_Generated::NullableHeaderHttpApi" + "TestExecutableServerlessApp" ] }, "Events": { @@ -499,7 +499,7 @@ "ImageUri": ".", "ImageConfig": { "Command": [ - "TestExecutableServerlessApp::TestServerlessApp.IntrinsicExample_HasIntrinsic_Generated::HasIntrinsic" + "TestExecutableServerlessApp" ] }, "Environment": { @@ -522,13 +522,13 @@ ], "PackageType": "Zip", "CodeUri": ".", - "Handler": "TestExecutableServerlessApp::TestServerlessApp.Sub1.FunctionsZipOutput_ToLower_Generated::ToLower", + "Handler": "TestExecutableServerlessApp", "Environment": { "Variables": { "ANNOTATIONS_HANDLER": "ToLower" } }, - "Runtime": "dotnet6" + "Runtime": "provided.al2" } }, "TestServerlessAppParameterlessMethodsNoParameterGenerated": { @@ -537,7 +537,7 @@ "Tool": "Amazon.Lambda.Annotations" }, "Properties": { - "Runtime": "dotnet6", + "Runtime": "provided.al2", "CodeUri": ".", "MemorySize": 256, "Timeout": 30, @@ -545,16 +545,21 @@ "AWSLambdaBasicExecutionRole" ], "PackageType": "Zip", - "Handler": "TestExecutableServerlessApp::TestServerlessApp.ParameterlessMethods_NoParameter_Generated::NoParameter" + "Handler": "TestExecutableServerlessApp", + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "NoParameter" + } + } } }, - "TestServerlessAppParameterlessMethodWithResponseNoParameterGenerated": { + "TestServerlessAppParameterlessMethodWithResponseNoParameterWithResponseGenerated": { "Type": "AWS::Serverless::Function", "Metadata": { "Tool": "Amazon.Lambda.Annotations" }, "Properties": { - "Runtime": "dotnet6", + "Runtime": "provided.al2", "CodeUri": ".", "MemorySize": 256, "Timeout": 30, @@ -562,7 +567,12 @@ "AWSLambdaBasicExecutionRole" ], "PackageType": "Zip", - "Handler": "TestExecutableServerlessApp::TestServerlessApp.ParameterlessMethodWithResponse_NoParameter_Generated::NoParameter" + "Handler": "TestExecutableServerlessApp", + "Environment": { + "Variables": { + "ANNOTATIONS_HANDLER": "NoParameterWithResponse" + } + } } } }, diff --git a/Libraries/test/TestServerlessApp/aws-lambda-tools-defaults.json b/Libraries/test/TestServerlessApp/aws-lambda-tools-defaults.json index a5f516588..0b96350ff 100644 --- a/Libraries/test/TestServerlessApp/aws-lambda-tools-defaults.json +++ b/Libraries/test/TestServerlessApp/aws-lambda-tools-defaults.json @@ -13,7 +13,7 @@ "template": "serverless.template", "template-parameters": "", "docker-host-build-output-dir": "./bin/Release/lambda-publish", -"s3-bucket" : "test-serverless-app-81ae0673", -"stack-name" : "test-serverless-app-81ae0673", -"function-architecture" : "x86_64" -} + "s3-bucket": "test-serverless-app", + "stack-name": "test-serverless-app", + "function-architecture": "x86_64" +} \ No newline at end of file