Skip to content

Commit 2218656

Browse files
committed
Fix issue of syncing CF template when all LambdaFunctions are removed.
1 parent a467db6 commit 2218656

File tree

3 files changed

+50
-15
lines changed

3 files changed

+50
-15
lines changed

Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/CloudFormationTemplateFinder.cs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,28 @@ public string DetermineProjectRootDirectory(string sourceFilePath)
3434
}
3535

3636
public string FindCloudFormationTemplate(string projectRootDirectory)
37+
{
38+
var templateAbsolutePath = DetermineCloudFormationTemplatePath(projectRootDirectory);
39+
40+
if (!_fileManager.Exists(templateAbsolutePath))
41+
_fileManager.Create(templateAbsolutePath).Close();
42+
43+
return templateAbsolutePath;
44+
}
45+
46+
public bool DoesCloudFormationTemplateExist(string projectRootDirectory)
47+
{
48+
var templateAbsolutePath = DetermineCloudFormationTemplatePath(projectRootDirectory);
49+
return _fileManager.Exists(templateAbsolutePath);
50+
}
51+
52+
private string DetermineCloudFormationTemplatePath(string projectRootDirectory)
3753
{
3854
if (!_directoryManager.Exists(projectRootDirectory))
3955
throw new DirectoryNotFoundException("Failed to find the project root directory");
4056

4157
var templateAbsolutePath = string.Empty;
42-
58+
4359
var defaultConfigFile = _directoryManager.GetFiles(projectRootDirectory, "aws-lambda-tools-defaults.json", SearchOption.AllDirectories)
4460
.FirstOrDefault();
4561

@@ -51,10 +67,7 @@ public string FindCloudFormationTemplate(string projectRootDirectory)
5167
// set the template path inside the project root directory.
5268
if (string.IsNullOrEmpty(templateAbsolutePath))
5369
templateAbsolutePath = Path.Combine(projectRootDirectory, "serverless.template");
54-
55-
if (!_fileManager.Exists(templateAbsolutePath))
56-
_fileManager.Create(templateAbsolutePath).Close();
57-
70+
5871
return templateAbsolutePath;
5972
}
6073

Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ public void Execute(GeneratorExecutionContext context)
4646
return;
4747
}
4848

49-
// If there are no Lambda methods, return early
50-
if (!receiver.LambdaMethods.Any())
49+
// If no project directory was detected then skip the generator.
50+
// This is most likely to happen when the project is empty and doesn't have any classes in it yet.
51+
if(string.IsNullOrEmpty(receiver.ProjectDirectory))
5152
{
5253
return;
5354
}
@@ -69,7 +70,6 @@ public void Execute(GeneratorExecutionContext context)
6970
var annotationReport = new AnnotationReport();
7071

7172
var templateFinder = new CloudFormationTemplateFinder(_fileManager, _directoryManager);
72-
var projectRootDirectory = string.Empty;
7373

7474
foreach (var lambdaMethod in receiver.LambdaMethods)
7575
{
@@ -112,15 +112,19 @@ public void Execute(GeneratorExecutionContext context)
112112
diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.CodeGeneration, Location.None, $"{model.GeneratedMethod.ContainingType.Name}.g.cs", sourceText));
113113

114114
annotationReport.LambdaFunctions.Add(model);
115+
}
115116

116-
if (string.IsNullOrEmpty(projectRootDirectory))
117-
projectRootDirectory = templateFinder.DetermineProjectRootDirectory(lambdaMethod.SyntaxTree.FilePath);
117+
// Run the CloudFormation sync if any LambdaMethods exists. Also run if no LambdaMethods exists but there is a
118+
// CloudFormation template in case orphaned functions in the template need to be removed.
119+
// Both checks are required because if there is no template but there are LambdaMethods the CF template the template will be created.
120+
if (receiver.LambdaMethods.Any() || templateFinder.DoesCloudFormationTemplateExist(receiver.ProjectDirectory))
121+
{
122+
annotationReport.CloudFormationTemplatePath = templateFinder.FindCloudFormationTemplate(receiver.ProjectDirectory);
123+
annotationReport.ProjectRootDirectory = receiver.ProjectDirectory;
124+
var cloudFormationJsonWriter = new CloudFormationJsonWriter(_fileManager, _directoryManager, _jsonWriter, diagnosticReporter);
125+
cloudFormationJsonWriter.ApplyReport(annotationReport);
118126
}
119127

120-
annotationReport.CloudFormationTemplatePath = templateFinder.FindCloudFormationTemplate(projectRootDirectory);
121-
annotationReport.ProjectRootDirectory = projectRootDirectory;
122-
var cloudFormationJsonWriter = new CloudFormationJsonWriter(_fileManager, _directoryManager,_jsonWriter, diagnosticReporter);
123-
cloudFormationJsonWriter.ApplyReport(annotationReport);
124128
}
125129
catch (Exception e)
126130
{
@@ -135,7 +139,7 @@ public void Execute(GeneratorExecutionContext context)
135139
public void Initialize(GeneratorInitializationContext context)
136140
{
137141
// Register a syntax receiver that will be created for each generation pass
138-
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
142+
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver(_fileManager, _directoryManager));
139143
}
140144
}
141145
}

Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/SyntaxReceiver.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using Amazon.Lambda.Annotations.SourceGenerator.FileIO;
45
using Microsoft.CodeAnalysis;
56
using Microsoft.CodeAnalysis.CSharp.Syntax;
67

@@ -12,8 +13,25 @@ internal class SyntaxReceiver : ISyntaxContextReceiver
1213

1314
public List<ClassDeclarationSyntax> StartupClasses { get; private set; } = new List<ClassDeclarationSyntax>();
1415

16+
public string ProjectDirectory { get; private set; }
17+
18+
private readonly IFileManager _fileManager;
19+
private readonly IDirectoryManager _directoryManager;
20+
21+
public SyntaxReceiver(IFileManager fileManager, IDirectoryManager directoryManager)
22+
{
23+
_fileManager = fileManager;
24+
_directoryManager = directoryManager;
25+
}
26+
1527
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
1628
{
29+
if(this.ProjectDirectory == null && context.Node is ClassDeclarationSyntax)
30+
{
31+
var templateFinder = new CloudFormationTemplateFinder(_fileManager, _directoryManager);
32+
this.ProjectDirectory = templateFinder.DetermineProjectRootDirectory(context.Node.SyntaxTree.FilePath);
33+
}
34+
1735
// any method with at least one attribute is a candidate of function generation
1836
if (context.Node is MethodDeclarationSyntax methodDeclarationSyntax && methodDeclarationSyntax.AttributeLists.Count > 0)
1937
{

0 commit comments

Comments
 (0)