ef update wip

This commit is contained in:
CodeLiturgy 2022-08-27 20:56:19 +01:00
parent 340a89bbd2
commit c34da98ad8
5 changed files with 102 additions and 26 deletions

View File

@ -45,6 +45,7 @@
<ItemGroup>
<Folder Include="bin\Release\netstandard2.0" />
<Folder Include="Sources\EntityFramework" />
</ItemGroup>
</Project>

View File

@ -46,11 +46,11 @@ namespace MapTo
protected ImmutableArray<string> 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()
};

View File

@ -10,15 +10,6 @@ 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>
@ -34,12 +25,15 @@ namespace MapTo
/// <inheritdoc />
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<MemberDeclarationSyntax> candidateTypes, SourceGenerationOptions options)
private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable<CandidateMember> 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()

View File

@ -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]
.FirstOrDefault(a =>
{
Left: IdentifierNameSyntax { Identifier: { ValueText: Constants.RootNamespace } },
Right: IdentifierNameSyntax { Identifier: { ValueText: EfAddMethodsAttributeSource.AttributeName } }
}
);
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
};
}
}
}

View File

@ -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");
}
}
}