End merge Add with template and Update
This commit is contained in:
commit
4d9cc4b029
|
@ -45,6 +45,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Folder Include="bin\Release\netstandard2.0" />
|
||||
<Folder Include="Sources\EntityFramework" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -10,11 +10,20 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|||
|
||||
namespace MapTo
|
||||
{
|
||||
/*/// <summary>
|
||||
/// Base source code generator typed class.
|
||||
/// </summary>
|
||||
public class SourceCodeGenerator : ISourceGenerator
|
||||
{
|
||||
public virtual void Initialize(GeneratorInitializationContext context) {}
|
||||
public virtual void Execute(GeneratorExecutionContext context) {}
|
||||
}*/
|
||||
|
||||
/// <summary>
|
||||
/// Ef methods source generator
|
||||
/// </summary>
|
||||
[Generator]
|
||||
public class EfAddMethodsGenerator: ISourceGenerator
|
||||
public class EfMethodsGenerator: ISourceGenerator
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
|
@ -44,11 +53,11 @@ namespace MapTo
|
|||
}
|
||||
}
|
||||
|
||||
private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable<MemberDeclarationSyntax> candidateTypes, SourceGenerationOptions options)
|
||||
private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable<CandidateMember> 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()
|
||||
|
|
|
@ -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<MemberDeclarationSyntax> CandidateMembers { get; } = new();
|
||||
public List<CandidateMember> 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
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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("/// <summary>")
|
||||
.WriteLine("/// Generate Add methods for interacting with the entity")
|
||||
.WriteLine("/// </summary>");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue