Using GetOne and GetMany templates
This commit is contained in:
parent
32bf670b9e
commit
b8637c94ab
|
@ -0,0 +1,47 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using static MapTo.Sources.Constants;
|
||||||
|
|
||||||
|
namespace MapTo.Sources
|
||||||
|
{
|
||||||
|
internal static class EfGetManyAttributeSource
|
||||||
|
{
|
||||||
|
internal const string AttributeName = "EfGetMany";
|
||||||
|
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("/// Attribute for generating a function to get one EF entity with a predicate as argument and a return type for the projection.")
|
||||||
|
.WriteLine("/// </summary>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]")
|
||||||
|
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
|
||||||
|
.WriteOpeningBracket();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine($"public {AttributeName}Attribute(Type returnType){"{}"}")
|
||||||
|
.WriteLine();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteClosingBracket() // class
|
||||||
|
.WriteClosingBracket(); // namespace
|
||||||
|
|
||||||
|
return new(builder.ToString(), $"{AttributeName}Attribute.g.cs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ namespace MapTo.Sources
|
||||||
internal const string AttributeName = "EfUpdateMethods";
|
internal const string AttributeName = "EfUpdateMethods";
|
||||||
internal const string AttributeClassName = AttributeName + "Attribute";
|
internal const string AttributeClassName = AttributeName + "Attribute";
|
||||||
internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
|
internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
|
||||||
|
|
||||||
internal static SourceCode Generate(SourceGenerationOptions options)
|
internal static SourceCode Generate(SourceGenerationOptions options)
|
||||||
{
|
{
|
||||||
using var builder = new SourceBuilder()
|
using var builder = new SourceBuilder()
|
||||||
|
@ -29,7 +29,7 @@ namespace MapTo.Sources
|
||||||
.WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]")
|
.WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]")
|
||||||
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
|
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
|
||||||
.WriteOpeningBracket();
|
.WriteOpeningBracket();
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.WriteLine($"public {AttributeName}Attribute(Type updateType, Type returnType, string keyPropertyMemberName)")
|
.WriteLine($"public {AttributeName}Attribute(Type updateType, Type returnType, string keyPropertyMemberName)")
|
||||||
.WriteOpeningBracket()
|
.WriteOpeningBracket()
|
|
@ -0,0 +1,47 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using static MapTo.Sources.Constants;
|
||||||
|
|
||||||
|
namespace MapTo.Sources
|
||||||
|
{
|
||||||
|
internal static class EfGetOneAttributeSource
|
||||||
|
{
|
||||||
|
internal const string AttributeName = "EfGetOne";
|
||||||
|
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("/// Attribute for generating a function to get one EF entity with a predicate as argument and a return type for the projection.")
|
||||||
|
.WriteLine("/// </summary>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]")
|
||||||
|
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
|
||||||
|
.WriteOpeningBracket();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine($"public {AttributeName}Attribute(Type returnType){"{}"}")
|
||||||
|
.WriteLine();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteClosingBracket() // class
|
||||||
|
.WriteClosingBracket(); // namespace
|
||||||
|
|
||||||
|
return new(builder.ToString(), $"{AttributeName}Attribute.g.cs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,9 +32,7 @@ namespace MapTo.Sources
|
||||||
.WriteOpeningBracket();
|
.WriteOpeningBracket();
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.WriteLine($"public {AttributeName}Attribute(Type createType = null, Type returnType = null)")
|
.WriteLine($"public {AttributeName}Attribute(Type createType = null, Type returnType = null){"{}"}")
|
||||||
.WriteOpeningBracket()
|
|
||||||
.WriteClosingBracket()
|
|
||||||
.WriteLine();
|
.WriteLine();
|
||||||
|
|
||||||
builder
|
builder
|
||||||
|
|
|
@ -21,22 +21,14 @@ namespace MapTo
|
||||||
|
|
||||||
|
|
||||||
public ImmutableArray<Diagnostic> Diagnostics { get; private set; }
|
public ImmutableArray<Diagnostic> Diagnostics { get; private set; }
|
||||||
|
|
||||||
public EfMethodsModel? Model { get; private set; }
|
public EfMethodsModel? Model { get; private set; }
|
||||||
|
|
||||||
protected Compilation Compilation { get; }
|
protected Compilation Compilation { get; }
|
||||||
|
|
||||||
protected INamedTypeSymbol MappingContextTypeSymbol { get; }
|
protected INamedTypeSymbol MappingContextTypeSymbol { get; }
|
||||||
|
|
||||||
protected SourceGenerationOptions SourceGenerationOptions { get; }
|
protected SourceGenerationOptions SourceGenerationOptions { get; }
|
||||||
|
|
||||||
protected TypeDeclarationSyntax TypeSyntax { get; }
|
protected TypeDeclarationSyntax TypeSyntax { get; }
|
||||||
|
|
||||||
protected ImmutableArray<string> Usings { get; private set; }
|
protected ImmutableArray<string> Usings { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
protected INamedTypeSymbol EfUpdateMethodsTypeSymbol { get; }
|
protected INamedTypeSymbol EfUpdateMethodsTypeSymbol { get; }
|
||||||
|
|
||||||
protected INamedTypeSymbol EfAddMethodsTypeSymbol { get; }
|
protected INamedTypeSymbol EfAddMethodsTypeSymbol { get; }
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +211,6 @@ namespace MapTo
|
||||||
|
|
||||||
protected bool IsEnumerable(ISymbol property, out INamedTypeSymbol? namedTypeSymbolResult)
|
protected bool IsEnumerable(ISymbol property, out INamedTypeSymbol? namedTypeSymbolResult)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!property.TryGetTypeSymbol(out var propertyType))
|
if (!property.TryGetTypeSymbol(out var propertyType))
|
||||||
{
|
{
|
||||||
AddDiagnostic(DiagnosticsFactory.NoMatchingPropertyTypeFoundError(property));
|
AddDiagnostic(DiagnosticsFactory.NoMatchingPropertyTypeFoundError(property));
|
||||||
|
@ -241,7 +232,7 @@ namespace MapTo
|
||||||
|
|
||||||
private ImmutableArray<MemberDeclarationSyntax> GetAllowedMemberSyntaxes(string attributeName)
|
private ImmutableArray<MemberDeclarationSyntax> GetAllowedMemberSyntaxes(string attributeName)
|
||||||
{
|
{
|
||||||
ClassDeclarationSyntax classDeclarationSyntax = TypeSyntax as ClassDeclarationSyntax;
|
var classDeclarationSyntax = TypeSyntax;
|
||||||
|
|
||||||
var syntaxes = classDeclarationSyntax.DescendantNodes()
|
var syntaxes = classDeclarationSyntax.DescendantNodes()
|
||||||
.OfType<MemberDeclarationSyntax>()
|
.OfType<MemberDeclarationSyntax>()
|
||||||
|
@ -265,44 +256,58 @@ namespace MapTo
|
||||||
var dbContextName = classDeclarationSyntax.Identifier.ValueText;
|
var dbContextName = classDeclarationSyntax.Identifier.ValueText;
|
||||||
var namespaceDeclaration = classDeclarationSyntax.Parent as NamespaceDeclarationSyntax;
|
var namespaceDeclaration = classDeclarationSyntax.Parent as NamespaceDeclarationSyntax;
|
||||||
var contextNamespace = namespaceDeclaration.Name.ToString();
|
var contextNamespace = namespaceDeclaration.Name.ToString();
|
||||||
|
|
||||||
var contextTypeFullName = $"{contextNamespace}.{dbContextName}";
|
var contextTypeFullName = $"{contextNamespace}.{dbContextName}";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// handles different attributes
|
||||||
var addAttributeSymbols = GetAllowedMemberSyntaxes(EfAddMethodsAttributeSource.AttributeName);
|
var addAttributeSymbols = GetAllowedMemberSyntaxes(EfAddMethodsAttributeSource.AttributeName);
|
||||||
|
|
||||||
var updateAttributesMembers = GetAllowedMemberSyntaxes(EfUpdateMethodsAttributeSource.AttributeName);
|
var updateAttributesMembers = GetAllowedMemberSyntaxes(EfUpdateMethodsAttributeSource.AttributeName);
|
||||||
|
|
||||||
var getOneAttributesMembers = GetAllowedMemberSyntaxes(EfGetOneByAttributeSource.AttributeName);
|
var getOneAttributesMembers = GetAllowedMemberSyntaxes(EfGetOneByAttributeSource.AttributeName);
|
||||||
|
var getOneWithAttributesMembers = GetAllowedMemberSyntaxes(EfGetOneAttributeSource.AttributeName);
|
||||||
|
var getManyWithAttributesMembers = GetAllowedMemberSyntaxes(EfGetManyAttributeSource.AttributeName);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
List<EfEntityDataModel> methodsModels = new List<EfEntityDataModel>();
|
List<EfEntityDataModel> methodsModels = new List<EfEntityDataModel>();
|
||||||
|
|
||||||
foreach (var uProperty in getOneAttributesMembers)
|
foreach (var uProperty in getOneAttributesMembers)
|
||||||
{
|
{
|
||||||
var newUpdateModel = ExtractEfGetEntityByModel(semanticModel, uProperty);
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
||||||
|
var newUpdateModel = ExtractEfGetEntityByModel(uProperty, semanticModel, entityDataModel);
|
||||||
methodsModels.Add(newUpdateModel);
|
methodsModels.Add(newUpdateModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
foreach (var uProperty in addAttributeSymbols)
|
foreach (var uProperty in addAttributeSymbols)
|
||||||
{
|
{
|
||||||
var entityTypeData = GetEntityTypeData(uProperty, semanticModel);
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
||||||
string entityIdentifierName = entityTypeData.Name;
|
|
||||||
string entityFullName = entityTypeData.ToDisplayString();
|
|
||||||
var propertyNamex = (uProperty as PropertyDeclarationSyntax).Identifier.ValueText;
|
|
||||||
var entityDataModel = new EfEntityDataModel(propertyNamex, entityFullName, entityIdentifierName);
|
|
||||||
var newAddModel = ExtractEfAddMethodsModel(semanticModel, uProperty, entityDataModel);
|
var newAddModel = ExtractEfAddMethodsModel(semanticModel, uProperty, entityDataModel);
|
||||||
methodsModels.Add(newAddModel);
|
methodsModels.Add(newAddModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var uProperty in updateAttributesMembers)
|
foreach (var uProperty in updateAttributesMembers)
|
||||||
{
|
{
|
||||||
var newUpdateModel = ExtractEfUpdateMethodsModel(semanticModel, uProperty);
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
||||||
|
var newUpdateModel = ExtractEfUpdateMethodsModel(uProperty, semanticModel, entityDataModel);
|
||||||
methodsModels.Add(newUpdateModel);
|
methodsModels.Add(newUpdateModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var uProperty in getOneWithAttributesMembers)
|
||||||
|
{
|
||||||
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
||||||
|
var newUpdateModel = ExtractEfGetEntityWithModel(uProperty, semanticModel, entityDataModel);
|
||||||
|
methodsModels.Add(newUpdateModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var uProperty in getManyWithAttributesMembers)
|
||||||
|
{
|
||||||
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
||||||
|
var newUpdateModel = ExtractEfGetManyModel(uProperty, semanticModel, entityDataModel);
|
||||||
|
methodsModels.Add(newUpdateModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//SpinWait.SpinUntil(() => Debugger.IsAttached);
|
//SpinWait.SpinUntil(() => Debugger.IsAttached);
|
||||||
|
@ -315,6 +320,15 @@ namespace MapTo
|
||||||
Usings);
|
Usings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static EfEntityDataModel GetEntityData(MemberDeclarationSyntax uProperty, SemanticModel semanticModel)
|
||||||
|
{
|
||||||
|
var entityTypeData = GetEntityTypeData(uProperty, semanticModel);
|
||||||
|
string entityIdentifierName = entityTypeData.Name;
|
||||||
|
string entityFullName = entityTypeData.ToDisplayString();
|
||||||
|
var propertyNamex = (uProperty as PropertyDeclarationSyntax).Identifier.ValueText;
|
||||||
|
return new EfEntityDataModel(propertyNamex, entityFullName, entityIdentifierName);
|
||||||
|
}
|
||||||
|
|
||||||
private EfAddMethodsModel ExtractEfAddMethodsModel(SemanticModel semanticModel, MemberDeclarationSyntax memberSyntax, EfEntityDataModel efEntityDataModel)
|
private EfAddMethodsModel ExtractEfAddMethodsModel(SemanticModel semanticModel, MemberDeclarationSyntax memberSyntax, EfEntityDataModel efEntityDataModel)
|
||||||
{
|
{
|
||||||
var efAddAttributeTypeSymbols =
|
var efAddAttributeTypeSymbols =
|
||||||
|
@ -343,28 +357,17 @@ namespace MapTo
|
||||||
returnTypeIdentifierName);
|
returnTypeIdentifierName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EfUpdateMethodsModel ExtractEfUpdateMethodsModel(SemanticModel semanticModel, MemberDeclarationSyntax uProperty)
|
private EfUpdateMethodsModel ExtractEfUpdateMethodsModel(MemberDeclarationSyntax uProperty, SemanticModel semanticModel, EfEntityDataModel entityDataModel)
|
||||||
{
|
{
|
||||||
var entityTypeData = GetEntityTypeData(uProperty, semanticModel);
|
|
||||||
string entityIdentifierName = entityTypeData.Name;
|
|
||||||
string entityFullName = entityTypeData.ToDisplayString();
|
|
||||||
var propertyNamex = (uProperty as PropertyDeclarationSyntax ).Identifier.ValueText;
|
|
||||||
var entityDataModel = new EfEntityDataModel(propertyNamex, entityFullName, entityIdentifierName);
|
|
||||||
|
|
||||||
var efAddAttributeTypeSymbols =
|
var efAddAttributeTypeSymbols =
|
||||||
GetEntityTypeSymbol(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel);
|
GetEntityTypeSymbol(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel);
|
||||||
|
|
||||||
var keyPropertyName = ExtractNameOfMemberName(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel);
|
var keyPropertyName = ExtractNameOfMemberName(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel);
|
||||||
|
|
||||||
var keyMemberType = FindFirstTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
var keyMemberType = FindFirstTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
||||||
|
//var secondTypeInfo = FindSecondTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
||||||
var secondTypeInfo = FindSecondTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var keyMemberFullName = keyMemberType.Value.Type.ToDisplayString();
|
var keyMemberFullName = keyMemberType.Value.Type.ToDisplayString();
|
||||||
var keyMemberName = keyMemberType.Value.Type.Name;
|
//var keyMemberName = keyMemberType.Value.Type.Name;
|
||||||
|
|
||||||
// Try grabbing string literal if there's no nameof in it
|
// Try grabbing string literal if there's no nameof in it
|
||||||
if (keyPropertyName == string.Empty)
|
if (keyPropertyName == string.Empty)
|
||||||
|
@ -399,29 +402,59 @@ namespace MapTo
|
||||||
returnTypeIdentifierName, keyPropertyName, keyMemberFullName);
|
returnTypeIdentifierName, keyPropertyName, keyMemberFullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EfGetOneByModel ExtractEfGetEntityByModel(SemanticModel semanticModel, MemberDeclarationSyntax uProperty)
|
private EfGetOneWithModel ExtractEfGetEntityWithModel(MemberDeclarationSyntax uProperty, SemanticModel semanticModel, EfEntityDataModel entityDataModel)
|
||||||
{
|
{
|
||||||
//SpinWait.SpinUntil(() => Debugger.IsAttached);
|
|
||||||
var entityTypeData = GetEntityTypeData(uProperty, semanticModel);
|
var efTypeofSymbols =GetEntityTypeSymbol(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel);
|
||||||
string entityIdentifierName = entityTypeData.Name;
|
if (efTypeofSymbols == null) return null;
|
||||||
string entityFullName = entityTypeData.ToDisplayString();
|
|
||||||
var propertyNamex = (uProperty as PropertyDeclarationSyntax).Identifier.ValueText;
|
string returnTypeIdentifierName = entityDataModel.EntityTypeIdentifierName;
|
||||||
var entityDataModel = new EfEntityDataModel(propertyNamex, entityFullName, entityIdentifierName);
|
string returnTypeFullName = entityDataModel.EntityTypeFullName;
|
||||||
|
|
||||||
|
|
||||||
var efTypeofSymbols =
|
// Grab return type from attribute argument
|
||||||
GetEntityTypeSymbol(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel);
|
if (efTypeofSymbols.Length > 0)
|
||||||
|
{
|
||||||
|
returnTypeIdentifierName = efTypeofSymbols[0].Name;
|
||||||
|
returnTypeFullName = efTypeofSymbols[0].ToDisplayString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return new EfGetOneWithModel(entityDataModel, returnTypeFullName, returnTypeIdentifierName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private EfGetManyModel ExtractEfGetManyModel(MemberDeclarationSyntax uProperty, SemanticModel semanticModel, EfEntityDataModel entityDataModel)
|
||||||
|
{
|
||||||
|
|
||||||
|
var efTypeofSymbols =GetEntityTypeSymbol(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel);
|
||||||
|
if (efTypeofSymbols == null) return null;
|
||||||
|
|
||||||
|
string returnTypeIdentifierName = entityDataModel.EntityTypeIdentifierName;
|
||||||
|
string returnTypeFullName = entityDataModel.EntityTypeFullName;
|
||||||
|
|
||||||
|
|
||||||
|
// Grab return type from attribute argument
|
||||||
|
if (efTypeofSymbols.Length > 0)
|
||||||
|
{
|
||||||
|
returnTypeIdentifierName = efTypeofSymbols[0].Name;
|
||||||
|
returnTypeFullName = efTypeofSymbols[0].ToDisplayString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return new EfGetManyModel(entityDataModel, returnTypeFullName, returnTypeIdentifierName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private EfGetOneByModel ExtractEfGetEntityByModel(MemberDeclarationSyntax uProperty, SemanticModel semanticModel, EfEntityDataModel entityDataModel)
|
||||||
|
{
|
||||||
|
|
||||||
|
var efTypeofSymbols = GetEntityTypeSymbol(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel);
|
||||||
var byParamPropertyName = ExtractNameOfMemberName(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel);
|
var byParamPropertyName = ExtractNameOfMemberName(uProperty, EfGetOneByAttributeSource.AttributeName, semanticModel);
|
||||||
|
|
||||||
var keyMemberType = FindFirstTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
var keyMemberType = FindFirstTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
||||||
|
|
||||||
var secondTypeInfo = FindSecondTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
|
||||||
|
|
||||||
|
var byParamFullTypeName = keyMemberType.Value.Type.ToDisplayString();
|
||||||
|
|
||||||
|
|
||||||
var byParamFullName = keyMemberType.Value.Type.ToDisplayString();
|
|
||||||
var byParamMemberName = keyMemberType.Value.Type.Name;
|
|
||||||
|
|
||||||
// Try grabbing string literal if there's no nameof in it
|
// Try grabbing string literal if there's no nameof in it
|
||||||
if (byParamPropertyName == string.Empty)
|
if (byParamPropertyName == string.Empty)
|
||||||
|
@ -445,19 +478,10 @@ namespace MapTo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return new EfGetOneByModel(entityDataModel, byParamPropertyName, byParamFullName, returnTypeFullName, returnTypeIdentifierName);
|
return new EfGetOneByModel(entityDataModel, byParamPropertyName, byParamFullTypeName, returnTypeFullName, returnTypeIdentifierName);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected ImmutableArray<IPropertySymbol> GetSymbolsFromAttribute(ITypeSymbol typeSymbol, INamedTypeSymbol attributeTypeSymbol)
|
|
||||||
{
|
|
||||||
return typeSymbol
|
|
||||||
.GetAllMembers()
|
|
||||||
.OfType<IPropertySymbol>()
|
|
||||||
.Where(p => p.HasAttribute(attributeTypeSymbol))
|
|
||||||
.ToImmutableArray()!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static ITypeSymbol GetEntityTypeData(MemberDeclarationSyntax memberDeclarationSyntax, SemanticModel? semanticModel = null)
|
private static ITypeSymbol GetEntityTypeData(MemberDeclarationSyntax memberDeclarationSyntax, SemanticModel? semanticModel = null)
|
||||||
{
|
{
|
||||||
var member = (memberDeclarationSyntax as PropertyDeclarationSyntax).Type;
|
var member = (memberDeclarationSyntax as PropertyDeclarationSyntax).Type;
|
||||||
|
@ -467,20 +491,5 @@ namespace MapTo
|
||||||
return firstTypeArgument;
|
return firstTypeArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private string? ToQualifiedDisplayName(ISymbol? symbol)
|
|
||||||
{
|
|
||||||
if (symbol is null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var containingNamespace = TypeSyntax.GetNamespace();
|
|
||||||
var symbolNamespace = symbol.ContainingNamespace.ToDisplayString();
|
|
||||||
return containingNamespace != symbolNamespace && _ignoredNamespaces.Contains(symbol.ContainingNamespace.ToDisplayParts().First())
|
|
||||||
? symbol.ToDisplayString()
|
|
||||||
: symbol.Name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,7 +33,9 @@ namespace MapTo
|
||||||
.AddSource(ref context, EfGeneratorAttributeSource.Generate(options))
|
.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))
|
||||||
.AddSource(ref context, EfGetOneByAttributeSource.Generate(options));
|
.AddSource(ref context, EfGetOneByAttributeSource.Generate(options))
|
||||||
|
.AddSource(ref context, EfGetOneAttributeSource.Generate(options))
|
||||||
|
.AddSource(ref context, EfGetManyAttributeSource.Generate(options));
|
||||||
|
|
||||||
|
|
||||||
if (context.SyntaxReceiver is EfMethodsSyntaxReceiver receiver && receiver.CandidateTypes.Any())
|
if (context.SyntaxReceiver is EfMethodsSyntaxReceiver receiver && receiver.CandidateTypes.Any())
|
||||||
|
@ -53,6 +55,10 @@ namespace MapTo
|
||||||
string addSourceTemplate = GetCsxMethodTemplate(context, "AddToEntityTemplate");
|
string addSourceTemplate = GetCsxMethodTemplate(context, "AddToEntityTemplate");
|
||||||
string updateSourceTemplate = GetCsxMethodTemplate(context, "UpdateEntityTemplate");
|
string updateSourceTemplate = GetCsxMethodTemplate(context, "UpdateEntityTemplate");
|
||||||
string getOneByTemplate = GetCsxMethodTemplate(context, "GetOneByTemplate");
|
string getOneByTemplate = GetCsxMethodTemplate(context, "GetOneByTemplate");
|
||||||
|
string getOneWithByTemplate = GetCsxMethodTemplate(context, "GetOneTemplate");
|
||||||
|
string getManyWithTemplate = GetCsxMethodTemplate(context, "GetManyTemplate");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var candidateMember in candidateMembers)
|
foreach (var candidateMember in candidateMembers)
|
||||||
{
|
{
|
||||||
|
@ -68,7 +74,13 @@ namespace MapTo
|
||||||
|
|
||||||
var (source, hintName) = candidateMember switch
|
var (source, hintName) = candidateMember switch
|
||||||
{
|
{
|
||||||
ClassDeclarationSyntax => EfMethodsSource.Generate(mappingContext.Model, addSourceTemplate, updateSourceTemplate, getOneByTemplate),
|
ClassDeclarationSyntax => EfMethodsSource.Generate(
|
||||||
|
mappingContext.Model,
|
||||||
|
addSourceTemplate,
|
||||||
|
updateSourceTemplate,
|
||||||
|
getOneByTemplate,
|
||||||
|
getOneWithByTemplate,
|
||||||
|
getManyWithTemplate),
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,13 @@ namespace MapTo.Sources
|
||||||
{
|
{
|
||||||
internal static class EfMethodsSource
|
internal static class EfMethodsSource
|
||||||
{
|
{
|
||||||
internal static SourceCode Generate(EfMethodsModel model, string addSourceTemplate, string updateSourceTemplate, string getOneBySourceTemplate)
|
internal static SourceCode Generate(EfMethodsModel model,
|
||||||
|
string addSourceTemplate,
|
||||||
|
string updateSourceTemplate,
|
||||||
|
string getOneBySourceTemplate,
|
||||||
|
string getOneWithSourceTemplate,
|
||||||
|
string getManyWithSourceTemplate
|
||||||
|
)
|
||||||
{
|
{
|
||||||
using var builder = new SourceBuilder();
|
using var builder = new SourceBuilder();
|
||||||
|
|
||||||
|
@ -38,27 +44,38 @@ namespace MapTo.Sources
|
||||||
|
|
||||||
foreach (var methodModel in model.MethodsModels.OrderBy(x => x.PropertyName))
|
foreach (var methodModel in model.MethodsModels.OrderBy(x => x.PropertyName))
|
||||||
{
|
{
|
||||||
if (methodModel is EfAddMethodsModel m)
|
switch (methodModel)
|
||||||
{
|
{
|
||||||
builder
|
case EfAddMethodsModel modl:
|
||||||
.EfAddAddEntityMethod(model,m, addSourceTemplate)
|
builder
|
||||||
|
.EfAddAddEntityMethod(model, modl, addSourceTemplate)
|
||||||
|
.WriteLine();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EfUpdateMethodsModel modl:
|
||||||
|
builder
|
||||||
|
.EfAddUpdateEntityMethod(model, modl, updateSourceTemplate)
|
||||||
|
.WriteLine();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EfGetOneByModel modl:
|
||||||
|
builder
|
||||||
|
.EfAddGetOneEntityByMethod(model, modl, getOneBySourceTemplate)
|
||||||
.WriteLine();
|
.WriteLine();
|
||||||
continue;
|
break;
|
||||||
}
|
case EfGetManyModel modl:
|
||||||
|
builder
|
||||||
if (methodModel is EfUpdateMethodsModel updateModel)
|
.EfAddGetManyWithMethod(model, modl, getManyWithSourceTemplate)
|
||||||
{
|
|
||||||
builder
|
|
||||||
.EfAddUpdateEntityMethod(model, updateModel, updateSourceTemplate)
|
|
||||||
.WriteLine();
|
.WriteLine();
|
||||||
continue;
|
break;
|
||||||
}
|
case EfGetOneWithModel modl:
|
||||||
if (methodModel is EfGetOneByModel getOneByModel)
|
builder
|
||||||
{
|
.EfAddGetOneEntityWithMethod(model, modl, getOneWithSourceTemplate)
|
||||||
builder
|
|
||||||
.EfAddGetOneEntityByMethod(model, getOneByModel, getOneBySourceTemplate)
|
|
||||||
.WriteLine();
|
.WriteLine();
|
||||||
continue;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
using MapTo.Extensions;
|
||||||
|
using MapTo.Sources;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MapTo
|
||||||
|
{
|
||||||
|
internal static class EfGetOneWithTemplateSource
|
||||||
|
{
|
||||||
|
internal static SourceBuilder EfAddGetOneEntityWithMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfGetOneWithModel model, string addSourceTemplate)
|
||||||
|
{
|
||||||
|
var returnTypeFullName = model.ReturnTypeFullName;
|
||||||
|
var entityTypeName = model.EntityTypeIdentifierName;
|
||||||
|
|
||||||
|
var contextFullName = methodsModel.ContextFullType;
|
||||||
|
var findEntityVarName = model.EntityTypeIdentifierName.ToCamelCase();
|
||||||
|
var propertyName = model.PropertyName;
|
||||||
|
|
||||||
|
if (!addSourceTemplate.IsEmpty())
|
||||||
|
{
|
||||||
|
var templateToSourceBuilder = new StringBuilder(addSourceTemplate);
|
||||||
|
templateToSourceBuilder
|
||||||
|
.Replace("{returnTypeFullName}", returnTypeFullName)
|
||||||
|
.Replace("{entityTypeName}", entityTypeName)
|
||||||
|
.Replace("{contextFullName}", contextFullName)
|
||||||
|
.Replace("{contextFullName}", contextFullName)
|
||||||
|
.Replace("{findEntityVarName}", findEntityVarName)
|
||||||
|
.Replace("{propertyName}", propertyName);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.ParseTemplate(templateToSourceBuilder.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addSourceTemplate.IsEmpty())
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteComment("Generated body")
|
||||||
|
//.WriteLine(GeneratedFilesHeader)
|
||||||
|
.WriteLine($"public static (bool, {returnTypeFullName}) GetOne{entityTypeName}With (this {contextFullName} dbContext, Expression<Func<{returnTypeFullName},bool>> with) ")
|
||||||
|
.WriteOpeningBracket()
|
||||||
|
.WriteLine($"var {findEntityVarName} =")
|
||||||
|
.WriteLine($".Select(x => new {returnTypeFullName}(x))")
|
||||||
|
.WriteLine($".FirstOrDefault(with);")
|
||||||
|
.WriteLine()
|
||||||
|
.WriteLine($"return ({findEntityVarName} != null, {findEntityVarName});")
|
||||||
|
.WriteClosingBracket();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static SourceBuilder EfAddGetManyWithMethod(this SourceBuilder builder, EfMethodsModel methodsModel, EfGetManyModel model, string addSourceTemplate)
|
||||||
|
{
|
||||||
|
var returnTypeFullName = model.ReturnTypeFullName;
|
||||||
|
var entityTypeName = model.EntityTypeIdentifierName;
|
||||||
|
|
||||||
|
var contextFullName = methodsModel.ContextFullType;
|
||||||
|
var findEntityVarName = model.EntityTypeIdentifierName.ToCamelCase();
|
||||||
|
var propertyName = model.PropertyName;
|
||||||
|
|
||||||
|
if (!addSourceTemplate.IsEmpty())
|
||||||
|
{
|
||||||
|
var templateToSourceBuilder = new StringBuilder(addSourceTemplate);
|
||||||
|
templateToSourceBuilder
|
||||||
|
.Replace("{returnTypeFullName}", returnTypeFullName)
|
||||||
|
.Replace("{entityTypeName}", entityTypeName)
|
||||||
|
.Replace("{contextFullName}", contextFullName)
|
||||||
|
.Replace("{contextFullName}", contextFullName)
|
||||||
|
.Replace("{findEntityVarName}", findEntityVarName)
|
||||||
|
.Replace("{propertyName}", propertyName);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.ParseTemplate(templateToSourceBuilder.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addSourceTemplate.IsEmpty())
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.WriteComment("Generated body")
|
||||||
|
//.WriteLine(GeneratedFilesHeader)
|
||||||
|
.WriteLine($"public static (bool, ImmutableArray<{returnTypeFullName}>) Get{propertyName}(this {contextFullName}dbContext, Expression <Func<{returnTypeFullName}, bool> > where = null,")
|
||||||
|
.WriteLine($"Expression <Func<{returnTypeFullName}, object> > orderBy = null, int skip = 0, int take = 50, int orderDir = 1)")
|
||||||
|
.WriteOpeningBracket()
|
||||||
|
.WriteLine($"var query = dbContext")
|
||||||
|
.WriteLine($".{propertyName}")
|
||||||
|
.WriteLine($".Select(x => new {returnTypeFullName}(x));")
|
||||||
|
.WriteComment("limit take by 200 records")
|
||||||
|
.WriteLine("if (take > 200) take = 200;")
|
||||||
|
.WriteLine("query.Skip(skip).Take(take);")
|
||||||
|
.WriteLine("if (where != null) query.Where(where);")
|
||||||
|
.WriteLine("if (orderDir == 1) query.OrderBy(orderBy);")
|
||||||
|
.WriteLine("else query.OrderByDescending(orderBy);")
|
||||||
|
.WriteLine($"return query.ToImmutableArray();")
|
||||||
|
.WriteClosingBracket();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -58,6 +58,7 @@ namespace MapTo
|
||||||
foreach (var typeDeclarationSyntax in candidateTypes)
|
foreach (var typeDeclarationSyntax in candidateTypes)
|
||||||
{
|
{
|
||||||
var mappingContext = MappingContext.Create(compilation, options, typeDeclarationSyntax);
|
var mappingContext = MappingContext.Create(compilation, options, typeDeclarationSyntax);
|
||||||
|
|
||||||
mappingContext.Diagnostics.ForEach(context.ReportDiagnostic);
|
mappingContext.Diagnostics.ForEach(context.ReportDiagnostic);
|
||||||
|
|
||||||
if (mappingContext.Model is null)
|
if (mappingContext.Model is null)
|
||||||
|
@ -65,7 +66,6 @@ namespace MapTo
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var (source, hintName) = typeDeclarationSyntax switch
|
var (source, hintName) = typeDeclarationSyntax switch
|
||||||
{
|
{
|
||||||
StructDeclarationSyntax => MapStructSource.Generate(mappingContext.Model),
|
StructDeclarationSyntax => MapStructSource.Generate(mappingContext.Model),
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace MapTo
|
||||||
internal class EfAddMethodsModel : EfEntityDataModel
|
internal class EfAddMethodsModel : EfEntityDataModel
|
||||||
{
|
{
|
||||||
public string CreateTypeFullName { get; set; }
|
public string CreateTypeFullName { get; set; }
|
||||||
public string CreateTypeIdentifierName { get; set; }
|
public string CreateTypeIdentifierName { get; set; }
|
||||||
public string ReturnTypeFullName { get; set; }
|
public string ReturnTypeFullName { get; set; }
|
||||||
public string ReturnTypeIdentifierName { get; set; }
|
public string ReturnTypeIdentifierName { get; set; }
|
||||||
|
|
||||||
|
@ -137,6 +137,32 @@ namespace MapTo
|
||||||
ByParamTypeName = returnTypeFullName;
|
ByParamTypeName = returnTypeFullName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class EfGetOneWithModel : EfEntityDataModel
|
||||||
|
{
|
||||||
|
public string ReturnTypeIdentifierName { get; set; }
|
||||||
|
public string ReturnTypeFullName { get; set; }
|
||||||
|
|
||||||
|
public EfGetOneWithModel(EfEntityDataModel entity, string returnTypeFullName,
|
||||||
|
string returnTypeIdentifierName) : base(entity.PropertyName, entity.EntityTypeFullName, entity.EntityTypeIdentifierName)
|
||||||
|
{
|
||||||
|
ReturnTypeIdentifierName = returnTypeIdentifierName;
|
||||||
|
ReturnTypeFullName = returnTypeFullName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class EfGetManyModel : EfEntityDataModel
|
||||||
|
{
|
||||||
|
public string ReturnTypeIdentifierName { get; set; }
|
||||||
|
public string ReturnTypeFullName { get; set; }
|
||||||
|
|
||||||
|
public EfGetManyModel(EfEntityDataModel entity, string returnTypeFullName,
|
||||||
|
string returnTypeIdentifierName) : base(entity.PropertyName, entity.EntityTypeFullName, entity.EntityTypeIdentifierName)
|
||||||
|
{
|
||||||
|
ReturnTypeIdentifierName = returnTypeIdentifierName;
|
||||||
|
ReturnTypeFullName = returnTypeFullName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class EfUpdateMethodsModel : EfEntityDataModel
|
internal class EfUpdateMethodsModel : EfEntityDataModel
|
||||||
|
|
Loading…
Reference in New Issue