work with field

This commit is contained in:
Wvader 2021-12-11 23:54:21 +00:00
parent 768dbb4532
commit 5faebd9141
11 changed files with 300 additions and 89 deletions

View File

@ -11,20 +11,20 @@ namespace MapTo
internal ClassMappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax) internal ClassMappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax)
: base(compilation, sourceGenerationOptions, typeSyntax) { } : base(compilation, sourceGenerationOptions, typeSyntax) { }
protected override ImmutableArray<MappedProperty> GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) protected override ImmutableArray<MappedMember> GetSourceMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass)
{ {
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray(); var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IFieldSymbol>().ToArray();
return typeSymbol return typeSymbol
.GetAllMembers(!isInheritFromMappedBaseClass) .GetAllMembers()
.OfType<IPropertySymbol>() .OfType<IFieldSymbol>()
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol)) .Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
.Select(property => MapProperty(sourceTypeSymbol, sourceProperties, property)) .Select(property => MapField(sourceTypeSymbol, sourceProperties, property))
.Where(mappedProperty => mappedProperty is not null) .Where(mappedProperty => mappedProperty is not null)
.ToImmutableArray()!; .ToImmutableArray()!;
} }
protected override ImmutableArray<MappedProperty> GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) protected override ImmutableArray<MappedMember> GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass)
{ {
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray(); var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray();
@ -32,9 +32,36 @@ namespace MapTo
.GetAllMembers() .GetAllMembers()
.OfType<IPropertySymbol>() .OfType<IPropertySymbol>()
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol)) .Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
.Select(property => MapProperty(typeSymbol, sourceProperties, property)) .Select(property => MapProperty(sourceTypeSymbol, sourceProperties, property))
.Where(mappedProperty => mappedProperty is not null) .Where(mappedProperty => mappedProperty is not null)
.ToImmutableArray()!; .ToImmutableArray()!;
} }
protected override ImmutableArray<MappedMember> GetTypeMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass)
{
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IFieldSymbol>().ToArray();
return sourceTypeSymbol
.GetAllMembers()
.OfType<IFieldSymbol>()
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
.Select(property => MapFieldSimple(typeSymbol, property))
.Where(mappedProperty => mappedProperty is not null)
.ToImmutableArray()!;
}
protected override ImmutableArray<MappedMember> GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass)
{
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray();
return sourceTypeSymbol
.GetAllMembers()
.OfType<IPropertySymbol>()
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
.Select(property => MapPropertySimple(typeSymbol, property))
.Where(mappedProperty => mappedProperty is not null)
.ToImmutableArray()!;
}
} }
} }

View File

@ -28,7 +28,7 @@ namespace MapTo.Extensions
} }
internal static SourceBuilder WriteMappedProperties(this SourceBuilder builder, System.Collections.Immutable.ImmutableArray<MappedProperty> mappedProperties) internal static SourceBuilder WriteMappedProperties(this SourceBuilder builder, System.Collections.Immutable.ImmutableArray<MappedMember> mappedProperties)
{ {
foreach (var item in mappedProperties) foreach (var item in mappedProperties)
{ {

View File

@ -32,7 +32,13 @@ namespace MapTo.Extensions
.WriteMappedProperties(model.TypeProperties) .WriteMappedProperties(model.TypeProperties)
.WriteLine() .WriteLine()
.WriteComment("Source properties") .WriteComment("Source properties")
.WriteMappedProperties(model.SourceProperties) .WriteLine()
.WriteComment("Type fields")
.WriteComment()
.WriteMappedProperties(model.TypeFields)
.WriteLine()
.WriteComment("Source fields")
.WriteMappedProperties(model.SourceFields)
.WriteLine(); .WriteLine();
builder builder
@ -65,7 +71,7 @@ namespace MapTo.Extensions
var stringBuilder = new StringBuilder(); var stringBuilder = new StringBuilder();
var otherProperties = new List<MappedProperty>(); var otherProperties = new List<MappedMember>();
foreach (var property in model.TypeProperties) foreach (var property in model.TypeProperties)
{ {
@ -76,19 +82,30 @@ namespace MapTo.Extensions
otherProperties.Add(property); 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(); var readOnlyPropertiesArguments = stringBuilder.ToString();
builder builder
.WriteLine($"public {model.TypeIdentifierName}({model.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}") .WriteLine($"public {model.TypeIdentifierName}({model.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}")
.WriteOpeningBracket() .WriteOpeningBracket()
.TryWriteProperties(model.SourceProperties, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false); .WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false);
// End constructor declaration // End constructor declaration
return builder.WriteClosingBracket(); return builder.WriteClosingBracket();
} }
private static bool IsMappedProperty(this System.Collections.Immutable.ImmutableArray<MappedProperty> properties, MappedProperty property) { private static bool IsMappedProperty(this System.Collections.Immutable.ImmutableArray<MappedMember> properties, MappedMember property) {
foreach(var prop in properties) foreach(var prop in properties)
{ {
@ -98,44 +115,25 @@ namespace MapTo.Extensions
return false; return false;
} }
private static SourceBuilder TryWriteProperties(this SourceBuilder builder, System.Collections.Immutable.ImmutableArray<MappedProperty> properties, System.Collections.Immutable.ImmutableArray<MappedProperty>? otherProperties, private static SourceBuilder WriteAssignmentMethod(this SourceBuilder builder, MappingModel model, System.Collections.Immutable.ImmutableArray<MappedMember>? otherProperties,
string? sourceClassParameterName, string mappingContextParameterName, bool fromUpdate) 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.isReadOnly && fromUpdate) continue;
if (property.TypeConverter is null) builder.WriteLine( $"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};");
{
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});");
}
} }
foreach (var property in model.SourceFields)
{
if (property.isReadOnly && fromUpdate) continue;
builder.WriteLine($"{property.Name} = {sourceClassParameterName}.{property.SourcePropertyName};");
}
if (otherProperties == null) return builder; if (otherProperties == null) return builder;
@ -160,7 +158,7 @@ namespace MapTo.Extensions
.GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName) .GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName)
.WriteLine($"public void Update({model.SourceType} {sourceClassParameterName})") .WriteLine($"public void Update({model.SourceType} {sourceClassParameterName})")
.WriteOpeningBracket() .WriteOpeningBracket()
.TryWriteProperties(model.SourceProperties, null, sourceClassParameterName, "context", true) .WriteAssignmentMethod(model, null, sourceClassParameterName, "context", true)
.WriteClosingBracket(); .WriteClosingBracket();
return builder; return builder;

View File

@ -68,6 +68,10 @@ namespace MapTo.Extensions
typeSymbol = propertySymbol.Type; typeSymbol = propertySymbol.Type;
return true; return true;
case IFieldSymbol fieldSymbol:
typeSymbol = fieldSymbol.Type;
return true;
case IParameterSymbol parameterSymbol: case IParameterSymbol parameterSymbol:
typeSymbol = parameterSymbol.Type; typeSymbol = parameterSymbol.Type;
return true; return true;

View File

@ -11,8 +11,8 @@ namespace MapTo
{ {
internal static class MappingContextExtensions internal static class MappingContextExtensions
{ {
internal static ImmutableArray<MappedProperty> GetReadOnlyMappedProperties(this ImmutableArray<MappedProperty> mappedProperties) => mappedProperties.Where(p => p.isReadOnly).ToImmutableArray()!; internal static ImmutableArray<MappedMember> GetReadOnlyMappedProperties(this ImmutableArray<MappedMember> mappedProperties) => mappedProperties.Where(p => p.isReadOnly).ToImmutableArray()!;
internal static ImmutableArray<MappedProperty> GetWritableMappedProperties(this ImmutableArray<MappedProperty> mappedProperties) => mappedProperties.Where(p => !p.isReadOnly).ToImmutableArray()!; internal static ImmutableArray<MappedMember> GetWritableMappedProperties(this ImmutableArray<MappedMember> mappedProperties) => mappedProperties.Where(p => !p.isReadOnly).ToImmutableArray()!;
} }
internal abstract class MappingContext internal abstract class MappingContext
@ -109,9 +109,24 @@ namespace MapTo
return sourceProperties.SingleOrDefault(p => p.Name == propertyName); return sourceProperties.SingleOrDefault(p => p.Name == propertyName);
} }
protected IFieldSymbol? FindSourceField(IEnumerable<IFieldSymbol> 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<MappedMember> GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass);
protected abstract ImmutableArray<MappedMember> GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass);
protected abstract ImmutableArray<MappedMember> GetSourceMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass);
protected abstract ImmutableArray<MappedMember> GetTypeMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass);
protected abstract ImmutableArray<MappedProperty> GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass);
protected abstract ImmutableArray<MappedProperty> GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass);
protected INamedTypeSymbol? GetSourceTypeSymbol(TypeDeclarationSyntax typeDeclarationSyntax, SemanticModel? semanticModel = null) => protected INamedTypeSymbol? GetSourceTypeSymbol(TypeDeclarationSyntax typeDeclarationSyntax, SemanticModel? semanticModel = null) =>
GetSourceTypeSymbol(typeDeclarationSyntax.GetAttribute(MapFromAttributeSource.AttributeName), semanticModel); GetSourceTypeSymbol(typeDeclarationSyntax.GetAttribute(MapFromAttributeSource.AttributeName), semanticModel);
@ -144,7 +159,7 @@ namespace MapTo
return TypeSyntax.GetAttribute("UseUpdate") != null; return TypeSyntax.GetAttribute("UseUpdate") != null;
} }
protected virtual MappedProperty? MapProperty(ISymbol sourceTypeSymbol, IReadOnlyCollection<IPropertySymbol> sourceProperties, ISymbol property) protected virtual MappedMember? MapProperty(ISymbol sourceTypeSymbol, IReadOnlyCollection<IPropertySymbol> sourceProperties, ISymbol property)
{ {
var sourceProperty = FindSourceProperty(sourceProperties, property); var sourceProperty = FindSourceProperty(sourceProperties, property);
if (sourceProperty is null || !property.TryGetTypeSymbol(out var propertyType)) if (sourceProperty is null || !property.TryGetTypeSymbol(out var propertyType))
@ -160,7 +175,7 @@ namespace MapTo
if (!Compilation.HasCompatibleTypes(sourceProperty, property)) 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)) !TryGetNestedObjectMappings(property, out mappedSourcePropertyType, out enumerableTypeArgumentType))
{ {
return null; return null;
@ -172,7 +187,7 @@ namespace MapTo
AddUsingIfRequired(mappedSourcePropertyType); AddUsingIfRequired(mappedSourcePropertyType);
return new MappedProperty( return new MappedMember(
property.Name, property.Name,
property.GetTypeSymbol().ToString(), property.GetTypeSymbol().ToString(),
ToQualifiedDisplayName(propertyType) ?? propertyType.Name, ToQualifiedDisplayName(propertyType) ?? propertyType.Name,
@ -184,7 +199,52 @@ namespace MapTo
(property as IPropertySymbol).IsReadOnly); (property as IPropertySymbol).IsReadOnly);
; ;
} }
protected virtual MappedProperty? MapPropertySimple(ISymbol sourceTypeSymbol, ISymbol property)
protected virtual MappedMember? MapField(ISymbol sourceTypeSymbol, IReadOnlyCollection<IFieldSymbol> 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<string>.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)) if (!property.TryGetTypeSymbol(out var propertyType))
{ {
@ -203,7 +263,7 @@ namespace MapTo
AddUsingIfRequired(mappedSourcePropertyType); AddUsingIfRequired(mappedSourcePropertyType);
return new MappedProperty( return new MappedMember(
property.Name, property.Name,
property.GetTypeSymbol().ToString(), property.GetTypeSymbol().ToString(),
ToQualifiedDisplayName(propertyType) ?? propertyType.Name, ToQualifiedDisplayName(propertyType) ?? propertyType.Name,
@ -215,7 +275,44 @@ namespace MapTo
(property as IPropertySymbol).IsReadOnly); (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<string>.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<string> converterParameters) out ImmutableArray<string> converterParameters)
{ {
converterFullyQualifiedName = null; converterFullyQualifiedName = null;
@ -232,7 +329,7 @@ namespace MapTo
return false; return false;
} }
var baseInterface = GetTypeConverterBaseInterface(converterTypeSymbol, property, sourceProperty); var baseInterface = GetTypeConverterBaseInterfaceForProperty(converterTypeSymbol, property, sourceProperty);
if (baseInterface is null) if (baseInterface is null)
{ {
AddDiagnostic(DiagnosticsFactory.InvalidTypeConverterGenericTypesError(property, sourceProperty)); AddDiagnostic(DiagnosticsFactory.InvalidTypeConverterGenericTypesError(property, sourceProperty));
@ -243,7 +340,34 @@ namespace MapTo
converterParameters = GetTypeConverterParameters(typeConverterAttribute); converterParameters = GetTypeConverterParameters(typeConverterAttribute);
return true; return true;
} }
protected bool TryGetMapTypeConverterForField(ISymbol property, IFieldSymbol sourceProperty, out string? converterFullyQualifiedName,
out ImmutableArray<string> converterParameters)
{
converterFullyQualifiedName = null;
converterParameters = ImmutableArray<string>.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) protected bool TryGetNestedObjectMappings(ISymbol property, out ITypeSymbol? mappedSourcePropertyType, out ITypeSymbol? enumerableTypeArgument)
{ {
mappedSourcePropertyType = null; mappedSourcePropertyType = null;
@ -313,15 +437,18 @@ namespace MapTo
var shouldGenerateSecondaryConstructor = ShouldGenerateSecondaryConstructor(semanticModel, sourceTypeSymbol); var shouldGenerateSecondaryConstructor = ShouldGenerateSecondaryConstructor(semanticModel, sourceTypeSymbol);
var mappedProperties = GetSourceMappedProperties(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass); 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)); AddDiagnostic(DiagnosticsFactory.NoMatchingPropertyFoundError(TypeSyntax.GetLocation(), typeSymbol, sourceTypeSymbol));
return null; return null;
} }*/
AddUsingIfRequired(mappedProperties.Any(p => p.IsEnumerable), "System.Linq"); AddUsingIfRequired(mappedProperties.Any(p => p.IsEnumerable), "System.Linq");
var allProperties = GetTypeMappedProperties(sourceTypeSymbol, typeSymbol , isTypeInheritFromMappedBaseClass); var allProperties = GetTypeMappedProperties(sourceTypeSymbol, typeSymbol , isTypeInheritFromMappedBaseClass);
var allFields = GetTypeMappedFields(sourceTypeSymbol, typeSymbol, isTypeInheritFromMappedBaseClass);
return new MappingModel( return new MappingModel(
SourceGenerationOptions, SourceGenerationOptions,
@ -335,6 +462,8 @@ namespace MapTo
isTypeUpdatable, isTypeUpdatable,
mappedProperties, mappedProperties,
allProperties, allProperties,
mappedFields,
allFields,
isTypeInheritFromMappedBaseClass, isTypeInheritFromMappedBaseClass,
Usings, Usings,
shouldGenerateSecondaryConstructor); 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)) if (!property.TryGetTypeSymbol(out var propertyType))
{ {

View File

@ -22,7 +22,7 @@ namespace MapTo
internal record SourceCode(string Text, string HintName); internal record SourceCode(string Text, string HintName);
internal record MappedProperty( internal record MappedMember(
string Name, string Name,
string FullyQualifiedType, string FullyQualifiedType,
string Type, string Type,
@ -46,8 +46,10 @@ namespace MapTo
string SourceTypeIdentifierName, string SourceTypeIdentifierName,
string SourceTypeFullName, string SourceTypeFullName,
bool IsTypeUpdatable, bool IsTypeUpdatable,
ImmutableArray<MappedProperty> SourceProperties, ImmutableArray<MappedMember> SourceProperties,
ImmutableArray<MappedProperty> TypeProperties, ImmutableArray<MappedMember> TypeProperties,
ImmutableArray<MappedMember> SourceFields,
ImmutableArray<MappedMember> TypeFields,
bool HasMappedBaseClass, bool HasMappedBaseClass,
ImmutableArray<string> Usings, ImmutableArray<string> Usings,
bool GenerateSecondaryConstructor bool GenerateSecondaryConstructor

View File

@ -11,7 +11,12 @@ namespace MapTo
internal RecordMappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax) internal RecordMappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax)
: base(compilation, sourceGenerationOptions, typeSyntax) { } : base(compilation, sourceGenerationOptions, typeSyntax) { }
protected override ImmutableArray<MappedProperty> GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) protected override ImmutableArray<MappedMember> GetSourceMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass)
{
throw new System.NotImplementedException();
}
protected override ImmutableArray<MappedMember> GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass)
{ {
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray(); var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray();
return typeSymbol.GetMembers() return typeSymbol.GetMembers()
@ -25,7 +30,12 @@ namespace MapTo
.ToImmutableArray()!; .ToImmutableArray()!;
} }
protected override ImmutableArray<MappedProperty> GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass) protected override ImmutableArray<MappedMember> GetTypeMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass)
{
throw new System.NotImplementedException();
}
protected override ImmutableArray<MappedMember> GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass)
{ {
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray(); var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray();
return typeSymbol.GetMembers() return typeSymbol.GetMembers()

View File

@ -11,7 +11,20 @@ namespace MapTo
internal StructMappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax) internal StructMappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax)
: base(compilation, sourceGenerationOptions, typeSyntax) { } : base(compilation, sourceGenerationOptions, typeSyntax) { }
protected override ImmutableArray<MappedProperty> GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass) protected override ImmutableArray<MappedMember> GetSourceMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass)
{
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IFieldSymbol>().ToArray();
return typeSymbol
.GetAllMembers()
.OfType<IFieldSymbol>()
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
.Select(property => MapField(sourceTypeSymbol, sourceProperties, property))
.Where(mappedProperty => mappedProperty is not null)
.ToImmutableArray()!;
}
protected override ImmutableArray<MappedMember> GetSourceMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass)
{ {
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray(); var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray();
@ -23,7 +36,21 @@ namespace MapTo
.Where(mappedProperty => mappedProperty is not null) .Where(mappedProperty => mappedProperty is not null)
.ToImmutableArray()!; .ToImmutableArray()!;
} }
protected override ImmutableArray<MappedProperty> GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass)
protected override ImmutableArray<MappedMember> GetTypeMappedFields(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool isInheritFromMappedBaseClass)
{
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IFieldSymbol>().ToArray();
return sourceTypeSymbol
.GetAllMembers()
.OfType<IFieldSymbol>()
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
.Select(property => MapFieldSimple(typeSymbol, property))
.Where(mappedProperty => mappedProperty is not null)
.ToImmutableArray()!;
}
protected override ImmutableArray<MappedMember> GetTypeMappedProperties(ITypeSymbol typeSymbol, ITypeSymbol sourceTypeSymbol, bool hasInheritedClass)
{ {
var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray(); var sourceProperties = sourceTypeSymbol.GetAllMembers().OfType<IPropertySymbol>().ToArray();

View File

@ -23,14 +23,14 @@ namespace BlueWest.Data
[MapFrom(typeof(FinanceTransactionInsertDto))] [MapFrom(typeof(FinanceTransactionInsertDto))]
public partial struct FinanceTransaction public partial struct FinanceTransaction
{ {
public int Id { get; } public readonly int Id;
public int UserId { get; set; } public readonly int UserId;
public FinanceTransactionType FinanceTransactionType { get; } public readonly FinanceTransactionType FinanceTransactionType;
public FinanceSymbol FinanceSymbol { get; } public readonly FinanceSymbol FinanceSymbol;
public double Amount { get; } // To Buy public readonly double Amount; // To Buy
public double Quantity { get; } // Bought public readonly double Quantity; // Bought
public double Fee { get; } public readonly double Fee;
public DateTime DateTime { get; } public readonly DateTime DateTime;
public FinanceTransaction(int id, int userId, FinanceTransactionType financeTransactionType, public FinanceTransaction(int id, int userId, FinanceTransactionType financeTransactionType,

View File

@ -8,17 +8,17 @@ namespace BlueWest.Data
[MapFrom(typeof(UserUpdateDto))] [MapFrom(typeof(UserUpdateDto))]
public partial class User public partial class User
{ {
public int Id { get; } public readonly int Id;
public string Name { get; set; } public string Name;
public string Address { get; set; } public string Address;
public string BTCAddress { get; set; }
public string LTCAddress { get; set; }
public double BTCAmount { get; set; } public string BTCAddress;
public double LTCAmount { get; set; } public string LTCAddress;
public List<FinanceTransaction> FinanceTransactions { get; } public double BTCAmount;
public double LTCAmount;
public readonly List<FinanceTransaction> FinanceTransactions;
public User(int id, string name, string address, string btcAddress, string ltcAddress, double btcAmount, double ltcAmount, List<FinanceTransaction> financeTransactions) public User(int id, string name, string address, string btcAddress, string ltcAddress, double btcAmount, double ltcAmount, List<FinanceTransaction> financeTransactions)
{ {

View File

@ -4,16 +4,16 @@ namespace BlueWest.Data
{ {
[MapFrom(typeof(User))] [MapFrom(typeof(User))]
public partial struct UserUpdateDto public partial class UserUpdateDto
{ {
public string Name { get; set; } public string Name;
public string Address { get; set; } public string Address;
public string BTCAddress { get; set; }
public string LTCAddress { get; set; }
public double BTCAmount { get; set; } public string BTCAddress;
public double LTCAmount { get; set; } public string LTCAddress;
public double BTCAmount;
public double LTCAmount;
} }
} }