work with field
This commit is contained in:
parent
768dbb4532
commit
5faebd9141
|
@ -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()!;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue