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/EfGeneratorContext.cs b/src/BlueWest.MapTo/EfGeneratorContext.cs
index 2619cfa..1583403 100644
--- a/src/BlueWest.MapTo/EfGeneratorContext.cs
+++ b/src/BlueWest.MapTo/EfGeneratorContext.cs
@@ -46,11 +46,11 @@ namespace MapTo
protected ImmutableArray Usings { get; private set; }
- public static EfGeneratorContext Create(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, MemberDeclarationSyntax typeSyntax)
+ public static EfGeneratorContext Create(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, CandidateMember candidateMember)
{
- EfGeneratorContext context = typeSyntax switch
+ EfGeneratorContext context = candidateMember.MemberDeclarationSyntax switch
{
- PropertyDeclarationSyntax => new EfGeneratorContext(compilation, sourceGenerationOptions, typeSyntax),
+ PropertyDeclarationSyntax => new EfGeneratorContext(compilation, sourceGenerationOptions, candidateMember.MemberDeclarationSyntax),
_ => throw new ArgumentOutOfRangeException()
};
diff --git a/src/BlueWest.MapTo/EfMethodsGenerator.cs b/src/BlueWest.MapTo/EfMethodsGenerator.cs
index 7798385..604ccef 100644
--- a/src/BlueWest.MapTo/EfMethodsGenerator.cs
+++ b/src/BlueWest.MapTo/EfMethodsGenerator.cs
@@ -10,15 +10,6 @@ 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
///
@@ -34,12 +25,15 @@ namespace MapTo
///
public void Execute(GeneratorExecutionContext context)
{
+
try
{
var options = SourceGenerationOptions.From(context);
var compilation = context.Compilation
- .AddSource(ref context, EfAddMethodsAttributeSource.Generate(options));
+ .AddSource(ref context, EfAddMethodsAttributeSource.Generate(options))
+ .AddSource(ref context, EfUpdateMethodsAttributeSource.Generate(options));
+
if (context.SyntaxReceiver is EfMethodsSyntaxReceiver receiver && receiver.CandidateMembers.Any())
{
@@ -53,7 +47,7 @@ namespace MapTo
}
}
- private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable candidateTypes, SourceGenerationOptions options)
+ private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable candidateTypes, SourceGenerationOptions options)
{
//SpinWait.SpinUntil(() => Debugger.IsAttached);
@@ -68,7 +62,7 @@ namespace MapTo
}
- var (source, hintName) = memberDeclarationSyntax switch
+ var (source, hintName) = memberDeclarationSyntax.MemberDeclarationSyntax switch
{
PropertyDeclarationSyntax => EfMethodsSource.Generate(mappingContext.Model),
_ => 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