public void Execute()

in Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs [50:240]


        public void Execute(GeneratorExecutionContext context)
        {
            var diagnosticReporter = new DiagnosticReporter(context);

            try
            {
                // retrieve the populated receiver
                if (!(context.SyntaxContextReceiver is SyntaxReceiver receiver))
                {
                    return;
                }

                // Check to see if any of the current syntax trees has any error diagnostics. If so
                // Skip generation. We only want to sync the CloudFormation template if the project
                // can compile.
                foreach (var syntaxTree in context.Compilation.SyntaxTrees)
                {
                    if(syntaxTree.GetDiagnostics().Any(x => x.Severity == DiagnosticSeverity.Error))
                    {
                        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 isExecutable = false;

                bool foundFatalError = false;

                var assemblyAttributes = context.Compilation.Assembly.GetAttributes();

                var globalPropertiesAttribute = assemblyAttributes
                    .FirstOrDefault(attr => attr.AttributeClass.Name == nameof(LambdaGlobalPropertiesAttribute));

                var defaultRuntime = "dotnet6";

                // Try to determine the target framework from the source generator context
                if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.TargetFramework", out var targetFramework))
                {
                    if (_targetFrameworksToRuntimes.ContainsKey(targetFramework))
                    {
                        defaultRuntime = _targetFrameworksToRuntimes[targetFramework];
                    }
                }

                // The runtime specified in the global property has precedence over the one we determined from the TFM (if we did)
                if (globalPropertiesAttribute != null)
                {
                    var generateMain = globalPropertiesAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "GenerateMain").Value;
                    var runtimeAttributeValue = globalPropertiesAttribute.NamedArguments.FirstOrDefault(kvp => kvp.Key == "Runtime").Value;
                    var runtime = runtimeAttributeValue.Value == null ? defaultRuntime : runtimeAttributeValue.Value.ToString();

                    if (!_allowedRuntimeValues.Contains(runtime))
                    {
                        diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.InvalidRuntimeSelection, Location.None));
                        return;
                    }

                    defaultRuntime = runtime;

                    isExecutable = generateMain.Value != null && bool.Parse(generateMain.Value.ToString());

                    if (isExecutable && context.Compilation.Options.OutputKind != OutputKind.ConsoleApplication)
                    {
                        diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.SetOutputTypeExecutable, Location.None));
                        return;
                    }
                }

                var configureHostBuilderMethodSymbol = semanticModelProvider.GetConfigureHostBuilderMethodModel(receiver.StartupClasses.FirstOrDefault());
                var configureServicesMethodSymbol = semanticModelProvider.GetConfigureServicesMethodModel(receiver.StartupClasses.FirstOrDefault());
                var configureMethodSymbol = configureServicesMethodSymbol;

                if (configureServicesMethodSymbol != null && configureHostBuilderMethodSymbol != null)
                {
                    diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.MultipleConfigureMethodsNotAllowed, configureServicesMethodSymbol.Locations.FirstOrDefault(), configureServicesMethodSymbol.Name, configureHostBuilderMethodSymbol.Name));
                }

                if (configureHostBuilderMethodSymbol != null)
                {
                    configureMethodSymbol = configureHostBuilderMethodSymbol;
                }

                var annotationReport = new AnnotationReport();

                var templateHandler = new CloudFormationTemplateHandler(_fileManager, _directoryManager);

                var lambdaModels = new List<LambdaFunctionModel>();

                foreach (var lambdaMethodDeclarationSyntax in receiver.LambdaMethods)
                {
                    var lambdaMethodSymbol = semanticModelProvider.GetMethodSemanticModel(lambdaMethodDeclarationSyntax);
                    var lambdaMethodLocation = lambdaMethodDeclarationSyntax.GetLocation();

                    var lambdaFunctionModel = LambdaFunctionModelBuilder.BuildAndValidate(lambdaMethodSymbol, lambdaMethodLocation, configureMethodSymbol, context, isExecutable, defaultRuntime, diagnosticReporter);
                    if (!lambdaFunctionModel.IsValid)
                    {
                        // If the model is not valid then skip it from further processing
                        foundFatalError = true;
                        continue;
                    }

                    var template = new LambdaFunctionTemplate(lambdaFunctionModel);

                    string sourceText;
                    try
                    {
                        sourceText = template.TransformText().ToEnvironmentLineEndings();
                        context.AddSource($"{lambdaFunctionModel.GeneratedMethod.ContainingType.Name}.g.cs", SourceText.From(sourceText, Encoding.UTF8, SourceHashAlgorithm.Sha256));
                    }
                    catch (Exception e) when (e is NotSupportedException || e is InvalidOperationException)
                    {
                        diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.CodeGenerationFailed, Location.Create(lambdaMethodDeclarationSyntax.SyntaxTree, lambdaMethodDeclarationSyntax.Span), e.Message));
                        return;
                    }

                    // report every generated file to build output
                    diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.CodeGeneration, Location.None, $"{lambdaFunctionModel.GeneratedMethod.ContainingType.Name}.g.cs", sourceText));

                    lambdaModels.Add(lambdaFunctionModel);
                    annotationReport.LambdaFunctions.Add(lambdaFunctionModel);
                }

                if (isExecutable)
                {
                    var executableAssembly = GenerateExecutableAssemblySource(
                        context,
                        diagnosticReporter,
                        receiver,
                        lambdaModels);

                    if (executableAssembly == null)
                    {
                        foundFatalError = true;
                        return;
                    }

                    context.AddSource("Program.g.cs", SourceText.From(executableAssembly.TransformText().ToEnvironmentLineEndings(), Encoding.UTF8, SourceHashAlgorithm.Sha256));
                }

                // Run the CloudFormation sync if any LambdaMethods exists. Also run if no LambdaMethods exists but there is a
                // 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 (!foundFatalError && (receiver.LambdaMethods.Any() || templateHandler.DoesTemplateExist(receiver.ProjectDirectory)))
                {
                    annotationReport.CloudFormationTemplatePath = templateHandler.FindTemplate(receiver.ProjectDirectory);
                    annotationReport.ProjectRootDirectory = receiver.ProjectDirectory;
                    annotationReport.IsTelemetrySuppressed = ProjectFileHandler.IsTelemetrySuppressed(receiver.ProjectPath, _fileManager);

                    var templateFormat = templateHandler.DetermineTemplateFormat(annotationReport.CloudFormationTemplatePath);
                    ITemplateWriter templateWriter;
                    if (templateFormat == CloudFormationTemplateFormat.Json)
                    {
                        templateWriter = new JsonWriter();
                    }
                    else
                    {
                        templateWriter = new YamlWriter();
                    }
                    var cloudFormationWriter = new CloudFormationWriter(_fileManager, _directoryManager, templateWriter, diagnosticReporter);
                    cloudFormationWriter.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
            }
        }