From 5faebd9141db55db0b3aac0a3b2cba92de49c5e5 Mon Sep 17 00:00:00 2001 From: Wvader <34067397+wvader@users.noreply.github.com> Date: Sat, 11 Dec 2021 23:54:21 +0000 Subject: [PATCH] work with field --- src/MapTo/ClassMappingContext.cs | 41 ++++- src/MapTo/Extensions/CommonExtensions.cs | 2 +- src/MapTo/Extensions/CommonSource.cs | 68 ++++--- src/MapTo/Extensions/RoslynExtensions.cs | 4 + src/MapTo/MappingContext.cs | 171 ++++++++++++++++-- src/MapTo/Models.cs | 8 +- src/MapTo/RecordMappingContext.cs | 14 +- src/MapTo/StructMappingContext.cs | 31 +++- .../TestConsoleApp/Data/FinanceTransaction.cs | 16 +- test/TestConsoleApp/Data/User.cs | 18 +- test/TestConsoleApp/Data/UserUpdateDto.cs | 16 +- 11 files changed, 300 insertions(+), 89 deletions(-) diff --git a/src/MapTo/ClassMappingContext.cs b/src/MapTo/ClassMappingContext.cs index 3abc4fc..d7edeb0 100644 --- a/src/MapTo/ClassMappingContext.cs +++ b/src/MapTo/ClassMappingContext.cs @@ -11,20 +11,20 @@ namespace MapTo internal ClassMappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax) : base(compilation, sourceGenerationOptions, typeSyntax) { } - protected override ImmutableArray GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) + protected override ImmutableArray GetSourceMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) { - var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); + var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); return typeSymbol - .GetAllMembers(!isInheritFromMappedBaseClass) - .OfType() + .GetAllMembers() + .OfType() .Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol)) - .Select(property => MapProperty(sourceTypeSymbol, sourceProperties, property)) + .Select(property => MapField(sourceTypeSymbol, sourceProperties, property)) .Where(mappedProperty => mappedProperty is not null) .ToImmutableArray()!; } - protected override ImmutableArray GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) + protected override ImmutableArray GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass) { var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); @@ -32,9 +32,36 @@ namespace MapTo .GetAllMembers() .OfType() .Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol)) - .Select(property => MapProperty(typeSymbol, sourceProperties, property)) + .Select(property => MapProperty(sourceTypeSymbol, sourceProperties, property)) .Where(mappedProperty => mappedProperty is not null) .ToImmutableArray()!; } + + protected override ImmutableArray GetTypeMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) + { + var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); + + return sourceTypeSymbol + .GetAllMembers() + .OfType() + .Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol)) + .Select(property => MapFieldSimple(typeSymbol, property)) + .Where(mappedProperty => mappedProperty is not null) + .ToImmutableArray()!; + } + + protected override ImmutableArray GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass) + { + var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); + + return sourceTypeSymbol + .GetAllMembers() + .OfType() + .Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol)) + .Select(property => MapPropertySimple(typeSymbol, property)) + .Where(mappedProperty => mappedProperty is not null) + .ToImmutableArray()!; + } + } } \ No newline at end of file diff --git a/src/MapTo/Extensions/CommonExtensions.cs b/src/MapTo/Extensions/CommonExtensions.cs index f02df28..bf43e97 100644 --- a/src/MapTo/Extensions/CommonExtensions.cs +++ b/src/MapTo/Extensions/CommonExtensions.cs @@ -28,7 +28,7 @@ namespace MapTo.Extensions } - internal static SourceBuilder WriteMappedProperties(this SourceBuilder builder, System.Collections.Immutable.ImmutableArray mappedProperties) + internal static SourceBuilder WriteMappedProperties(this SourceBuilder builder, System.Collections.Immutable.ImmutableArray mappedProperties) { foreach (var item in mappedProperties) { diff --git a/src/MapTo/Extensions/CommonSource.cs b/src/MapTo/Extensions/CommonSource.cs index 2de8fa6..5ae7c1d 100644 --- a/src/MapTo/Extensions/CommonSource.cs +++ b/src/MapTo/Extensions/CommonSource.cs @@ -32,7 +32,13 @@ namespace MapTo.Extensions .WriteMappedProperties(model.TypeProperties) .WriteLine() .WriteComment("Source properties") - .WriteMappedProperties(model.SourceProperties) + .WriteLine() + .WriteComment("Type fields") + .WriteComment() + .WriteMappedProperties(model.TypeFields) + .WriteLine() + .WriteComment("Source fields") + .WriteMappedProperties(model.SourceFields) .WriteLine(); builder @@ -65,7 +71,7 @@ namespace MapTo.Extensions var stringBuilder = new StringBuilder(); - var otherProperties = new List(); + var otherProperties = new List(); foreach (var property in model.TypeProperties) { @@ -76,19 +82,30 @@ namespace MapTo.Extensions otherProperties.Add(property); } } - + + foreach (var property in model.TypeFields) + { + if (!model.SourceFields.IsMappedProperty(property)) + { + stringBuilder.Append(", "); + stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); + otherProperties.Add(property); + } + } + + var readOnlyPropertiesArguments = stringBuilder.ToString(); builder .WriteLine($"public {model.TypeIdentifierName}({model.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}") .WriteOpeningBracket() - .TryWriteProperties(model.SourceProperties, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false); + .WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false); // End constructor declaration return builder.WriteClosingBracket(); } - private static bool IsMappedProperty(this System.Collections.Immutable.ImmutableArray properties, MappedProperty property) { + private static bool IsMappedProperty(this System.Collections.Immutable.ImmutableArray properties, MappedMember property) { foreach(var prop in properties) { @@ -98,44 +115,25 @@ namespace MapTo.Extensions return false; } - private static SourceBuilder TryWriteProperties(this SourceBuilder builder, System.Collections.Immutable.ImmutableArray properties, System.Collections.Immutable.ImmutableArray? otherProperties, + private static SourceBuilder WriteAssignmentMethod(this SourceBuilder builder, MappingModel model, System.Collections.Immutable.ImmutableArray? otherProperties, string? sourceClassParameterName, string mappingContextParameterName, bool fromUpdate) { - if (fromUpdate) - { - properties = properties.GetWritableMappedProperties(); - } - foreach (var property in properties) + foreach (var property in model.SourceProperties) { if (property.isReadOnly && fromUpdate) continue; - if (property.TypeConverter is null) - { - if (property.IsEnumerable) - { - builder.WriteLine( - $"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName}.Select({mappingContextParameterName}.{MappingContextSource.MapMethodName}<{property.MappedSourcePropertyTypeName}, {property.EnumerableTypeArgument}>).ToList();"); - } - else - { - builder.WriteLine(property.MappedSourcePropertyTypeName is null - ? $"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};" - : ""); - } - } - else - { - var parameters = property.TypeConverterParameters.IsEmpty - ? "null" - : $"new object[] {{ {string.Join(", ", property.TypeConverterParameters)} }}"; - - builder.WriteLine( - $"{property.Name} = new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters});"); - } + builder.WriteLine( $"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};"); } + foreach (var property in model.SourceFields) + { + if (property.isReadOnly && fromUpdate) continue; + + builder.WriteLine($"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};"); + + } if (otherProperties == null) return builder; @@ -160,7 +158,7 @@ namespace MapTo.Extensions .GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName) .WriteLine($"public void Update({model.SourceType} {sourceClassParameterName})") .WriteOpeningBracket() - .TryWriteProperties(model.SourceProperties, null, sourceClassParameterName, "context", true) + .WriteAssignmentMethod(model, null, sourceClassParameterName, "context", true) .WriteClosingBracket(); return builder; diff --git a/src/MapTo/Extensions/RoslynExtensions.cs b/src/MapTo/Extensions/RoslynExtensions.cs index edae4c8..c08f60a 100644 --- a/src/MapTo/Extensions/RoslynExtensions.cs +++ b/src/MapTo/Extensions/RoslynExtensions.cs @@ -68,6 +68,10 @@ namespace MapTo.Extensions typeSymbol = propertySymbol.Type; return true; + case IFieldSymbol fieldSymbol: + typeSymbol = fieldSymbol.Type; + return true; + case IParameterSymbol parameterSymbol: typeSymbol = parameterSymbol.Type; return true; diff --git a/src/MapTo/MappingContext.cs b/src/MapTo/MappingContext.cs index 892e2c5..d884bcf 100644 --- a/src/MapTo/MappingContext.cs +++ b/src/MapTo/MappingContext.cs @@ -11,8 +11,8 @@ namespace MapTo { internal static class MappingContextExtensions { - internal static ImmutableArray GetReadOnlyMappedProperties(this ImmutableArray mappedProperties) => mappedProperties.Where(p => p.isReadOnly).ToImmutableArray()!; - internal static ImmutableArray GetWritableMappedProperties(this ImmutableArray mappedProperties) => mappedProperties.Where(p => !p.isReadOnly).ToImmutableArray()!; + internal static ImmutableArray GetReadOnlyMappedProperties(this ImmutableArray mappedProperties) => mappedProperties.Where(p => p.isReadOnly).ToImmutableArray()!; + internal static ImmutableArray GetWritableMappedProperties(this ImmutableArray mappedProperties) => mappedProperties.Where(p => !p.isReadOnly).ToImmutableArray()!; } internal abstract class MappingContext @@ -109,9 +109,24 @@ namespace MapTo return sourceProperties.SingleOrDefault(p => p.Name == propertyName); } + protected IFieldSymbol? FindSourceField(IEnumerable sourceProperties, ISymbol property) + { + var propertyName = property + .GetAttribute(MapPropertyAttributeTypeSymbol) + ?.NamedArguments + .SingleOrDefault(a => a.Key == MapPropertyAttributeSource.SourcePropertyNamePropertyName) + .Value.Value as string ?? property.Name; + + return sourceProperties.SingleOrDefault(p => p.Name == propertyName); + } + + protected abstract ImmutableArray GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass); + protected abstract ImmutableArray GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass); + + + protected abstract ImmutableArray GetSourceMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass); + protected abstract ImmutableArray GetTypeMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass); - protected abstract ImmutableArray GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass); - protected abstract ImmutableArray GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass); protected INamedTypeSymbol? GetSourceTypeSymbol(TypeDeclarationSyntax typeDeclarationSyntax, SemanticModel? semanticModel = null) => GetSourceTypeSymbol(typeDeclarationSyntax.GetAttribute(MapFromAttributeSource.AttributeName), semanticModel); @@ -144,7 +159,7 @@ namespace MapTo return TypeSyntax.GetAttribute("UseUpdate") != null; } - protected virtual MappedProperty? MapProperty(ISymbol sourceTypeSymbol, IReadOnlyCollection sourceProperties, ISymbol property) + protected virtual MappedMember? MapProperty(ISymbol sourceTypeSymbol, IReadOnlyCollection sourceProperties, ISymbol property) { var sourceProperty = FindSourceProperty(sourceProperties, property); if (sourceProperty is null || !property.TryGetTypeSymbol(out var propertyType)) @@ -160,7 +175,7 @@ namespace MapTo if (!Compilation.HasCompatibleTypes(sourceProperty, property)) { - if (!TryGetMapTypeConverter(property, sourceProperty, out converterFullyQualifiedName, out converterParameters) && + if (!TryGetMapTypeConverterForProperty(property, sourceProperty, out converterFullyQualifiedName, out converterParameters) && !TryGetNestedObjectMappings(property, out mappedSourcePropertyType, out enumerableTypeArgumentType)) { return null; @@ -172,7 +187,7 @@ namespace MapTo AddUsingIfRequired(mappedSourcePropertyType); - return new MappedProperty( + return new MappedMember( property.Name, property.GetTypeSymbol().ToString(), ToQualifiedDisplayName(propertyType) ?? propertyType.Name, @@ -184,7 +199,52 @@ namespace MapTo (property as IPropertySymbol).IsReadOnly); ; } - protected virtual MappedProperty? MapPropertySimple(ISymbol sourceTypeSymbol, ISymbol property) + + protected virtual MappedMember? MapField(ISymbol sourceTypeSymbol, IReadOnlyCollection sourceProperties, ISymbol property) + { + var sourceProperty = FindSourceField(sourceProperties, property); + if (sourceProperty is null || !property.TryGetTypeSymbol(out var propertyType)) + { + return null; + } + + if (property is IFieldSymbol symbol) + { + if (symbol.AssociatedSymbol != null) return null; + } + + string? converterFullyQualifiedName = null; + var converterParameters = ImmutableArray.Empty; + ITypeSymbol? mappedSourcePropertyType = null; + ITypeSymbol? enumerableTypeArgumentType = null; + + if (!Compilation.HasCompatibleTypes(sourceProperty, property)) + { + if (!TryGetMapTypeConverterForField(property, sourceProperty, out converterFullyQualifiedName, out converterParameters) && + !TryGetNestedObjectMappings(property, out mappedSourcePropertyType, out enumerableTypeArgumentType)) + { + return null; + } + } + + AddUsingIfRequired(propertyType); + AddUsingIfRequired(enumerableTypeArgumentType); + AddUsingIfRequired(mappedSourcePropertyType); + + + return new MappedMember( + property.Name, + property.GetTypeSymbol().ToString(), + ToQualifiedDisplayName(propertyType) ?? propertyType.Name, + converterFullyQualifiedName, + converterParameters.ToImmutableArray(), + sourceProperty.Name, + ToQualifiedDisplayName(mappedSourcePropertyType), + ToQualifiedDisplayName(enumerableTypeArgumentType), + (property as IFieldSymbol).IsReadOnly); + ; + } + protected virtual MappedMember? MapPropertySimple(ISymbol sourceTypeSymbol, ISymbol property) { if (!property.TryGetTypeSymbol(out var propertyType)) { @@ -203,7 +263,7 @@ namespace MapTo AddUsingIfRequired(mappedSourcePropertyType); - return new MappedProperty( + return new MappedMember( property.Name, property.GetTypeSymbol().ToString(), ToQualifiedDisplayName(propertyType) ?? propertyType.Name, @@ -215,7 +275,44 @@ namespace MapTo (property as IPropertySymbol).IsReadOnly); ; } - protected bool TryGetMapTypeConverter(ISymbol property, IPropertySymbol sourceProperty, out string? converterFullyQualifiedName, + + protected virtual MappedMember? MapFieldSimple(ISymbol sourceTypeSymbol, ISymbol property) + { + if (!property.TryGetTypeSymbol(out var propertyType)) + { + return null; + } + + if(property is IFieldSymbol symbol) + { + if (symbol.AssociatedSymbol != null) return null; + } + + + string? converterFullyQualifiedName = null; + var converterParameters = ImmutableArray.Empty; + ITypeSymbol? mappedSourcePropertyType = null; + ITypeSymbol? enumerableTypeArgumentType = null; + + + AddUsingIfRequired(propertyType); + AddUsingIfRequired(enumerableTypeArgumentType); + AddUsingIfRequired(mappedSourcePropertyType); + + + return new MappedMember( + property.Name, + property.GetTypeSymbol().ToString(), + ToQualifiedDisplayName(propertyType) ?? propertyType.Name, + converterFullyQualifiedName, + converterParameters.ToImmutableArray(), + property.Name, + ToQualifiedDisplayName(mappedSourcePropertyType), + ToQualifiedDisplayName(enumerableTypeArgumentType), + (property as IFieldSymbol).IsReadOnly); + ; + } + protected bool TryGetMapTypeConverterForProperty(ISymbol property, IPropertySymbol sourceProperty, out string? converterFullyQualifiedName, out ImmutableArray converterParameters) { converterFullyQualifiedName = null; @@ -232,7 +329,7 @@ namespace MapTo return false; } - var baseInterface = GetTypeConverterBaseInterface(converterTypeSymbol, property, sourceProperty); + var baseInterface = GetTypeConverterBaseInterfaceForProperty(converterTypeSymbol, property, sourceProperty); if (baseInterface is null) { AddDiagnostic(DiagnosticsFactory.InvalidTypeConverterGenericTypesError(property, sourceProperty)); @@ -243,7 +340,34 @@ namespace MapTo converterParameters = GetTypeConverterParameters(typeConverterAttribute); return true; } + protected bool TryGetMapTypeConverterForField(ISymbol property, IFieldSymbol sourceProperty, out string? converterFullyQualifiedName, + out ImmutableArray converterParameters) + { + converterFullyQualifiedName = null; + converterParameters = ImmutableArray.Empty; + if (!Diagnostics.IsEmpty()) + { + return false; + } + + var typeConverterAttribute = property.GetAttribute(MapTypeConverterAttributeTypeSymbol); + if (typeConverterAttribute?.ConstructorArguments.First().Value is not INamedTypeSymbol converterTypeSymbol) + { + return false; + } + + var baseInterface = GetTypeConverterBaseInterfaceForField(converterTypeSymbol, property, sourceProperty); + if (baseInterface is null) + { + //AddDiagnostic(DiagnosticsFactory.InvalidTypeConverterGenericTypesError(property, null)); + return false; + } + + converterFullyQualifiedName = converterTypeSymbol.ToDisplayString(); + converterParameters = GetTypeConverterParameters(typeConverterAttribute); + return true; + } protected bool TryGetNestedObjectMappings(ISymbol property, out ITypeSymbol? mappedSourcePropertyType, out ITypeSymbol? enumerableTypeArgument) { mappedSourcePropertyType = null; @@ -313,15 +437,18 @@ namespace MapTo var shouldGenerateSecondaryConstructor = ShouldGenerateSecondaryConstructor(semanticModel, sourceTypeSymbol); var mappedProperties = GetSourceMappedProperties(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass); - if (!mappedProperties.Any()) + var mappedFields = GetSourceMappedFields(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass); + + /*if (!mappedProperties.Any()) { AddDiagnostic(DiagnosticsFactory.NoMatchingPropertyFoundError(TypeSyntax.GetLocation(), typeSymbol, sourceTypeSymbol)); return null; - } + }*/ AddUsingIfRequired(mappedProperties.Any(p => p.IsEnumerable), "System.Linq"); var allProperties = GetTypeMappedProperties(sourceTypeSymbol, typeSymbol , isTypeInheritFromMappedBaseClass); + var allFields = GetTypeMappedFields(sourceTypeSymbol, typeSymbol, isTypeInheritFromMappedBaseClass); return new MappingModel( SourceGenerationOptions, @@ -335,6 +462,8 @@ namespace MapTo isTypeUpdatable, mappedProperties, allProperties, + mappedFields, + allFields, isTypeInheritFromMappedBaseClass, Usings, shouldGenerateSecondaryConstructor); @@ -342,7 +471,21 @@ namespace MapTo - private INamedTypeSymbol? GetTypeConverterBaseInterface(ITypeSymbol converterTypeSymbol, ISymbol property, IPropertySymbol sourceProperty) + private INamedTypeSymbol? GetTypeConverterBaseInterfaceForProperty(ITypeSymbol converterTypeSymbol, ISymbol property, IPropertySymbol sourceProperty) + { + if (!property.TryGetTypeSymbol(out var propertyType)) + { + return null; + } + + return converterTypeSymbol.AllInterfaces + .SingleOrDefault(i => + i.TypeArguments.Length == 2 && + SymbolEqualityComparer.Default.Equals(i.ConstructedFrom, TypeConverterInterfaceTypeSymbol) && + SymbolEqualityComparer.Default.Equals(sourceProperty.Type, i.TypeArguments[0]) && + SymbolEqualityComparer.Default.Equals(propertyType, i.TypeArguments[1])); + } + private INamedTypeSymbol? GetTypeConverterBaseInterfaceForField(ITypeSymbol converterTypeSymbol, ISymbol property, IFieldSymbol sourceProperty) { if (!property.TryGetTypeSymbol(out var propertyType)) { diff --git a/src/MapTo/Models.cs b/src/MapTo/Models.cs index e8997bd..e7cb893 100644 --- a/src/MapTo/Models.cs +++ b/src/MapTo/Models.cs @@ -22,7 +22,7 @@ namespace MapTo internal record SourceCode(string Text, string HintName); - internal record MappedProperty( + internal record MappedMember( string Name, string FullyQualifiedType, string Type, @@ -46,8 +46,10 @@ namespace MapTo string SourceTypeIdentifierName, string SourceTypeFullName, bool IsTypeUpdatable, - ImmutableArray SourceProperties, - ImmutableArray TypeProperties, + ImmutableArray SourceProperties, + ImmutableArray TypeProperties, + ImmutableArray SourceFields, + ImmutableArray TypeFields, bool HasMappedBaseClass, ImmutableArray Usings, bool GenerateSecondaryConstructor diff --git a/src/MapTo/RecordMappingContext.cs b/src/MapTo/RecordMappingContext.cs index 5aab2de..619236c 100644 --- a/src/MapTo/RecordMappingContext.cs +++ b/src/MapTo/RecordMappingContext.cs @@ -11,7 +11,12 @@ namespace MapTo internal RecordMappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax) : base(compilation, sourceGenerationOptions, typeSyntax) { } - protected override ImmutableArray GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) + protected override ImmutableArray GetSourceMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) + { + throw new System.NotImplementedException(); + } + + protected override ImmutableArray GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) { var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); return typeSymbol.GetMembers() @@ -25,7 +30,12 @@ namespace MapTo .ToImmutableArray()!; } - protected override ImmutableArray GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) + protected override ImmutableArray GetTypeMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) + { + throw new System.NotImplementedException(); + } + + protected override ImmutableArray GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) { var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); return typeSymbol.GetMembers() diff --git a/src/MapTo/StructMappingContext.cs b/src/MapTo/StructMappingContext.cs index 9347568..52751d1 100644 --- a/src/MapTo/StructMappingContext.cs +++ b/src/MapTo/StructMappingContext.cs @@ -11,7 +11,20 @@ namespace MapTo internal StructMappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax) : base(compilation, sourceGenerationOptions, typeSyntax) { } - protected override ImmutableArray GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass) + protected override ImmutableArray GetSourceMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) + { + var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); + + return typeSymbol + .GetAllMembers() + .OfType() + .Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol)) + .Select(property => MapField(sourceTypeSymbol, sourceProperties, property)) + .Where(mappedProperty => mappedProperty is not null) + .ToImmutableArray()!; + } + + protected override ImmutableArray GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass) { var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); @@ -23,7 +36,21 @@ namespace MapTo .Where(mappedProperty => mappedProperty is not null) .ToImmutableArray()!; } - protected override ImmutableArray GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass) + + protected override ImmutableArray GetTypeMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) + { + var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); + + return sourceTypeSymbol + .GetAllMembers() + .OfType() + .Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol)) + .Select(property => MapFieldSimple(typeSymbol, property)) + .Where(mappedProperty => mappedProperty is not null) + .ToImmutableArray()!; + } + + protected override ImmutableArray GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass) { var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType().ToArray(); diff --git a/test/TestConsoleApp/Data/FinanceTransaction.cs b/test/TestConsoleApp/Data/FinanceTransaction.cs index 99c13e2..49249d0 100644 --- a/test/TestConsoleApp/Data/FinanceTransaction.cs +++ b/test/TestConsoleApp/Data/FinanceTransaction.cs @@ -23,14 +23,14 @@ namespace BlueWest.Data [MapFrom(typeof(FinanceTransactionInsertDto))] public partial struct FinanceTransaction { - public int Id { get; } - public int UserId { get; set; } - public FinanceTransactionType FinanceTransactionType { get; } - public FinanceSymbol FinanceSymbol { get; } - public double Amount { get; } // To Buy - public double Quantity { get; } // Bought - public double Fee { get; } - public DateTime DateTime { get; } + public readonly int Id; + public readonly int UserId; + public readonly FinanceTransactionType FinanceTransactionType; + public readonly FinanceSymbol FinanceSymbol; + public readonly double Amount; // To Buy + public readonly double Quantity; // Bought + public readonly double Fee; + public readonly DateTime DateTime; public FinanceTransaction(int id, int userId, FinanceTransactionType financeTransactionType, diff --git a/test/TestConsoleApp/Data/User.cs b/test/TestConsoleApp/Data/User.cs index 2a1bbd8..b92a5f7 100644 --- a/test/TestConsoleApp/Data/User.cs +++ b/test/TestConsoleApp/Data/User.cs @@ -8,17 +8,17 @@ namespace BlueWest.Data [MapFrom(typeof(UserUpdateDto))] public partial class User { - public int Id { get; } - public string Name { get; set; } - public string Address { get; set; } - - public string BTCAddress { get; set; } - public string LTCAddress { get; set; } + public readonly int Id; + public string Name; + public string Address; - public double BTCAmount { get; set; } - public double LTCAmount { get; set; } + public string BTCAddress; + public string LTCAddress; - public List FinanceTransactions { get; } + public double BTCAmount; + public double LTCAmount; + + public readonly List FinanceTransactions; public User(int id, string name, string address, string btcAddress, string ltcAddress, double btcAmount, double ltcAmount, List financeTransactions) { diff --git a/test/TestConsoleApp/Data/UserUpdateDto.cs b/test/TestConsoleApp/Data/UserUpdateDto.cs index 456193f..a1b18d3 100644 --- a/test/TestConsoleApp/Data/UserUpdateDto.cs +++ b/test/TestConsoleApp/Data/UserUpdateDto.cs @@ -4,16 +4,16 @@ namespace BlueWest.Data { [MapFrom(typeof(User))] - public partial struct UserUpdateDto + public partial class UserUpdateDto { - public string Name { get; set; } - public string Address { get; set; } - - public string BTCAddress { get; set; } - public string LTCAddress { get; set; } + public string Name; + public string Address; - public double BTCAmount { get; set; } - public double LTCAmount { get; set; } + public string BTCAddress; + public string LTCAddress; + + public double BTCAmount; + public double LTCAmount; } } \ No newline at end of file