diff --git a/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorAttributeSource.cs b/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorAttributeSource.cs new file mode 100644 index 0000000..a742cf3 --- /dev/null +++ b/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorAttributeSource.cs @@ -0,0 +1,41 @@ +using static MapTo.Sources.Constants; + +namespace MapTo.Sources +{ + public class EfGeneratorAttributeSource + { + internal const string AttributeName = "EfGenerator"; + 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.Class)]") + .WriteLine($"public sealed class {AttributeName}Attribute : Attribute") + .WriteOpeningBracket() + .WriteLine(); + + builder + .WriteClosingBracket() // class + .WriteClosingBracket(); // namespace + + return new(builder.ToString(), $"{AttributeName}Attribute.g.cs"); + } + } +} \ No newline at end of file diff --git a/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorExtensionMethods.cs b/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorExtensionMethods.cs new file mode 100644 index 0000000..32f25ff --- /dev/null +++ b/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorExtensionMethods.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using MapTo.Extensions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace MapTo.Sources.EfMethods +{ + public static class EfGeneratorExtensionMethods + { + public static void InitializeEfGenerator(this ISourceGenerator sourceGenerator, GeneratorInitializationContext context) + { + context.RegisterForSyntaxNotifications(() => new EfMethodsSyntaxReceiver()); + } + + /// + public static void ExecuteEfGenerator(this ISourceGenerator sourceGenerator, GeneratorExecutionContext context) + { + try + { + var options = SourceGenerationOptions.From(context); + + var compilation = context.Compilation + .AddSource(ref context, EfAddMethodsAttributeSource.Generate(options)) + .AddSource(ref context, EfUpdateMethodsAttributeSource.Generate(options)); + + + if (context.SyntaxReceiver is EfMethodsSyntaxReceiver receiver && receiver.CandidateMembers.Any()) + { + AddGeneratedExtensions(context, compilation, receiver.CandidateMembers, options); + } + } + catch (Exception ex) + { + Console.WriteLine(ex); + throw; + } + } + + private static void AddGeneratedExtensions( GeneratorExecutionContext context, Compilation compilation, IEnumerable candidateMembers, SourceGenerationOptions options) + { + //SpinWait.SpinUntil(() => Debugger.IsAttached); + + foreach (var candidateMember in candidateMembers) + { + string addSourceTemplate = context.AdditionalFiles + .FirstOrDefault(x => x.Path.Contains("AddToEntityTemplate"))? + .GetText()? + .ToString() ?? string.Empty; + + string updateSourceTemplate = context.AdditionalFiles + .FirstOrDefault(x => x.Path.Contains("UpdateEntityTemplate"))? + .GetText()? + .ToString() ?? string.Empty; + + + var mappingContext = EfGeneratorContext.Create(compilation, options, candidateMember.MemberDeclarationSyntax); + + mappingContext.Diagnostics.ForEach(context.ReportDiagnostic); + + if (mappingContext.Model is null) + { + continue; + } + + var (source, hintName) = candidateMember.MemberDeclarationSyntax switch + { + PropertyDeclarationSyntax => EfMethodsSource.Generate(mappingContext.Model, addSourceTemplate, updateSourceTemplate), + _ => throw new ArgumentOutOfRangeException() + }; + + context.AddSource(hintName, source); + } + } + } +} \ No newline at end of file diff --git a/src/BlueWest.MapTo/Sources/EfMethods/EfAddMethodsGenerator.cs b/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsGenerator.cs similarity index 97% rename from src/BlueWest.MapTo/Sources/EfMethods/EfAddMethodsGenerator.cs rename to src/BlueWest.MapTo/Sources/EfMethods/EfMethodsGenerator.cs index bc2f61f..0e8b1e4 100644 --- a/src/BlueWest.MapTo/Sources/EfMethods/EfAddMethodsGenerator.cs +++ b/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsGenerator.cs @@ -30,6 +30,7 @@ namespace MapTo var options = SourceGenerationOptions.From(context); var compilation = context.Compilation + .AddSource(ref context, EfGeneratorAttributeSource.Generate(options)) .AddSource(ref context, EfAddMethodsAttributeSource.Generate(options)) .AddSource(ref context, EfUpdateMethodsAttributeSource.Generate(options));