public void Execute(GeneratorExecutionContext context) { var diagnosticReporter = new DiagnosticReporter(context); try { // retrieve the populated receiver if (!(context.SyntaxContextReceiver is SyntaxReceiver receiver)) { return; } // If no project directory was detected then skip the generator. // This is most likely to happen when the project is empty and doesn't have any classes in it yet. if (string.IsNullOrEmpty(receiver.ProjectDirectory)) { return; } var semanticModelProvider = new SemanticModelProvider(context); if (receiver.StartupClasses.Count > 1) { foreach (var startup in receiver.StartupClasses) { // If there are more than one startup class, report them as errors diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.MultipleStartupNotAllowed, Location.Create(startup.SyntaxTree, startup.Span), startup.SyntaxTree.FilePath)); } } var configureMethodModel = semanticModelProvider.GetConfigureMethodModel(receiver.StartupClasses.FirstOrDefault()); var annotationReport = new AnnotationReport(); var templateFinder = new CloudFormationTemplateFinder(_fileManager, _directoryManager); foreach (var lambdaMethod in receiver.LambdaMethods) { var lambdaMethodModel = semanticModelProvider.GetMethodSemanticModel(lambdaMethod); // Check for necessary references if (lambdaMethodModel.HasAttribute(context, TypeFullNames.RestApiAttribute) || lambdaMethodModel.HasAttribute(context, TypeFullNames.HttpApiAttribute)) { // Check for arbitrary type from "Amazon.Lambda.APIGatewayEvents" if (context.Compilation.ReferencedAssemblyNames.FirstOrDefault(x => x.Name == "Amazon.Lambda.APIGatewayEvents") == null) { diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.MissingDependencies, lambdaMethod.GetLocation(), "Amazon.Lambda.APIGatewayEvents")); } } var model = LambdaFunctionModelBuilder.Build(lambdaMethodModel, configureMethodModel, context); // If there are more than one event, report them as errors if (model.LambdaMethod.Events.Count > 1) { foreach (var attribute in lambdaMethodModel.GetAttributes().Where(attribute => TypeFullNames.Events.Contains(attribute.AttributeClass.ToDisplayString()))) { diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.MultipleEventsNotSupported, Location.Create(attribute.ApplicationSyntaxReference.SyntaxTree, attribute.ApplicationSyntaxReference.Span), DiagnosticSeverity.Error)); } // Skip multi-event lambda method from processing and check remaining lambda methods for diagnostics continue; } var template = new LambdaFunctionTemplate(model); var sourceText = template.TransformText().ToEnvironmentLineEndings(); context.AddSource($"{model.GeneratedMethod.ContainingType.Name}.g.cs", SourceText.From(sourceText, Encoding.UTF8, SourceHashAlgorithm.Sha256)); // report every generated file to build output diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.CodeGeneration, Location.None, $"{model.GeneratedMethod.ContainingType.Name}.g.cs", sourceText)); annotationReport.LambdaFunctions.Add(model); } // Run the CloudFormation sync if any LambdaMethods exists. Also run if no LambdaMethods exists but there is a // CloudFormation template in case orphaned functions in the template need to be removed. // Both checks are required because if there is no template but there are LambdaMethods the CF template the template will be created. if (receiver.LambdaMethods.Any() || templateFinder.DoesCloudFormationTemplateExist(receiver.ProjectDirectory)) { annotationReport.CloudFormationTemplatePath = templateFinder.FindCloudFormationTemplate(receiver.ProjectDirectory); annotationReport.ProjectRootDirectory = receiver.ProjectDirectory; var cloudFormationJsonWriter = new CloudFormationJsonWriter(_fileManager, _directoryManager, _jsonWriter, diagnosticReporter); cloudFormationJsonWriter.ApplyReport(annotationReport); } } catch (Exception e) { // this is a generator failure, report this as error diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.UnhandledException, Location.None, e.PrettyPrint())); #if DEBUG throw; #endif } }