diff --git a/src/BlueWest.MapTo/BlueWest.MapTo.csproj b/src/BlueWest.MapTo/BlueWest.MapTo.csproj
index 01debfe..04ec218 100644
--- a/src/BlueWest.MapTo/BlueWest.MapTo.csproj
+++ b/src/BlueWest.MapTo/BlueWest.MapTo.csproj
@@ -45,6 +45,7 @@
+
diff --git a/src/BlueWest.MapTo/EfAddMethodsGenerator.cs b/src/BlueWest.MapTo/EfAddMethodsGenerator.cs
index ac63178..f73093a 100644
--- a/src/BlueWest.MapTo/EfAddMethodsGenerator.cs
+++ b/src/BlueWest.MapTo/EfAddMethodsGenerator.cs
@@ -10,11 +10,20 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace MapTo
{
+ /*///
+ /// Base source code generator typed class.
+ ///
+ public class SourceCodeGenerator : ISourceGenerator
+ {
+ public virtual void Initialize(GeneratorInitializationContext context) {}
+ public virtual void Execute(GeneratorExecutionContext context) {}
+ }*/
+
///
/// Ef methods source generator
///
[Generator]
- public class EfAddMethodsGenerator: ISourceGenerator
+ public class EfMethodsGenerator: ISourceGenerator
{
///
public void Initialize(GeneratorInitializationContext context)
@@ -44,11 +53,11 @@ namespace MapTo
}
}
- private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable candidateTypes, SourceGenerationOptions options)
+ private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable candidateMembers, SourceGenerationOptions options)
{
//SpinWait.SpinUntil(() => Debugger.IsAttached);
- foreach (var memberDeclarationSyntax in candidateTypes)
+ foreach (var candidateMember in candidateMembers)
{
string addSourceTemplate = string.Empty;
@@ -60,7 +69,7 @@ namespace MapTo
.ToString() ?? string.Empty;
}
- var mappingContext = EfAddGeneratorContext.Create(compilation, options, memberDeclarationSyntax, addSourceTemplate);
+ var mappingContext = EfAddGeneratorContext.Create(compilation, options, candidateMember.MemberDeclarationSyntax, addSourceTemplate);
mappingContext.Diagnostics.ForEach(context.ReportDiagnostic);
@@ -69,7 +78,7 @@ namespace MapTo
continue;
}
- var (source, hintName) = memberDeclarationSyntax switch
+ var (source, hintName) = candidateMember.MemberDeclarationSyntax switch
{
PropertyDeclarationSyntax => EfMethodsSource.Generate(mappingContext.Model, addSourceTemplate),
_ => throw new ArgumentOutOfRangeException()
diff --git a/src/BlueWest.MapTo/EfMethodsSyntaxReceiver.cs b/src/BlueWest.MapTo/EfMethodsSyntaxReceiver.cs
index df28571..30b048e 100644
--- a/src/BlueWest.MapTo/EfMethodsSyntaxReceiver.cs
+++ b/src/BlueWest.MapTo/EfMethodsSyntaxReceiver.cs
@@ -6,9 +6,22 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace MapTo
{
+ internal enum EfMethodsAttributeType
+ {
+ Add,
+ Update,
+ Invalid
+ }
+
+ internal record CandidateMember(
+ MemberDeclarationSyntax MemberDeclarationSyntax,
+ EfMethodsAttributeType AttributeType
+ );
+
+
internal class EfMethodsSyntaxReceiver : ISyntaxReceiver
{
- public List CandidateMembers { get; } = new();
+ public List CandidateMembers { get; } = new();
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
@@ -17,22 +30,44 @@ namespace MapTo
return;
}
+ var syntaxAttributeState = EfMethodsAttributeType.Invalid;
+
var attributeSyntax = attributes
.SelectMany(a => a.Attributes)
- .FirstOrDefault(a => a.Name is
- IdentifierNameSyntax { Identifier: { ValueText: EfAddMethodsAttributeSource.AttributeName } } // For: [EfAddMethods]
- or
- QualifiedNameSyntax // For: [MapTo.EfAddMethods]
- {
- Left: IdentifierNameSyntax { Identifier: { ValueText: Constants.RootNamespace } },
- Right: IdentifierNameSyntax { Identifier: { ValueText: EfAddMethodsAttributeSource.AttributeName } }
- }
- );
+ .FirstOrDefault(a =>
+ {
+ syntaxAttributeState = IsValidAttributeType(a);
+ return syntaxAttributeState != EfMethodsAttributeType.Invalid;
+ });
+
if (attributeSyntax is not null)
{
- CandidateMembers.Add(typeDeclarationSyntax);
+ CandidateMembers.Add(new CandidateMember(typeDeclarationSyntax, syntaxAttributeState));
}
}
+
+ private static EfMethodsAttributeType IsValidAttributeType(AttributeSyntax a)
+ {
+ return a.Name switch
+ {
+ IdentifierNameSyntax { Identifier: { ValueText: EfAddMethodsAttributeSource.AttributeName } } // For: [EfAddMethods]
+ or QualifiedNameSyntax // For: [MapTo.EfAddMethods]
+ {
+ Left: IdentifierNameSyntax { Identifier: { ValueText: Constants.RootNamespace } },
+ Right: IdentifierNameSyntax { Identifier: { ValueText: EfAddMethodsAttributeSource.AttributeName } }
+ } => EfMethodsAttributeType.Add,
+
+ IdentifierNameSyntax { Identifier: { ValueText: EfUpdateMethodsAttributeSource.AttributeName } } // For: [EfAddMethods]
+ or QualifiedNameSyntax // For: [MapTo.EfUpdateMethods]
+ {
+ Left: IdentifierNameSyntax { Identifier: { ValueText: Constants.RootNamespace } },
+ Right: IdentifierNameSyntax { Identifier: { ValueText: EfUpdateMethodsAttributeSource.AttributeName } }
+ } => EfMethodsAttributeType.Update,
+
+ _ => EfMethodsAttributeType.Invalid
+ };
+ }
+
}
}
\ No newline at end of file
diff --git a/src/BlueWest.MapTo/Sources/EfUpdateMethodsAttributeSource.cs b/src/BlueWest.MapTo/Sources/EfUpdateMethodsAttributeSource.cs
new file mode 100644
index 0000000..36457ff
--- /dev/null
+++ b/src/BlueWest.MapTo/Sources/EfUpdateMethodsAttributeSource.cs
@@ -0,0 +1,46 @@
+using static MapTo.Sources.Constants;
+
+namespace MapTo.Sources
+{
+ public class EfUpdateMethodsAttributeSource
+ {
+ internal const string AttributeName = "EfUpdateMethods";
+ internal const string AttributeClassName = AttributeName + "Attribute";
+ internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
+
+ internal static SourceCode Generate(SourceGenerationOptions options)
+ {
+ using var builder = new SourceBuilder()
+ .WriteLine(GeneratedFilesHeader)
+ .WriteLine("using System;")
+ .WriteLine()
+ .WriteLine($"namespace {RootNamespace}")
+ .WriteOpeningBracket();
+
+ if (options.GenerateXmlDocument)
+ {
+ builder
+ .WriteLine("/// ")
+ .WriteLine("/// Generate Add methods for interacting with the entity")
+ .WriteLine("/// ");
+ }
+
+ builder
+ .WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]")
+ .WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
+ .WriteOpeningBracket();
+
+ builder
+ .WriteLine($"public {AttributeName}Attribute(Type updateType = null, Type returnType = null, string keyPropertyMemberName, Type keyPropertyMemberType)")
+ .WriteOpeningBracket()
+ .WriteClosingBracket()
+ .WriteLine();
+
+ builder
+ .WriteClosingBracket() // class
+ .WriteClosingBracket(); // namespace
+
+ return new(builder.ToString(), $"{AttributeName}Attribute.g.cs");
+ }
+ }
+}
\ No newline at end of file