2022-09-06 00:47:58 +03:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Collections.Immutable;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Threading;
|
2022-09-08 06:16:31 +03:00
|
|
|
using BlueWest.EfMethods.EfMethods.AttributeSources;
|
2022-09-06 01:14:31 +03:00
|
|
|
using BlueWest.EfMethods.Extensions;
|
|
|
|
using BlueWest.EfMethods.Sources;
|
2022-09-08 06:16:31 +03:00
|
|
|
using BlueWest.Sources;
|
2022-09-06 00:47:58 +03:00
|
|
|
using Microsoft.CodeAnalysis;
|
|
|
|
using Microsoft.CodeAnalysis.CSharp;
|
|
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
|
|
using CSharpExtensions = Microsoft.CodeAnalysis.CSharpExtensions;
|
|
|
|
|
|
|
|
#pragma warning disable CS8602
|
|
|
|
|
2022-09-06 01:14:31 +03:00
|
|
|
namespace BlueWest.EfMethods
|
2022-09-06 00:47:58 +03:00
|
|
|
{
|
|
|
|
internal class EfGeneratorContext
|
|
|
|
{
|
|
|
|
private readonly List<SymbolDisplayPart> _ignoredNamespaces;
|
|
|
|
|
|
|
|
|
|
|
|
public ImmutableArray<Diagnostic> Diagnostics { get; private set; }
|
|
|
|
public EfMethodsModel? Model { get; private set; }
|
|
|
|
protected Compilation Compilation { get; }
|
|
|
|
protected INamedTypeSymbol MappingContextTypeSymbol { get; }
|
|
|
|
protected SourceGenerationOptions SourceGenerationOptions { get; }
|
|
|
|
protected TypeDeclarationSyntax TypeSyntax { get; }
|
|
|
|
|
|
|
|
protected ImmutableArray<string> Usings { get; private set; }
|
|
|
|
protected INamedTypeSymbol EfUpdateMethodsTypeSymbol { get; }
|
|
|
|
protected INamedTypeSymbol EfAddMethodsTypeSymbol { get; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected EfGeneratorContext(
|
|
|
|
Compilation compilation,
|
|
|
|
SourceGenerationOptions sourceGenerationOptions,
|
|
|
|
TypeDeclarationSyntax typeSyntax)
|
|
|
|
{
|
|
|
|
Compilation = compilation;
|
|
|
|
_ignoredNamespaces = new();
|
|
|
|
Diagnostics = ImmutableArray<Diagnostic>.Empty;
|
|
|
|
Usings = ImmutableArray.Create("System", Constants.RootNamespace);
|
|
|
|
SourceGenerationOptions = sourceGenerationOptions;
|
|
|
|
TypeSyntax = typeSyntax;
|
|
|
|
EfUpdateMethodsTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(EfUpdateMethodsAttributeSource.FullyQualifiedName);
|
|
|
|
EfAddMethodsTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(EfAddMethodsAttributeSource.FullyQualifiedName);
|
|
|
|
AddUsingIfRequired(sourceGenerationOptions.SupportNullableStaticAnalysis, "System.Diagnostics.CodeAnalysis");
|
|
|
|
}
|
|
|
|
|
|
|
|
public static EfGeneratorContext Create(
|
|
|
|
Compilation compilation,
|
|
|
|
SourceGenerationOptions sourceGenerationOptions,
|
|
|
|
TypeDeclarationSyntax typeSyntax)
|
|
|
|
{
|
|
|
|
EfGeneratorContext context = typeSyntax switch
|
|
|
|
{
|
|
|
|
ClassDeclarationSyntax => new EfGeneratorContext(compilation, sourceGenerationOptions, typeSyntax),
|
|
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
|
|
};
|
|
|
|
|
|
|
|
context.Model = context.CreateMappingModel();
|
|
|
|
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void AddDiagnostic(Diagnostic diagnostic)
|
|
|
|
{
|
|
|
|
Diagnostics = Diagnostics.Add(diagnostic);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void AddUsingIfRequired(ISymbol? namedTypeSymbol) =>
|
|
|
|
AddUsingIfRequired(namedTypeSymbol?.ContainingNamespace.IsGlobalNamespace == false, namedTypeSymbol?.ContainingNamespace);
|
|
|
|
|
|
|
|
protected void AddUsingIfRequired(bool condition, INamespaceSymbol? ns) =>
|
|
|
|
AddUsingIfRequired(condition && ns is not null && !_ignoredNamespaces.Contains(ns.ToDisplayParts().First()), ns?.ToDisplayString());
|
|
|
|
|
|
|
|
protected void AddUsingIfRequired(bool condition, string? ns)
|
|
|
|
{
|
|
|
|
if (ns is not null && condition && ns != TypeSyntax.GetNamespace() && !Usings.Contains(ns))
|
|
|
|
{
|
|
|
|
Usings = Usings.Add(ns);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected ImmutableArray<INamedTypeSymbol> GetEntityTypeSymbol(MemberDeclarationSyntax memberDeclarationSyntax, string attributeName, SemanticModel? semanticModel = null)
|
|
|
|
{
|
|
|
|
var attributeData = memberDeclarationSyntax.GetAttribute(attributeName);
|
|
|
|
var sourceSymbol = GetEntityTypeSymbols(attributeData, semanticModel);
|
|
|
|
return sourceSymbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected ImmutableArray<LiteralExpressionSyntax> GetEntityStringLiteralSymbol(MemberDeclarationSyntax memberDeclarationSyntax, string attributeName, SemanticModel? semanticModel = null)
|
|
|
|
{
|
|
|
|
var attributeData = memberDeclarationSyntax.GetAttribute(attributeName);
|
|
|
|
var sourceSymbol = GetEntityStringLiteralSymbol(attributeData);
|
|
|
|
return sourceSymbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected TypeInfo FindSecondTypeInfoOfMemberExpressionSyntax(SemanticModel semanticModel, SyntaxNode attributeSyntax)
|
|
|
|
{
|
|
|
|
semanticModel ??= Compilation.GetSemanticModel(attributeSyntax.SyntaxTree);
|
|
|
|
var descendentNodes = attributeSyntax
|
|
|
|
.DescendantNodes();
|
|
|
|
|
|
|
|
var expression = descendentNodes.OfType<MemberAccessExpressionSyntax>().FirstOrDefault()?.Expression;
|
|
|
|
if (expression != null)
|
|
|
|
{
|
|
|
|
return semanticModel.GetTypeInfo(expression);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new TypeInfo();
|
|
|
|
}
|
|
|
|
|
2022-09-08 06:16:31 +03:00
|
|
|
protected TypeInfo? FindTypeInfoOfMemberExpressionSyntax(SemanticModel semanticModel, SyntaxNode attributeSyntax, int skip = 0)
|
2022-09-06 00:47:58 +03:00
|
|
|
{
|
|
|
|
semanticModel ??= Compilation.GetSemanticModel(attributeSyntax.SyntaxTree);
|
|
|
|
var descendentNodes = attributeSyntax
|
|
|
|
.DescendantNodes();
|
|
|
|
|
|
|
|
// Get the type of the key member id
|
2022-09-08 06:16:31 +03:00
|
|
|
var expression = descendentNodes
|
|
|
|
.OfType<MemberAccessExpressionSyntax>()
|
|
|
|
.Skip(skip)
|
|
|
|
.FirstOrDefault();
|
|
|
|
|
2022-09-06 00:47:58 +03:00
|
|
|
if (expression != null)
|
|
|
|
{
|
|
|
|
return semanticModel.GetTypeInfo(expression);
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-08 06:16:31 +03:00
|
|
|
protected string ExtractNameOfMemberName(MemberDeclarationSyntax memberDeclarationSyntax, string attributeName, SemanticModel? semanticModel = null, int skip = 0)
|
2022-09-06 00:47:58 +03:00
|
|
|
{
|
|
|
|
var attributeData = memberDeclarationSyntax.GetAttribute(attributeName);
|
2022-09-08 06:16:31 +03:00
|
|
|
var sourceSymbol = ExtractNameOfMemberName(attributeData, semanticModel, skip);
|
2022-09-06 00:47:58 +03:00
|
|
|
return sourceSymbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected ImmutableArray<INamedTypeSymbol> GetEntityTypeSymbols(SyntaxNode? attributeSyntax, SemanticModel? semanticModel = null)
|
|
|
|
{
|
|
|
|
if (attributeSyntax is null)
|
|
|
|
{
|
|
|
|
return new ImmutableArray<INamedTypeSymbol>(){};
|
|
|
|
}
|
|
|
|
|
|
|
|
semanticModel ??= Compilation.GetSemanticModel(attributeSyntax.SyntaxTree);
|
|
|
|
var descendentNodes = attributeSyntax
|
|
|
|
.DescendantNodes();
|
|
|
|
|
|
|
|
var sourceTypeExpressionSyntax = descendentNodes
|
|
|
|
.OfType<TypeOfExpressionSyntax>()
|
|
|
|
.ToImmutableArray();
|
|
|
|
|
|
|
|
// cast
|
|
|
|
var resultList = new List<INamedTypeSymbol>();
|
|
|
|
for (int i = 0; i < sourceTypeExpressionSyntax.Length; i++)
|
|
|
|
{
|
|
|
|
var sourceTypeExpression = sourceTypeExpressionSyntax[i];
|
|
|
|
if (semanticModel.GetTypeInfo(sourceTypeExpression.Type).Type is INamedTypeSymbol namedTypeSymbol)
|
|
|
|
{
|
|
|
|
resultList.Add(namedTypeSymbol);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return resultList.ToImmutableArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected ImmutableArray<LiteralExpressionSyntax> GetEntityStringLiteralSymbol(SyntaxNode? attributeSyntax)
|
|
|
|
{
|
|
|
|
if (attributeSyntax is null)
|
|
|
|
{
|
|
|
|
return new ImmutableArray<LiteralExpressionSyntax>(){};
|
|
|
|
}
|
|
|
|
|
|
|
|
var descendentNodes = attributeSyntax
|
|
|
|
.DescendantNodes();
|
|
|
|
|
|
|
|
var sourceTypeExpressionSyntax = descendentNodes
|
|
|
|
.OfType<LiteralExpressionSyntax>()
|
|
|
|
.ToImmutableArray();
|
|
|
|
|
|
|
|
|
|
|
|
return sourceTypeExpressionSyntax;
|
|
|
|
}
|
|
|
|
|
2022-09-08 06:16:31 +03:00
|
|
|
protected string ExtractNameOfMemberName(SyntaxNode? attributeSyntax, SemanticModel semanticModel, int skip)
|
2022-09-06 00:47:58 +03:00
|
|
|
{
|
|
|
|
if (attributeSyntax is null)
|
|
|
|
{
|
|
|
|
return string.Empty;
|
|
|
|
}
|
|
|
|
|
|
|
|
var descendentNodes = attributeSyntax
|
|
|
|
.DescendantNodes();
|
|
|
|
|
|
|
|
var idNode = descendentNodes.OfType<InvocationExpressionSyntax>()
|
2022-09-08 06:16:31 +03:00
|
|
|
.Skip(skip)
|
2022-09-06 00:47:58 +03:00
|
|
|
.FirstOrDefault()
|
|
|
|
?.ChildNodesAndTokens()
|
|
|
|
.FirstOrDefault(x => x.IsKind(SyntaxKind.ArgumentList))
|
|
|
|
.ChildNodesAndTokens()
|
|
|
|
.FirstOrDefault(x => x.IsKind(SyntaxKind.Argument))
|
|
|
|
.ChildNodesAndTokens()
|
|
|
|
.FirstOrDefault()
|
|
|
|
.ChildNodesAndTokens()
|
|
|
|
.LastOrDefault();
|
|
|
|
|
|
|
|
return idNode != null ? idNode.ToString() : String.Empty;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected bool IsEnumerable(ISymbol property, out INamedTypeSymbol? namedTypeSymbolResult)
|
|
|
|
{
|
|
|
|
if (!property.TryGetTypeSymbol(out var propertyType))
|
|
|
|
{
|
2022-09-06 01:14:31 +03:00
|
|
|
// Todo add diagnostic
|
|
|
|
//AddDiagnostic(DiagnosticsFactory.NoMatchingPropertyTypeFoundError(property));
|
2022-09-06 00:47:58 +03:00
|
|
|
namedTypeSymbolResult = null;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
propertyType is INamedTypeSymbol namedTypeSymbol &&
|
|
|
|
!propertyType.IsPrimitiveType() &&
|
|
|
|
(Compilation.IsGenericEnumerable(propertyType) || propertyType.AllInterfaces.Any(i => Compilation.IsGenericEnumerable(i))))
|
|
|
|
{
|
|
|
|
namedTypeSymbolResult = namedTypeSymbol;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
namedTypeSymbolResult = null;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private ImmutableArray<MemberDeclarationSyntax> GetAllowedMemberSyntaxes(string attributeName)
|
|
|
|
{
|
|
|
|
var classDeclarationSyntax = TypeSyntax;
|
|
|
|
|
|
|
|
var syntaxes = classDeclarationSyntax.DescendantNodes()
|
|
|
|
.OfType<MemberDeclarationSyntax>()
|
|
|
|
.Where(x => x
|
|
|
|
.DescendantNodes()
|
|
|
|
.OfType<AttributeSyntax>().Any(syntax =>
|
|
|
|
syntax.Name.ToString() == attributeName))
|
|
|
|
.ToImmutableArray();
|
|
|
|
|
|
|
|
return syntaxes;
|
|
|
|
}
|
|
|
|
|
|
|
|
private EfMethodsModel? CreateMappingModel()
|
|
|
|
{
|
|
|
|
var semanticModel = Compilation.GetSemanticModel(TypeSyntax.SyntaxTree);
|
|
|
|
|
|
|
|
// get containing class type information
|
|
|
|
ClassDeclarationSyntax classDeclarationSyntax = TypeSyntax as ClassDeclarationSyntax;
|
|
|
|
|
|
|
|
// context name
|
|
|
|
var dbContextName = classDeclarationSyntax.Identifier.ValueText;
|
|
|
|
var namespaceDeclaration = classDeclarationSyntax.Parent as NamespaceDeclarationSyntax;
|
|
|
|
var contextNamespace = namespaceDeclaration.Name.ToString();
|
|
|
|
var contextTypeFullName = $"{contextNamespace}.{dbContextName}";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// handles different attributes
|
2022-09-08 06:16:31 +03:00
|
|
|
var addMembers = GetAllowedMemberSyntaxes(EfAddMethodsAttributeSource.AttributeName);
|
|
|
|
var updateMembers = GetAllowedMemberSyntaxes(EfUpdateMethodsAttributeSource.AttributeName);
|
|
|
|
var getOneByMembers = GetAllowedMemberSyntaxes(EfGetOneByAttributeSource.AttributeName);
|
|
|
|
var getOneMembers = GetAllowedMemberSyntaxes(EfGetOneAttributeSource.AttributeName);
|
|
|
|
var efGetManyMembers = GetAllowedMemberSyntaxes(EfGetManyAttributeSource.AttributeName);
|
|
|
|
var getListMembers = GetAllowedMemberSyntaxes(EfGetListAttributeSource.AttributeName);
|
|
|
|
var getAddToListMembers = GetAllowedMemberSyntaxes(EfAddToListAttributeSource.AttributeName);
|
|
|
|
|
2022-09-06 00:47:58 +03:00
|
|
|
|
|
|
|
|
|
|
|
List<EfEntityDataModel> methodsModels = new List<EfEntityDataModel>();
|
|
|
|
|
2022-09-08 06:16:31 +03:00
|
|
|
foreach (var uProperty in getOneByMembers)
|
2022-09-06 00:47:58 +03:00
|
|
|
{
|
|
|
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
|
|
|
var newUpdateModel = ExtractEfGetEntityByModel(uProperty, semanticModel, entityDataModel);
|
|
|
|
methodsModels.Add(newUpdateModel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-08 06:16:31 +03:00
|
|
|
foreach (var uProperty in addMembers)
|
2022-09-06 00:47:58 +03:00
|
|
|
{
|
|
|
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
|
|
|
var newAddModel = ExtractEfAddMethodsModel(semanticModel, uProperty, entityDataModel);
|
|
|
|
methodsModels.Add(newAddModel);
|
|
|
|
}
|
|
|
|
|
2022-09-08 06:16:31 +03:00
|
|
|
foreach (var uProperty in updateMembers)
|
2022-09-06 00:47:58 +03:00
|
|
|
{
|
|
|
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
|
|
|
var newUpdateModel = ExtractEfUpdateMethodsModel(uProperty, semanticModel, entityDataModel);
|
|
|
|
methodsModels.Add(newUpdateModel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-08 06:16:31 +03:00
|
|
|
foreach (var uProperty in getOneMembers)
|
2022-09-06 00:47:58 +03:00
|
|
|
{
|
|
|
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
|
|
|
var newUpdateModel = ExtractEfGetEntityWithModel(uProperty, semanticModel, entityDataModel);
|
|
|
|
methodsModels.Add(newUpdateModel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-08 06:16:31 +03:00
|
|
|
foreach (var uProperty in efGetManyMembers)
|
2022-09-06 00:47:58 +03:00
|
|
|
{
|
|
|
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
|
|
|
var newUpdateModel = ExtractEfGetManyModel(uProperty, semanticModel, entityDataModel);
|
|
|
|
methodsModels.Add(newUpdateModel);
|
|
|
|
}
|
2022-09-08 06:16:31 +03:00
|
|
|
|
|
|
|
foreach (var uProperty in getListMembers)
|
|
|
|
{
|
|
|
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
|
|
|
var newModel = ExtractEfGetListModel(uProperty, semanticModel, entityDataModel);
|
|
|
|
methodsModels.Add(newModel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var uProperty in getAddToListMembers)
|
|
|
|
{
|
|
|
|
var entityDataModel = GetEntityData(uProperty, semanticModel);
|
|
|
|
var newModel = ExtractEfAddToListMethodsModel(uProperty, semanticModel, entityDataModel);
|
|
|
|
methodsModels.Add(newModel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-06 00:47:58 +03:00
|
|
|
|
|
|
|
|
|
|
|
//SpinWait.SpinUntil(() => Debugger.IsAttached);
|
|
|
|
|
|
|
|
return new EfMethodsModel(
|
|
|
|
SourceGenerationOptions,
|
|
|
|
contextNamespace,
|
|
|
|
dbContextName, contextTypeFullName,
|
|
|
|
methodsModels.ToImmutableArray(),
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
var efAddAttributeTypeSymbols =
|
|
|
|
GetEntityTypeSymbol(memberSyntax, EfAddMethodsAttributeSource.AttributeName, semanticModel);
|
|
|
|
|
|
|
|
string createTypeIdentifierName = efEntityDataModel.EntityTypeIdentifierName;
|
|
|
|
string createTypeFullName = efEntityDataModel.EntityTypeFullName;
|
|
|
|
string returnTypeIdentifierName = efEntityDataModel.EntityTypeIdentifierName;
|
|
|
|
string returnTypeFullName = efEntityDataModel.EntityTypeFullName;
|
|
|
|
|
|
|
|
|
|
|
|
if (efAddAttributeTypeSymbols.Length > 0)
|
|
|
|
{
|
|
|
|
createTypeIdentifierName = efAddAttributeTypeSymbols[0].Name;
|
|
|
|
createTypeFullName = efAddAttributeTypeSymbols[0].ToDisplayString();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (efAddAttributeTypeSymbols.Length > 1)
|
|
|
|
{
|
|
|
|
returnTypeIdentifierName = efAddAttributeTypeSymbols[1].Name;
|
|
|
|
returnTypeFullName = efAddAttributeTypeSymbols[1].ToDisplayString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return new EfAddMethodsModel(efEntityDataModel, createTypeFullName, createTypeIdentifierName, returnTypeFullName,
|
|
|
|
returnTypeIdentifierName);
|
|
|
|
}
|
|
|
|
|
|
|
|
private EfUpdateMethodsModel ExtractEfUpdateMethodsModel(MemberDeclarationSyntax uProperty, SemanticModel semanticModel, EfEntityDataModel entityDataModel)
|
|
|
|
{
|
|
|
|
var efAddAttributeTypeSymbols =
|
|
|
|
GetEntityTypeSymbol(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel);
|
|
|
|
|
|
|
|
var keyPropertyName = ExtractNameOfMemberName(uProperty, EfUpdateMethodsAttributeSource.AttributeName, semanticModel);
|
2022-09-08 06:16:31 +03:00
|
|
|
var keyMemberType = FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
2022-09-06 00:47:58 +03:00
|
|
|
//var secondTypeInfo = FindSecondTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
|
|
|
|
|
|
|
var keyMemberFullName = keyMemberType.Value.Type.ToDisplayString();
|
|
|
|
//var keyMemberName = keyMemberType.Value.Type.Name;
|
|
|
|
|
|
|
|
// Try grabbing string literal if there's no nameof in it
|
|
|
|
if (keyPropertyName == string.Empty)
|
|
|
|
{
|
|
|
|
keyPropertyName = GetEntityStringLiteralSymbol(TypeSyntax, EfUpdateMethodsAttributeSource.AttributeName, semanticModel)
|
|
|
|
.FirstOrDefault()?
|
|
|
|
.Token.ValueText ?? "Id";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (efAddAttributeTypeSymbols == null) return null;
|
|
|
|
|
|
|
|
string updateTypeIdentifierName = entityDataModel.EntityTypeIdentifierName;
|
|
|
|
string updateTypeFullName = entityDataModel.EntityTypeFullName;
|
|
|
|
string returnTypeIdentifierName = entityDataModel.EntityTypeIdentifierName;
|
|
|
|
string returnTypeFullName = entityDataModel.EntityTypeFullName;
|
|
|
|
|
|
|
|
if (efAddAttributeTypeSymbols.Length > 0)
|
|
|
|
{
|
|
|
|
updateTypeIdentifierName = efAddAttributeTypeSymbols[0].Name;
|
|
|
|
updateTypeFullName = efAddAttributeTypeSymbols[0].ToDisplayString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Grab return type from attribute argument
|
|
|
|
if (efAddAttributeTypeSymbols.Length > 1)
|
|
|
|
{
|
|
|
|
returnTypeIdentifierName = efAddAttributeTypeSymbols[1].Name;
|
|
|
|
returnTypeFullName = efAddAttributeTypeSymbols[1].ToDisplayString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return new EfUpdateMethodsModel(entityDataModel, updateTypeFullName, updateTypeIdentifierName, returnTypeFullName,
|
|
|
|
returnTypeIdentifierName, keyPropertyName, keyMemberFullName);
|
|
|
|
}
|
|
|
|
|
|
|
|
private EfGetOneWithModel ExtractEfGetEntityWithModel(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 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);
|
2022-09-08 06:16:31 +03:00
|
|
|
var keyMemberType = FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
2022-09-06 00:47:58 +03:00
|
|
|
|
|
|
|
var byParamFullTypeName = keyMemberType.Value.Type.ToDisplayString();
|
|
|
|
|
|
|
|
// Try grabbing string literal if there's no nameof in it
|
|
|
|
if (byParamPropertyName == string.Empty)
|
|
|
|
{
|
|
|
|
byParamPropertyName = GetEntityStringLiteralSymbol(TypeSyntax, EfGetOneByAttributeSource.AttributeName, semanticModel)
|
|
|
|
.FirstOrDefault()?
|
|
|
|
.Token.ValueText ?? "Id";
|
|
|
|
}
|
|
|
|
|
|
|
|
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 EfGetOneByModel(entityDataModel, byParamPropertyName, byParamFullTypeName, returnTypeFullName, returnTypeIdentifierName);
|
|
|
|
}
|
|
|
|
|
2022-09-08 06:16:31 +03:00
|
|
|
|
|
|
|
private EfGetListModel ExtractEfGetListModel(MemberDeclarationSyntax uProperty, SemanticModel semanticModel, EfEntityDataModel entityDataModel)
|
|
|
|
{
|
|
|
|
|
|
|
|
var efTypeofSymbols = GetEntityTypeSymbol(uProperty, EfGetListAttributeSource.AttributeName, semanticModel);
|
|
|
|
|
|
|
|
var listPropertyName = ExtractNameOfMemberName(uProperty, EfGetListAttributeSource.AttributeName, semanticModel);
|
|
|
|
var keyPropertyName = ExtractNameOfMemberName(uProperty, EfGetListAttributeSource.AttributeName, semanticModel, 1);;
|
|
|
|
var keyMemberType = FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
|
|
|
var keyFullTypeName = keyMemberType.Value.Type.ToDisplayString();
|
|
|
|
|
|
|
|
|
|
|
|
// Try grabbing string literal if there's no nameof in it
|
|
|
|
if (keyPropertyName == string.Empty)
|
|
|
|
{
|
|
|
|
listPropertyName = GetEntityStringLiteralSymbol(TypeSyntax, EfGetListAttributeSource.AttributeName, semanticModel)
|
|
|
|
.FirstOrDefault()?
|
|
|
|
.Token.ValueText ?? "Id";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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 EfGetListModel(entityDataModel, listPropertyName, keyPropertyName, keyFullTypeName, returnTypeIdentifierName, returnTypeFullName);
|
|
|
|
}
|
|
|
|
|
|
|
|
private EfAddToListModel ExtractEfAddToListMethodsModel(MemberDeclarationSyntax uProperty, SemanticModel semanticModel, EfEntityDataModel entityDataModel)
|
|
|
|
{
|
|
|
|
|
|
|
|
//SpinWait.SpinUntil(() => Debugger.IsAttached);
|
|
|
|
|
|
|
|
var efTypeofSymbols = GetEntityTypeSymbol(uProperty, EfAddToListAttributeSource.AttributeName, semanticModel);
|
|
|
|
|
|
|
|
var listPropertyName = ExtractNameOfMemberName(uProperty, EfAddToListAttributeSource.AttributeName, semanticModel);
|
|
|
|
var keyPropertyName = ExtractNameOfMemberName(uProperty, EfAddToListAttributeSource.AttributeName, semanticModel, 1);;
|
|
|
|
var keyMemberType = FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax);
|
|
|
|
var keyFullTypeName = keyMemberType.Value.Type.ToDisplayString();
|
|
|
|
var listEntityTypeInfo = (FindTypeInfoOfMemberExpressionSyntax(semanticModel, TypeSyntax, 2).Value.Type as INamedTypeSymbol).TypeArguments.FirstOrDefault();
|
|
|
|
var listEntityIdentifierName = listEntityTypeInfo.Name;
|
|
|
|
var listEntityFullTypeName = listEntityTypeInfo.ToDisplayString();
|
|
|
|
|
|
|
|
|
|
|
|
// Try grabbing string literal if there's no nameof in it
|
|
|
|
if (keyPropertyName == string.Empty)
|
|
|
|
{
|
|
|
|
listPropertyName = GetEntityStringLiteralSymbol(TypeSyntax, EfAddToListAttributeSource.AttributeName, semanticModel)
|
|
|
|
.FirstOrDefault()?
|
|
|
|
.Token.ValueText ?? "Id";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string returnTypeIdentifierName = entityDataModel.EntityTypeIdentifierName;
|
|
|
|
string returnTypeFullName = entityDataModel.EntityTypeFullName;
|
|
|
|
|
|
|
|
var createTypeIdentifierName =listEntityIdentifierName;
|
|
|
|
var createTypeFullName = listEntityFullTypeName;
|
|
|
|
|
|
|
|
// Grab create type from attribute argument
|
|
|
|
if (efTypeofSymbols.Length > 0)
|
|
|
|
{
|
|
|
|
createTypeIdentifierName = efTypeofSymbols[0].Name;
|
|
|
|
createTypeFullName = efTypeofSymbols[0].ToDisplayString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Grab return type from attribute argument
|
|
|
|
if (efTypeofSymbols.Length > 1)
|
|
|
|
{
|
|
|
|
returnTypeIdentifierName = efTypeofSymbols[1].Name;
|
|
|
|
returnTypeFullName = efTypeofSymbols[1].ToDisplayString();
|
|
|
|
}
|
|
|
|
|
|
|
|
return new EfAddToListModel(
|
|
|
|
entityDataModel,
|
|
|
|
listPropertyName,
|
|
|
|
listEntityIdentifierName,
|
|
|
|
listEntityFullTypeName,
|
|
|
|
keyPropertyName,
|
|
|
|
keyFullTypeName,
|
|
|
|
createTypeIdentifierName,
|
|
|
|
createTypeFullName,
|
|
|
|
returnTypeIdentifierName,
|
|
|
|
returnTypeFullName);
|
|
|
|
}
|
|
|
|
|
2022-09-06 00:47:58 +03:00
|
|
|
|
|
|
|
private static ITypeSymbol GetEntityTypeData(MemberDeclarationSyntax memberDeclarationSyntax, SemanticModel? semanticModel = null)
|
|
|
|
{
|
|
|
|
var member = (memberDeclarationSyntax as PropertyDeclarationSyntax).Type;
|
|
|
|
var genericSyntax = member as GenericNameSyntax;
|
|
|
|
var typeInfo = semanticModel.GetTypeInfo( genericSyntax);
|
|
|
|
var firstTypeArgument = (typeInfo.ConvertedType as INamedTypeSymbol).TypeArguments[0];
|
|
|
|
return firstTypeArgument;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|