diff --git a/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorContext.cs b/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorContext.cs index 14cea85..1ec556f 100644 --- a/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorContext.cs +++ b/src/BlueWest.MapTo/Sources/EfMethods/EfGeneratorContext.cs @@ -19,23 +19,6 @@ namespace MapTo { private readonly List _ignoredNamespaces; - protected EfGeneratorContext( - Compilation compilation, - SourceGenerationOptions sourceGenerationOptions, - MemberDeclarationSyntax memberSyntax) - { - Compilation = compilation; - _ignoredNamespaces = new(); - Diagnostics = ImmutableArray.Empty; - Usings = ImmutableArray.Create("System", Constants.RootNamespace); - SourceGenerationOptions = sourceGenerationOptions; - MemberSyntax = memberSyntax; - - MappingContextTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(MappingContextSource.FullyQualifiedName); - - AddUsingIfRequired(sourceGenerationOptions.SupportNullableStaticAnalysis, "System.Diagnostics.CodeAnalysis"); - } - public ImmutableArray Diagnostics { get; private set; } @@ -50,6 +33,29 @@ namespace MapTo protected MemberDeclarationSyntax MemberSyntax { get; } protected ImmutableArray Usings { get; private set; } + + + protected INamedTypeSymbol EfUpdateMethodsTypeSymbol { get; } + + protected INamedTypeSymbol EfAddMethodsTypeSymbol { get; } + + + + protected EfGeneratorContext( + Compilation compilation, + SourceGenerationOptions sourceGenerationOptions, + MemberDeclarationSyntax memberSyntax) + { + Compilation = compilation; + _ignoredNamespaces = new(); + Diagnostics = ImmutableArray.Empty; + Usings = ImmutableArray.Create("System", Constants.RootNamespace); + SourceGenerationOptions = sourceGenerationOptions; + MemberSyntax = memberSyntax; + EfUpdateMethodsTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(EfUpdateMethodsAttributeSource.FullyQualifiedName); + EfAddMethodsTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(EfAddMethodsAttributeSource.FullyQualifiedName); + AddUsingIfRequired(sourceGenerationOptions.SupportNullableStaticAnalysis, "System.Diagnostics.CodeAnalysis"); + } public static EfGeneratorContext Create( Compilation compilation, @@ -236,20 +242,7 @@ namespace MapTo private EfMethodsModel? CreateMappingModel() { var semanticModel = Compilation.GetSemanticModel(MemberSyntax.SyntaxTree); - /*if (semanticModel.GetDeclaredSymbol(MemberSyntax) is not INamedTypeSymbol typeSymbol) - { - AddDiagnostic(DiagnosticsFactory.TypeNotFoundError(MemberSyntax.GetLocation(), MemberSyntax.Identifier.ValueText)); - return null; - }*/ - - // Main Entity - var entityData = GetEntityTypeData(MemberSyntax, semanticModel); - - string entityTypeName = entityData.Name; - - string entityTypeFullName = entityData.ToDisplayString(); - // get containing class type information ClassDeclarationSyntax classDeclarationSyntax = MemberSyntax.Parent as ClassDeclarationSyntax; @@ -259,58 +252,71 @@ namespace MapTo var contextNamespace = namespaceDeclaration.Name.ToString(); var contextTypeFullName = $"{contextNamespace}.{dbContextName}"; - - var propertyName = entityTypeName; - if (MemberSyntax is PropertyDeclarationSyntax propertyDeclarationSyntax) - { - propertyName = propertyDeclarationSyntax.Identifier.ValueText; - } - if (MemberSyntax is FieldDeclarationSyntax fieldDeclaration) - { - // TODO: Test - propertyName = fieldDeclaration.ToString(); - } - var efEntity = new EfEntityDataModel(propertyName, entityTypeFullName, entityTypeName); + var addAttributeSymbols = classDeclarationSyntax.DescendantNodes() + .OfType() + .Where(x => x.DescendantNodes().OfType().Any( + syntax => syntax.Name.ToString() == EfUpdateMethodsAttributeSource.AttributeName + )) + .ToImmutableArray(); + + var updateAttributesMembers = classDeclarationSyntax.DescendantNodes() + .OfType() + .Where(x => x.DescendantNodes().OfType().Any( + syntax => syntax.Name.ToString() == EfUpdateMethodsAttributeSource.AttributeName + )) + .ToImmutableArray(); + + - var addConfig = ExtractEfAddMethodsModel(semanticModel, efEntity); - - if (addConfig == null) + List methodsModels = new List(); + + foreach (var uProperty in updateAttributesMembers) { - AddDiagnostic(DiagnosticsFactory.MapFromAttributeNotFoundError(MemberSyntax.GetLocation())); - return null; + 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 newUpdateModel = ExtractEfUpdateMethodsModel(semanticModel, uProperty, entityDataModel); + methodsModels.Add(newUpdateModel); } - var updateConfig = ExtractEfUpdateMethodsModel(semanticModel, efEntity); - - if (updateConfig == null) + + foreach (var uProperty in addAttributeSymbols) { - AddDiagnostic(DiagnosticsFactory.MapFromAttributeNotFoundError(MemberSyntax.GetLocation())); - return null; + 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 newAddModel = ExtractEfAddMethodsModel(semanticModel, uProperty, entityDataModel); + methodsModels.Add(newAddModel); } - // Create list of configurations - - List models = new List(); - - models.Add(addConfig); - models.Add(updateConfig); - + SpinWait.SpinUntil(() => Debugger.IsAttached); + + var classType = semanticModel.GetTypeInfo(classDeclarationSyntax); + if (classType.Type != null) + { + var addAttributes = GetSymbolsFromAttribute(classType.Type, EfAddMethodsTypeSymbol); + } + return new EfMethodsModel( SourceGenerationOptions, contextNamespace, dbContextName, contextTypeFullName, - models.ToImmutableArray(), + methodsModels.ToImmutableArray(), Usings); } - private EfAddMethodsModel ExtractEfAddMethodsModel(SemanticModel semanticModel, EfEntityDataModel efEntityDataModel) + private EfAddMethodsModel ExtractEfAddMethodsModel(SemanticModel semanticModel, MemberDeclarationSyntax memberSyntax, EfEntityDataModel efEntityDataModel) { var efAddAttributeTypeSymbols = - GetEntityTypeSymbol(MemberSyntax, EfAddMethodsAttributeSource.AttributeName, semanticModel); + GetEntityTypeSymbol(memberSyntax, EfAddMethodsAttributeSource.AttributeName, semanticModel); string createTypeIdentifierName = efEntityDataModel.EntityTypeIdentifierName; string createTypeFullName = efEntityDataModel.EntityTypeFullName; @@ -335,12 +341,12 @@ namespace MapTo returnTypeIdentifierName); } - private EfUpdateMethodsModel ExtractEfUpdateMethodsModel(SemanticModel semanticModel,EfEntityDataModel efEntityDataModel) + private EfUpdateMethodsModel ExtractEfUpdateMethodsModel(SemanticModel semanticModel, MemberDeclarationSyntax memberDeclarationSyntax, EfEntityDataModel efEntityDataModel) { var efAddAttributeTypeSymbols = GetEntityTypeSymbol(MemberSyntax, EfUpdateMethodsAttributeSource.AttributeName, semanticModel); - var keyPropertyName = ExtractNameOfMemberName(MemberSyntax, EfUpdateMethodsAttributeSource.AttributeName, semanticModel); + var keyPropertyName = ExtractNameOfMemberName(memberDeclarationSyntax, EfUpdateMethodsAttributeSource.AttributeName, semanticModel); var keyMemberType = FindFirstTypeInfoOfMemberExpressionSyntax(semanticModel, MemberSyntax); @@ -386,12 +392,20 @@ namespace MapTo } - + protected ImmutableArray GetSymbolsFromAttribute(ITypeSymbol typeSymbol, INamedTypeSymbol attributeTypeSymbol) + { + return typeSymbol + .GetAllMembers() + .OfType() + .Where(p => p.HasAttribute(attributeTypeSymbol)) + .ToImmutableArray()!; + } + private static ITypeSymbol GetEntityTypeData(MemberDeclarationSyntax memberDeclarationSyntax, SemanticModel? semanticModel = null) { var member = (memberDeclarationSyntax as PropertyDeclarationSyntax).Type; var genericSyntax = member as GenericNameSyntax; - var typeInfo = ModelExtensions.GetTypeInfo(semanticModel, genericSyntax); + var typeInfo = semanticModel.GetTypeInfo( genericSyntax); var firstTypeArgument = (typeInfo.ConvertedType as INamedTypeSymbol).TypeArguments[0]; return firstTypeArgument; } diff --git a/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsGenerator.cs b/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsGenerator.cs index 0e8b1e4..09a0a12 100644 --- a/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsGenerator.cs +++ b/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsGenerator.cs @@ -49,7 +49,6 @@ namespace MapTo private static void AddGeneratedExtensions(GeneratorExecutionContext context, Compilation compilation, IEnumerable candidateMembers, SourceGenerationOptions options) { - //SpinWait.SpinUntil(() => Debugger.IsAttached); foreach (var candidateMember in candidateMembers) { diff --git a/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsSource.cs b/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsSource.cs index 7d08c9e..365b085 100644 --- a/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsSource.cs +++ b/src/BlueWest.MapTo/Sources/EfMethods/EfMethodsSource.cs @@ -70,8 +70,6 @@ namespace MapTo.Sources } - - builder // End class declaration .WriteClosingBracket()