Add generator attribute source
This commit is contained in:
parent
9257d389ba
commit
3917d231a2
|
@ -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("/// <summary>")
|
||||||
|
.WriteLine("/// Generate Add methods for interacting with the entity")
|
||||||
|
.WriteLine("/// </summary>");
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
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<CandidateMember> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ namespace MapTo
|
||||||
var options = SourceGenerationOptions.From(context);
|
var options = SourceGenerationOptions.From(context);
|
||||||
|
|
||||||
var compilation = context.Compilation
|
var compilation = context.Compilation
|
||||||
|
.AddSource(ref context, EfGeneratorAttributeSource.Generate(options))
|
||||||
.AddSource(ref context, EfAddMethodsAttributeSource.Generate(options))
|
.AddSource(ref context, EfAddMethodsAttributeSource.Generate(options))
|
||||||
.AddSource(ref context, EfUpdateMethodsAttributeSource.Generate(options));
|
.AddSource(ref context, EfUpdateMethodsAttributeSource.Generate(options));
|
||||||
|
|
Loading…
Reference in New Issue