From 57a23ae11e637ac52e631f717cec448ae3186d10 Mon Sep 17 00:00:00 2001 From: PFSerra Date: Sun, 26 Mar 2023 18:49:42 +0100 Subject: [PATCH 01/10] Added FromCustomAuthorizerAttribute and tests. --- .../Attributes/AttributeModelBuilder.cs | 9 + .../FromCustomAuthorizerAttributeBuilder.cs | 22 + .../Templates/LambdaFunctionTemplate.cs | 3479 +++++++++-------- .../Templates/LambdaFunctionTemplate.tt | 1075 ++--- .../TypeFullNames.cs | 1 + .../FromCustomAuthorizerAttribute.cs | 19 + ....Annotations.SourceGenerators.Tests.csproj | 2 + ...piExample_HttpApiAuthorizer_Generated.g.cs | 65 + ...rRestExample_RestAuthorizer_Generated.g.cs | 65 + .../authorizerHttpApi.template | 39 + .../authorizerRest.template | 39 + .../SourceGeneratorTests.cs | 84 +- .../CustomAuthorizerHttpApiExample.cs | 18 + .../CustomAuthorizerRestExample.cs | 18 + .../TestServerlessApp/serverless.template | 1366 ++++--- 15 files changed, 3407 insertions(+), 2894 deletions(-) create mode 100644 Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FromCustomAuthorizerAttributeBuilder.cs create mode 100644 Libraries/src/Amazon.Lambda.Annotations/APIGateway/FromCustomAuthorizerAttribute.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template create mode 100644 Libraries/test/TestServerlessApp/CustomAuthorizerHttpApiExample.cs create mode 100644 Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/AttributeModelBuilder.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/AttributeModelBuilder.cs index 21419dcb8..859935d71 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/AttributeModelBuilder.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/AttributeModelBuilder.cs @@ -53,6 +53,15 @@ public static AttributeModel Build(AttributeData att, GeneratorExecutionContext Type = TypeModelBuilder.Build(att.AttributeClass, context) }; } + else if(att.AttributeClass.Equals(context.Compilation.GetTypeByMetadataName(TypeFullNames.FromCustomAuthorizerAttribute), SymbolEqualityComparer.Default)) + { + var data = FromCustomAuthorizerAttributeBuilder.Build(att); + model = new AttributeModel + { + Data = data, + Type = TypeModelBuilder.Build(att.AttributeClass, context) + }; + } else if (att.AttributeClass.Equals(context.Compilation.GetTypeByMetadataName(TypeFullNames.HttpApiAttribute), SymbolEqualityComparer.Default)) { var data = HttpApiAttributeBuilder.Build(att); diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FromCustomAuthorizerAttributeBuilder.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FromCustomAuthorizerAttributeBuilder.cs new file mode 100644 index 000000000..687e27446 --- /dev/null +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FromCustomAuthorizerAttributeBuilder.cs @@ -0,0 +1,22 @@ +using Amazon.Lambda.Annotations.APIGateway; +using Microsoft.CodeAnalysis; + +namespace Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes +{ + public class FromCustomAuthorizerAttributeBuilder + { + public static FromCustomAuthorizerAttribute Build(AttributeData att) + { + var data = new FromCustomAuthorizerAttribute(); + foreach (var pair in att.NamedArguments) + { + if (pair.Key == nameof(data.Name) && pair.Value.Value is string value) + { + data.Name = value; + } + } + + return data; + } + } +} \ 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 788385918..17e1a4ac7 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -1,1711 +1,1768 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version: 17.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 Amazon.Lambda.Annotations.SourceGenerator.Models; - using Amazon.Lambda.Annotations.SourceGenerator.Extensions; - using Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes; - using Microsoft.CodeAnalysis; - using Amazon.Lambda.Annotations.SourceGenerator.Validation; - using System; - - /// - /// 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")] - public partial class LambdaFunctionTemplate : LambdaFunctionTemplateBase - { -#line hidden - /// - /// Create the template output - /// - public virtual string TransformText() - { - - #line 11 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - foreach (var ns in _model.GeneratedMethod.Usings) - { - - - #line default - #line hidden - this.Write("using "); - - #line 15 "C:\codebase\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 default - #line hidden - this.Write("\r\nnamespace "); - - #line 20 "C:\codebase\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 "); - - #line 22 "C:\codebase\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" - - if (_model.LambdaMethod.UsingDependencyInjection) - { - - - #line default - #line hidden - this.Write(" private readonly ServiceProvider serviceProvider;\r\n"); - - #line 29 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" private readonly "); - - #line 34 "C:\codebase\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(" "); - - #line 34 "C:\codebase\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(";\r\n"); - - #line 35 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - - #line default - #line hidden - this.Write("\r\n public "); - - #line 39 "C:\codebase\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 SetExecutionEnvironment();\r\n"); - - #line 42 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - if (_model.LambdaMethod.UsingDependencyInjection) - { - - - #line default - #line hidden - this.Write(@" 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<"); - - #line 50 "C:\codebase\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 var startup = new "); - - #line 52 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 55 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" "); - - #line 60 "C:\codebase\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(" = new "); - - #line 60 "C:\codebase\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"); - - #line 61 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - - #line default - #line hidden - this.Write(" }\r\n\r\n public "); - - #line 66 "C:\codebase\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 66 "C:\codebase\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 66 "C:\codebase\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 66 "C:\codebase\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 68 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - if (_model.LambdaMethod.UsingDependencyInjection) - { - - - #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 "); - - #line 75 "C:\codebase\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 76 "C:\codebase\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 78 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - if (_model.LambdaMethod.Events.Contains(EventType.API)) - { - var parameters = string.Join(", ", _model.LambdaMethod.Parameters - .Select(p => - { - // Pass the same context parameter for ILambdaContext that comes from the generated method. - if (p.Type.FullName == TypeFullNames.ILambdaContext) - { - return "__context__"; - } - - // Pass the same request parameter for Request Type that comes from the generated method. - if (TypeFullNames.Requests.Contains(p.Type.FullName)) - { - return "__request__"; - } - - return p.Name; - })); - 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; - - if (restApiAttribute != null && httpApiAttribute != null) - { - throw new NotSupportedException($"A method cannot have both {TypeFullNames.RestApiAttribute} and {TypeFullNames.HttpApiAttribute} attribute at the same time."); - } - - var routeParameters = restApiAttribute?.Data?.GetTemplateParameters() ?? httpApiAttribute?.Data?.GetTemplateParameters() ?? new HashSet(); - - var (routeTemplateValid, missingRouteParams) = RouteParametersValidator.Validate(routeParameters, _model.LambdaMethod.Parameters); - if (!routeTemplateValid) - { - var template = restApiAttribute?.Data?.Template ?? httpApiAttribute?.Data?.Template ?? string.Empty; - throw new InvalidOperationException($"Route template {template} is invalid. Missing {string.Join(",", missingRouteParams)} parameters in method definition."); - } - - if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) - { - - - #line default - #line hidden - this.Write(" var validationErrors = new List();\r\n\r\n"); - - #line 122 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - foreach (var parameter in _model.LambdaMethod.Parameters) - { - if (parameter.Type.FullName == TypeFullNames.ILambdaContext || TypeFullNames.Requests.Contains(parameter.Type.FullName)) - { - // No action required for ILambdaContext and RequestType, they are passed from the generated method parameter directly to the original method. - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) - { - - - #line default - #line hidden - this.Write(" var "); - - #line 134 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = scope.ServiceProvider.GetRequiredService<"); - - #line 134 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(">();\r\n"); - - #line 135 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromQueryAttribute)) - { - var fromQueryAttribute = parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromQueryAttribute) as AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var parameterKey = fromQueryAttribute?.Data?.Name ?? parameter.Name; - - var queryStringParameters = "QueryStringParameters"; - - - - #line default - #line hidden - this.Write(" var "); - - #line 147 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = default("); - - #line 147 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 148 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - - if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) - { - // In HTTP API V2 multiple values for the same parameter are represented via comma separated string - // Therefore, it is required to split the string to convert to an enumerable - // and convert individual item to target data type. - var commaSplit = ""; - if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) - { - commaSplit = @".Split("","")"; - } - - // HTTP API V1 and Rest API, multiple values for the same parameter are provided - // dedicated dictionary of string key and list value. - if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) - { - queryStringParameters = "MultiValueQueryStringParameters"; - } - - if (parameter.Type.TypeArguments.Count != 1) - { - throw new NotSupportedException("Only one type argument is supported for generic types."); - } - - // Generic types are mapped using Select statement to the target parameter type argument. - var typeArgument = parameter.Type.TypeArguments.First(); - - - #line default - #line hidden - this.Write(" if (__request__."); - - #line 176 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("?.ContainsKey(\""); - - #line 176 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n "); - - #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = __request__."); - - #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("[\""); - - #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\"]"); - - #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 ("); - - #line 183 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(q, typeof("); - - #line 183 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); - - #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 '"); - - #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 194 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - // Non-generic types are mapped directly to the target parameter. - - - #line default - #line hidden - this.Write(" if (__request__."); - - #line 200 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("?.ContainsKey(\""); - - #line 200 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = ("); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(__request__."); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("[\""); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\"], typeof("); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #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__."); - - #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("[\""); - - #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\"]} at \'"); - - #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 212 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute)) - { - var fromHeaderAttribute = - parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute) as - AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var headerKey = fromHeaderAttribute?.Data?.Name ?? parameter.Name; - - var headers = "Headers"; - - - - #line default - #line hidden - this.Write(" var "); - - #line 228 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = default("); - - #line 228 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 229 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - - if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) - { - // In HTTP API V2 multiple values for the same header are represented via comma separated string - // Therefore, it is required to split the string to convert to an enumerable - // and convert individual item to target data type. - var commaSplit = ""; - if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) - { - commaSplit = @".Split("","")"; - } - - // HTTP API V1 and Rest API, multiple values for the same header are provided - // dedicated dictionary of string key and list value. - if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) - { - headers = "MultiValueHeaders"; - } - - if (parameter.Type.TypeArguments.Count != 1) - { - throw new NotSupportedException("Only one type argument is supported for generic types."); - } - - // Generic types are mapped using Select statement to the target parameter type argument. - var typeArgument = parameter.Type.TypeArguments.First(); - - - #line default - #line hidden - this.Write(" if (__request__."); - - #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("?.ContainsKey(\""); - - #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n "); - - #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = __request__."); - - #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("[\""); - - #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\"]"); - - #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 ("); - - #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(q, typeof("); - - #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); - - #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 '"); - - #line 268 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 275 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - // Non-generic types are mapped directly to the target parameter. - - - #line default - #line hidden - this.Write(" if (__request__."); - - #line 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("?.ContainsKey(\""); - - #line 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = ("); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(__request__."); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("[\""); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\"], typeof("); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #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__."); - - #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("[\""); - - #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\"]} at \'"); - - #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 293 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromBodyAttribute)) - { - // string parameter does not need to be de-serialized - if (parameter.Type.IsString()) - { - - - #line default - #line hidden - this.Write(" var "); - - #line 302 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = __request__.Body;\r\n\r\n"); - - #line 304 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" var "); - - #line 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = default("); - - #line 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(");\r\n try\r\n {\r\n "); - - #line 312 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = "); - - #line 312 "C:\codebase\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(".Deserialize<"); - - #line 312 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 319 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) - { - var fromRouteAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) as AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var routeKey = fromRouteAttribute?.Data?.Name ?? parameter.Name; - - - #line default - #line hidden - this.Write(" var "); - - #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = default("); - - #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(");\r\n if (__request__.PathParameters?.ContainsKey(\""); - - #line 330 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); - - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = ("); - - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(__request__.PathParameters[\""); - - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); - - #line default - #line hidden - this.Write("\"], typeof("); - - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #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["""); - - #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); - - #line default - #line hidden - this.Write("\"]} at \'"); - - #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 342 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - throw new NotSupportedException($"{parameter.Name} parameter of type {parameter.Type.FullName} passing is not supported."); - } - } - - if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) - { - - - #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 "); - - #line 356 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 366 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - if(_model.LambdaMethod.ReturnsIHttpResults) - { - - - #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"); - - #line 373 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" return errorResult;\r\n"); - - #line 379 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - - #line default - #line hidden - this.Write(" }\r\n\r\n"); - - #line 384 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - if (_model.LambdaMethod.ReturnsIHttpResults) - { - - - #line default - #line hidden - this.Write(" var httpResults = "); - - #line 390 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); - - #line default - #line hidden - - #line 390 "C:\codebase\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("."); - - #line 390 "C:\codebase\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 390 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n HttpResultSerializationOptions.ProtocolFormat serializationFormat" + - " = "); - - #line 391 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 = "); - - #line 392 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 395 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (_model.LambdaMethod.ReturnsVoid) - { - - - #line default - #line hidden - this.Write(" "); - - #line 400 "C:\codebase\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("."); - - #line 400 "C:\codebase\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 400 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 401 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (_model.LambdaMethod.ReturnsVoidTask) - { - - - #line default - #line hidden - this.Write(" await "); - - #line 406 "C:\codebase\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("."); - - #line 406 "C:\codebase\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 406 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 407 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" var response = "); - - #line 412 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); - - #line default - #line hidden - - #line 412 "C:\codebase\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("."); - - #line 412 "C:\codebase\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 412 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 413 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - if (_model.GeneratedMethod.ReturnType.FullName == _model.LambdaMethod.ReturnType.FullName || _model.LambdaMethod.ReturnsIHttpResults) - { - - - #line default - #line hidden - this.Write(" return response;\r\n"); - - #line 420 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) - { - if (_model.LambdaMethod.ReturnType.IsValueType) - { - - - #line default - #line hidden - this.Write("\r\n var body = response.ToString();\r\n"); - - #line 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (_model.LambdaMethod.ReturnType.IsString()) - { - // no action - } - else - { - - - #line default - #line hidden - this.Write("\r\n var body = "); - - #line 441 "C:\codebase\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(".Serialize(response);\r\n"); - - #line 442 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - - - #line default - #line hidden - this.Write("\r\n return new "); - - #line 447 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 449 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) - { - - - #line default - #line hidden - this.Write(" Body = "); - - #line 453 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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\", "); - - #line 456 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 458 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - - #line default - #line hidden - this.Write(" StatusCode = 200\r\n };\r\n"); - - #line 463 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - else if (_model.LambdaMethod.Events.Count == 0) - { - var parameters = string.Join(", ", _model.LambdaMethod.Parameters - .Select(p => - { - // Pass the same context parameter for ILambdaContext that comes from the generated method. - if (p.Type.FullName == TypeFullNames.ILambdaContext) - { - return "__context__"; - } - - return p.Name; - })); - - foreach (var parameter in _model.LambdaMethod.Parameters) - { - if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) - { - - - #line default - #line hidden - this.Write(" var "); - - #line 485 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = scope.ServiceProvider.GetRequiredService<"); - - #line 485 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(">();\r\n"); - - #line 486 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - - if (_model.LambdaMethod.ReturnsVoid) - { - - - #line default - #line hidden - this.Write(" "); - - #line 493 "C:\codebase\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("."); - - #line 493 "C:\codebase\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 493 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 494 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (_model.LambdaMethod.ReturnsVoidTask) - { - - - #line default - #line hidden - this.Write(" await "); - - #line 499 "C:\codebase\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("."); - - #line 499 "C:\codebase\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 499 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 500 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" return "); - - #line 505 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); - - #line default - #line hidden - - #line 505 "C:\codebase\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("."); - - #line 505 "C:\codebase\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 505 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 506 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - - - #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_"); - - #line 524 "C:\codebase\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}"); - return this.GenerationEnvironment.ToString(); - } - } - - #line default - #line hidden - #region Base class - /// - /// Base class for this transformation - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] - public class LambdaFunctionTemplateBase - { - #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 -} +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 17.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 Amazon.Lambda.Annotations.SourceGenerator.Models; + using Amazon.Lambda.Annotations.SourceGenerator.Extensions; + using Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes; + using Microsoft.CodeAnalysis; + using Amazon.Lambda.Annotations.SourceGenerator.Validation; + using System; + + /// + /// 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")] + public partial class LambdaFunctionTemplate : LambdaFunctionTemplateBase + { +#line hidden + /// + /// Create the template output + /// + public virtual string TransformText() + { + + #line 11 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + foreach (var ns in _model.GeneratedMethod.Usings) + { + + + #line default + #line hidden + this.Write("using "); + + #line 15 "C:\codebase\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 default + #line hidden + this.Write("\r\nnamespace "); + + #line 20 "C:\codebase\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 "); + + #line 22 "C:\codebase\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" + + if (_model.LambdaMethod.UsingDependencyInjection) + { + + + #line default + #line hidden + this.Write(" private readonly ServiceProvider serviceProvider;\r\n"); + + #line 29 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" private readonly "); + + #line 34 "C:\codebase\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(" "); + + #line 34 "C:\codebase\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(";\r\n"); + + #line 35 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + + #line default + #line hidden + this.Write("\r\n public "); + + #line 39 "C:\codebase\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 SetExecutionEnvironment();\r\n"); + + #line 42 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + if (_model.LambdaMethod.UsingDependencyInjection) + { + + + #line default + #line hidden + this.Write(@" 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<"); + + #line 50 "C:\codebase\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 var startup = new "); + + #line 52 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 55 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" "); + + #line 60 "C:\codebase\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(" = new "); + + #line 60 "C:\codebase\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"); + + #line 61 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + + #line default + #line hidden + this.Write(" }\r\n\r\n public "); + + #line 66 "C:\codebase\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 66 "C:\codebase\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 66 "C:\codebase\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 66 "C:\codebase\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 68 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + if (_model.LambdaMethod.UsingDependencyInjection) + { + + + #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 "); + + #line 75 "C:\codebase\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 76 "C:\codebase\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 78 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + if (_model.LambdaMethod.Events.Contains(EventType.API)) + { + var parameters = string.Join(", ", _model.LambdaMethod.Parameters + .Select(p => + { + // Pass the same context parameter for ILambdaContext that comes from the generated method. + if (p.Type.FullName == TypeFullNames.ILambdaContext) + { + return "__context__"; + } + + // Pass the same request parameter for Request Type that comes from the generated method. + if (TypeFullNames.Requests.Contains(p.Type.FullName)) + { + return "__request__"; + } + + return p.Name; + })); + 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; + + if (restApiAttribute != null && httpApiAttribute != null) + { + throw new NotSupportedException($"A method cannot have both {TypeFullNames.RestApiAttribute} and {TypeFullNames.HttpApiAttribute} attribute at the same time."); + } + + var routeParameters = restApiAttribute?.Data?.GetTemplateParameters() ?? httpApiAttribute?.Data?.GetTemplateParameters() ?? new HashSet(); + + var (routeTemplateValid, missingRouteParams) = RouteParametersValidator.Validate(routeParameters, _model.LambdaMethod.Parameters); + if (!routeTemplateValid) + { + var template = restApiAttribute?.Data?.Template ?? httpApiAttribute?.Data?.Template ?? string.Empty; + throw new InvalidOperationException($"Route template {template} is invalid. Missing {string.Join(",", missingRouteParams)} parameters in method definition."); + } + + if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) + { + + + #line default + #line hidden + this.Write(" var validationErrors = new List();\r\n\r\n"); + + #line 122 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + foreach (var parameter in _model.LambdaMethod.Parameters) + { + if (parameter.Type.FullName == TypeFullNames.ILambdaContext || TypeFullNames.Requests.Contains(parameter.Type.FullName)) + { + // No action required for ILambdaContext and RequestType, they are passed from the generated method parameter directly to the original method. + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) + { + + + #line default + #line hidden + this.Write(" var "); + + #line 134 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = scope.ServiceProvider.GetRequiredService<"); + + #line 134 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(">();\r\n"); + + #line 135 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromQueryAttribute)) + { + var fromQueryAttribute = parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromQueryAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var parameterKey = fromQueryAttribute?.Data?.Name ?? parameter.Name; + + var queryStringParameters = "QueryStringParameters"; + + + + #line default + #line hidden + this.Write(" var "); + + #line 147 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = default("); + + #line 147 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 148 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + + if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) + { + // In HTTP API V2 multiple values for the same parameter are represented via comma separated string + // Therefore, it is required to split the string to convert to an enumerable + // and convert individual item to target data type. + var commaSplit = ""; + if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) + { + commaSplit = @".Split("","")"; + } + + // HTTP API V1 and Rest API, multiple values for the same parameter are provided + // dedicated dictionary of string key and list value. + if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) + { + queryStringParameters = "MultiValueQueryStringParameters"; + } + + if (parameter.Type.TypeArguments.Count != 1) + { + throw new NotSupportedException("Only one type argument is supported for generic types."); + } + + // Generic types are mapped using Select statement to the target parameter type argument. + var typeArgument = parameter.Type.TypeArguments.First(); + + + #line default + #line hidden + this.Write(" if (__request__."); + + #line 176 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("?.ContainsKey(\""); + + #line 176 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n "); + + #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__."); + + #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("[\""); + + #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\"]"); + + #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 ("); + + #line 183 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(q, typeof("); + + #line 183 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + + #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 '"); + + #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 194 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + // Non-generic types are mapped directly to the target parameter. + + + #line default + #line hidden + this.Write(" if (__request__."); + + #line 200 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("?.ContainsKey(\""); + + #line 200 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + + " "); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = ("); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(__request__."); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("[\""); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\"], typeof("); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #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__."); + + #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("[\""); + + #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\"]} at \'"); + + #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 212 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute)) + { + var fromHeaderAttribute = + parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute) as + AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var headerKey = fromHeaderAttribute?.Data?.Name ?? parameter.Name; + + var headers = "Headers"; + + + + #line default + #line hidden + this.Write(" var "); + + #line 228 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = default("); + + #line 228 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 229 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + + if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) + { + // In HTTP API V2 multiple values for the same header are represented via comma separated string + // Therefore, it is required to split the string to convert to an enumerable + // and convert individual item to target data type. + var commaSplit = ""; + if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) + { + commaSplit = @".Split("","")"; + } + + // HTTP API V1 and Rest API, multiple values for the same header are provided + // dedicated dictionary of string key and list value. + if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) + { + headers = "MultiValueHeaders"; + } + + if (parameter.Type.TypeArguments.Count != 1) + { + throw new NotSupportedException("Only one type argument is supported for generic types."); + } + + // Generic types are mapped using Select statement to the target parameter type argument. + var typeArgument = parameter.Type.TypeArguments.First(); + + + #line default + #line hidden + this.Write(" if (__request__."); + + #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("?.ContainsKey(\""); + + #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n "); + + #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__."); + + #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("[\""); + + #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\"]"); + + #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 ("); + + #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(q, typeof("); + + #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + + #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 '"); + + #line 268 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 275 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + // Non-generic types are mapped directly to the target parameter. + + + #line default + #line hidden + this.Write(" if (__request__."); + + #line 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("?.ContainsKey(\""); + + #line 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + + " "); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = ("); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(__request__."); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("[\""); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\"], typeof("); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #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__."); + + #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("[\""); + + #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\"]} at \'"); + + #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 293 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromBodyAttribute)) + { + // string parameter does not need to be de-serialized + if (parameter.Type.IsString()) + { + + + #line default + #line hidden + this.Write(" var "); + + #line 302 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__.Body;\r\n\r\n"); + + #line 304 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" var "); + + #line 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = default("); + + #line 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(");\r\n try\r\n {\r\n "); + + #line 312 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = "); + + #line 312 "C:\codebase\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(".Deserialize<"); + + #line 312 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 319 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) + { + var fromRouteAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var routeKey = fromRouteAttribute?.Data?.Name ?? parameter.Name; + + + #line default + #line hidden + this.Write(" var "); + + #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = default("); + + #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(");\r\n if (__request__.PathParameters?.ContainsKey(\""); + + #line 330 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + + " "); + + #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = ("); + + #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(__request__.PathParameters[\""); + + #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); + + #line default + #line hidden + this.Write("\"], typeof("); + + #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #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["""); + + #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); + + #line default + #line hidden + this.Write("\"]} at \'"); + + #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 342 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) + { + var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; + + var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; + if(restApiAttribute != null) + { + + + + #line default + #line hidden + this.Write(" var "); + + #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__.RequestContext.Authorizer[\""); + + #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"].ToString();\r\n"); + + #line 354 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" var "); + + #line 359 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__.RequestContext.Authorizer.Lambda[\""); + + #line 359 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"].ToString();\r\n"); + + #line 360 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + else + { + throw new NotSupportedException($"{parameter.Name} parameter of type {parameter.Type.FullName} passing is not supported."); + } + } + + if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) + { + + + #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 "); + + #line 375 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 385 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + if(_model.LambdaMethod.ReturnsIHttpResults) + { + + + #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"); + + #line 392 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" return errorResult;\r\n"); + + #line 398 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + + #line default + #line hidden + this.Write(" }\r\n\r\n"); + + #line 403 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + if (_model.LambdaMethod.ReturnsIHttpResults) + { + + + #line default + #line hidden + this.Write(" var httpResults = "); + + #line 409 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); + + #line default + #line hidden + + #line 409 "C:\codebase\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("."); + + #line 409 "C:\codebase\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 409 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n HttpResultSerializationOptions.ProtocolFormat serializationFormat" + + " = "); + + #line 410 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 = "); + + #line 411 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 414 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (_model.LambdaMethod.ReturnsVoid) + { + + + #line default + #line hidden + this.Write(" "); + + #line 419 "C:\codebase\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("."); + + #line 419 "C:\codebase\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 419 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 420 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (_model.LambdaMethod.ReturnsVoidTask) + { + + + #line default + #line hidden + this.Write(" await "); + + #line 425 "C:\codebase\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("."); + + #line 425 "C:\codebase\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 425 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 426 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" var response = "); + + #line 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); + + #line default + #line hidden + + #line 431 "C:\codebase\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("."); + + #line 431 "C:\codebase\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 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 432 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + if (_model.GeneratedMethod.ReturnType.FullName == _model.LambdaMethod.ReturnType.FullName || _model.LambdaMethod.ReturnsIHttpResults) + { + + + #line default + #line hidden + this.Write(" return response;\r\n"); + + #line 439 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) + { + if (_model.LambdaMethod.ReturnType.IsValueType) + { + + + #line default + #line hidden + this.Write("\r\n var body = response.ToString();\r\n"); + + #line 450 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (_model.LambdaMethod.ReturnType.IsString()) + { + // no action + } + else + { + + + #line default + #line hidden + this.Write("\r\n var body = "); + + #line 460 "C:\codebase\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(".Serialize(response);\r\n"); + + #line 461 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + + + #line default + #line hidden + this.Write("\r\n return new "); + + #line 466 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 468 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) + { + + + #line default + #line hidden + this.Write(" Body = "); + + #line 472 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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\", "); + + #line 475 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 477 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + + #line default + #line hidden + this.Write(" StatusCode = 200\r\n };\r\n"); + + #line 482 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + else if (_model.LambdaMethod.Events.Count == 0) + { + var parameters = string.Join(", ", _model.LambdaMethod.Parameters + .Select(p => + { + // Pass the same context parameter for ILambdaContext that comes from the generated method. + if (p.Type.FullName == TypeFullNames.ILambdaContext) + { + return "__context__"; + } + + return p.Name; + })); + + foreach (var parameter in _model.LambdaMethod.Parameters) + { + if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) + { + + + #line default + #line hidden + this.Write(" var "); + + #line 504 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = scope.ServiceProvider.GetRequiredService<"); + + #line 504 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(">();\r\n"); + + #line 505 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + + if (_model.LambdaMethod.ReturnsVoid) + { + + + #line default + #line hidden + this.Write(" "); + + #line 512 "C:\codebase\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("."); + + #line 512 "C:\codebase\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 512 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 513 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (_model.LambdaMethod.ReturnsVoidTask) + { + + + #line default + #line hidden + this.Write(" await "); + + #line 518 "C:\codebase\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("."); + + #line 518 "C:\codebase\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 518 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 519 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" return "); + + #line 524 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); + + #line default + #line hidden + + #line 524 "C:\codebase\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("."); + + #line 524 "C:\codebase\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 524 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 525 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + + + #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_"); + + #line 543 "C:\codebase\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}"); + return this.GenerationEnvironment.ToString(); + } + } + + #line default + #line hidden + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + public class LambdaFunctionTemplateBase + { + #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/LambdaFunctionTemplate.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt index c9502352d..3032c0e82 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt @@ -1,529 +1,548 @@ -<#@ template language="C#" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Extensions" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes" #> -<#@ import namespace="Microsoft.CodeAnalysis" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Validation" #> -<# - foreach (var ns in _model.GeneratedMethod.Usings) - { -#> -using <#= ns #>; -<# - } -#> - -namespace <#= _model.LambdaMethod.ContainingNamespace #> -{ - public class <#= _model.GeneratedMethod.ContainingType.Name #> - { -<# - if (_model.LambdaMethod.UsingDependencyInjection) - { -#> - private readonly ServiceProvider serviceProvider; -<# - } - else - { -#> - private readonly <#= _model.LambdaMethod.ContainingType.Name #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>; -<# - } -#> - - public <#= _model.GeneratedMethod.ContainingType.Name #>() - { - SetExecutionEnvironment(); -<# - if (_model.LambdaMethod.UsingDependencyInjection) - { -#> - 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<<#= _model.LambdaMethod.ContainingType.Name #>>(); - - var startup = new <#= _model.StartupType.FullName #>(); - startup.ConfigureServices(services); - serviceProvider = services.BuildServiceProvider(); -<# - } - else - { -#> - <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = new <#= _model.LambdaMethod.ContainingType.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) - { -#> - // Create a scope for every request, - // this allows creating scoped dependencies without creating a scope manually. - using var scope = serviceProvider.CreateScope(); - var <#= - _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = scope.ServiceProvider.GetRequiredService<<#= _model.LambdaMethod.ContainingType.Name #>>(); - -<# - } - - if (_model.LambdaMethod.Events.Contains(EventType.API)) - { - var parameters = string.Join(", ", _model.LambdaMethod.Parameters - .Select(p => - { - // Pass the same context parameter for ILambdaContext that comes from the generated method. - if (p.Type.FullName == TypeFullNames.ILambdaContext) - { - return "__context__"; - } - - // Pass the same request parameter for Request Type that comes from the generated method. - if (TypeFullNames.Requests.Contains(p.Type.FullName)) - { - return "__request__"; - } - - return p.Name; - })); - 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; - - if (restApiAttribute != null && httpApiAttribute != null) - { - throw new NotSupportedException($"A method cannot have both {TypeFullNames.RestApiAttribute} and {TypeFullNames.HttpApiAttribute} attribute at the same time."); - } - - var routeParameters = restApiAttribute?.Data?.GetTemplateParameters() ?? httpApiAttribute?.Data?.GetTemplateParameters() ?? new HashSet(); - - var (routeTemplateValid, missingRouteParams) = RouteParametersValidator.Validate(routeParameters, _model.LambdaMethod.Parameters); - if (!routeTemplateValid) - { - var template = restApiAttribute?.Data?.Template ?? httpApiAttribute?.Data?.Template ?? string.Empty; - throw new InvalidOperationException($"Route template {template} is invalid. Missing {string.Join(",", missingRouteParams)} parameters in method definition."); - } - - if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) - { -#> - var validationErrors = new List(); - -<# - } - - foreach (var parameter in _model.LambdaMethod.Parameters) - { - if (parameter.Type.FullName == TypeFullNames.ILambdaContext || TypeFullNames.Requests.Contains(parameter.Type.FullName)) - { - // No action required for ILambdaContext and RequestType, they are passed from the generated method parameter directly to the original method. - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) - { -#> - var <#= parameter.Name #> = scope.ServiceProvider.GetRequiredService<<#= parameter.Type.FullName #>>(); -<# - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromQueryAttribute)) - { - var fromQueryAttribute = parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromQueryAttribute) as AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var parameterKey = fromQueryAttribute?.Data?.Name ?? parameter.Name; - - var queryStringParameters = "QueryStringParameters"; - -#> - var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); -<# - - if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) - { - // In HTTP API V2 multiple values for the same parameter are represented via comma separated string - // Therefore, it is required to split the string to convert to an enumerable - // and convert individual item to target data type. - var commaSplit = ""; - if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) - { - commaSplit = @".Split("","")"; - } - - // HTTP API V1 and Rest API, multiple values for the same parameter are provided - // dedicated dictionary of string key and list value. - if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) - { - queryStringParameters = "MultiValueQueryStringParameters"; - } - - if (parameter.Type.TypeArguments.Count != 1) - { - throw new NotSupportedException("Only one type argument is supported for generic types."); - } - - // Generic types are mapped using Select statement to the target parameter type argument. - var typeArgument = parameter.Type.TypeArguments.First(); -#> - if (__request__.<#= queryStringParameters #>?.ContainsKey("<#= parameterKey #>") == true) - { - <#= parameter.Name #> = __request__.<#= queryStringParameters #>["<#= parameterKey #>"]<#= commaSplit #> - .Select(q => - { - try - { - return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {q} at '<#= parameterKey #>' failed to satisfy constraint: {e.Message}"); - return default; - } - }) - .ToList(); - } - -<# - } - else - { - // Non-generic types are mapped directly to the target parameter. -#> - if (__request__.<#= queryStringParameters #>?.ContainsKey("<#= parameterKey #>") == true) - { - try - { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= queryStringParameters #>["<#= parameterKey #>"], typeof(<#= parameter.Type.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.<#= queryStringParameters #>["<#= parameterKey #>"]} at '<#= parameterKey #>' failed to satisfy constraint: {e.Message}"); - } - } - -<# - } - - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute)) - { - var fromHeaderAttribute = - parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute) as - AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var headerKey = fromHeaderAttribute?.Data?.Name ?? parameter.Name; - - var headers = "Headers"; - -#> - var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); -<# - - if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) - { - // In HTTP API V2 multiple values for the same header are represented via comma separated string - // Therefore, it is required to split the string to convert to an enumerable - // and convert individual item to target data type. - var commaSplit = ""; - if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) - { - commaSplit = @".Split("","")"; - } - - // HTTP API V1 and Rest API, multiple values for the same header are provided - // dedicated dictionary of string key and list value. - if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) - { - headers = "MultiValueHeaders"; - } - - if (parameter.Type.TypeArguments.Count != 1) - { - throw new NotSupportedException("Only one type argument is supported for generic types."); - } - - // Generic types are mapped using Select statement to the target parameter type argument. - var typeArgument = parameter.Type.TypeArguments.First(); -#> - if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) - { - <#= parameter.Name #> = __request__.<#= headers #>["<#= headerKey #>"]<#= commaSplit #> - .Select(q => - { - try - { - return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {q} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); - return default; - } - }) - .ToList(); - } - -<# - } - else - { - // Non-generic types are mapped directly to the target parameter. -#> - if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) - { - try - { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= headers #>["<#= headerKey #>"], typeof(<#= parameter.Type.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.<#= headers #>["<#= headerKey #>"]} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); - } - } - -<# - } - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromBodyAttribute)) - { - // string parameter does not need to be de-serialized - if (parameter.Type.IsString()) - { - #> - var <#= parameter.Name #> = __request__.Body; - -<# - } - else - { - #> - var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); - try - { - <#= parameter.Name #> = <#= _model.Serializer #>.Deserialize<<#= parameter.Type.FullName #>>(__request__.Body); - } - catch (Exception e) - { - validationErrors.Add($"Value {__request__.Body} at 'body' failed to satisfy constraint: {e.Message}"); - } - -<# - } - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) - { - var fromRouteAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) as AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var routeKey = fromRouteAttribute?.Data?.Name ?? parameter.Name; -#> - var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); - if (__request__.PathParameters?.ContainsKey("<#= routeKey #>") == true) - { - try - { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.PathParameters["<#= routeKey #>"], typeof(<#= parameter.Type.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.PathParameters["<#= routeKey #>"]} at '<#= routeKey #>' failed to satisfy constraint: {e.Message}"); - } - } - -<# - } - else - { - throw new NotSupportedException($"{parameter.Name} parameter of type {parameter.Type.FullName} passing is not supported."); - } - } - - if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) - { -#> - // return 400 Bad Request if there exists a validation error - if (validationErrors.Any()) - { - var errorResult = new <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse" : "Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse" #> - { - Body = @$"{{""message"": ""{validationErrors.Count} validation error(s) detected: {string.Join(",", validationErrors)}""}}", - Headers = new Dictionary - { - {"Content-Type", "application/json"}, - {"x-amzn-ErrorType", "ValidationException"} - }, - StatusCode = 400 - }; -<# - if(_model.LambdaMethod.ReturnsIHttpResults) - { -#> - var errorStream = new System.IO.MemoryStream(); - System.Text.Json.JsonSerializer.Serialize(errorStream, errorResult); - return errorStream; -<# - } - else - { -#> - return errorResult; -<# - } -#> - } - -<# - } - - if (_model.LambdaMethod.ReturnsIHttpResults) - { -#> - var httpResults = <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); - HttpResultSerializationOptions.ProtocolFormat serializationFormat = <#= restApiAttribute != null ? "HttpResultSerializationOptions.ProtocolFormat.RestApi" : "HttpResultSerializationOptions.ProtocolFormat.HttpApi"#>; - HttpResultSerializationOptions.ProtocolVersion serializationVersion = <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "HttpResultSerializationOptions.ProtocolVersion.V1" : "HttpResultSerializationOptions.ProtocolVersion.V2"#>; - var serializationOptions = new HttpResultSerializationOptions { Format = serializationFormat, Version = serializationVersion }; - var response = httpResults.Serialize(serializationOptions); -<# - } - else if (_model.LambdaMethod.ReturnsVoid) - { -#> - <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - else if (_model.LambdaMethod.ReturnsVoidTask) - { -#> - await <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - else - { -#> - var response = <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - - if (_model.GeneratedMethod.ReturnType.FullName == _model.LambdaMethod.ReturnType.FullName || _model.LambdaMethod.ReturnsIHttpResults) - { -#> - return response; -<# - } - else - { - if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) - { - if (_model.LambdaMethod.ReturnType.IsValueType) - { -#> - - var body = response.ToString(); -<# - } - else if (_model.LambdaMethod.ReturnType.IsString()) - { - // no action - } - else - { -#> - - var body = <#= _model.Serializer #>.Serialize(response); -<# - } - } -#> - - return new <#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? _model.GeneratedMethod.ReturnType.TaskTypeArgument : _model.GeneratedMethod.ReturnType.FullName #> - { -<# - if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) - { -#> - Body = <#= _model.LambdaMethod.ReturnType.IsString() ? "response" : "body" #>, - Headers = new Dictionary - { - {"Content-Type", <#= _model.LambdaMethod.ReturnType.IsString() ? "\"text/plain\"" : "\"application/json\"" #>} - }, -<# - } -#> - StatusCode = 200 - }; -<# - } - } - else if (_model.LambdaMethod.Events.Count == 0) - { - var parameters = string.Join(", ", _model.LambdaMethod.Parameters - .Select(p => - { - // Pass the same context parameter for ILambdaContext that comes from the generated method. - if (p.Type.FullName == TypeFullNames.ILambdaContext) - { - return "__context__"; - } - - return p.Name; - })); - - foreach (var parameter in _model.LambdaMethod.Parameters) - { - if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) - { -#> - var <#= parameter.Name #> = scope.ServiceProvider.GetRequiredService<<#= parameter.Type.FullName #>>(); -<# - } - } - - if (_model.LambdaMethod.ReturnsVoid) - { -#> - <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - else if (_model.LambdaMethod.ReturnsVoidTask) - { -#> - await <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - else - { -#> - return <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - } -#> - } - - 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_<#= _model.SourceGeneratorVersion #>"); - - Environment.SetEnvironmentVariable(envName, envValue.ToString()); - } - } +<#@ template hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Extensions" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes" #> +<#@ import namespace="Microsoft.CodeAnalysis" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Validation" #> +<# + foreach (var ns in _model.GeneratedMethod.Usings) + { +#> +using <#= ns #>; +<# + } +#> + +namespace <#= _model.LambdaMethod.ContainingNamespace #> +{ + public class <#= _model.GeneratedMethod.ContainingType.Name #> + { +<# + if (_model.LambdaMethod.UsingDependencyInjection) + { +#> + private readonly ServiceProvider serviceProvider; +<# + } + else + { +#> + private readonly <#= _model.LambdaMethod.ContainingType.Name #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>; +<# + } +#> + + public <#= _model.GeneratedMethod.ContainingType.Name #>() + { + SetExecutionEnvironment(); +<# + if (_model.LambdaMethod.UsingDependencyInjection) + { +#> + 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<<#= _model.LambdaMethod.ContainingType.Name #>>(); + + var startup = new <#= _model.StartupType.FullName #>(); + startup.ConfigureServices(services); + serviceProvider = services.BuildServiceProvider(); +<# + } + else + { +#> + <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = new <#= _model.LambdaMethod.ContainingType.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) + { +#> + // Create a scope for every request, + // this allows creating scoped dependencies without creating a scope manually. + using var scope = serviceProvider.CreateScope(); + var <#= + _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = scope.ServiceProvider.GetRequiredService<<#= _model.LambdaMethod.ContainingType.Name #>>(); + +<# + } + + if (_model.LambdaMethod.Events.Contains(EventType.API)) + { + var parameters = string.Join(", ", _model.LambdaMethod.Parameters + .Select(p => + { + // Pass the same context parameter for ILambdaContext that comes from the generated method. + if (p.Type.FullName == TypeFullNames.ILambdaContext) + { + return "__context__"; + } + + // Pass the same request parameter for Request Type that comes from the generated method. + if (TypeFullNames.Requests.Contains(p.Type.FullName)) + { + return "__request__"; + } + + return p.Name; + })); + 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; + + if (restApiAttribute != null && httpApiAttribute != null) + { + throw new NotSupportedException($"A method cannot have both {TypeFullNames.RestApiAttribute} and {TypeFullNames.HttpApiAttribute} attribute at the same time."); + } + + var routeParameters = restApiAttribute?.Data?.GetTemplateParameters() ?? httpApiAttribute?.Data?.GetTemplateParameters() ?? new HashSet(); + + var (routeTemplateValid, missingRouteParams) = RouteParametersValidator.Validate(routeParameters, _model.LambdaMethod.Parameters); + if (!routeTemplateValid) + { + var template = restApiAttribute?.Data?.Template ?? httpApiAttribute?.Data?.Template ?? string.Empty; + throw new InvalidOperationException($"Route template {template} is invalid. Missing {string.Join(",", missingRouteParams)} parameters in method definition."); + } + + if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) + { +#> + var validationErrors = new List(); + +<# + } + + foreach (var parameter in _model.LambdaMethod.Parameters) + { + if (parameter.Type.FullName == TypeFullNames.ILambdaContext || TypeFullNames.Requests.Contains(parameter.Type.FullName)) + { + // No action required for ILambdaContext and RequestType, they are passed from the generated method parameter directly to the original method. + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) + { +#> + var <#= parameter.Name #> = scope.ServiceProvider.GetRequiredService<<#= parameter.Type.FullName #>>(); +<# + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromQueryAttribute)) + { + var fromQueryAttribute = parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromQueryAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var parameterKey = fromQueryAttribute?.Data?.Name ?? parameter.Name; + + var queryStringParameters = "QueryStringParameters"; + +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); +<# + + if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) + { + // In HTTP API V2 multiple values for the same parameter are represented via comma separated string + // Therefore, it is required to split the string to convert to an enumerable + // and convert individual item to target data type. + var commaSplit = ""; + if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) + { + commaSplit = @".Split("","")"; + } + + // HTTP API V1 and Rest API, multiple values for the same parameter are provided + // dedicated dictionary of string key and list value. + if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) + { + queryStringParameters = "MultiValueQueryStringParameters"; + } + + if (parameter.Type.TypeArguments.Count != 1) + { + throw new NotSupportedException("Only one type argument is supported for generic types."); + } + + // Generic types are mapped using Select statement to the target parameter type argument. + var typeArgument = parameter.Type.TypeArguments.First(); +#> + if (__request__.<#= queryStringParameters #>?.ContainsKey("<#= parameterKey #>") == true) + { + <#= parameter.Name #> = __request__.<#= queryStringParameters #>["<#= parameterKey #>"]<#= commaSplit #> + .Select(q => + { + try + { + return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {q} at '<#= parameterKey #>' failed to satisfy constraint: {e.Message}"); + return default; + } + }) + .ToList(); + } + +<# + } + else + { + // Non-generic types are mapped directly to the target parameter. +#> + if (__request__.<#= queryStringParameters #>?.ContainsKey("<#= parameterKey #>") == true) + { + try + { + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= queryStringParameters #>["<#= parameterKey #>"], typeof(<#= parameter.Type.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.<#= queryStringParameters #>["<#= parameterKey #>"]} at '<#= parameterKey #>' failed to satisfy constraint: {e.Message}"); + } + } + +<# + } + + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute)) + { + var fromHeaderAttribute = + parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute) as + AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var headerKey = fromHeaderAttribute?.Data?.Name ?? parameter.Name; + + var headers = "Headers"; + +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); +<# + + if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) + { + // In HTTP API V2 multiple values for the same header are represented via comma separated string + // Therefore, it is required to split the string to convert to an enumerable + // and convert individual item to target data type. + var commaSplit = ""; + if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) + { + commaSplit = @".Split("","")"; + } + + // HTTP API V1 and Rest API, multiple values for the same header are provided + // dedicated dictionary of string key and list value. + if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) + { + headers = "MultiValueHeaders"; + } + + if (parameter.Type.TypeArguments.Count != 1) + { + throw new NotSupportedException("Only one type argument is supported for generic types."); + } + + // Generic types are mapped using Select statement to the target parameter type argument. + var typeArgument = parameter.Type.TypeArguments.First(); +#> + if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) + { + <#= parameter.Name #> = __request__.<#= headers #>["<#= headerKey #>"]<#= commaSplit #> + .Select(q => + { + try + { + return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {q} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); + return default; + } + }) + .ToList(); + } + +<# + } + else + { + // Non-generic types are mapped directly to the target parameter. +#> + if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) + { + try + { + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= headers #>["<#= headerKey #>"], typeof(<#= parameter.Type.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.<#= headers #>["<#= headerKey #>"]} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); + } + } + +<# + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromBodyAttribute)) + { + // string parameter does not need to be de-serialized + if (parameter.Type.IsString()) + { +#> + var <#= parameter.Name #> = __request__.Body; + +<# + } + else + { +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); + try + { + <#= parameter.Name #> = <#= _model.Serializer #>.Deserialize<<#= parameter.Type.FullName #>>(__request__.Body); + } + catch (Exception e) + { + validationErrors.Add($"Value {__request__.Body} at 'body' failed to satisfy constraint: {e.Message}"); + } + +<# + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) + { + var fromRouteAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var routeKey = fromRouteAttribute?.Data?.Name ?? parameter.Name; +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); + if (__request__.PathParameters?.ContainsKey("<#= routeKey #>") == true) + { + try + { + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.PathParameters["<#= routeKey #>"], typeof(<#= parameter.Type.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.PathParameters["<#= routeKey #>"]} at '<#= routeKey #>' failed to satisfy constraint: {e.Message}"); + } + } + +<# + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) + { + var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; + + var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; + if(restApiAttribute != null) + { + +#> + var <#= parameter.Name #> = __request__.RequestContext.Authorizer["<#= authKey #>"].ToString(); +<# + } + else + { +#> + var <#= parameter.Name #> = __request__.RequestContext.Authorizer.Lambda["<#= authKey #>"].ToString(); +<# + } + } + else + { + throw new NotSupportedException($"{parameter.Name} parameter of type {parameter.Type.FullName} passing is not supported."); + } + } + + if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) + { +#> + // return 400 Bad Request if there exists a validation error + if (validationErrors.Any()) + { + var errorResult = new <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse" : "Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse" #> + { + Body = @$"{{""message"": ""{validationErrors.Count} validation error(s) detected: {string.Join(",", validationErrors)}""}}", + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "ValidationException"} + }, + StatusCode = 400 + }; +<# + if(_model.LambdaMethod.ReturnsIHttpResults) + { +#> + var errorStream = new System.IO.MemoryStream(); + System.Text.Json.JsonSerializer.Serialize(errorStream, errorResult); + return errorStream; +<# + } + else + { +#> + return errorResult; +<# + } +#> + } + +<# + } + + if (_model.LambdaMethod.ReturnsIHttpResults) + { +#> + var httpResults = <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); + HttpResultSerializationOptions.ProtocolFormat serializationFormat = <#= restApiAttribute != null ? "HttpResultSerializationOptions.ProtocolFormat.RestApi" : "HttpResultSerializationOptions.ProtocolFormat.HttpApi"#>; + HttpResultSerializationOptions.ProtocolVersion serializationVersion = <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "HttpResultSerializationOptions.ProtocolVersion.V1" : "HttpResultSerializationOptions.ProtocolVersion.V2"#>; + var serializationOptions = new HttpResultSerializationOptions { Format = serializationFormat, Version = serializationVersion }; + var response = httpResults.Serialize(serializationOptions); +<# + } + else if (_model.LambdaMethod.ReturnsVoid) + { +#> + <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + else if (_model.LambdaMethod.ReturnsVoidTask) + { +#> + await <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + else + { +#> + var response = <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + + if (_model.GeneratedMethod.ReturnType.FullName == _model.LambdaMethod.ReturnType.FullName || _model.LambdaMethod.ReturnsIHttpResults) + { +#> + return response; +<# + } + else + { + if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) + { + if (_model.LambdaMethod.ReturnType.IsValueType) + { +#> + + var body = response.ToString(); +<# + } + else if (_model.LambdaMethod.ReturnType.IsString()) + { + // no action + } + else + { +#> + + var body = <#= _model.Serializer #>.Serialize(response); +<# + } + } +#> + + return new <#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? _model.GeneratedMethod.ReturnType.TaskTypeArgument : _model.GeneratedMethod.ReturnType.FullName #> + { +<# + if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) + { +#> + Body = <#= _model.LambdaMethod.ReturnType.IsString() ? "response" : "body" #>, + Headers = new Dictionary + { + {"Content-Type", <#= _model.LambdaMethod.ReturnType.IsString() ? "\"text/plain\"" : "\"application/json\"" #>} + }, +<# + } +#> + StatusCode = 200 + }; +<# + } + } + else if (_model.LambdaMethod.Events.Count == 0) + { + var parameters = string.Join(", ", _model.LambdaMethod.Parameters + .Select(p => + { + // Pass the same context parameter for ILambdaContext that comes from the generated method. + if (p.Type.FullName == TypeFullNames.ILambdaContext) + { + return "__context__"; + } + + return p.Name; + })); + + foreach (var parameter in _model.LambdaMethod.Parameters) + { + if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) + { +#> + var <#= parameter.Name #> = scope.ServiceProvider.GetRequiredService<<#= parameter.Type.FullName #>>(); +<# + } + } + + if (_model.LambdaMethod.ReturnsVoid) + { +#> + <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + else if (_model.LambdaMethod.ReturnsVoidTask) + { +#> + await <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + else + { +#> + return <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + } +#> + } + + 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_<#= _model.SourceGeneratorVersion #>"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } } \ No newline at end of file diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs index 70cd575d9..7c0084f19 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs @@ -31,6 +31,7 @@ public static class TypeFullNames public const string FromHeaderAttribute = "Amazon.Lambda.Annotations.APIGateway.FromHeaderAttribute"; public const string FromBodyAttribute = "Amazon.Lambda.Annotations.APIGateway.FromBodyAttribute"; public const string FromRouteAttribute = "Amazon.Lambda.Annotations.APIGateway.FromRouteAttribute"; + public const string FromCustomAuthorizerAttribute = "Amazon.Lambda.Annotations.APIGateway.FromCustomAuthorizerAttribute"; public static HashSet Requests = new HashSet { diff --git a/Libraries/src/Amazon.Lambda.Annotations/APIGateway/FromCustomAuthorizerAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/APIGateway/FromCustomAuthorizerAttribute.cs new file mode 100644 index 000000000..4bdc173e6 --- /dev/null +++ b/Libraries/src/Amazon.Lambda.Annotations/APIGateway/FromCustomAuthorizerAttribute.cs @@ -0,0 +1,19 @@ +using System; + +namespace Amazon.Lambda.Annotations.APIGateway +{ + /// + /// Maps this parameter to a custom authorizer item + /// + /// + /// Will try to get the specified key from Custom Authorizer values + /// + [AttributeUsage(AttributeTargets.Parameter)] + public class FromCustomAuthorizerAttribute : Attribute, INamedAttribute + { + /// + /// Key of the value + /// + public string Name { get; set; } + } +} 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 108b13cd7..e4f8af98d 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 @@ -58,6 +58,8 @@ + + diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs new file mode 100644 index 000000000..6c9d311f2 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated + { + private readonly CustomAuthorizerHttpApiExample customAuthorizerHttpApiExample; + + public CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated() + { + SetExecutionEnvironment(); + customAuthorizerHttpApiExample = new CustomAuthorizerHttpApiExample(); + } + + public async System.Threading.Tasks.Task HttpApiAuthorizer(Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + { + var validationErrors = new List(); + + var authorizerValue = __request__.RequestContext.Authorizer.Lambda["authKey"].ToString(); + // return 400 Bad Request if there exists a validation error + if (validationErrors.Any()) + { + var errorResult = new Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse + { + 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 customAuthorizerHttpApiExample.HttpApiAuthorizer(authorizerValue, __context__); + + return new Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse + { + 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_0.13.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs new file mode 100644 index 000000000..fd93dd9d0 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class CustomAuthorizerRestExample_RestAuthorizer_Generated + { + private readonly CustomAuthorizerRestExample customAuthorizerRestExample; + + public CustomAuthorizerRestExample_RestAuthorizer_Generated() + { + SetExecutionEnvironment(); + customAuthorizerRestExample = new CustomAuthorizerRestExample(); + } + + public async System.Threading.Tasks.Task RestAuthorizer(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + { + var validationErrors = new List(); + + var authorizerValue = __request__.RequestContext.Authorizer["authKey"].ToString(); + // 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 customAuthorizerRestExample.RestAuthorizer(authorizerValue, __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_0.13.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template new file mode 100644 index 000000000..45ea454f9 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template @@ -0,0 +1,39 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.0.0).", + "Resources": { + "HttpApiAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestProject::TestServerlessApp.CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated::HttpApiAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/api/authorizer", + "Method": "GET" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template new file mode 100644 index 000000000..942e498b9 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template @@ -0,0 +1,39 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.0.0).", + "Resources": { + "RestAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestProject::TestServerlessApp.CustomAuthorizerRestExample_RestAuthorizer_Generated::RestAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/rest/authorizer", + "Method": "GET" + } + } + } + } + } + } +} \ 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 4b9f8a5bd..7a2fc35d0 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -67,7 +67,7 @@ public async Task GeneratorDoesNotRunDueToCompileError() await new VerifyCS.Test { TestState = - { + { Sources = { (Path.Combine("TestServerlessApp", "Greeter.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "Greeter.cs"))), @@ -437,7 +437,7 @@ public async Task CustomizeResponses() new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated.g.cs", expectedNotFoundResponseWithHeaderV2Generated), new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated.g.cs", expectedNotFoundResponseWithHeaderV2AsyncGenerated), - + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated.g.cs", expectedNotFoundResponseWithHeaderV1Generated), new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated.g.cs", expectedNotFoundResponseWithHeaderV1AsyncGenerated), @@ -445,7 +445,7 @@ public async Task CustomizeResponses() }, ReferenceAssemblies = ReferenceAssemblies.Net.Net60 } - + }.RunAsync(); var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); @@ -472,12 +472,88 @@ public async Task InvalidReturnTypeIHttpResult() }, ExpectedDiagnostics = { - DiagnosticResult.CompilerError("AWSLambda0105").WithSpan($"TestServerlessApp{Path.DirectorySeparatorChar}CustomizeResponseWithErrors.cs", 14, 9, 21, 10).WithArguments("Error") + DiagnosticResult.CompilerError("AWSLambda0105").WithSpan($"TestServerlessApp{Path.DirectorySeparatorChar}CustomizeResponseWithErrors.cs", 14, 9, 21, 10).WithArguments("Error") }, ReferenceAssemblies = ReferenceAssemblies.Net.Net60 } }.RunAsync(); } + + [Fact] + public async Task CustomAuthorizerRestTest() + { + var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "authorizerRest.template")).ToEnvironmentLineEndings(); + var expectedRestAuthorizerGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs")).ToEnvironmentLineEndings(); + + await new VerifyCS.Test + { + TestState = + { + Sources = + { + (Path.Combine("TestServerlessApp", "CustomAuthorizerRestExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "CustomAuthorizerRestExample.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"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", + SourceText.From(expectedRestAuthorizerGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", expectedRestAuthorizerGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent) + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }.RunAsync(); + + var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + Assert.Equal(expectedTemplateContent, actualTemplateContent); + } + + [Fact] + public async Task CustomAuthorizerHttpApiTest() + { + var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "authorizerHttpApi.template")).ToEnvironmentLineEndings(); + var expectedRestAuthorizerGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs")).ToEnvironmentLineEndings(); + + await new VerifyCS.Test + { + TestState = + { + Sources = + { + (Path.Combine("TestServerlessApp", "CustomAuthorizerHttpApiExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "CustomAuthorizerHttpApiExample.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"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", + SourceText.From(expectedRestAuthorizerGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs", expectedRestAuthorizerGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent) + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }.RunAsync(); + + var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + Assert.Equal(expectedTemplateContent, actualTemplateContent); + } } } \ No newline at end of file diff --git a/Libraries/test/TestServerlessApp/CustomAuthorizerHttpApiExample.cs b/Libraries/test/TestServerlessApp/CustomAuthorizerHttpApiExample.cs new file mode 100644 index 000000000..7754a189f --- /dev/null +++ b/Libraries/test/TestServerlessApp/CustomAuthorizerHttpApiExample.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class CustomAuthorizerHttpApiExample + { + [LambdaFunction(ResourceName = "HttpApiAuthorizerTest", PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/api/authorizer")] + public async Task HttpApiAuthorizer([FromCustomAuthorizer(Name = "authKey")] string authorizerValue, ILambdaContext context) + { + context.Logger.LogLine(authorizerValue); + await Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs b/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs new file mode 100644 index 000000000..1086d1519 --- /dev/null +++ b/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class CustomAuthorizerRestExample + { + [LambdaFunction(ResourceName = "RestAuthorizerTest", PackageType = LambdaPackageType.Image)] + [RestApi(LambdaHttpMethod.Get, "/rest/authorizer")] + public async Task RestAuthorizer([FromCustomAuthorizer(Name = "authKey")] string authorizerValue, ILambdaContext context) + { + context.Logger.LogLine(authorizerValue); + await Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Libraries/test/TestServerlessApp/serverless.template b/Libraries/test/TestServerlessApp/serverless.template index 93d55014c..679796131 100644 --- a/Libraries/test/TestServerlessApp/serverless.template +++ b/Libraries/test/TestServerlessApp/serverless.template @@ -1,652 +1,716 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09", - "Transform": "AWS::Serverless-2016-10-31", - "Description": "An AWS Serverless Application. This template is partially managed by Amazon.Lambda.Annotations (v0.13.0.0).", - "Parameters": { - "ArchitectureTypeParameter": { - "Type": "String", - "Default": "x86_64", - "AllowedValues": [ - "x86_64", - "arm64" - ] - } - }, - "Globals": { - "Function": { - "Architectures": [ - { - "Ref": "ArchitectureTypeParameter" - } - ] - } - }, - "Resources": { - "TestServerlessAppComplexCalculatorAddGenerated": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations", - "SyncedEvents": [ - "RootPost" - ] - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.ComplexCalculator_Add_Generated::Add" - ] - }, - "Events": { - "RootPost": { - "Type": "HttpApi", - "Properties": { - "Path": "/ComplexCalculator/Add", - "Method": "POST" - } - } - } - } - }, - "TestServerlessAppComplexCalculatorSubtractGenerated": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations", - "SyncedEvents": [ - "RootPost" - ] - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.ComplexCalculator_Subtract_Generated::Subtract" - ] - }, - "Events": { - "RootPost": { - "Type": "HttpApi", - "Properties": { - "Path": "/ComplexCalculator/Subtract", - "Method": "POST" - } - } - } - } - }, - "TestServerlessAppDynamicExampleDynamicReturnGenerated": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations" - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::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": [ - "TestServerlessApp::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" - ] - }, - "Events": { - "RootGet": { - "Type": "HttpApi", - "Properties": { - "Path": "/Greeter/SayHelloAsync", - "Method": "GET", - "PayloadFormatVersion": "1.0" - } - } - } - } - }, - "SimpleCalculatorAdd": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations", - "SyncedEvents": [ - "RootGet" - ] - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.SimpleCalculator_Add_Generated::Add" - ] - }, - "Events": { - "RootGet": { - "Type": "Api", - "Properties": { - "Path": "/SimpleCalculator/Add", - "Method": "GET" - } - } - } - } - }, - "SimpleCalculatorSubtract": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations", - "SyncedEvents": [ - "RootGet" - ] - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.SimpleCalculator_Subtract_Generated::Subtract" - ] - }, - "Events": { - "RootGet": { - "Type": "Api", - "Properties": { - "Path": "/SimpleCalculator/Subtract", - "Method": "GET" - } - } - } - } - }, - "SimpleCalculatorMultiply": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations", - "SyncedEvents": [ - "RootGet" - ] - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.SimpleCalculator_Multiply_Generated::Multiply" - ] - }, - "Events": { - "RootGet": { - "Type": "Api", - "Properties": { - "Path": "/SimpleCalculator/Multiply/{x}/{y}", - "Method": "GET" - } - } - } - } - }, - "SimpleCalculatorDivideAsync": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations", - "SyncedEvents": [ - "RootGet" - ] - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.SimpleCalculator_DivideAsync_Generated::DivideAsync" - ] - }, - "Events": { - "RootGet": { - "Type": "Api", - "Properties": { - "Path": "/SimpleCalculator/DivideAsync/{x}/{y}", - "Method": "GET" - } - } - } - } - }, - "PI": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations" - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.SimpleCalculator_Pi_Generated::Pi" - ] - } - } - }, - "Random": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations" - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.SimpleCalculator_Random_Generated::Random" - ] - } - } - }, - "Randoms": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations" - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.SimpleCalculator_Randoms_Generated::Randoms" - ] - } - } - }, - "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": { - "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" - } - } - } +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "An AWS Serverless Application. This template is partially managed by Amazon.Lambda.Annotations (v0.13.0.0).", + "Parameters": { + "ArchitectureTypeParameter": { + "Type": "String", + "Default": "x86_64", + "AllowedValues": [ + "x86_64", + "arm64" + ] + } + }, + "Globals": { + "Function": { + "Architectures": [ + { + "Ref": "ArchitectureTypeParameter" + } + ] + } + }, + "Resources": { + "TestServerlessAppComplexCalculatorAddGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootPost" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.ComplexCalculator_Add_Generated::Add" + ] + }, + "Events": { + "RootPost": { + "Type": "HttpApi", + "Properties": { + "Path": "/ComplexCalculator/Add", + "Method": "POST" + } + } + } + } + }, + "TestServerlessAppComplexCalculatorSubtractGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootPost" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.ComplexCalculator_Subtract_Generated::Subtract" + ] + }, + "Events": { + "RootPost": { + "Type": "HttpApi", + "Properties": { + "Path": "/ComplexCalculator/Subtract", + "Method": "POST" + } + } + } + } + }, + "TestServerlessAppDynamicExampleDynamicReturnGenerated": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::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": [ + "TestServerlessApp::TestServerlessApp.Greeter_SayHelloAsync_Generated::SayHelloAsync" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/Greeter/SayHelloAsync", + "Method": "GET", + "PayloadFormatVersion": "1.0" + } + } + } + } + }, + "SimpleCalculatorAdd": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.SimpleCalculator_Add_Generated::Add" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/SimpleCalculator/Add", + "Method": "GET" + } + } + } + } + }, + "SimpleCalculatorSubtract": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.SimpleCalculator_Subtract_Generated::Subtract" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/SimpleCalculator/Subtract", + "Method": "GET" + } + } + } + } + }, + "SimpleCalculatorMultiply": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.SimpleCalculator_Multiply_Generated::Multiply" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/SimpleCalculator/Multiply/{x}/{y}", + "Method": "GET" + } + } + } + } + }, + "SimpleCalculatorDivideAsync": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.SimpleCalculator_DivideAsync_Generated::DivideAsync" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/SimpleCalculator/DivideAsync/{x}/{y}", + "Method": "GET" + } + } + } + } + }, + "PI": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.SimpleCalculator_Pi_Generated::Pi" + ] + } + } + }, + "Random": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.SimpleCalculator_Random_Generated::Random" + ] + } + } + }, + "Randoms": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations" + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.SimpleCalculator_Randoms_Generated::Randoms" + ] + } + } + }, + "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" + ] + } + } + }, + "RestAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.CustomAuthorizerRestExample_RestAuthorizer_Generated::RestAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/rest/authorizer", + "Method": "GET" + } + } + } + } + }, + "HttpApiAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated::HttpApiAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/api/authorizer", + "Method": "GET" + } + } + } + } + } + }, + "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 From da724d0d7b1f4f67c3e446177e0b54e982c45454 Mon Sep 17 00:00:00 2001 From: PFSerra Date: Sun, 26 Mar 2023 19:02:56 +0100 Subject: [PATCH 02/10] Fixed function name on test. --- .../SourceGeneratorTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index 7a2fc35d0..79774a35c 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -539,7 +539,7 @@ public async Task CustomAuthorizerHttpApiTest() { ( typeof(SourceGenerator.Generator), - "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", + "CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs", SourceText.From(expectedRestAuthorizerGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) ) }, From cc54ceb50f65de58da1881555b06d2cef40f57f2 Mon Sep 17 00:00:00 2001 From: PFSerra Date: Thu, 30 Mar 2023 01:28:17 +0100 Subject: [PATCH 03/10] Attempt at whitespace. --- .../Templates/LambdaFunctionTemplate.cs | 138 +++++++++--------- .../Templates/LambdaFunctionTemplate.tt | 44 +++--- 2 files changed, 91 insertions(+), 91 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs index 17e1a4ac7..4f8eecc8c 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -780,7 +780,7 @@ public virtual string TransformText() // string parameter does not need to be de-serialized if (parameter.Type.IsString()) { - + #line default #line hidden @@ -798,7 +798,7 @@ public virtual string TransformText() } else { - + #line default #line hidden @@ -842,8 +842,65 @@ public virtual string TransformText() "iled to satisfy constraint: {e.Message}\");\r\n }\r\n\r\n"); #line 319 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) + { + var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; + + var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; + if(restApiAttribute != null) + { + + + + #line default + #line hidden + this.Write(" var "); + + #line 331 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__.RequestContext.Authorizer[\""); + + #line 331 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"].ToString();\r\n"); + + #line 332 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } + else + { + + + #line default + #line hidden + this.Write(" var "); + + #line 337 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__.RequestContext.Authorizer.Lambda[\""); + + #line 337 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"].ToString();\r\n"); + + #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } } else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) { @@ -857,21 +914,21 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 348 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = default("); - #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 348 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(");\r\n if (__request__.PathParameters?.ContainsKey(\""); - #line 330 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 349 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default @@ -879,28 +936,28 @@ public virtual string TransformText() this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + " "); - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = ("); - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(")Convert.ChangeType(__request__.PathParameters[\""); - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default #line hidden this.Write("\"], typeof("); - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default @@ -911,14 +968,14 @@ public virtual string TransformText() { validationErrors.Add($""Value {__request__.PathParameters["""); - #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 357 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default #line hidden this.Write("\"]} at \'"); - #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 357 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default @@ -926,65 +983,8 @@ public virtual string TransformText() this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + "\n\r\n"); - #line 342 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) - { - var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; - - var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; - if(restApiAttribute != null) - { - + #line 361 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - #line default - #line hidden - this.Write(" var "); - - #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = __request__.RequestContext.Authorizer[\""); - - #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); - - #line default - #line hidden - this.Write("\"].ToString();\r\n"); - - #line 354 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" var "); - - #line 359 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = __request__.RequestContext.Authorizer.Lambda[\""); - - #line 359 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); - - #line default - #line hidden - this.Write("\"].ToString();\r\n"); - - #line 360 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } } else { diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt index 3032c0e82..4215a5878 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt @@ -1,4 +1,4 @@ -<#@ template hostspecific="false" language="C#" #> +<#@ template language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> @@ -298,14 +298,14 @@ namespace <#= _model.LambdaMethod.ContainingNamespace #> // string parameter does not need to be de-serialized if (parameter.Type.IsString()) { -#> + #> var <#= parameter.Name #> = __request__.Body; <# } else { -#> + #> var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); try { @@ -316,8 +316,27 @@ namespace <#= _model.LambdaMethod.ContainingNamespace #> validationErrors.Add($"Value {__request__.Body} at 'body' failed to satisfy constraint: {e.Message}"); } +<# + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) + { + var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; + + var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; + if(restApiAttribute != null) + { + +#> + var <#= parameter.Name #> = __request__.RequestContext.Authorizer["<#= authKey #>"].ToString(); <# } + else + { +#> + var <#= parameter.Name #> = __request__.RequestContext.Authorizer.Lambda["<#= authKey #>"].ToString(); +<# + } } else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) { @@ -339,26 +358,7 @@ namespace <#= _model.LambdaMethod.ContainingNamespace #> } } -<# - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) - { - var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; - - var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; - if(restApiAttribute != null) - { - -#> - var <#= parameter.Name #> = __request__.RequestContext.Authorizer["<#= authKey #>"].ToString(); <# - } - else - { -#> - var <#= parameter.Name #> = __request__.RequestContext.Authorizer.Lambda["<#= authKey #>"].ToString(); -<# - } } else { From c8752a3af298a5d5b2802e46126656ed246421aa Mon Sep 17 00:00:00 2001 From: PFSerra Date: Sun, 26 Mar 2023 18:49:42 +0100 Subject: [PATCH 04/10] Added FromCustomAuthorizerAttribute and tests. --- .../Attributes/AttributeModelBuilder.cs | 9 + .../FromCustomAuthorizerAttributeBuilder.cs | 22 + .../Templates/LambdaFunctionTemplate.cs | 3479 +++++++++-------- .../Templates/LambdaFunctionTemplate.tt | 1075 ++--- .../TypeFullNames.cs | 1 + .../FromCustomAuthorizerAttribute.cs | 19 + ....Annotations.SourceGenerators.Tests.csproj | 2 + ...piExample_HttpApiAuthorizer_Generated.g.cs | 65 + ...rRestExample_RestAuthorizer_Generated.g.cs | 65 + .../authorizerHttpApi.template | 39 + .../authorizerRest.template | 39 + .../SourceGeneratorTests.cs | 84 +- .../CustomAuthorizerHttpApiExample.cs | 18 + .../CustomAuthorizerRestExample.cs | 18 + .../TestServerlessApp/serverless.template | 64 + 15 files changed, 2756 insertions(+), 2243 deletions(-) create mode 100644 Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FromCustomAuthorizerAttributeBuilder.cs create mode 100644 Libraries/src/Amazon.Lambda.Annotations/APIGateway/FromCustomAuthorizerAttribute.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template create mode 100644 Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template create mode 100644 Libraries/test/TestServerlessApp/CustomAuthorizerHttpApiExample.cs create mode 100644 Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/AttributeModelBuilder.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/AttributeModelBuilder.cs index 21419dcb8..859935d71 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/AttributeModelBuilder.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/AttributeModelBuilder.cs @@ -53,6 +53,15 @@ public static AttributeModel Build(AttributeData att, GeneratorExecutionContext Type = TypeModelBuilder.Build(att.AttributeClass, context) }; } + else if(att.AttributeClass.Equals(context.Compilation.GetTypeByMetadataName(TypeFullNames.FromCustomAuthorizerAttribute), SymbolEqualityComparer.Default)) + { + var data = FromCustomAuthorizerAttributeBuilder.Build(att); + model = new AttributeModel + { + Data = data, + Type = TypeModelBuilder.Build(att.AttributeClass, context) + }; + } else if (att.AttributeClass.Equals(context.Compilation.GetTypeByMetadataName(TypeFullNames.HttpApiAttribute), SymbolEqualityComparer.Default)) { var data = HttpApiAttributeBuilder.Build(att); diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FromCustomAuthorizerAttributeBuilder.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FromCustomAuthorizerAttributeBuilder.cs new file mode 100644 index 000000000..687e27446 --- /dev/null +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Models/Attributes/FromCustomAuthorizerAttributeBuilder.cs @@ -0,0 +1,22 @@ +using Amazon.Lambda.Annotations.APIGateway; +using Microsoft.CodeAnalysis; + +namespace Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes +{ + public class FromCustomAuthorizerAttributeBuilder + { + public static FromCustomAuthorizerAttribute Build(AttributeData att) + { + var data = new FromCustomAuthorizerAttribute(); + foreach (var pair in att.NamedArguments) + { + if (pair.Key == nameof(data.Name) && pair.Value.Value is string value) + { + data.Name = value; + } + } + + return data; + } + } +} \ 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 788385918..17e1a4ac7 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -1,1711 +1,1768 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version: 17.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 Amazon.Lambda.Annotations.SourceGenerator.Models; - using Amazon.Lambda.Annotations.SourceGenerator.Extensions; - using Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes; - using Microsoft.CodeAnalysis; - using Amazon.Lambda.Annotations.SourceGenerator.Validation; - using System; - - /// - /// 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")] - public partial class LambdaFunctionTemplate : LambdaFunctionTemplateBase - { -#line hidden - /// - /// Create the template output - /// - public virtual string TransformText() - { - - #line 11 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - foreach (var ns in _model.GeneratedMethod.Usings) - { - - - #line default - #line hidden - this.Write("using "); - - #line 15 "C:\codebase\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 default - #line hidden - this.Write("\r\nnamespace "); - - #line 20 "C:\codebase\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 "); - - #line 22 "C:\codebase\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" - - if (_model.LambdaMethod.UsingDependencyInjection) - { - - - #line default - #line hidden - this.Write(" private readonly ServiceProvider serviceProvider;\r\n"); - - #line 29 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" private readonly "); - - #line 34 "C:\codebase\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(" "); - - #line 34 "C:\codebase\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(";\r\n"); - - #line 35 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - - #line default - #line hidden - this.Write("\r\n public "); - - #line 39 "C:\codebase\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 SetExecutionEnvironment();\r\n"); - - #line 42 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - if (_model.LambdaMethod.UsingDependencyInjection) - { - - - #line default - #line hidden - this.Write(@" 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<"); - - #line 50 "C:\codebase\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 var startup = new "); - - #line 52 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 55 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" "); - - #line 60 "C:\codebase\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(" = new "); - - #line 60 "C:\codebase\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"); - - #line 61 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - - #line default - #line hidden - this.Write(" }\r\n\r\n public "); - - #line 66 "C:\codebase\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 66 "C:\codebase\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 66 "C:\codebase\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 66 "C:\codebase\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 68 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - if (_model.LambdaMethod.UsingDependencyInjection) - { - - - #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 "); - - #line 75 "C:\codebase\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 76 "C:\codebase\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 78 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - if (_model.LambdaMethod.Events.Contains(EventType.API)) - { - var parameters = string.Join(", ", _model.LambdaMethod.Parameters - .Select(p => - { - // Pass the same context parameter for ILambdaContext that comes from the generated method. - if (p.Type.FullName == TypeFullNames.ILambdaContext) - { - return "__context__"; - } - - // Pass the same request parameter for Request Type that comes from the generated method. - if (TypeFullNames.Requests.Contains(p.Type.FullName)) - { - return "__request__"; - } - - return p.Name; - })); - 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; - - if (restApiAttribute != null && httpApiAttribute != null) - { - throw new NotSupportedException($"A method cannot have both {TypeFullNames.RestApiAttribute} and {TypeFullNames.HttpApiAttribute} attribute at the same time."); - } - - var routeParameters = restApiAttribute?.Data?.GetTemplateParameters() ?? httpApiAttribute?.Data?.GetTemplateParameters() ?? new HashSet(); - - var (routeTemplateValid, missingRouteParams) = RouteParametersValidator.Validate(routeParameters, _model.LambdaMethod.Parameters); - if (!routeTemplateValid) - { - var template = restApiAttribute?.Data?.Template ?? httpApiAttribute?.Data?.Template ?? string.Empty; - throw new InvalidOperationException($"Route template {template} is invalid. Missing {string.Join(",", missingRouteParams)} parameters in method definition."); - } - - if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) - { - - - #line default - #line hidden - this.Write(" var validationErrors = new List();\r\n\r\n"); - - #line 122 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - foreach (var parameter in _model.LambdaMethod.Parameters) - { - if (parameter.Type.FullName == TypeFullNames.ILambdaContext || TypeFullNames.Requests.Contains(parameter.Type.FullName)) - { - // No action required for ILambdaContext and RequestType, they are passed from the generated method parameter directly to the original method. - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) - { - - - #line default - #line hidden - this.Write(" var "); - - #line 134 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = scope.ServiceProvider.GetRequiredService<"); - - #line 134 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(">();\r\n"); - - #line 135 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromQueryAttribute)) - { - var fromQueryAttribute = parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromQueryAttribute) as AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var parameterKey = fromQueryAttribute?.Data?.Name ?? parameter.Name; - - var queryStringParameters = "QueryStringParameters"; - - - - #line default - #line hidden - this.Write(" var "); - - #line 147 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = default("); - - #line 147 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 148 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - - if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) - { - // In HTTP API V2 multiple values for the same parameter are represented via comma separated string - // Therefore, it is required to split the string to convert to an enumerable - // and convert individual item to target data type. - var commaSplit = ""; - if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) - { - commaSplit = @".Split("","")"; - } - - // HTTP API V1 and Rest API, multiple values for the same parameter are provided - // dedicated dictionary of string key and list value. - if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) - { - queryStringParameters = "MultiValueQueryStringParameters"; - } - - if (parameter.Type.TypeArguments.Count != 1) - { - throw new NotSupportedException("Only one type argument is supported for generic types."); - } - - // Generic types are mapped using Select statement to the target parameter type argument. - var typeArgument = parameter.Type.TypeArguments.First(); - - - #line default - #line hidden - this.Write(" if (__request__."); - - #line 176 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("?.ContainsKey(\""); - - #line 176 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n "); - - #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = __request__."); - - #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("[\""); - - #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\"]"); - - #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 ("); - - #line 183 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(q, typeof("); - - #line 183 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); - - #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 '"); - - #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 194 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - // Non-generic types are mapped directly to the target parameter. - - - #line default - #line hidden - this.Write(" if (__request__."); - - #line 200 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("?.ContainsKey(\""); - - #line 200 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = ("); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(__request__."); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("[\""); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\"], typeof("); - - #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #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__."); - - #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); - - #line default - #line hidden - this.Write("[\""); - - #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); - - #line default - #line hidden - this.Write("\"]} at \'"); - - #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 212 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute)) - { - var fromHeaderAttribute = - parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute) as - AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var headerKey = fromHeaderAttribute?.Data?.Name ?? parameter.Name; - - var headers = "Headers"; - - - - #line default - #line hidden - this.Write(" var "); - - #line 228 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = default("); - - #line 228 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 229 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - - if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) - { - // In HTTP API V2 multiple values for the same header are represented via comma separated string - // Therefore, it is required to split the string to convert to an enumerable - // and convert individual item to target data type. - var commaSplit = ""; - if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) - { - commaSplit = @".Split("","")"; - } - - // HTTP API V1 and Rest API, multiple values for the same header are provided - // dedicated dictionary of string key and list value. - if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) - { - headers = "MultiValueHeaders"; - } - - if (parameter.Type.TypeArguments.Count != 1) - { - throw new NotSupportedException("Only one type argument is supported for generic types."); - } - - // Generic types are mapped using Select statement to the target parameter type argument. - var typeArgument = parameter.Type.TypeArguments.First(); - - - #line default - #line hidden - this.Write(" if (__request__."); - - #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("?.ContainsKey(\""); - - #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n "); - - #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = __request__."); - - #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("[\""); - - #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\"]"); - - #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 ("); - - #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(q, typeof("); - - #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); - - #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 '"); - - #line 268 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 275 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - // Non-generic types are mapped directly to the target parameter. - - - #line default - #line hidden - this.Write(" if (__request__."); - - #line 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("?.ContainsKey(\""); - - #line 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = ("); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(__request__."); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("[\""); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\"], typeof("); - - #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #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__."); - - #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headers)); - - #line default - #line hidden - this.Write("[\""); - - #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); - - #line default - #line hidden - this.Write("\"]} at \'"); - - #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 293 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromBodyAttribute)) - { - // string parameter does not need to be de-serialized - if (parameter.Type.IsString()) - { - - - #line default - #line hidden - this.Write(" var "); - - #line 302 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = __request__.Body;\r\n\r\n"); - - #line 304 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" var "); - - #line 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = default("); - - #line 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(");\r\n try\r\n {\r\n "); - - #line 312 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = "); - - #line 312 "C:\codebase\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(".Deserialize<"); - - #line 312 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 319 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) - { - var fromRouteAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) as AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var routeKey = fromRouteAttribute?.Data?.Name ?? parameter.Name; - - - #line default - #line hidden - this.Write(" var "); - - #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = default("); - - #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(");\r\n if (__request__.PathParameters?.ContainsKey(\""); - - #line 330 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); - - #line default - #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); - - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = ("); - - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(")Convert.ChangeType(__request__.PathParameters[\""); - - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); - - #line default - #line hidden - this.Write("\"], typeof("); - - #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #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["""); - - #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); - - #line default - #line hidden - this.Write("\"]} at \'"); - - #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 342 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - throw new NotSupportedException($"{parameter.Name} parameter of type {parameter.Type.FullName} passing is not supported."); - } - } - - if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) - { - - - #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 "); - - #line 356 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 366 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - if(_model.LambdaMethod.ReturnsIHttpResults) - { - - - #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"); - - #line 373 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" return errorResult;\r\n"); - - #line 379 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - - #line default - #line hidden - this.Write(" }\r\n\r\n"); - - #line 384 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - if (_model.LambdaMethod.ReturnsIHttpResults) - { - - - #line default - #line hidden - this.Write(" var httpResults = "); - - #line 390 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); - - #line default - #line hidden - - #line 390 "C:\codebase\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("."); - - #line 390 "C:\codebase\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 390 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n HttpResultSerializationOptions.ProtocolFormat serializationFormat" + - " = "); - - #line 391 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 = "); - - #line 392 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); - - #line 395 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (_model.LambdaMethod.ReturnsVoid) - { - - - #line default - #line hidden - this.Write(" "); - - #line 400 "C:\codebase\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("."); - - #line 400 "C:\codebase\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 400 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 401 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (_model.LambdaMethod.ReturnsVoidTask) - { - - - #line default - #line hidden - this.Write(" await "); - - #line 406 "C:\codebase\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("."); - - #line 406 "C:\codebase\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 406 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 407 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" var response = "); - - #line 412 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); - - #line default - #line hidden - - #line 412 "C:\codebase\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("."); - - #line 412 "C:\codebase\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 412 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 413 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - if (_model.GeneratedMethod.ReturnType.FullName == _model.LambdaMethod.ReturnType.FullName || _model.LambdaMethod.ReturnsIHttpResults) - { - - - #line default - #line hidden - this.Write(" return response;\r\n"); - - #line 420 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) - { - if (_model.LambdaMethod.ReturnType.IsValueType) - { - - - #line default - #line hidden - this.Write("\r\n var body = response.ToString();\r\n"); - - #line 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (_model.LambdaMethod.ReturnType.IsString()) - { - // no action - } - else - { - - - #line default - #line hidden - this.Write("\r\n var body = "); - - #line 441 "C:\codebase\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(".Serialize(response);\r\n"); - - #line 442 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - - - #line default - #line hidden - this.Write("\r\n return new "); - - #line 447 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 449 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) - { - - - #line default - #line hidden - this.Write(" Body = "); - - #line 453 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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\", "); - - #line 456 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 458 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - - - #line default - #line hidden - this.Write(" StatusCode = 200\r\n };\r\n"); - - #line 463 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - else if (_model.LambdaMethod.Events.Count == 0) - { - var parameters = string.Join(", ", _model.LambdaMethod.Parameters - .Select(p => - { - // Pass the same context parameter for ILambdaContext that comes from the generated method. - if (p.Type.FullName == TypeFullNames.ILambdaContext) - { - return "__context__"; - } - - return p.Name; - })); - - foreach (var parameter in _model.LambdaMethod.Parameters) - { - if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) - { - - - #line default - #line hidden - this.Write(" var "); - - #line 485 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - - #line default - #line hidden - this.Write(" = scope.ServiceProvider.GetRequiredService<"); - - #line 485 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); - - #line default - #line hidden - this.Write(">();\r\n"); - - #line 486 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - - if (_model.LambdaMethod.ReturnsVoid) - { - - - #line default - #line hidden - this.Write(" "); - - #line 493 "C:\codebase\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("."); - - #line 493 "C:\codebase\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 493 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 494 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else if (_model.LambdaMethod.ReturnsVoidTask) - { - - - #line default - #line hidden - this.Write(" await "); - - #line 499 "C:\codebase\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("."); - - #line 499 "C:\codebase\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 499 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 500 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - else - { - - - #line default - #line hidden - this.Write(" return "); - - #line 505 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); - - #line default - #line hidden - - #line 505 "C:\codebase\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("."); - - #line 505 "C:\codebase\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 505 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); - - #line default - #line hidden - this.Write(");\r\n"); - - #line 506 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - } - } - - - #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_"); - - #line 524 "C:\codebase\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}"); - return this.GenerationEnvironment.ToString(); - } - } - - #line default - #line hidden - #region Base class - /// - /// Base class for this transformation - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] - public class LambdaFunctionTemplateBase - { - #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 -} +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 17.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 Amazon.Lambda.Annotations.SourceGenerator.Models; + using Amazon.Lambda.Annotations.SourceGenerator.Extensions; + using Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes; + using Microsoft.CodeAnalysis; + using Amazon.Lambda.Annotations.SourceGenerator.Validation; + using System; + + /// + /// 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")] + public partial class LambdaFunctionTemplate : LambdaFunctionTemplateBase + { +#line hidden + /// + /// Create the template output + /// + public virtual string TransformText() + { + + #line 11 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + foreach (var ns in _model.GeneratedMethod.Usings) + { + + + #line default + #line hidden + this.Write("using "); + + #line 15 "C:\codebase\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 default + #line hidden + this.Write("\r\nnamespace "); + + #line 20 "C:\codebase\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 "); + + #line 22 "C:\codebase\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" + + if (_model.LambdaMethod.UsingDependencyInjection) + { + + + #line default + #line hidden + this.Write(" private readonly ServiceProvider serviceProvider;\r\n"); + + #line 29 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" private readonly "); + + #line 34 "C:\codebase\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(" "); + + #line 34 "C:\codebase\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(";\r\n"); + + #line 35 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + + #line default + #line hidden + this.Write("\r\n public "); + + #line 39 "C:\codebase\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 SetExecutionEnvironment();\r\n"); + + #line 42 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + if (_model.LambdaMethod.UsingDependencyInjection) + { + + + #line default + #line hidden + this.Write(@" 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<"); + + #line 50 "C:\codebase\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 var startup = new "); + + #line 52 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 55 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" "); + + #line 60 "C:\codebase\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(" = new "); + + #line 60 "C:\codebase\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"); + + #line 61 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + + #line default + #line hidden + this.Write(" }\r\n\r\n public "); + + #line 66 "C:\codebase\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 66 "C:\codebase\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 66 "C:\codebase\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 66 "C:\codebase\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 68 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + if (_model.LambdaMethod.UsingDependencyInjection) + { + + + #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 "); + + #line 75 "C:\codebase\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 76 "C:\codebase\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 78 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + if (_model.LambdaMethod.Events.Contains(EventType.API)) + { + var parameters = string.Join(", ", _model.LambdaMethod.Parameters + .Select(p => + { + // Pass the same context parameter for ILambdaContext that comes from the generated method. + if (p.Type.FullName == TypeFullNames.ILambdaContext) + { + return "__context__"; + } + + // Pass the same request parameter for Request Type that comes from the generated method. + if (TypeFullNames.Requests.Contains(p.Type.FullName)) + { + return "__request__"; + } + + return p.Name; + })); + 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; + + if (restApiAttribute != null && httpApiAttribute != null) + { + throw new NotSupportedException($"A method cannot have both {TypeFullNames.RestApiAttribute} and {TypeFullNames.HttpApiAttribute} attribute at the same time."); + } + + var routeParameters = restApiAttribute?.Data?.GetTemplateParameters() ?? httpApiAttribute?.Data?.GetTemplateParameters() ?? new HashSet(); + + var (routeTemplateValid, missingRouteParams) = RouteParametersValidator.Validate(routeParameters, _model.LambdaMethod.Parameters); + if (!routeTemplateValid) + { + var template = restApiAttribute?.Data?.Template ?? httpApiAttribute?.Data?.Template ?? string.Empty; + throw new InvalidOperationException($"Route template {template} is invalid. Missing {string.Join(",", missingRouteParams)} parameters in method definition."); + } + + if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) + { + + + #line default + #line hidden + this.Write(" var validationErrors = new List();\r\n\r\n"); + + #line 122 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + foreach (var parameter in _model.LambdaMethod.Parameters) + { + if (parameter.Type.FullName == TypeFullNames.ILambdaContext || TypeFullNames.Requests.Contains(parameter.Type.FullName)) + { + // No action required for ILambdaContext and RequestType, they are passed from the generated method parameter directly to the original method. + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) + { + + + #line default + #line hidden + this.Write(" var "); + + #line 134 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = scope.ServiceProvider.GetRequiredService<"); + + #line 134 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(">();\r\n"); + + #line 135 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromQueryAttribute)) + { + var fromQueryAttribute = parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromQueryAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var parameterKey = fromQueryAttribute?.Data?.Name ?? parameter.Name; + + var queryStringParameters = "QueryStringParameters"; + + + + #line default + #line hidden + this.Write(" var "); + + #line 147 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = default("); + + #line 147 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 148 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + + if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) + { + // In HTTP API V2 multiple values for the same parameter are represented via comma separated string + // Therefore, it is required to split the string to convert to an enumerable + // and convert individual item to target data type. + var commaSplit = ""; + if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) + { + commaSplit = @".Split("","")"; + } + + // HTTP API V1 and Rest API, multiple values for the same parameter are provided + // dedicated dictionary of string key and list value. + if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) + { + queryStringParameters = "MultiValueQueryStringParameters"; + } + + if (parameter.Type.TypeArguments.Count != 1) + { + throw new NotSupportedException("Only one type argument is supported for generic types."); + } + + // Generic types are mapped using Select statement to the target parameter type argument. + var typeArgument = parameter.Type.TypeArguments.First(); + + + #line default + #line hidden + this.Write(" if (__request__."); + + #line 176 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("?.ContainsKey(\""); + + #line 176 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n "); + + #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__."); + + #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("[\""); + + #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\"]"); + + #line 178 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 ("); + + #line 183 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(q, typeof("); + + #line 183 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + + #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 '"); + + #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 194 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + // Non-generic types are mapped directly to the target parameter. + + + #line default + #line hidden + this.Write(" if (__request__."); + + #line 200 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("?.ContainsKey(\""); + + #line 200 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + + " "); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = ("); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(__request__."); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("[\""); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\"], typeof("); + + #line 204 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #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__."); + + #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(queryStringParameters)); + + #line default + #line hidden + this.Write("[\""); + + #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameterKey)); + + #line default + #line hidden + this.Write("\"]} at \'"); + + #line 208 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 212 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute)) + { + var fromHeaderAttribute = + parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute) as + AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var headerKey = fromHeaderAttribute?.Data?.Name ?? parameter.Name; + + var headers = "Headers"; + + + + #line default + #line hidden + this.Write(" var "); + + #line 228 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = default("); + + #line 228 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 229 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + + if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) + { + // In HTTP API V2 multiple values for the same header are represented via comma separated string + // Therefore, it is required to split the string to convert to an enumerable + // and convert individual item to target data type. + var commaSplit = ""; + if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) + { + commaSplit = @".Split("","")"; + } + + // HTTP API V1 and Rest API, multiple values for the same header are provided + // dedicated dictionary of string key and list value. + if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) + { + headers = "MultiValueHeaders"; + } + + if (parameter.Type.TypeArguments.Count != 1) + { + throw new NotSupportedException("Only one type argument is supported for generic types."); + } + + // Generic types are mapped using Select statement to the target parameter type argument. + var typeArgument = parameter.Type.TypeArguments.First(); + + + #line default + #line hidden + this.Write(" if (__request__."); + + #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("?.ContainsKey(\""); + + #line 257 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n "); + + #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__."); + + #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("[\""); + + #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\"]"); + + #line 259 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 ("); + + #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(q, typeof("); + + #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + + #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 '"); + + #line 268 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 275 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + // Non-generic types are mapped directly to the target parameter. + + + #line default + #line hidden + this.Write(" if (__request__."); + + #line 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("?.ContainsKey(\""); + + #line 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + + " "); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = ("); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(__request__."); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("[\""); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\"], typeof("); + + #line 285 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #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__."); + + #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headers)); + + #line default + #line hidden + this.Write("[\""); + + #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); + + #line default + #line hidden + this.Write("\"]} at \'"); + + #line 289 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 293 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromBodyAttribute)) + { + // string parameter does not need to be de-serialized + if (parameter.Type.IsString()) + { + + + #line default + #line hidden + this.Write(" var "); + + #line 302 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__.Body;\r\n\r\n"); + + #line 304 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" var "); + + #line 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = default("); + + #line 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(");\r\n try\r\n {\r\n "); + + #line 312 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = "); + + #line 312 "C:\codebase\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(".Deserialize<"); + + #line 312 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 319 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) + { + var fromRouteAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var routeKey = fromRouteAttribute?.Data?.Name ?? parameter.Name; + + + #line default + #line hidden + this.Write(" var "); + + #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = default("); + + #line 329 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(");\r\n if (__request__.PathParameters?.ContainsKey(\""); + + #line 330 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + + " "); + + #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = ("); + + #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(")Convert.ChangeType(__request__.PathParameters[\""); + + #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); + + #line default + #line hidden + this.Write("\"], typeof("); + + #line 334 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #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["""); + + #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); + + #line default + #line hidden + this.Write("\"]} at \'"); + + #line 338 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 342 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) + { + var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; + + var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; + if(restApiAttribute != null) + { + + + + #line default + #line hidden + this.Write(" var "); + + #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__.RequestContext.Authorizer[\""); + + #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"].ToString();\r\n"); + + #line 354 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" var "); + + #line 359 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = __request__.RequestContext.Authorizer.Lambda[\""); + + #line 359 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"].ToString();\r\n"); + + #line 360 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + else + { + throw new NotSupportedException($"{parameter.Name} parameter of type {parameter.Type.FullName} passing is not supported."); + } + } + + if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) + { + + + #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 "); + + #line 375 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 385 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + if(_model.LambdaMethod.ReturnsIHttpResults) + { + + + #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"); + + #line 392 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" return errorResult;\r\n"); + + #line 398 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + + #line default + #line hidden + this.Write(" }\r\n\r\n"); + + #line 403 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + if (_model.LambdaMethod.ReturnsIHttpResults) + { + + + #line default + #line hidden + this.Write(" var httpResults = "); + + #line 409 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); + + #line default + #line hidden + + #line 409 "C:\codebase\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("."); + + #line 409 "C:\codebase\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 409 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n HttpResultSerializationOptions.ProtocolFormat serializationFormat" + + " = "); + + #line 410 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 = "); + + #line 411 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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"); + + #line 414 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (_model.LambdaMethod.ReturnsVoid) + { + + + #line default + #line hidden + this.Write(" "); + + #line 419 "C:\codebase\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("."); + + #line 419 "C:\codebase\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 419 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 420 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (_model.LambdaMethod.ReturnsVoidTask) + { + + + #line default + #line hidden + this.Write(" await "); + + #line 425 "C:\codebase\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("."); + + #line 425 "C:\codebase\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 425 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 426 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" var response = "); + + #line 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); + + #line default + #line hidden + + #line 431 "C:\codebase\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("."); + + #line 431 "C:\codebase\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 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 432 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + if (_model.GeneratedMethod.ReturnType.FullName == _model.LambdaMethod.ReturnType.FullName || _model.LambdaMethod.ReturnsIHttpResults) + { + + + #line default + #line hidden + this.Write(" return response;\r\n"); + + #line 439 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) + { + if (_model.LambdaMethod.ReturnType.IsValueType) + { + + + #line default + #line hidden + this.Write("\r\n var body = response.ToString();\r\n"); + + #line 450 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (_model.LambdaMethod.ReturnType.IsString()) + { + // no action + } + else + { + + + #line default + #line hidden + this.Write("\r\n var body = "); + + #line 460 "C:\codebase\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(".Serialize(response);\r\n"); + + #line 461 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + + + #line default + #line hidden + this.Write("\r\n return new "); + + #line 466 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 468 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) + { + + + #line default + #line hidden + this.Write(" Body = "); + + #line 472 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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\", "); + + #line 475 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 477 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + + + #line default + #line hidden + this.Write(" StatusCode = 200\r\n };\r\n"); + + #line 482 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + else if (_model.LambdaMethod.Events.Count == 0) + { + var parameters = string.Join(", ", _model.LambdaMethod.Parameters + .Select(p => + { + // Pass the same context parameter for ILambdaContext that comes from the generated method. + if (p.Type.FullName == TypeFullNames.ILambdaContext) + { + return "__context__"; + } + + return p.Name; + })); + + foreach (var parameter in _model.LambdaMethod.Parameters) + { + if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) + { + + + #line default + #line hidden + this.Write(" var "); + + #line 504 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); + + #line default + #line hidden + this.Write(" = scope.ServiceProvider.GetRequiredService<"); + + #line 504 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + + #line default + #line hidden + this.Write(">();\r\n"); + + #line 505 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + + if (_model.LambdaMethod.ReturnsVoid) + { + + + #line default + #line hidden + this.Write(" "); + + #line 512 "C:\codebase\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("."); + + #line 512 "C:\codebase\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 512 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 513 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else if (_model.LambdaMethod.ReturnsVoidTask) + { + + + #line default + #line hidden + this.Write(" await "); + + #line 518 "C:\codebase\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("."); + + #line 518 "C:\codebase\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 518 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 519 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" return "); + + #line 524 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); + + #line default + #line hidden + + #line 524 "C:\codebase\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("."); + + #line 524 "C:\codebase\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 524 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); + + #line default + #line hidden + this.Write(");\r\n"); + + #line 525 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + } + } + + + #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_"); + + #line 543 "C:\codebase\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}"); + return this.GenerationEnvironment.ToString(); + } + } + + #line default + #line hidden + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + public class LambdaFunctionTemplateBase + { + #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/LambdaFunctionTemplate.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt index c9502352d..3032c0e82 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt @@ -1,529 +1,548 @@ -<#@ template language="C#" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Extensions" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes" #> -<#@ import namespace="Microsoft.CodeAnalysis" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Validation" #> -<# - foreach (var ns in _model.GeneratedMethod.Usings) - { -#> -using <#= ns #>; -<# - } -#> - -namespace <#= _model.LambdaMethod.ContainingNamespace #> -{ - public class <#= _model.GeneratedMethod.ContainingType.Name #> - { -<# - if (_model.LambdaMethod.UsingDependencyInjection) - { -#> - private readonly ServiceProvider serviceProvider; -<# - } - else - { -#> - private readonly <#= _model.LambdaMethod.ContainingType.Name #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>; -<# - } -#> - - public <#= _model.GeneratedMethod.ContainingType.Name #>() - { - SetExecutionEnvironment(); -<# - if (_model.LambdaMethod.UsingDependencyInjection) - { -#> - 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<<#= _model.LambdaMethod.ContainingType.Name #>>(); - - var startup = new <#= _model.StartupType.FullName #>(); - startup.ConfigureServices(services); - serviceProvider = services.BuildServiceProvider(); -<# - } - else - { -#> - <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = new <#= _model.LambdaMethod.ContainingType.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) - { -#> - // Create a scope for every request, - // this allows creating scoped dependencies without creating a scope manually. - using var scope = serviceProvider.CreateScope(); - var <#= - _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = scope.ServiceProvider.GetRequiredService<<#= _model.LambdaMethod.ContainingType.Name #>>(); - -<# - } - - if (_model.LambdaMethod.Events.Contains(EventType.API)) - { - var parameters = string.Join(", ", _model.LambdaMethod.Parameters - .Select(p => - { - // Pass the same context parameter for ILambdaContext that comes from the generated method. - if (p.Type.FullName == TypeFullNames.ILambdaContext) - { - return "__context__"; - } - - // Pass the same request parameter for Request Type that comes from the generated method. - if (TypeFullNames.Requests.Contains(p.Type.FullName)) - { - return "__request__"; - } - - return p.Name; - })); - 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; - - if (restApiAttribute != null && httpApiAttribute != null) - { - throw new NotSupportedException($"A method cannot have both {TypeFullNames.RestApiAttribute} and {TypeFullNames.HttpApiAttribute} attribute at the same time."); - } - - var routeParameters = restApiAttribute?.Data?.GetTemplateParameters() ?? httpApiAttribute?.Data?.GetTemplateParameters() ?? new HashSet(); - - var (routeTemplateValid, missingRouteParams) = RouteParametersValidator.Validate(routeParameters, _model.LambdaMethod.Parameters); - if (!routeTemplateValid) - { - var template = restApiAttribute?.Data?.Template ?? httpApiAttribute?.Data?.Template ?? string.Empty; - throw new InvalidOperationException($"Route template {template} is invalid. Missing {string.Join(",", missingRouteParams)} parameters in method definition."); - } - - if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) - { -#> - var validationErrors = new List(); - -<# - } - - foreach (var parameter in _model.LambdaMethod.Parameters) - { - if (parameter.Type.FullName == TypeFullNames.ILambdaContext || TypeFullNames.Requests.Contains(parameter.Type.FullName)) - { - // No action required for ILambdaContext and RequestType, they are passed from the generated method parameter directly to the original method. - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) - { -#> - var <#= parameter.Name #> = scope.ServiceProvider.GetRequiredService<<#= parameter.Type.FullName #>>(); -<# - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromQueryAttribute)) - { - var fromQueryAttribute = parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromQueryAttribute) as AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var parameterKey = fromQueryAttribute?.Data?.Name ?? parameter.Name; - - var queryStringParameters = "QueryStringParameters"; - -#> - var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); -<# - - if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) - { - // In HTTP API V2 multiple values for the same parameter are represented via comma separated string - // Therefore, it is required to split the string to convert to an enumerable - // and convert individual item to target data type. - var commaSplit = ""; - if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) - { - commaSplit = @".Split("","")"; - } - - // HTTP API V1 and Rest API, multiple values for the same parameter are provided - // dedicated dictionary of string key and list value. - if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) - { - queryStringParameters = "MultiValueQueryStringParameters"; - } - - if (parameter.Type.TypeArguments.Count != 1) - { - throw new NotSupportedException("Only one type argument is supported for generic types."); - } - - // Generic types are mapped using Select statement to the target parameter type argument. - var typeArgument = parameter.Type.TypeArguments.First(); -#> - if (__request__.<#= queryStringParameters #>?.ContainsKey("<#= parameterKey #>") == true) - { - <#= parameter.Name #> = __request__.<#= queryStringParameters #>["<#= parameterKey #>"]<#= commaSplit #> - .Select(q => - { - try - { - return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {q} at '<#= parameterKey #>' failed to satisfy constraint: {e.Message}"); - return default; - } - }) - .ToList(); - } - -<# - } - else - { - // Non-generic types are mapped directly to the target parameter. -#> - if (__request__.<#= queryStringParameters #>?.ContainsKey("<#= parameterKey #>") == true) - { - try - { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= queryStringParameters #>["<#= parameterKey #>"], typeof(<#= parameter.Type.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.<#= queryStringParameters #>["<#= parameterKey #>"]} at '<#= parameterKey #>' failed to satisfy constraint: {e.Message}"); - } - } - -<# - } - - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute)) - { - var fromHeaderAttribute = - parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute) as - AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var headerKey = fromHeaderAttribute?.Data?.Name ?? parameter.Name; - - var headers = "Headers"; - -#> - var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); -<# - - if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) - { - // In HTTP API V2 multiple values for the same header are represented via comma separated string - // Therefore, it is required to split the string to convert to an enumerable - // and convert individual item to target data type. - var commaSplit = ""; - if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) - { - commaSplit = @".Split("","")"; - } - - // HTTP API V1 and Rest API, multiple values for the same header are provided - // dedicated dictionary of string key and list value. - if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) - { - headers = "MultiValueHeaders"; - } - - if (parameter.Type.TypeArguments.Count != 1) - { - throw new NotSupportedException("Only one type argument is supported for generic types."); - } - - // Generic types are mapped using Select statement to the target parameter type argument. - var typeArgument = parameter.Type.TypeArguments.First(); -#> - if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) - { - <#= parameter.Name #> = __request__.<#= headers #>["<#= headerKey #>"]<#= commaSplit #> - .Select(q => - { - try - { - return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {q} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); - return default; - } - }) - .ToList(); - } - -<# - } - else - { - // Non-generic types are mapped directly to the target parameter. -#> - if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) - { - try - { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= headers #>["<#= headerKey #>"], typeof(<#= parameter.Type.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.<#= headers #>["<#= headerKey #>"]} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); - } - } - -<# - } - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromBodyAttribute)) - { - // string parameter does not need to be de-serialized - if (parameter.Type.IsString()) - { - #> - var <#= parameter.Name #> = __request__.Body; - -<# - } - else - { - #> - var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); - try - { - <#= parameter.Name #> = <#= _model.Serializer #>.Deserialize<<#= parameter.Type.FullName #>>(__request__.Body); - } - catch (Exception e) - { - validationErrors.Add($"Value {__request__.Body} at 'body' failed to satisfy constraint: {e.Message}"); - } - -<# - } - } - else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) - { - var fromRouteAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) as AttributeModel; - - // Use parameter name as key, if Name has not specified explicitly in the attribute definition. - var routeKey = fromRouteAttribute?.Data?.Name ?? parameter.Name; -#> - var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); - if (__request__.PathParameters?.ContainsKey("<#= routeKey #>") == true) - { - try - { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.PathParameters["<#= routeKey #>"], typeof(<#= parameter.Type.FullName #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.PathParameters["<#= routeKey #>"]} at '<#= routeKey #>' failed to satisfy constraint: {e.Message}"); - } - } - -<# - } - else - { - throw new NotSupportedException($"{parameter.Name} parameter of type {parameter.Type.FullName} passing is not supported."); - } - } - - if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) - { -#> - // return 400 Bad Request if there exists a validation error - if (validationErrors.Any()) - { - var errorResult = new <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse" : "Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse" #> - { - Body = @$"{{""message"": ""{validationErrors.Count} validation error(s) detected: {string.Join(",", validationErrors)}""}}", - Headers = new Dictionary - { - {"Content-Type", "application/json"}, - {"x-amzn-ErrorType", "ValidationException"} - }, - StatusCode = 400 - }; -<# - if(_model.LambdaMethod.ReturnsIHttpResults) - { -#> - var errorStream = new System.IO.MemoryStream(); - System.Text.Json.JsonSerializer.Serialize(errorStream, errorResult); - return errorStream; -<# - } - else - { -#> - return errorResult; -<# - } -#> - } - -<# - } - - if (_model.LambdaMethod.ReturnsIHttpResults) - { -#> - var httpResults = <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); - HttpResultSerializationOptions.ProtocolFormat serializationFormat = <#= restApiAttribute != null ? "HttpResultSerializationOptions.ProtocolFormat.RestApi" : "HttpResultSerializationOptions.ProtocolFormat.HttpApi"#>; - HttpResultSerializationOptions.ProtocolVersion serializationVersion = <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "HttpResultSerializationOptions.ProtocolVersion.V1" : "HttpResultSerializationOptions.ProtocolVersion.V2"#>; - var serializationOptions = new HttpResultSerializationOptions { Format = serializationFormat, Version = serializationVersion }; - var response = httpResults.Serialize(serializationOptions); -<# - } - else if (_model.LambdaMethod.ReturnsVoid) - { -#> - <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - else if (_model.LambdaMethod.ReturnsVoidTask) - { -#> - await <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - else - { -#> - var response = <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - - if (_model.GeneratedMethod.ReturnType.FullName == _model.LambdaMethod.ReturnType.FullName || _model.LambdaMethod.ReturnsIHttpResults) - { -#> - return response; -<# - } - else - { - if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) - { - if (_model.LambdaMethod.ReturnType.IsValueType) - { -#> - - var body = response.ToString(); -<# - } - else if (_model.LambdaMethod.ReturnType.IsString()) - { - // no action - } - else - { -#> - - var body = <#= _model.Serializer #>.Serialize(response); -<# - } - } -#> - - return new <#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? _model.GeneratedMethod.ReturnType.TaskTypeArgument : _model.GeneratedMethod.ReturnType.FullName #> - { -<# - if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) - { -#> - Body = <#= _model.LambdaMethod.ReturnType.IsString() ? "response" : "body" #>, - Headers = new Dictionary - { - {"Content-Type", <#= _model.LambdaMethod.ReturnType.IsString() ? "\"text/plain\"" : "\"application/json\"" #>} - }, -<# - } -#> - StatusCode = 200 - }; -<# - } - } - else if (_model.LambdaMethod.Events.Count == 0) - { - var parameters = string.Join(", ", _model.LambdaMethod.Parameters - .Select(p => - { - // Pass the same context parameter for ILambdaContext that comes from the generated method. - if (p.Type.FullName == TypeFullNames.ILambdaContext) - { - return "__context__"; - } - - return p.Name; - })); - - foreach (var parameter in _model.LambdaMethod.Parameters) - { - if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) - { -#> - var <#= parameter.Name #> = scope.ServiceProvider.GetRequiredService<<#= parameter.Type.FullName #>>(); -<# - } - } - - if (_model.LambdaMethod.ReturnsVoid) - { -#> - <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - else if (_model.LambdaMethod.ReturnsVoidTask) - { -#> - await <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - else - { -#> - return <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); -<# - } - } -#> - } - - 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_<#= _model.SourceGeneratorVersion #>"); - - Environment.SetEnvironmentVariable(envName, envValue.ToString()); - } - } +<#@ template hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Extensions" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes" #> +<#@ import namespace="Microsoft.CodeAnalysis" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Validation" #> +<# + foreach (var ns in _model.GeneratedMethod.Usings) + { +#> +using <#= ns #>; +<# + } +#> + +namespace <#= _model.LambdaMethod.ContainingNamespace #> +{ + public class <#= _model.GeneratedMethod.ContainingType.Name #> + { +<# + if (_model.LambdaMethod.UsingDependencyInjection) + { +#> + private readonly ServiceProvider serviceProvider; +<# + } + else + { +#> + private readonly <#= _model.LambdaMethod.ContainingType.Name #> <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>; +<# + } +#> + + public <#= _model.GeneratedMethod.ContainingType.Name #>() + { + SetExecutionEnvironment(); +<# + if (_model.LambdaMethod.UsingDependencyInjection) + { +#> + 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<<#= _model.LambdaMethod.ContainingType.Name #>>(); + + var startup = new <#= _model.StartupType.FullName #>(); + startup.ConfigureServices(services); + serviceProvider = services.BuildServiceProvider(); +<# + } + else + { +#> + <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = new <#= _model.LambdaMethod.ContainingType.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) + { +#> + // Create a scope for every request, + // this allows creating scoped dependencies without creating a scope manually. + using var scope = serviceProvider.CreateScope(); + var <#= + _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = scope.ServiceProvider.GetRequiredService<<#= _model.LambdaMethod.ContainingType.Name #>>(); + +<# + } + + if (_model.LambdaMethod.Events.Contains(EventType.API)) + { + var parameters = string.Join(", ", _model.LambdaMethod.Parameters + .Select(p => + { + // Pass the same context parameter for ILambdaContext that comes from the generated method. + if (p.Type.FullName == TypeFullNames.ILambdaContext) + { + return "__context__"; + } + + // Pass the same request parameter for Request Type that comes from the generated method. + if (TypeFullNames.Requests.Contains(p.Type.FullName)) + { + return "__request__"; + } + + return p.Name; + })); + 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; + + if (restApiAttribute != null && httpApiAttribute != null) + { + throw new NotSupportedException($"A method cannot have both {TypeFullNames.RestApiAttribute} and {TypeFullNames.HttpApiAttribute} attribute at the same time."); + } + + var routeParameters = restApiAttribute?.Data?.GetTemplateParameters() ?? httpApiAttribute?.Data?.GetTemplateParameters() ?? new HashSet(); + + var (routeTemplateValid, missingRouteParams) = RouteParametersValidator.Validate(routeParameters, _model.LambdaMethod.Parameters); + if (!routeTemplateValid) + { + var template = restApiAttribute?.Data?.Template ?? httpApiAttribute?.Data?.Template ?? string.Empty; + throw new InvalidOperationException($"Route template {template} is invalid. Missing {string.Join(",", missingRouteParams)} parameters in method definition."); + } + + if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) + { +#> + var validationErrors = new List(); + +<# + } + + foreach (var parameter in _model.LambdaMethod.Parameters) + { + if (parameter.Type.FullName == TypeFullNames.ILambdaContext || TypeFullNames.Requests.Contains(parameter.Type.FullName)) + { + // No action required for ILambdaContext and RequestType, they are passed from the generated method parameter directly to the original method. + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) + { +#> + var <#= parameter.Name #> = scope.ServiceProvider.GetRequiredService<<#= parameter.Type.FullName #>>(); +<# + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromQueryAttribute)) + { + var fromQueryAttribute = parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromQueryAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var parameterKey = fromQueryAttribute?.Data?.Name ?? parameter.Name; + + var queryStringParameters = "QueryStringParameters"; + +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); +<# + + if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) + { + // In HTTP API V2 multiple values for the same parameter are represented via comma separated string + // Therefore, it is required to split the string to convert to an enumerable + // and convert individual item to target data type. + var commaSplit = ""; + if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) + { + commaSplit = @".Split("","")"; + } + + // HTTP API V1 and Rest API, multiple values for the same parameter are provided + // dedicated dictionary of string key and list value. + if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) + { + queryStringParameters = "MultiValueQueryStringParameters"; + } + + if (parameter.Type.TypeArguments.Count != 1) + { + throw new NotSupportedException("Only one type argument is supported for generic types."); + } + + // Generic types are mapped using Select statement to the target parameter type argument. + var typeArgument = parameter.Type.TypeArguments.First(); +#> + if (__request__.<#= queryStringParameters #>?.ContainsKey("<#= parameterKey #>") == true) + { + <#= parameter.Name #> = __request__.<#= queryStringParameters #>["<#= parameterKey #>"]<#= commaSplit #> + .Select(q => + { + try + { + return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {q} at '<#= parameterKey #>' failed to satisfy constraint: {e.Message}"); + return default; + } + }) + .ToList(); + } + +<# + } + else + { + // Non-generic types are mapped directly to the target parameter. +#> + if (__request__.<#= queryStringParameters #>?.ContainsKey("<#= parameterKey #>") == true) + { + try + { + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= queryStringParameters #>["<#= parameterKey #>"], typeof(<#= parameter.Type.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.<#= queryStringParameters #>["<#= parameterKey #>"]} at '<#= parameterKey #>' failed to satisfy constraint: {e.Message}"); + } + } + +<# + } + + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute)) + { + var fromHeaderAttribute = + parameter.Attributes.First(att => att.Type.FullName == TypeFullNames.FromHeaderAttribute) as + AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var headerKey = fromHeaderAttribute?.Data?.Name ?? parameter.Name; + + var headers = "Headers"; + +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); +<# + + if (parameter.Type.IsEnumerable && parameter.Type.IsGenericType) + { + // In HTTP API V2 multiple values for the same header are represented via comma separated string + // Therefore, it is required to split the string to convert to an enumerable + // and convert individual item to target data type. + var commaSplit = ""; + if (httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V2) + { + commaSplit = @".Split("","")"; + } + + // HTTP API V1 and Rest API, multiple values for the same header are provided + // dedicated dictionary of string key and list value. + if (restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1) + { + headers = "MultiValueHeaders"; + } + + if (parameter.Type.TypeArguments.Count != 1) + { + throw new NotSupportedException("Only one type argument is supported for generic types."); + } + + // Generic types are mapped using Select statement to the target parameter type argument. + var typeArgument = parameter.Type.TypeArguments.First(); +#> + if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) + { + <#= parameter.Name #> = __request__.<#= headers #>["<#= headerKey #>"]<#= commaSplit #> + .Select(q => + { + try + { + return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {q} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); + return default; + } + }) + .ToList(); + } + +<# + } + else + { + // Non-generic types are mapped directly to the target parameter. +#> + if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) + { + try + { + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= headers #>["<#= headerKey #>"], typeof(<#= parameter.Type.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.<#= headers #>["<#= headerKey #>"]} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); + } + } + +<# + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromBodyAttribute)) + { + // string parameter does not need to be de-serialized + if (parameter.Type.IsString()) + { +#> + var <#= parameter.Name #> = __request__.Body; + +<# + } + else + { +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); + try + { + <#= parameter.Name #> = <#= _model.Serializer #>.Deserialize<<#= parameter.Type.FullName #>>(__request__.Body); + } + catch (Exception e) + { + validationErrors.Add($"Value {__request__.Body} at 'body' failed to satisfy constraint: {e.Message}"); + } + +<# + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) || routeParameters.Contains(parameter.Name)) + { + var fromRouteAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromRouteAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var routeKey = fromRouteAttribute?.Data?.Name ?? parameter.Name; +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); + if (__request__.PathParameters?.ContainsKey("<#= routeKey #>") == true) + { + try + { + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.PathParameters["<#= routeKey #>"], typeof(<#= parameter.Type.FullName #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.PathParameters["<#= routeKey #>"]} at '<#= routeKey #>' failed to satisfy constraint: {e.Message}"); + } + } + +<# + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) + { + var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; + + var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; + if(restApiAttribute != null) + { + +#> + var <#= parameter.Name #> = __request__.RequestContext.Authorizer["<#= authKey #>"].ToString(); +<# + } + else + { +#> + var <#= parameter.Name #> = __request__.RequestContext.Authorizer.Lambda["<#= authKey #>"].ToString(); +<# + } + } + else + { + throw new NotSupportedException($"{parameter.Name} parameter of type {parameter.Type.FullName} passing is not supported."); + } + } + + if (_model.LambdaMethod.Parameters.HasConvertibleParameter()) + { +#> + // return 400 Bad Request if there exists a validation error + if (validationErrors.Any()) + { + var errorResult = new <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse" : "Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse" #> + { + Body = @$"{{""message"": ""{validationErrors.Count} validation error(s) detected: {string.Join(",", validationErrors)}""}}", + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "ValidationException"} + }, + StatusCode = 400 + }; +<# + if(_model.LambdaMethod.ReturnsIHttpResults) + { +#> + var errorStream = new System.IO.MemoryStream(); + System.Text.Json.JsonSerializer.Serialize(errorStream, errorResult); + return errorStream; +<# + } + else + { +#> + return errorResult; +<# + } +#> + } + +<# + } + + if (_model.LambdaMethod.ReturnsIHttpResults) + { +#> + var httpResults = <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); + HttpResultSerializationOptions.ProtocolFormat serializationFormat = <#= restApiAttribute != null ? "HttpResultSerializationOptions.ProtocolFormat.RestApi" : "HttpResultSerializationOptions.ProtocolFormat.HttpApi"#>; + HttpResultSerializationOptions.ProtocolVersion serializationVersion = <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "HttpResultSerializationOptions.ProtocolVersion.V1" : "HttpResultSerializationOptions.ProtocolVersion.V2"#>; + var serializationOptions = new HttpResultSerializationOptions { Format = serializationFormat, Version = serializationVersion }; + var response = httpResults.Serialize(serializationOptions); +<# + } + else if (_model.LambdaMethod.ReturnsVoid) + { +#> + <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + else if (_model.LambdaMethod.ReturnsVoidTask) + { +#> + await <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + else + { +#> + var response = <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + + if (_model.GeneratedMethod.ReturnType.FullName == _model.LambdaMethod.ReturnType.FullName || _model.LambdaMethod.ReturnsIHttpResults) + { +#> + return response; +<# + } + else + { + if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) + { + if (_model.LambdaMethod.ReturnType.IsValueType) + { +#> + + var body = response.ToString(); +<# + } + else if (_model.LambdaMethod.ReturnType.IsString()) + { + // no action + } + else + { +#> + + var body = <#= _model.Serializer #>.Serialize(response); +<# + } + } +#> + + return new <#= _model.LambdaMethod.ReturnsVoidOrGenericTask ? _model.GeneratedMethod.ReturnType.TaskTypeArgument : _model.GeneratedMethod.ReturnType.FullName #> + { +<# + if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) + { +#> + Body = <#= _model.LambdaMethod.ReturnType.IsString() ? "response" : "body" #>, + Headers = new Dictionary + { + {"Content-Type", <#= _model.LambdaMethod.ReturnType.IsString() ? "\"text/plain\"" : "\"application/json\"" #>} + }, +<# + } +#> + StatusCode = 200 + }; +<# + } + } + else if (_model.LambdaMethod.Events.Count == 0) + { + var parameters = string.Join(", ", _model.LambdaMethod.Parameters + .Select(p => + { + // Pass the same context parameter for ILambdaContext that comes from the generated method. + if (p.Type.FullName == TypeFullNames.ILambdaContext) + { + return "__context__"; + } + + return p.Name; + })); + + foreach (var parameter in _model.LambdaMethod.Parameters) + { + if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromServiceAttribute)) + { +#> + var <#= parameter.Name #> = scope.ServiceProvider.GetRequiredService<<#= parameter.Type.FullName #>>(); +<# + } + } + + if (_model.LambdaMethod.ReturnsVoid) + { +#> + <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + else if (_model.LambdaMethod.ReturnsVoidTask) + { +#> + await <#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + else + { +#> + return <#= _model.LambdaMethod.ReturnsGenericTask ? "await " : "" #><#= _model.LambdaMethod.ContainingType.Name.ToCamelCase() #>.<#= _model.LambdaMethod.Name #>(<#= parameters #>); +<# + } + } +#> + } + + 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_<#= _model.SourceGeneratorVersion #>"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } } \ No newline at end of file diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs index 70cd575d9..7c0084f19 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/TypeFullNames.cs @@ -31,6 +31,7 @@ public static class TypeFullNames public const string FromHeaderAttribute = "Amazon.Lambda.Annotations.APIGateway.FromHeaderAttribute"; public const string FromBodyAttribute = "Amazon.Lambda.Annotations.APIGateway.FromBodyAttribute"; public const string FromRouteAttribute = "Amazon.Lambda.Annotations.APIGateway.FromRouteAttribute"; + public const string FromCustomAuthorizerAttribute = "Amazon.Lambda.Annotations.APIGateway.FromCustomAuthorizerAttribute"; public static HashSet Requests = new HashSet { diff --git a/Libraries/src/Amazon.Lambda.Annotations/APIGateway/FromCustomAuthorizerAttribute.cs b/Libraries/src/Amazon.Lambda.Annotations/APIGateway/FromCustomAuthorizerAttribute.cs new file mode 100644 index 000000000..4bdc173e6 --- /dev/null +++ b/Libraries/src/Amazon.Lambda.Annotations/APIGateway/FromCustomAuthorizerAttribute.cs @@ -0,0 +1,19 @@ +using System; + +namespace Amazon.Lambda.Annotations.APIGateway +{ + /// + /// Maps this parameter to a custom authorizer item + /// + /// + /// Will try to get the specified key from Custom Authorizer values + /// + [AttributeUsage(AttributeTargets.Parameter)] + public class FromCustomAuthorizerAttribute : Attribute, INamedAttribute + { + /// + /// Key of the value + /// + public string Name { get; set; } + } +} 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 108b13cd7..e4f8af98d 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 @@ -58,6 +58,8 @@ + + diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs new file mode 100644 index 000000000..6c9d311f2 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated + { + private readonly CustomAuthorizerHttpApiExample customAuthorizerHttpApiExample; + + public CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated() + { + SetExecutionEnvironment(); + customAuthorizerHttpApiExample = new CustomAuthorizerHttpApiExample(); + } + + public async System.Threading.Tasks.Task HttpApiAuthorizer(Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + { + var validationErrors = new List(); + + var authorizerValue = __request__.RequestContext.Authorizer.Lambda["authKey"].ToString(); + // return 400 Bad Request if there exists a validation error + if (validationErrors.Any()) + { + var errorResult = new Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse + { + 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 customAuthorizerHttpApiExample.HttpApiAuthorizer(authorizerValue, __context__); + + return new Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse + { + 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_0.13.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs new file mode 100644 index 000000000..fd93dd9d0 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class CustomAuthorizerRestExample_RestAuthorizer_Generated + { + private readonly CustomAuthorizerRestExample customAuthorizerRestExample; + + public CustomAuthorizerRestExample_RestAuthorizer_Generated() + { + SetExecutionEnvironment(); + customAuthorizerRestExample = new CustomAuthorizerRestExample(); + } + + public async System.Threading.Tasks.Task RestAuthorizer(Amazon.Lambda.APIGatewayEvents.APIGatewayProxyRequest __request__, Amazon.Lambda.Core.ILambdaContext __context__) + { + var validationErrors = new List(); + + var authorizerValue = __request__.RequestContext.Authorizer["authKey"].ToString(); + // 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 customAuthorizerRestExample.RestAuthorizer(authorizerValue, __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_0.13.0.0"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template new file mode 100644 index 000000000..45ea454f9 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template @@ -0,0 +1,39 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.0.0).", + "Resources": { + "HttpApiAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestProject::TestServerlessApp.CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated::HttpApiAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/api/authorizer", + "Method": "GET" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template new file mode 100644 index 000000000..942e498b9 --- /dev/null +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template @@ -0,0 +1,39 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Transform": "AWS::Serverless-2016-10-31", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.0.0).", + "Resources": { + "RestAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestProject::TestServerlessApp.CustomAuthorizerRestExample_RestAuthorizer_Generated::RestAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/rest/authorizer", + "Method": "GET" + } + } + } + } + } + } +} \ 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 985377e49..c8d75ecc4 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -67,7 +67,7 @@ public async Task GeneratorDoesNotRunDueToCompileError() await new VerifyCS.Test { TestState = - { + { Sources = { (Path.Combine("TestServerlessApp", "Greeter.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "Greeter.cs"))), @@ -437,7 +437,7 @@ public async Task CustomizeResponses() new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomizeResponseExamples_NotFoundResponseWithHeaderV2_Generated.g.cs", expectedNotFoundResponseWithHeaderV2Generated), new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomizeResponseExamples_NotFoundResponseWithHeaderV2Async_Generated.g.cs", expectedNotFoundResponseWithHeaderV2AsyncGenerated), - + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomizeResponseExamples_NotFoundResponseWithHeaderV1_Generated.g.cs", expectedNotFoundResponseWithHeaderV1Generated), new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomizeResponseExamples_NotFoundResponseWithHeaderV1Async_Generated.g.cs", expectedNotFoundResponseWithHeaderV1AsyncGenerated), @@ -445,7 +445,7 @@ public async Task CustomizeResponses() }, ReferenceAssemblies = ReferenceAssemblies.Net.Net60 } - + }.RunAsync(); var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); @@ -472,7 +472,7 @@ public async Task InvalidReturnTypeIHttpResult() }, ExpectedDiagnostics = { - DiagnosticResult.CompilerError("AWSLambda0105").WithSpan($"TestServerlessApp{Path.DirectorySeparatorChar}CustomizeResponseWithErrors.cs", 14, 9, 21, 10).WithArguments("Error") + DiagnosticResult.CompilerError("AWSLambda0105").WithSpan($"TestServerlessApp{Path.DirectorySeparatorChar}CustomizeResponseWithErrors.cs", 14, 9, 21, 10).WithArguments("Error") }, ReferenceAssemblies = ReferenceAssemblies.Net.Net60 } @@ -506,5 +506,81 @@ public async Task MissingResourePathMapping() }.RunAsync(); } + + [Fact] + public async Task CustomAuthorizerRestTest() + { + var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "authorizerRest.template")).ToEnvironmentLineEndings(); + var expectedRestAuthorizerGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs")).ToEnvironmentLineEndings(); + + await new VerifyCS.Test + { + TestState = + { + Sources = + { + (Path.Combine("TestServerlessApp", "CustomAuthorizerRestExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "CustomAuthorizerRestExample.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"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", + SourceText.From(expectedRestAuthorizerGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", expectedRestAuthorizerGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent) + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }.RunAsync(); + + var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + Assert.Equal(expectedTemplateContent, actualTemplateContent); + } + + [Fact] + public async Task CustomAuthorizerHttpApiTest() + { + var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "authorizerHttpApi.template")).ToEnvironmentLineEndings(); + var expectedRestAuthorizerGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs")).ToEnvironmentLineEndings(); + + await new VerifyCS.Test + { + TestState = + { + Sources = + { + (Path.Combine("TestServerlessApp", "CustomAuthorizerHttpApiExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "CustomAuthorizerHttpApiExample.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"))), + }, + GeneratedSources = + { + ( + typeof(SourceGenerator.Generator), + "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", + SourceText.From(expectedRestAuthorizerGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) + ) + }, + ExpectedDiagnostics = + { + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs", expectedRestAuthorizerGenerated), + new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent) + }, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + } + }.RunAsync(); + + var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); + Assert.Equal(expectedTemplateContent, actualTemplateContent); + } } } \ No newline at end of file diff --git a/Libraries/test/TestServerlessApp/CustomAuthorizerHttpApiExample.cs b/Libraries/test/TestServerlessApp/CustomAuthorizerHttpApiExample.cs new file mode 100644 index 000000000..7754a189f --- /dev/null +++ b/Libraries/test/TestServerlessApp/CustomAuthorizerHttpApiExample.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class CustomAuthorizerHttpApiExample + { + [LambdaFunction(ResourceName = "HttpApiAuthorizerTest", PackageType = LambdaPackageType.Image)] + [HttpApi(LambdaHttpMethod.Get, "/api/authorizer")] + public async Task HttpApiAuthorizer([FromCustomAuthorizer(Name = "authKey")] string authorizerValue, ILambdaContext context) + { + context.Logger.LogLine(authorizerValue); + await Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs b/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs new file mode 100644 index 000000000..1086d1519 --- /dev/null +++ b/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Amazon.Lambda.Annotations; +using Amazon.Lambda.Annotations.APIGateway; +using Amazon.Lambda.Core; + +namespace TestServerlessApp +{ + public class CustomAuthorizerRestExample + { + [LambdaFunction(ResourceName = "RestAuthorizerTest", PackageType = LambdaPackageType.Image)] + [RestApi(LambdaHttpMethod.Get, "/rest/authorizer")] + public async Task RestAuthorizer([FromCustomAuthorizer(Name = "authKey")] string authorizerValue, ILambdaContext context) + { + context.Logger.LogLine(authorizerValue); + await Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Libraries/test/TestServerlessApp/serverless.template b/Libraries/test/TestServerlessApp/serverless.template index 1cdf610fe..bd426d646 100644 --- a/Libraries/test/TestServerlessApp/serverless.template +++ b/Libraries/test/TestServerlessApp/serverless.template @@ -633,6 +633,70 @@ ] } } + }, + "RestAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.CustomAuthorizerRestExample_RestAuthorizer_Generated::RestAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/rest/authorizer", + "Method": "GET" + } + } + } + } + }, + "HttpApiAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated::HttpApiAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/api/authorizer", + "Method": "GET" + } + } + } + } } }, "Outputs": { From e32534c83c95bc13e6bd85354adf764e8e5d1a9c Mon Sep 17 00:00:00 2001 From: PFSerra Date: Thu, 4 May 2023 18:46:07 +0100 Subject: [PATCH 05/10] Must Fix Tests. --- .../Templates/LambdaFunctionTemplate.cs | 118 +++++++++--------- .../SourceGeneratorTests.cs | 76 ----------- .../TestServerlessApp/serverless.template | 66 +--------- 3 files changed, 60 insertions(+), 200 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs index 77ca97050..71d2e5a74 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -983,7 +983,7 @@ public virtual string TransformText() this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + "\n\r\n"); - #line 342 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 361 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) @@ -1000,21 +1000,21 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 372 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = __request__.RequestContext.Authorizer[\""); - #line 353 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 372 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); #line default #line hidden this.Write("\"].ToString();\r\n"); - #line 354 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 373 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else @@ -1025,21 +1025,21 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 359 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 378 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = __request__.RequestContext.Authorizer.Lambda[\""); - #line 359 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 378 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); #line default #line hidden this.Write("\"].ToString();\r\n"); - #line 360 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 379 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } } @@ -1059,7 +1059,7 @@ public virtual string TransformText() " if (validationErrors.Any())\r\n {\r\n var errorResult" + " = new "); - #line 375 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 394 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 @@ -1076,7 +1076,7 @@ public virtual string TransformText() }; "); - #line 385 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 404 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" if(_model.LambdaMethod.ReturnsIHttpResults) { @@ -1088,7 +1088,7 @@ public virtual string TransformText() "System.Text.Json.JsonSerializer.Serialize(errorStream, errorResult);\r\n " + " return errorStream;\r\n"); - #line 392 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 411 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else @@ -1099,7 +1099,7 @@ public virtual string TransformText() #line hidden this.Write(" return errorResult;\r\n"); - #line 398 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 417 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } @@ -1108,7 +1108,7 @@ public virtual string TransformText() #line hidden this.Write(" }\r\n\r\n"); - #line 403 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 422 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } @@ -1120,27 +1120,27 @@ public virtual string TransformText() #line hidden this.Write(" var httpResults = "); - #line 409 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 428 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); #line default #line hidden - #line 409 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 428 "C:\codebase\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("."); - #line 409 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 428 "C:\codebase\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 409 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 428 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); #line default @@ -1148,7 +1148,7 @@ public virtual string TransformText() this.Write(");\r\n HttpResultSerializationOptions.ProtocolFormat serializationFormat" + " = "); - #line 410 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 429 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(restApiAttribute != null ? "HttpResultSerializationOptions.ProtocolFormat.RestApi" : "HttpResultSerializationOptions.ProtocolFormat.HttpApi")); #line default @@ -1156,7 +1156,7 @@ public virtual string TransformText() this.Write(";\r\n HttpResultSerializationOptions.ProtocolVersion serializationVersio" + "n = "); - #line 411 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 430 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 @@ -1165,7 +1165,7 @@ public virtual string TransformText() "rmat = serializationFormat, Version = serializationVersion };\r\n var r" + "esponse = httpResults.Serialize(serializationOptions);\r\n"); - #line 414 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 433 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else if (_model.LambdaMethod.ReturnsVoid) @@ -1176,28 +1176,28 @@ public virtual string TransformText() #line hidden this.Write(" "); - #line 419 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 438 "C:\codebase\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("."); - #line 419 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 438 "C:\codebase\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 419 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 438 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); #line default #line hidden this.Write(");\r\n"); - #line 420 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 439 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else if (_model.LambdaMethod.ReturnsVoidTask) @@ -1208,28 +1208,28 @@ public virtual string TransformText() #line hidden this.Write(" await "); - #line 425 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 444 "C:\codebase\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("."); - #line 425 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 444 "C:\codebase\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 425 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 444 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); #line default #line hidden this.Write(");\r\n"); - #line 426 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 445 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else @@ -1240,34 +1240,34 @@ public virtual string TransformText() #line hidden this.Write(" var response = "); - #line 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 450 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); #line default #line hidden - #line 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 450 "C:\codebase\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("."); - #line 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 450 "C:\codebase\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 431 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 450 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); #line default #line hidden this.Write(");\r\n"); - #line 432 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 451 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } @@ -1279,7 +1279,7 @@ public virtual string TransformText() #line hidden this.Write(" return response;\r\n"); - #line 439 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 458 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else @@ -1294,7 +1294,7 @@ public virtual string TransformText() #line hidden this.Write("\r\n var body = response.ToString();\r\n"); - #line 450 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 469 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else if (_model.LambdaMethod.ReturnType.IsString()) @@ -1309,14 +1309,14 @@ public virtual string TransformText() #line hidden this.Write("\r\n var body = "); - #line 460 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 479 "C:\codebase\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(".Serialize(response);\r\n"); - #line 461 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 480 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } } @@ -1326,14 +1326,14 @@ public virtual string TransformText() #line hidden this.Write("\r\n return new "); - #line 466 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 485 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 468 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 487 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" if (!_model.LambdaMethod.ReturnsVoid && !_model.LambdaMethod.ReturnsVoidTask) { @@ -1343,7 +1343,7 @@ public virtual string TransformText() #line hidden this.Write(" Body = "); - #line 472 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 491 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnType.IsString() ? "response" : "body")); #line default @@ -1351,14 +1351,14 @@ public virtual string TransformText() this.Write(",\r\n Headers = new Dictionary\r\n {\r\n " + " {\"Content-Type\", "); - #line 475 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 494 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.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 477 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 496 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } @@ -1367,7 +1367,7 @@ public virtual string TransformText() #line hidden this.Write(" StatusCode = 200\r\n };\r\n"); - #line 482 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 501 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } } @@ -1395,21 +1395,21 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 504 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 523 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); #line default #line hidden this.Write(" = scope.ServiceProvider.GetRequiredService<"); - #line 504 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 523 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden this.Write(">();\r\n"); - #line 505 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 524 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } } @@ -1422,28 +1422,28 @@ public virtual string TransformText() #line hidden this.Write(" "); - #line 512 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 531 "C:\codebase\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("."); - #line 512 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 531 "C:\codebase\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 512 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 531 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); #line default #line hidden this.Write(");\r\n"); - #line 513 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 532 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else if (_model.LambdaMethod.ReturnsVoidTask) @@ -1454,28 +1454,28 @@ public virtual string TransformText() #line hidden this.Write(" await "); - #line 518 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 537 "C:\codebase\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("."); - #line 518 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 537 "C:\codebase\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 518 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 537 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); #line default #line hidden this.Write(");\r\n"); - #line 519 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 538 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } else @@ -1486,34 +1486,34 @@ public virtual string TransformText() #line hidden this.Write(" return "); - #line 524 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 543 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(_model.LambdaMethod.ReturnsGenericTask ? "await " : "")); #line default #line hidden - #line 524 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 543 "C:\codebase\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("."); - #line 524 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 543 "C:\codebase\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 524 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 543 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameters)); #line default #line hidden this.Write(");\r\n"); - #line 525 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 544 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" } } @@ -1537,7 +1537,7 @@ private static void SetExecutionEnvironment() envValue.Append(""amazon-lambda-annotations_"); - #line 543 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + #line 562 "C:\codebase\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/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index c3e371547..c8d75ecc4 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -582,81 +582,5 @@ public async Task CustomAuthorizerHttpApiTest() var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); Assert.Equal(expectedTemplateContent, actualTemplateContent); } - - [Fact] - public async Task CustomAuthorizerRestTest() - { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "authorizerRest.template")).ToEnvironmentLineEndings(); - var expectedRestAuthorizerGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs")).ToEnvironmentLineEndings(); - - await new VerifyCS.Test - { - TestState = - { - Sources = - { - (Path.Combine("TestServerlessApp", "CustomAuthorizerRestExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "CustomAuthorizerRestExample.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"))), - }, - GeneratedSources = - { - ( - typeof(SourceGenerator.Generator), - "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", - SourceText.From(expectedRestAuthorizerGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) - ) - }, - ExpectedDiagnostics = - { - new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", expectedRestAuthorizerGenerated), - new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent) - }, - ReferenceAssemblies = ReferenceAssemblies.Net.Net60 - } - }.RunAsync(); - - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); - Assert.Equal(expectedTemplateContent, actualTemplateContent); - } - - [Fact] - public async Task CustomAuthorizerHttpApiTest() - { - var expectedTemplateContent = File.ReadAllText(Path.Combine("Snapshots", "ServerlessTemplates", "authorizerHttpApi.template")).ToEnvironmentLineEndings(); - var expectedRestAuthorizerGenerated = File.ReadAllText(Path.Combine("Snapshots", "CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs")).ToEnvironmentLineEndings(); - - await new VerifyCS.Test - { - TestState = - { - Sources = - { - (Path.Combine("TestServerlessApp", "CustomAuthorizerHttpApiExample.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "CustomAuthorizerHttpApiExample.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"))), - }, - GeneratedSources = - { - ( - typeof(SourceGenerator.Generator), - "CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs", - SourceText.From(expectedRestAuthorizerGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) - ) - }, - ExpectedDiagnostics = - { - new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments("CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs", expectedRestAuthorizerGenerated), - new DiagnosticResult("AWSLambda0103", DiagnosticSeverity.Info).WithArguments($"TestServerlessApp{Path.DirectorySeparatorChar}serverless.template", expectedTemplateContent) - }, - ReferenceAssemblies = ReferenceAssemblies.Net.Net60 - } - }.RunAsync(); - - var actualTemplateContent = File.ReadAllText(Path.Combine("TestServerlessApp", "serverless.template")); - Assert.Equal(expectedTemplateContent, actualTemplateContent); - } } } \ No newline at end of file diff --git a/Libraries/test/TestServerlessApp/serverless.template b/Libraries/test/TestServerlessApp/serverless.template index e9b733da8..679796131 100644 --- a/Libraries/test/TestServerlessApp/serverless.template +++ b/Libraries/test/TestServerlessApp/serverless.template @@ -1,7 +1,7 @@ { "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::Serverless-2016-10-31", - "Description": "An AWS Serverless Application. This template is partially managed by Amazon.Lambda.Annotations (v0.13.2.0).", + "Description": "An AWS Serverless Application. This template is partially managed by Amazon.Lambda.Annotations (v0.13.0.0).", "Parameters": { "ArchitectureTypeParameter": { "Type": "String", @@ -666,70 +666,6 @@ } } }, - "HttpApiAuthorizerTest": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations", - "SyncedEvents": [ - "RootGet" - ] - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated::HttpApiAuthorizer" - ] - }, - "Events": { - "RootGet": { - "Type": "HttpApi", - "Properties": { - "Path": "/api/authorizer", - "Method": "GET" - } - } - } - } - }, - "RestAuthorizerTest": { - "Type": "AWS::Serverless::Function", - "Metadata": { - "Tool": "Amazon.Lambda.Annotations", - "SyncedEvents": [ - "RootGet" - ] - }, - "Properties": { - "MemorySize": 256, - "Timeout": 30, - "Policies": [ - "AWSLambdaBasicExecutionRole" - ], - "PackageType": "Image", - "ImageUri": ".", - "ImageConfig": { - "Command": [ - "TestServerlessApp::TestServerlessApp.CustomAuthorizerRestExample_RestAuthorizer_Generated::RestAuthorizer" - ] - }, - "Events": { - "RootGet": { - "Type": "Api", - "Properties": { - "Path": "/rest/authorizer", - "Method": "GET" - } - } - } - } - }, "HttpApiAuthorizerTest": { "Type": "AWS::Serverless::Function", "Metadata": { From ec38c1a1c1654d95888bd920412367d4fa8dcef4 Mon Sep 17 00:00:00 2001 From: PFSerra Date: Thu, 11 May 2023 21:52:56 +0100 Subject: [PATCH 06/10] Readded FromCustomAuthorizer --- .../Templates/APIGatewaySetupParameters.cs | 207 ++++++++++++++++-- .../Templates/APIGatewaySetupParameters.tt | 51 +++++ ...piExample_HttpApiAuthorizer_Generated.g.cs | 20 +- ...rRestExample_RestAuthorizer_Generated.g.cs | 20 +- .../authorizerHttpApi.template | 2 +- .../authorizerRest.template | 2 +- .../SourceGeneratorTests.cs | 4 +- .../TestServerlessApp/serverless.template | 64 ++++++ 8 files changed, 348 insertions(+), 22 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs index f00263815..fc119dce4 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs @@ -631,6 +631,183 @@ public virtual string TransformText() "iled 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" + + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) + { + var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; + if(restApiAttribute != null) + { + + + #line default + #line hidden + this.Write(" var "); + + #line 259 "C:\codebase\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 259 "C:\codebase\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(@"); + if (__request__.RequestContext?.Authorizer == null) + { + validationErrors.Add(""Could not find Authorizer data for request""); + } + else if (__request__.RequestContext?.Authorizer.ContainsKey("""); + + #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + + " "); + + #line 268 "C:\codebase\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 268 "C:\codebase\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__.RequestContext.Authorizer[\""); + + #line 268 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"], typeof("); + + #line 268 "C:\codebase\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__.RequestContext.Authorizer["""); + + #line 272 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"]} at \'"); + + #line 272 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + + "\n\r\n"); + + #line 276 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + + } + else + { + + + #line default + #line hidden + this.Write(" var "); + + #line 281 "C:\codebase\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 281 "C:\codebase\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(@"); + if (__request__.RequestContext?.Authorizer?.Lambda == null) + { + validationErrors.Add(""Could not find Lambda Authorizer data for request""); + } + else if (__request__.RequestContext?.Authorizer?.Lambda?.ContainsKey("""); + + #line 286 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + + " "); + + #line 290 "C:\codebase\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 290 "C:\codebase\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__.RequestContext.Authorizer.Lambda[\""); + + #line 290 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"], typeof("); + + #line 290 "C:\codebase\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__.RequestContext.Authorizer.Lambda["""); + + #line 294 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\"]} at \'"); + + #line 294 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + + #line default + #line hidden + this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + + "\n\r\n"); + + #line 298 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } } @@ -646,21 +823,21 @@ 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 308 "C:\codebase\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 308 "C:\codebase\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 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default @@ -668,28 +845,28 @@ public virtual string TransformText() 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 313 "C:\codebase\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 313 "C:\codebase\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 313 "C:\codebase\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 313 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); #line default @@ -700,14 +877,14 @@ public virtual string TransformText() { validationErrors.Add($""Value {__request__.PathParameters["""); - #line 266 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 317 "C:\codebase\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 \'"); - #line 266 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 317 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default @@ -715,7 +892,7 @@ public virtual string TransformText() 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 321 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -734,7 +911,7 @@ public virtual string TransformText() " 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 335 "C:\codebase\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 @@ -751,7 +928,7 @@ public virtual string TransformText() }; "); - #line 294 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 345 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" if(_model.LambdaMethod.ReturnsIHttpResults) { @@ -763,7 +940,7 @@ public virtual string TransformText() "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 352 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -774,7 +951,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 358 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } @@ -783,7 +960,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 363 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt index 321a3fc46..050406899 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt @@ -244,6 +244,57 @@ validationErrors.Add($"Value {__request__.Body} at 'body' failed to satisfy constraint: {e.Message}"); } +<# + } + } + else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) + { + var fromAuthorizerAttribute = parameter.Attributes?.FirstOrDefault(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute) as AttributeModel; + + // Use parameter name as key, if Name has not specified explicitly in the attribute definition. + var authKey = fromAuthorizerAttribute?.Data?.Name ?? parameter.Name; + if(restApiAttribute != null) + { +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); + if (__request__.RequestContext?.Authorizer == null) + { + validationErrors.Add("Could not find Authorizer data for request"); + } + else if (__request__.RequestContext?.Authorizer.ContainsKey("<#= authKey #>") == true) + { + try + { + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.RequestContext.Authorizer["<#= authKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.RequestContext.Authorizer["<#= authKey #>"]} at '<#= authKey #>' failed to satisfy constraint: {e.Message}"); + } + } + +<# + } + else + { +#> + var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); + if (__request__.RequestContext?.Authorizer?.Lambda == null) + { + validationErrors.Add("Could not find Lambda Authorizer data for request"); + } + else if (__request__.RequestContext?.Authorizer?.Lambda?.ContainsKey("<#= authKey #>") == true) + { + try + { + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.RequestContext.Authorizer.Lambda["<#= authKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.RequestContext.Authorizer.Lambda["<#= authKey #>"]} at '<#= authKey #>' failed to satisfy constraint: {e.Message}"); + } + } + <# } } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs index 6c9d311f2..3da38f910 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs @@ -20,7 +20,23 @@ public CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated() { var validationErrors = new List(); - var authorizerValue = __request__.RequestContext.Authorizer.Lambda["authKey"].ToString(); + var authorizerValue = default(string); + if (__request__.RequestContext?.Authorizer?.Lambda == null) + { + validationErrors.Add("Could not find Lambda Authorizer data for request"); + } + else if (__request__.RequestContext?.Authorizer?.Lambda?.ContainsKey("authKey") == true) + { + try + { + authorizerValue = (string)Convert.ChangeType(__request__.RequestContext.Authorizer.Lambda["authKey"], typeof(string)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.RequestContext.Authorizer.Lambda["authKey"]} at 'authKey' failed to satisfy constraint: {e.Message}"); + } + } + // return 400 Bad Request if there exists a validation error if (validationErrors.Any()) { @@ -57,7 +73,7 @@ private static void SetExecutionEnvironment() envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); } - envValue.Append("amazon-lambda-annotations_0.13.0.0"); + envValue.Append("amazon-lambda-annotations_0.13.3.0"); Environment.SetEnvironmentVariable(envName, envValue.ToString()); } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs index fd93dd9d0..ff35d5cea 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs @@ -20,7 +20,23 @@ public CustomAuthorizerRestExample_RestAuthorizer_Generated() { var validationErrors = new List(); - var authorizerValue = __request__.RequestContext.Authorizer["authKey"].ToString(); + var authorizerValue = default(string); + if (__request__.RequestContext?.Authorizer == null) + { + validationErrors.Add("Could not find Authorizer data for request"); + } + else if (__request__.RequestContext?.Authorizer.ContainsKey("authKey") == true) + { + try + { + authorizerValue = (string)Convert.ChangeType(__request__.RequestContext.Authorizer["authKey"], typeof(string)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + validationErrors.Add($"Value {__request__.RequestContext.Authorizer["authKey"]} at 'authKey' failed to satisfy constraint: {e.Message}"); + } + } + // return 400 Bad Request if there exists a validation error if (validationErrors.Any()) { @@ -57,7 +73,7 @@ private static void SetExecutionEnvironment() envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); } - envValue.Append("amazon-lambda-annotations_0.13.0.0"); + envValue.Append("amazon-lambda-annotations_0.13.3.0"); Environment.SetEnvironmentVariable(envName, envValue.ToString()); } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template index 45ea454f9..8721fa327 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template @@ -1,7 +1,7 @@ { "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::Serverless-2016-10-31", - "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.0.0).", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.3.0).", "Resources": { "HttpApiAuthorizerTest": { "Type": "AWS::Serverless::Function", diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template index 942e498b9..a34a4897a 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template @@ -1,7 +1,7 @@ { "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::Serverless-2016-10-31", - "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.0.0).", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.3.0).", "Resources": { "RestAuthorizerTest": { "Type": "AWS::Serverless::Function", diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs index 4e64012bf..d75333900 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs @@ -534,6 +534,7 @@ public async Task CustomAuthorizerRestTest() (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("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))), }, GeneratedSources = { @@ -572,12 +573,13 @@ public async Task CustomAuthorizerHttpApiTest() (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"))), }, GeneratedSources = { ( typeof(SourceGenerator.Generator), - "CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs", + "CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs", SourceText.From(expectedRestAuthorizerGenerated, Encoding.UTF8, SourceHashAlgorithm.Sha256) ) }, diff --git a/Libraries/test/TestServerlessApp/serverless.template b/Libraries/test/TestServerlessApp/serverless.template index a69faed3c..fdc3a39b9 100644 --- a/Libraries/test/TestServerlessApp/serverless.template +++ b/Libraries/test/TestServerlessApp/serverless.template @@ -718,6 +718,70 @@ ] } } + }, + "HttpApiAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated::HttpApiAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/api/authorizer", + "Method": "GET" + } + } + } + } + }, + "RestAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.CustomAuthorizerRestExample_RestAuthorizer_Generated::RestAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/rest/authorizer", + "Method": "GET" + } + } + } + } } }, "Outputs": { From 2876deb890466fc12eaaa4b11bdb5a05f1f443a3 Mon Sep 17 00:00:00 2001 From: Norm Johanson Date: Mon, 1 May 2023 16:47:48 -0700 Subject: [PATCH 07/10] Refactor the monolithic LambdaFunctionTemplate.tt into separate tt files per section being generated. --- .../Templates/APIGatewaySetupParameters.cs | 35 +++++++++---------- .../Templates/APIGatewaySetupParameters.tt | 20 +++++------ 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs index fc119dce4..e9b4c63c9 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs @@ -226,7 +226,7 @@ public virtual string TransformText() this.Write(")Convert.ChangeType(q, typeof("); #line 111 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullNameWithoutAnnotations)); + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); #line default #line hidden @@ -301,7 +301,7 @@ public virtual string TransformText() this.Write("\"], typeof("); #line 132 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden @@ -407,15 +407,14 @@ public virtual string TransformText() #line default #line hidden - this.Write("?.Any(x => string.Equals(x.Key, \""); + this.Write("?.ContainsKey(\""); #line 185 "C:\codebase\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("\") == true)\r\n {\r\n "); #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); @@ -429,14 +428,14 @@ public virtual string TransformText() #line default #line hidden - this.Write(".First(x => string.Equals(x.Key, \""); + this.Write("[\""); #line 187 "C:\codebase\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"); + this.Write("\"]"); #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(commaSplit)); @@ -454,7 +453,7 @@ public virtual string TransformText() this.Write(")Convert.ChangeType(q, typeof("); #line 192 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullNameWithoutAnnotations)); + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); #line default #line hidden @@ -490,15 +489,15 @@ public virtual string TransformText() #line default #line hidden - this.Write("?.Any(x => string.Equals(x.Key, \""); + this.Write("?.ContainsKey(\""); #line 209 "C:\codebase\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("\") == 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" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); @@ -519,17 +518,17 @@ public virtual string TransformText() #line default #line hidden - this.Write(".First(x => string.Equals(x.Key, \""); + this.Write("[\""); #line 213 "C:\codebase\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("); + this.Write("\"], typeof("); #line 213 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden @@ -543,14 +542,14 @@ public virtual string TransformText() #line default #line hidden - this.Write(".First(x => string.Equals(x.Key, \""); + this.Write("[\""); #line 217 "C:\codebase\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("\"]} at \'"); #line 217 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); @@ -631,7 +630,7 @@ public virtual string TransformText() "iled 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" - + } } else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) @@ -867,7 +866,7 @@ public virtual string TransformText() this.Write("\"], typeof("); #line 313 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); #line default #line hidden diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt index 050406899..ed3b82006 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt @@ -108,7 +108,7 @@ { try { - return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullNameWithoutAnnotations #>)); + return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { @@ -129,7 +129,7 @@ { try { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= queryStringParameters #>["<#= parameterKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= queryStringParameters #>["<#= parameterKey #>"], typeof(<#= parameter.Type.FullName #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { @@ -182,14 +182,14 @@ // Generic types are mapped using Select statement to the target parameter type argument. var typeArgument = parameter.Type.TypeArguments.First(); #> - if (__request__.<#= headers #>?.Any(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)) == true) + if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) { - <#= parameter.Name #> = __request__.<#= headers #>.First(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)).Value<#= commaSplit #> + <#= parameter.Name #> = __request__.<#= headers #>["<#= headerKey #>"]<#= commaSplit #> .Select(q => { try { - return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullNameWithoutAnnotations #>)); + return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { @@ -206,15 +206,15 @@ { // Non-generic types are mapped directly to the target parameter. #> - if (__request__.<#= headers #>?.Any(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)) == true) + if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) { try { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= headers #>.First(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)).Value, typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= headers #>["<#= headerKey #>"], typeof(<#= parameter.Type.FullName #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { - validationErrors.Add($"Value {__request__.<#= headers #>.First(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)).Value} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); + validationErrors.Add($"Value {__request__.<#= headers #>["<#= headerKey #>"]} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); } } @@ -244,7 +244,7 @@ validationErrors.Add($"Value {__request__.Body} at 'body' failed to satisfy constraint: {e.Message}"); } -<# +<# } } else if (parameter.Attributes.Any(att => att.Type.FullName == TypeFullNames.FromCustomAuthorizerAttribute)) @@ -310,7 +310,7 @@ { try { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.PathParameters["<#= routeKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.PathParameters["<#= routeKey #>"], typeof(<#= parameter.Type.FullName #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { From 14798bc34080047052e00b2d58e4567da62e37a9 Mon Sep 17 00:00:00 2001 From: PFSerra Date: Thu, 11 May 2023 22:44:56 +0100 Subject: [PATCH 08/10] Update. --- .../Templates/APIGatewaySetupParameters.cs | 33 ++++++++++--------- .../Templates/APIGatewaySetupParameters.tt | 18 +++++----- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs index e9b4c63c9..2867e6da2 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs @@ -226,7 +226,7 @@ public virtual string TransformText() this.Write(")Convert.ChangeType(q, typeof("); #line 111 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullNameWithoutAnnotations)); #line default #line hidden @@ -301,7 +301,7 @@ public virtual string TransformText() this.Write("\"], typeof("); #line 132 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); #line default #line hidden @@ -407,14 +407,15 @@ public virtual string TransformText() #line default #line hidden - this.Write("?.ContainsKey(\""); + this.Write("?.Any(x => string.Equals(x.Key, \""); #line 185 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\") == 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" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); @@ -428,14 +429,14 @@ public virtual string TransformText() #line default #line hidden - this.Write("[\""); + this.Write(".First(x => string.Equals(x.Key, \""); #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\"]"); + this.Write("\", StringComparison.OrdinalIgnoreCase)).Value"); #line 187 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(commaSplit)); @@ -453,7 +454,7 @@ public virtual string TransformText() this.Write(")Convert.ChangeType(q, typeof("); #line 192 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullName)); + this.Write(this.ToStringHelper.ToStringWithCulture(typeArgument.FullNameWithoutAnnotations)); #line default #line hidden @@ -489,15 +490,15 @@ public virtual string TransformText() #line default #line hidden - this.Write("?.ContainsKey(\""); + this.Write("?.Any(x => string.Equals(x.Key, \""); #line 209 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\") == 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" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); @@ -518,17 +519,17 @@ public virtual string TransformText() #line default #line hidden - this.Write("[\""); + this.Write(".First(x => string.Equals(x.Key, \""); #line 213 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\"], typeof("); + this.Write("\", StringComparison.OrdinalIgnoreCase)).Value, typeof("); #line 213 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); #line default #line hidden @@ -542,14 +543,14 @@ public virtual string TransformText() #line default #line hidden - this.Write("[\""); + this.Write(".First(x => string.Equals(x.Key, \""); #line 217 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); #line default #line hidden - this.Write("\"]} at \'"); + this.Write("\", StringComparison.OrdinalIgnoreCase)).Value} at \'"); #line 217 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(headerKey)); @@ -866,7 +867,7 @@ public virtual string TransformText() this.Write("\"], typeof("); #line 313 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullName)); + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); #line default #line hidden diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt index ed3b82006..11d62bad0 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt @@ -108,7 +108,7 @@ { try { - return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); + return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullNameWithoutAnnotations #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { @@ -129,7 +129,7 @@ { try { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= queryStringParameters #>["<#= parameterKey #>"], typeof(<#= parameter.Type.FullName #>)); + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= queryStringParameters #>["<#= parameterKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { @@ -182,14 +182,14 @@ // Generic types are mapped using Select statement to the target parameter type argument. var typeArgument = parameter.Type.TypeArguments.First(); #> - if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) + if (__request__.<#= headers #>?.Any(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)) == true) { - <#= parameter.Name #> = __request__.<#= headers #>["<#= headerKey #>"]<#= commaSplit #> + <#= parameter.Name #> = __request__.<#= headers #>.First(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)).Value<#= commaSplit #> .Select(q => { try { - return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullName #>)); + return (<#= typeArgument.FullName #>)Convert.ChangeType(q, typeof(<#= typeArgument.FullNameWithoutAnnotations #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { @@ -206,15 +206,15 @@ { // Non-generic types are mapped directly to the target parameter. #> - if (__request__.<#= headers #>?.ContainsKey("<#= headerKey #>") == true) + if (__request__.<#= headers #>?.Any(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)) == true) { try { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= headers #>["<#= headerKey #>"], typeof(<#= parameter.Type.FullName #>)); + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.<#= headers #>.First(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)).Value, typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { - validationErrors.Add($"Value {__request__.<#= headers #>["<#= headerKey #>"]} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); + validationErrors.Add($"Value {__request__.<#= headers #>.First(x => string.Equals(x.Key, "<#= headerKey #>", StringComparison.OrdinalIgnoreCase)).Value} at '<#= headerKey #>' failed to satisfy constraint: {e.Message}"); } } @@ -310,7 +310,7 @@ { try { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.PathParameters["<#= routeKey #>"], typeof(<#= parameter.Type.FullName #>)); + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.PathParameters["<#= routeKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); } catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) { From e78a457558e8afa50f3a84c00095ce7f81c3c17a Mon Sep 17 00:00:00 2001 From: PFSerra Date: Thu, 11 May 2023 23:01:29 +0100 Subject: [PATCH 09/10] revert files. --- .../Templates/LambdaFunctionTemplate.cs | 916 +++++++++--------- .../Templates/LambdaFunctionTemplate.tt | 146 +-- 2 files changed, 531 insertions(+), 531 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs index b1af6546e..26fe0b02f 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.cs @@ -1,458 +1,458 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version: 17.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 Amazon.Lambda.Annotations.SourceGenerator.Models; - using Amazon.Lambda.Annotations.SourceGenerator.Extensions; - using Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes; - using Microsoft.CodeAnalysis; - using Amazon.Lambda.Annotations.SourceGenerator.Validation; - using System; - - /// - /// 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")] - public partial class LambdaFunctionTemplate : LambdaFunctionTemplateBase - { -#line hidden - /// - /// Create the template output - /// - public virtual string TransformText() - { - - #line 11 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" - - foreach (var ns in _model.GeneratedMethod.Usings) - { - - - #line default - #line hidden - this.Write("using "); - - #line 15 "C:\codebase\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 default - #line hidden - this.Write("\r\nnamespace "); - - #line 20 "C:\codebase\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 "); - - #line 22 "C:\codebase\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" - -this.Write(new FieldsAndConstructor(_model).TransformText()); - - - #line default - #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" - 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" - 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" - 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" - 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" - - if (_model.LambdaMethod.UsingDependencyInjection) - { - - - #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 "); - - #line 38 "C:\codebase\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" - 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" - - } - - if (_model.LambdaMethod.Events.Contains(EventType.API)) - { - var apiParameters = new APIGatewaySetupParameters(_model); - this.Write(apiParameters.TransformText()); - this.Write(new APIGatewayInvoke(_model, apiParameters.ParameterSignature).TransformText()); - } - else if (_model.LambdaMethod.Events.Count == 0) - { - this.Write(new NoEventMethodBody(_model).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_"); - - #line 69 "C:\codebase\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}"); - return this.GenerationEnvironment.ToString(); - } - } - - #line default - #line hidden - #region Base class - /// - /// Base class for this transformation - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] - public class LambdaFunctionTemplateBase - { - #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 -} +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version: 17.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 Amazon.Lambda.Annotations.SourceGenerator.Models; + using Amazon.Lambda.Annotations.SourceGenerator.Extensions; + using Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes; + using Microsoft.CodeAnalysis; + using Amazon.Lambda.Annotations.SourceGenerator.Validation; + using System; + + /// + /// 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")] + public partial class LambdaFunctionTemplate : LambdaFunctionTemplateBase + { +#line hidden + /// + /// Create the template output + /// + public virtual string TransformText() + { + + #line 11 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\LambdaFunctionTemplate.tt" + + foreach (var ns in _model.GeneratedMethod.Usings) + { + + + #line default + #line hidden + this.Write("using "); + + #line 15 "C:\codebase\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 default + #line hidden + this.Write("\r\nnamespace "); + + #line 20 "C:\codebase\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 "); + + #line 22 "C:\codebase\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" + +this.Write(new FieldsAndConstructor(_model).TransformText()); + + + #line default + #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" + 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" + 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" + 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" + 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" + + if (_model.LambdaMethod.UsingDependencyInjection) + { + + + #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 "); + + #line 38 "C:\codebase\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" + 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" + + } + + if (_model.LambdaMethod.Events.Contains(EventType.API)) + { + var apiParameters = new APIGatewaySetupParameters(_model); + this.Write(apiParameters.TransformText()); + this.Write(new APIGatewayInvoke(_model, apiParameters.ParameterSignature).TransformText()); + } + else if (_model.LambdaMethod.Events.Count == 0) + { + this.Write(new NoEventMethodBody(_model).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_"); + + #line 69 "C:\codebase\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}"); + return this.GenerationEnvironment.ToString(); + } + } + + #line default + #line hidden + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + public class LambdaFunctionTemplateBase + { + #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/LambdaFunctionTemplate.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt index ca1bd185f..b7f088440 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/LambdaFunctionTemplate.tt @@ -1,74 +1,74 @@ -<#@ template language="C#" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Extensions" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes" #> -<#@ import namespace="Microsoft.CodeAnalysis" #> -<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Validation" #> -<# - foreach (var ns in _model.GeneratedMethod.Usings) - { -#> -using <#= ns #>; -<# - } -#> - -namespace <#= _model.LambdaMethod.ContainingNamespace #> -{ - public 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}")) #>) - { -<# - if (_model.LambdaMethod.UsingDependencyInjection) - { -#> - // Create a scope for every request, - // this allows creating scoped dependencies without creating a scope manually. - using var scope = serviceProvider.CreateScope(); - var <#= - _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = scope.ServiceProvider.GetRequiredService<<#= _model.LambdaMethod.ContainingType.Name #>>(); - -<# - } - - if (_model.LambdaMethod.Events.Contains(EventType.API)) - { - var apiParameters = new APIGatewaySetupParameters(_model); - this.Write(apiParameters.TransformText()); - this.Write(new APIGatewayInvoke(_model, apiParameters.ParameterSignature).TransformText()); - } - else if (_model.LambdaMethod.Events.Count == 0) - { - this.Write(new NoEventMethodBody(_model).TransformText()); - } -#> - } - - 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_<#= _model.SourceGeneratorVersion #>"); - - Environment.SetEnvironmentVariable(envName, envValue.ToString()); - } - } +<#@ template language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Extensions" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Models.Attributes" #> +<#@ import namespace="Microsoft.CodeAnalysis" #> +<#@ import namespace="Amazon.Lambda.Annotations.SourceGenerator.Validation" #> +<# + foreach (var ns in _model.GeneratedMethod.Usings) + { +#> +using <#= ns #>; +<# + } +#> + +namespace <#= _model.LambdaMethod.ContainingNamespace #> +{ + public 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}")) #>) + { +<# + if (_model.LambdaMethod.UsingDependencyInjection) + { +#> + // Create a scope for every request, + // this allows creating scoped dependencies without creating a scope manually. + using var scope = serviceProvider.CreateScope(); + var <#= + _model.LambdaMethod.ContainingType.Name.ToCamelCase() #> = scope.ServiceProvider.GetRequiredService<<#= _model.LambdaMethod.ContainingType.Name #>>(); + +<# + } + + if (_model.LambdaMethod.Events.Contains(EventType.API)) + { + var apiParameters = new APIGatewaySetupParameters(_model); + this.Write(apiParameters.TransformText()); + this.Write(new APIGatewayInvoke(_model, apiParameters.ParameterSignature).TransformText()); + } + else if (_model.LambdaMethod.Events.Count == 0) + { + this.Write(new NoEventMethodBody(_model).TransformText()); + } +#> + } + + 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_<#= _model.SourceGeneratorVersion #>"); + + Environment.SetEnvironmentVariable(envName, envValue.ToString()); + } + } } \ No newline at end of file From a6e782199e2f03b0a9ade229d33f5a6fdd6b2b20 Mon Sep 17 00:00:00 2001 From: PFSerra Date: Sun, 3 Sep 2023 18:56:56 +0100 Subject: [PATCH 10/10] Added unauthorized response as requested. --- .../Templates/APIGatewaySetupParameters.cs | 188 ++++++++++-------- .../Templates/APIGatewaySetupParameters.tt | 72 +++++-- ...piExample_HttpApiAuthorizer_Generated.g.cs | 38 ++-- ...rRestExample_RestAuthorizer_Generated.g.cs | 38 ++-- .../authorizerHttpApi.template | 2 +- .../authorizerRest.template | 2 +- .../CustomAuthorizerRestExample.cs | 2 +- .../TestServerlessApp/serverless.template | 86 +++++++- 8 files changed, 300 insertions(+), 128 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs index 2867e6da2..4a8a90b2d 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.cs @@ -660,69 +660,85 @@ public virtual string TransformText() #line default #line hidden - this.Write(@"); - if (__request__.RequestContext?.Authorizer == null) - { - validationErrors.Add(""Could not find Authorizer data for request""); - } - else if (__request__.RequestContext?.Authorizer.ContainsKey("""); + this.Write(");\r\n if (__request__.RequestContext?.Authorizer == null || __request__" + + ".RequestContext?.Authorizer.ContainsKey(\""); - #line 264 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 260 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); #line default #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); + this.Write("\") == false)\r\n {\r\n return new "); + + #line 262 "C:\codebase\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 268 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line default + #line hidden + this.Write(@" + { + Headers = new Dictionary + { + {""Content-Type"", ""application/json""}, + {""x-amzn-ErrorType"", ""AccessDeniedException""} + }, + StatusCode = 401 + }; + } + + try + { + "); + + #line 275 "C:\codebase\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 268 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 275 "C:\codebase\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__.RequestContext.Authorizer[\""); - #line 268 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 275 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); #line default #line hidden this.Write("\"], typeof("); - #line 268 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 275 "C:\codebase\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__.RequestContext.Authorizer["""); + this.Write("));\r\n }\r\n catch (Exception e) when (e is InvalidCastExcepti" + + "on || e is FormatException || e is OverflowException || e is ArgumentException)\r" + + "\n {\r\n return new "); - #line 272 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); - - #line default - #line hidden - this.Write("\"]} at \'"); - - #line 272 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + #line 279 "C:\codebase\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("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + - "\n\r\n"); + this.Write(@" + { + Headers = new Dictionary + { + {""Content-Type"", ""application/json""}, + {""x-amzn-ErrorType"", ""AccessDeniedException""} + }, + StatusCode = 401 + }; + } + +"); - #line 276 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 290 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -733,81 +749,97 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 295 "C:\codebase\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 281 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 295 "C:\codebase\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(@"); - if (__request__.RequestContext?.Authorizer?.Lambda == null) - { - validationErrors.Add(""Could not find Lambda Authorizer data for request""); - } - else if (__request__.RequestContext?.Authorizer?.Lambda?.ContainsKey("""); + this.Write(");\r\n if (__request__.RequestContext?.Authorizer?.Lambda == null || __r" + + "equest__.RequestContext?.Authorizer?.Lambda.ContainsKey(\""); - #line 286 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 296 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); #line default #line hidden - this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + - " "); + this.Write("\") == false)\r\n {\r\n return new "); - #line 290 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 298 "C:\codebase\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(@" + { + Headers = new Dictionary + { + {""Content-Type"", ""application/json""}, + {""x-amzn-ErrorType"", ""AccessDeniedException""} + }, + StatusCode = 401 + }; + } + + try + { + "); + + #line 311 "C:\codebase\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 290 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 311 "C:\codebase\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__.RequestContext.Authorizer.Lambda[\""); - #line 290 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 311 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); #line default #line hidden this.Write("\"], typeof("); - #line 290 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 311 "C:\codebase\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__.RequestContext.Authorizer.Lambda["""); - - #line 294 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); - - #line default - #line hidden - this.Write("\"]} at \'"); + this.Write("));\r\n }\r\n catch (Exception e) when (e is InvalidCastExcepti" + + "on || e is FormatException || e is OverflowException || e is ArgumentException)\r" + + "\n {\r\n return new "); - #line 294 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" - this.Write(this.ToStringHelper.ToStringWithCulture(authKey)); + #line 315 "C:\codebase\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("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + - "\n\r\n"); + this.Write(@" + { + Headers = new Dictionary + { + {""Content-Type"", ""application/json""}, + {""x-amzn-ErrorType"", ""AccessDeniedException""} + }, + StatusCode = 401 + }; + } + +"); - #line 298 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 326 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } } @@ -823,21 +855,21 @@ public virtual string TransformText() #line hidden this.Write(" var "); - #line 308 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 336 "C:\codebase\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 308 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 336 "C:\codebase\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 309 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 337 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default @@ -845,28 +877,28 @@ public virtual string TransformText() this.Write("\") == true)\r\n {\r\n try\r\n {\r\n " + " "); - #line 313 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 341 "C:\codebase\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 313 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 341 "C:\codebase\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 313 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 341 "C:\codebase\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 313 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 341 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type.FullNameWithoutAnnotations)); #line default @@ -877,14 +909,14 @@ public virtual string TransformText() { validationErrors.Add($""Value {__request__.PathParameters["""); - #line 317 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 345 "C:\codebase\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 \'"); - #line 317 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 345 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" this.Write(this.ToStringHelper.ToStringWithCulture(routeKey)); #line default @@ -892,7 +924,7 @@ public virtual string TransformText() this.Write("\' failed to satisfy constraint: {e.Message}\");\r\n }\r\n }\r" + "\n\r\n"); - #line 321 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 349 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -911,7 +943,7 @@ public virtual string TransformText() " if (validationErrors.Any())\r\n {\r\n var errorResult" + " = new "); - #line 335 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 363 "C:\codebase\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 @@ -928,7 +960,7 @@ public virtual string TransformText() }; "); - #line 345 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 373 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" if(_model.LambdaMethod.ReturnsIHttpResults) { @@ -940,7 +972,7 @@ public virtual string TransformText() "System.Text.Json.JsonSerializer.Serialize(errorStream, errorResult);\r\n " + " return errorStream;\r\n"); - #line 352 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 380 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } else @@ -951,7 +983,7 @@ public virtual string TransformText() #line hidden this.Write(" return errorResult;\r\n"); - #line 358 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 386 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } @@ -960,7 +992,7 @@ public virtual string TransformText() #line hidden this.Write(" }\r\n\r\n"); - #line 363 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" + #line 391 "C:\codebase\aws-lambda-dotnet\Libraries\src\Amazon.Lambda.Annotations.SourceGenerator\Templates\APIGatewaySetupParameters.tt" } @@ -992,7 +1024,7 @@ public class APIGatewaySetupParametersBase /// /// The string builder that generation-time code is using to assemble generated output /// - protected System.Text.StringBuilder GenerationEnvironment + public System.Text.StringBuilder GenerationEnvironment { get { diff --git a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt index 11d62bad0..d0b2cd101 100644 --- a/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt +++ b/Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Templates/APIGatewaySetupParameters.tt @@ -257,20 +257,34 @@ { #> var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); - if (__request__.RequestContext?.Authorizer == null) + if (__request__.RequestContext?.Authorizer == null || __request__.RequestContext?.Authorizer.ContainsKey("<#= authKey #>") == false) { - validationErrors.Add("Could not find Authorizer data for request"); + return new <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse" : "Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse" #> + { + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "AccessDeniedException"} + }, + StatusCode = 401 + }; } - else if (__request__.RequestContext?.Authorizer.ContainsKey("<#= authKey #>") == true) + + try { - try - { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.RequestContext.Authorizer["<#= authKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.RequestContext.Authorizer["<#= authKey #>"]} at '<#= authKey #>' failed to satisfy constraint: {e.Message}"); - } + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.RequestContext.Authorizer["<#= authKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + return new <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse" : "Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse" #> + { + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "AccessDeniedException"} + }, + StatusCode = 401 + }; } <# @@ -279,20 +293,34 @@ { #> var <#= parameter.Name #> = default(<#= parameter.Type.FullName #>); - if (__request__.RequestContext?.Authorizer?.Lambda == null) + if (__request__.RequestContext?.Authorizer?.Lambda == null || __request__.RequestContext?.Authorizer?.Lambda.ContainsKey("<#= authKey #>") == false) { - validationErrors.Add("Could not find Lambda Authorizer data for request"); + return new <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse" : "Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse" #> + { + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "AccessDeniedException"} + }, + StatusCode = 401 + }; } - else if (__request__.RequestContext?.Authorizer?.Lambda?.ContainsKey("<#= authKey #>") == true) + + try { - try - { - <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.RequestContext.Authorizer.Lambda["<#= authKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.RequestContext.Authorizer.Lambda["<#= authKey #>"]} at '<#= authKey #>' failed to satisfy constraint: {e.Message}"); - } + <#= parameter.Name #> = (<#= parameter.Type.FullName #>)Convert.ChangeType(__request__.RequestContext.Authorizer.Lambda["<#= authKey #>"], typeof(<#= parameter.Type.FullNameWithoutAnnotations #>)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + return new <#= restApiAttribute != null || httpApiAttribute?.Data.Version == Amazon.Lambda.Annotations.APIGateway.HttpApiVersion.V1 ? "Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse" : "Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse" #> + { + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "AccessDeniedException"} + }, + StatusCode = 401 + }; } <# diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs index 3da38f910..85d630792 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated.g.cs @@ -21,20 +21,34 @@ public CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated() var validationErrors = new List(); var authorizerValue = default(string); - if (__request__.RequestContext?.Authorizer?.Lambda == null) + if (__request__.RequestContext?.Authorizer?.Lambda == null || __request__.RequestContext?.Authorizer?.Lambda.ContainsKey("authKey") == false) { - validationErrors.Add("Could not find Lambda Authorizer data for request"); + return new Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse + { + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "AccessDeniedException"} + }, + StatusCode = 401 + }; } - else if (__request__.RequestContext?.Authorizer?.Lambda?.ContainsKey("authKey") == true) + + try { - try - { - authorizerValue = (string)Convert.ChangeType(__request__.RequestContext.Authorizer.Lambda["authKey"], typeof(string)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.RequestContext.Authorizer.Lambda["authKey"]} at 'authKey' failed to satisfy constraint: {e.Message}"); - } + authorizerValue = (string)Convert.ChangeType(__request__.RequestContext.Authorizer.Lambda["authKey"], typeof(string)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + return new Amazon.Lambda.APIGatewayEvents.APIGatewayHttpApiV2ProxyResponse + { + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "AccessDeniedException"} + }, + StatusCode = 401 + }; } // return 400 Bad Request if there exists a validation error @@ -73,7 +87,7 @@ private static void SetExecutionEnvironment() envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); } - envValue.Append("amazon-lambda-annotations_0.13.3.0"); + envValue.Append("amazon-lambda-annotations_1.0.0.0"); Environment.SetEnvironmentVariable(envName, envValue.ToString()); } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs index ff35d5cea..230c4b316 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/CustomAuthorizerRestExample_RestAuthorizer_Generated.g.cs @@ -21,20 +21,34 @@ public CustomAuthorizerRestExample_RestAuthorizer_Generated() var validationErrors = new List(); var authorizerValue = default(string); - if (__request__.RequestContext?.Authorizer == null) + if (__request__.RequestContext?.Authorizer == null || __request__.RequestContext?.Authorizer.ContainsKey("theAuthKey") == false) { - validationErrors.Add("Could not find Authorizer data for request"); + return new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse + { + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "AccessDeniedException"} + }, + StatusCode = 401 + }; } - else if (__request__.RequestContext?.Authorizer.ContainsKey("authKey") == true) + + try { - try - { - authorizerValue = (string)Convert.ChangeType(__request__.RequestContext.Authorizer["authKey"], typeof(string)); - } - catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) - { - validationErrors.Add($"Value {__request__.RequestContext.Authorizer["authKey"]} at 'authKey' failed to satisfy constraint: {e.Message}"); - } + authorizerValue = (string)Convert.ChangeType(__request__.RequestContext.Authorizer["theAuthKey"], typeof(string)); + } + catch (Exception e) when (e is InvalidCastException || e is FormatException || e is OverflowException || e is ArgumentException) + { + return new Amazon.Lambda.APIGatewayEvents.APIGatewayProxyResponse + { + Headers = new Dictionary + { + {"Content-Type", "application/json"}, + {"x-amzn-ErrorType", "AccessDeniedException"} + }, + StatusCode = 401 + }; } // return 400 Bad Request if there exists a validation error @@ -73,7 +87,7 @@ private static void SetExecutionEnvironment() envValue.Append($"{Environment.GetEnvironmentVariable(envName)}_"); } - envValue.Append("amazon-lambda-annotations_0.13.3.0"); + envValue.Append("amazon-lambda-annotations_1.0.0.0"); Environment.SetEnvironmentVariable(envName, envValue.ToString()); } diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template index 8721fa327..a73441fa6 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerHttpApi.template @@ -1,7 +1,7 @@ { "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::Serverless-2016-10-31", - "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.3.0).", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).", "Resources": { "HttpApiAuthorizerTest": { "Type": "AWS::Serverless::Function", diff --git a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template index a34a4897a..b8db4ef7d 100644 --- a/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template +++ b/Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/Snapshots/ServerlessTemplates/authorizerRest.template @@ -1,7 +1,7 @@ { "AWSTemplateFormatVersion": "2010-09-09", "Transform": "AWS::Serverless-2016-10-31", - "Description": "This template is partially managed by Amazon.Lambda.Annotations (v0.13.3.0).", + "Description": "This template is partially managed by Amazon.Lambda.Annotations (v1.0.0.0).", "Resources": { "RestAuthorizerTest": { "Type": "AWS::Serverless::Function", diff --git a/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs b/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs index 1086d1519..8779fa283 100644 --- a/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs +++ b/Libraries/test/TestServerlessApp/CustomAuthorizerRestExample.cs @@ -9,7 +9,7 @@ public class CustomAuthorizerRestExample { [LambdaFunction(ResourceName = "RestAuthorizerTest", PackageType = LambdaPackageType.Image)] [RestApi(LambdaHttpMethod.Get, "/rest/authorizer")] - public async Task RestAuthorizer([FromCustomAuthorizer(Name = "authKey")] string authorizerValue, ILambdaContext context) + public async Task RestAuthorizer([FromCustomAuthorizer(Name = "theAuthKey")] string authorizerValue, ILambdaContext context) { context.Logger.LogLine(authorizerValue); await Task.CompletedTask; diff --git a/Libraries/test/TestServerlessApp/serverless.template b/Libraries/test/TestServerlessApp/serverless.template index 55cf1283c..f2d6826fd 100644 --- a/Libraries/test/TestServerlessApp/serverless.template +++ b/Libraries/test/TestServerlessApp/serverless.template @@ -1,7 +1,7 @@ { "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).", + "Description": "An AWS Serverless Application. This template is partially managed by Amazon.Lambda.Annotations (v0.13.3.0).", "Parameters": { "ArchitectureTypeParameter": { "Type": "String", @@ -718,6 +718,90 @@ ] } } + }, + "RestAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.CustomAuthorizerRestExample_RestAuthorizer_Generated::RestAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "Api", + "Properties": { + "Path": "/rest/authorizer", + "Method": "GET" + } + } + } + } + }, + "HttpApiAuthorizerTest": { + "Type": "AWS::Serverless::Function", + "Metadata": { + "Tool": "Amazon.Lambda.Annotations", + "SyncedEvents": [ + "RootGet" + ] + }, + "Properties": { + "MemorySize": 256, + "Timeout": 30, + "Policies": [ + "AWSLambdaBasicExecutionRole" + ], + "PackageType": "Image", + "ImageUri": ".", + "ImageConfig": { + "Command": [ + "TestServerlessApp::TestServerlessApp.CustomAuthorizerHttpApiExample_HttpApiAuthorizer_Generated::HttpApiAuthorizer" + ] + }, + "Events": { + "RootGet": { + "Type": "HttpApi", + "Properties": { + "Path": "/api/authorizer", + "Method": "GET" + } + } + } + } + }, + "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": {