stuff
This commit is contained in:
parent
60ccbd53ca
commit
ffc3dc7729
|
@ -18,7 +18,7 @@ namespace MapTo
|
|||
return typeSymbol
|
||||
.GetAllMembers()
|
||||
.OfType<IFieldSymbol>()
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapField(sourceTypeSymbol, sourceProperties, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
@ -31,7 +31,7 @@ namespace MapTo
|
|||
return typeSymbol
|
||||
.GetAllMembers()
|
||||
.OfType<IPropertySymbol>()
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapProperty(sourceTypeSymbol, sourceProperties, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
@ -44,7 +44,7 @@ namespace MapTo
|
|||
return sourceTypeSymbol
|
||||
.GetAllMembers()
|
||||
.OfType<IFieldSymbol>()
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapFieldSimple(typeSymbol, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
@ -57,7 +57,7 @@ namespace MapTo
|
|||
return sourceTypeSymbol
|
||||
.GetAllMembers()
|
||||
.OfType<IPropertySymbol>()
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapPropertySimple(typeSymbol, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace MapTo
|
|||
Create($"{ErrorId}030", location, $"No matching properties found between '{classType.ToDisplayString()}' and '{sourceType.ToDisplayString()}' types.");
|
||||
|
||||
internal static Diagnostic NoMatchingPropertyTypeFoundError(ISymbol property) =>
|
||||
Create($"{ErrorId}031", property.Locations.FirstOrDefault(), $"Cannot create a map for '{property.ToDisplayString()}' property because source and destination types are not implicitly convertible. Consider using '{MapTypeConverterAttributeSource.FullyQualifiedName}' to provide a type converter or ignore the property using '{IgnorePropertyAttributeSource.FullyQualifiedName}'.");
|
||||
Create($"{ErrorId}031", property.Locations.FirstOrDefault(), $"Cannot create a map for '{property.ToDisplayString()}' property because source and destination types are not implicitly convertible. Consider using '{MapTypeConverterAttributeSource.FullyQualifiedName}' to provide a type converter or ignore the property using '{IgnoreMemberAttributeSource.FullyQualifiedName}'.");
|
||||
|
||||
internal static Diagnostic InvalidTypeConverterGenericTypesError(ISymbol property, IPropertySymbol sourceProperty) =>
|
||||
Create($"{ErrorId}032", property.Locations.FirstOrDefault(), $"Cannot map '{property.ToDisplayString()}' property because the annotated converter does not implement '{RootNamespace}.{ITypeConverterSource.InterfaceName}<{sourceProperty.Type.ToDisplayString()}, {property.GetTypeSymbol()?.ToDisplayString()}>'.");
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MapTo.Sources;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
@ -12,6 +13,21 @@ namespace MapTo.Extensions
|
|||
return builder.WriteLine($"// {comment}");
|
||||
}
|
||||
|
||||
internal static SourceBuilder WriteCommentArray(this SourceBuilder builder, IEnumerable<object> enumerable, string name = "")
|
||||
{
|
||||
builder.WriteComment($"Printing Array: {name}");
|
||||
foreach (var o in enumerable)
|
||||
{
|
||||
if (o != null)
|
||||
{
|
||||
builder.WriteComment($" {o.ToString()}");
|
||||
}
|
||||
}
|
||||
builder.WriteComment($"End printing Array: {name}");
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
internal static SourceBuilder WriteModelInfo(this SourceBuilder builder, MappingModel model)
|
||||
{
|
||||
return builder
|
||||
|
@ -32,6 +48,16 @@ namespace MapTo.Extensions
|
|||
{
|
||||
foreach (var item in mappedProperties)
|
||||
{
|
||||
string str = "";
|
||||
|
||||
if (item.NamedTypeSymbol != null)
|
||||
foreach (var named in item.NamedTypeSymbol?.TypeArguments)
|
||||
{
|
||||
str += $"typeToString: {named.ToString()} ";
|
||||
bool? containedTypeIsJsonEXtension = named?.HasAttribute(MappingContext.JsonExtensionAttributeSymbol);
|
||||
str += $"typeArgumentTypeIsJsonExtensioN: {containedTypeIsJsonEXtension.ToString()}";
|
||||
}
|
||||
|
||||
builder .WriteComment($" Name {item.Name}")
|
||||
.WriteComment($" Type {item.Type}")
|
||||
.WriteComment($" MappedSourcePropertyTypeName {item.MappedSourcePropertyTypeName}")
|
||||
|
@ -41,6 +67,10 @@ namespace MapTo.Extensions
|
|||
.WriteComment($" SourcePropertyName {item.SourcePropertyName}")
|
||||
.WriteComment($" TypeSymbol {item.FullyQualifiedType.ToString()}")
|
||||
.WriteComment($" isReadOnly {item.isReadOnly.ToString()}")
|
||||
.WriteComment($" isEnumerable {item.isEnumerable.ToString()}")
|
||||
.WriteComment($" INamedTypeSymbol {item.NamedTypeSymbol?.ToString()}")
|
||||
.WriteComment($" INamedTypeSymbolTypeArguments {str}")
|
||||
|
||||
.WriteLine();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace MapTo.Extensions
|
||||
{
|
||||
|
@ -49,7 +51,9 @@ namespace MapTo.Extensions
|
|||
// Class body
|
||||
.GeneratePublicConstructor(model);
|
||||
|
||||
if (model.IsJsonExtension) builder.WriteToJsonMethod(model);
|
||||
if (model.IsTypeUpdatable && model.TypeProperties.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model);
|
||||
if (model.IsTypeUpdatable && model.TypeFields.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model);
|
||||
|
||||
builder
|
||||
.WriteLine()
|
||||
|
@ -105,7 +109,8 @@ namespace MapTo.Extensions
|
|||
return builder.WriteClosingBracket();
|
||||
}
|
||||
|
||||
private static bool IsMappedProperty(this System.Collections.Immutable.ImmutableArray<MappedMember> properties, MappedMember property) {
|
||||
private static bool IsMappedProperty(this System.Collections.Immutable.ImmutableArray<MappedMember> properties, MappedMember property)
|
||||
{
|
||||
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
|
@ -115,6 +120,110 @@ namespace MapTo.Extensions
|
|||
return false;
|
||||
}
|
||||
|
||||
private static SourceBuilder WriteToJsonMethod(this SourceBuilder builder, MappingModel model)
|
||||
{
|
||||
builder
|
||||
.WriteLine($"public string ToJson()")
|
||||
.WriteOpeningBracket()
|
||||
.WriteLine("var stringBuilder = new System.Text.StringBuilder();")
|
||||
.WriteLine(GetStringBuilderAppendNoInterpolation("{"));
|
||||
|
||||
foreach (var property in model.TypeProperties)
|
||||
{
|
||||
if (!property.isEnumerable)
|
||||
HandlePropertyEnumerable(builder, property);
|
||||
else
|
||||
{
|
||||
builder = WriteJsonField(builder, property);
|
||||
}
|
||||
}
|
||||
foreach (var property in model.TypeFields)
|
||||
{
|
||||
if (!property.isEnumerable)
|
||||
HandleFieldEnumerable(builder, property);
|
||||
else
|
||||
{
|
||||
builder.WriteLine(GetStringBuilderAppend($"\\\"{property.Name.ToCamelCase()}\\\" : [{GetJsonArrayValue(property, ref builder)}],"));
|
||||
}
|
||||
}
|
||||
|
||||
builder.WriteLine(GetStringBuilderAppendNoInterpolation("}"));
|
||||
builder.WriteLine("return stringBuilder.ToString();");
|
||||
builder.WriteClosingBracket();
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static SourceBuilder WriteJsonField(SourceBuilder builder, MappedMember property)
|
||||
{
|
||||
builder.WriteLine(
|
||||
GetStringBuilderAppend(
|
||||
$"\\\"{property.Name.ToCamelCase()}\\\" : [{GetJsonArrayValue(property, ref builder)}],"));
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static void HandleEnumerable(SourceBuilder builder, MappedMember property)
|
||||
{
|
||||
var symbol = property.ActualSymbol as IPropertySymbol;
|
||||
builder.WriteCommentArray(symbol.Parameters, nameof(symbol.Parameters));
|
||||
builder.WriteCommentArray(symbol.TypeCustomModifiers, nameof(symbol.TypeCustomModifiers));
|
||||
|
||||
builder.WriteComment($"Is enumerable {(property.ActualSymbol as IPropertySymbol).Parameters}");
|
||||
builder.WriteLine(
|
||||
GetStringBuilderAppend($"\\\"{property.Name.ToCamelCase()}\\\" : {GetJsonValue(property, builder)},"));
|
||||
}
|
||||
|
||||
|
||||
private static void HandleFieldEnumerable(SourceBuilder builder, MappedMember property)
|
||||
{
|
||||
HandleEnumerable(builder, property);
|
||||
}
|
||||
|
||||
private static void HandlePropertyEnumerable(SourceBuilder builder, MappedMember property)
|
||||
{
|
||||
HandleEnumerable(builder, property);
|
||||
}
|
||||
|
||||
private static string GetJsonArrayValue(MappedMember member, ref SourceBuilder builder)
|
||||
{
|
||||
if (member.isEnumerable)
|
||||
{
|
||||
// get underlying type (check if is a json extension)
|
||||
|
||||
builder.WriteLine("var arrStrBuilder = new StringBuilder();");
|
||||
|
||||
foreach (var named in member.NamedTypeSymbol?.TypeArguments!)
|
||||
{
|
||||
bool? containedTypeIsJsonEXtension = named?.HasAttribute(MappingContext.JsonExtensionAttributeSymbol);
|
||||
if (!containedTypeIsJsonEXtension.HasValue) continue;
|
||||
builder.WriteLine($"foreach (var v in {member.SourcePropertyName.ToString()})");
|
||||
builder.WriteOpeningBracket();
|
||||
builder.WriteLine("arrStrBuilder.Append(v.ToJson());");
|
||||
builder.WriteLine("arrStrBuilder.Append(\", \");");
|
||||
builder.WriteClosingBracket();
|
||||
}
|
||||
builder.WriteLine("arrStrBuilder.Remove(arrStrBuilder.Length -1, 1);");
|
||||
}
|
||||
|
||||
return "{arrStrBuilder.ToString()}";
|
||||
}
|
||||
private static string GetJsonValue(MappedMember member, SourceBuilder builder)
|
||||
{
|
||||
|
||||
if (member.FullyQualifiedType == "string") return $"\\\"{{{member.SourcePropertyName}}}\\\"";
|
||||
if (member.FullyQualifiedType is "int" or "double" or "float" or "long") return $"{{{member.SourcePropertyName}}}";
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private static string GetStringBuilderAppend(string stringToAppend)
|
||||
{
|
||||
return $"stringBuilder.Append($\"{stringToAppend}\");";
|
||||
}
|
||||
private static string GetStringBuilderAppendNoInterpolation(string stringToAppend)
|
||||
{
|
||||
return $"stringBuilder.Append(\"{stringToAppend}\");";
|
||||
}
|
||||
|
||||
private static SourceBuilder WriteAssignmentMethod(this SourceBuilder builder, MappingModel model, System.Collections.Immutable.ImmutableArray<MappedMember>? otherProperties,
|
||||
string? sourceClassParameterName, string mappingContextParameterName, bool fromUpdate)
|
||||
{
|
||||
|
@ -178,5 +287,17 @@ namespace MapTo.Extensions
|
|||
.WriteLine("/// </summary>")
|
||||
.WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{model.SourceType}\"/> to use as source.</param>");
|
||||
}
|
||||
|
||||
private static SourceBuilder GenerateEnumerableJsonSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model)
|
||||
{
|
||||
var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase();
|
||||
|
||||
return builder
|
||||
.WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]")
|
||||
.WriteLine($"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static string ToJson(this IEnumerable<{model.SourceType}{model.Options.NullableReferenceSyntax}> {sourceClassParameterName}List)")
|
||||
.WriteOpeningBracket()
|
||||
.WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});")
|
||||
.WriteClosingBracket();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,9 @@ namespace MapTo
|
|||
|
||||
var compilation = context.Compilation
|
||||
.AddSource(ref context, UseUpdateAttributeSource.Generate(options))
|
||||
.AddSource(ref context, JsonExtensionAttributeSource.Generate(options))
|
||||
.AddSource(ref context, MapFromAttributeSource.Generate(options))
|
||||
.AddSource(ref context, IgnorePropertyAttributeSource.Generate(options))
|
||||
.AddSource(ref context, IgnoreMemberAttributeSource.Generate(options))
|
||||
.AddSource(ref context, ITypeConverterSource.Generate(options))
|
||||
.AddSource(ref context, MapTypeConverterAttributeSource.Generate(options))
|
||||
.AddSource(ref context, MapPropertyAttributeSource.Generate(options))
|
||||
|
|
|
@ -28,12 +28,13 @@ namespace MapTo
|
|||
TypeSyntax = typeSyntax;
|
||||
Compilation = compilation;
|
||||
|
||||
IgnorePropertyAttributeTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(IgnorePropertyAttributeSource.FullyQualifiedName);
|
||||
IgnoreMemberAttributeTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(IgnoreMemberAttributeSource.FullyQualifiedName);
|
||||
MapTypeConverterAttributeTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(MapTypeConverterAttributeSource.FullyQualifiedName);
|
||||
TypeConverterInterfaceTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(ITypeConverterSource.FullyQualifiedName);
|
||||
MapPropertyAttributeTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(MapPropertyAttributeSource.FullyQualifiedName);
|
||||
MapFromAttributeTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(MapFromAttributeSource.FullyQualifiedName);
|
||||
UseUpdateAttributeTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(UseUpdateAttributeSource.FullyQualifiedName);
|
||||
JsonExtensionAttributeSymbol = compilation.GetTypeByMetadataNameOrThrow(JsonExtensionAttributeSource.FullyQualifiedName);
|
||||
MappingContextTypeSymbol = compilation.GetTypeByMetadataNameOrThrow(MappingContextSource.FullyQualifiedName);
|
||||
|
||||
AddUsingIfRequired(sourceGenerationOptions.SupportNullableStaticAnalysis, "System.Diagnostics.CodeAnalysis");
|
||||
|
@ -45,12 +46,14 @@ namespace MapTo
|
|||
|
||||
protected Compilation Compilation { get; }
|
||||
|
||||
protected INamedTypeSymbol IgnorePropertyAttributeTypeSymbol { get; }
|
||||
protected INamedTypeSymbol IgnoreMemberAttributeTypeSymbol { get; }
|
||||
|
||||
protected INamedTypeSymbol MapFromAttributeTypeSymbol { get; }
|
||||
|
||||
protected INamedTypeSymbol UseUpdateAttributeTypeSymbol { get; }
|
||||
|
||||
public static INamedTypeSymbol JsonExtensionAttributeSymbol { get; set; }
|
||||
|
||||
protected INamedTypeSymbol MappingContextTypeSymbol { get; }
|
||||
|
||||
protected INamedTypeSymbol MapPropertyAttributeTypeSymbol { get; }
|
||||
|
@ -158,7 +161,10 @@ namespace MapTo
|
|||
{
|
||||
return TypeSyntax.GetAttribute("UseUpdate") != null;
|
||||
}
|
||||
|
||||
protected bool HasJsonExtension()
|
||||
{
|
||||
return TypeSyntax.GetAttribute("JsonExtension") != null;
|
||||
}
|
||||
protected virtual MappedMember? MapProperty(ISymbol sourceTypeSymbol, IReadOnlyCollection<IPropertySymbol> sourceProperties, ISymbol property)
|
||||
{
|
||||
var sourceProperty = FindSourceProperty(sourceProperties, property);
|
||||
|
@ -186,6 +192,9 @@ namespace MapTo
|
|||
AddUsingIfRequired(enumerableTypeArgumentType);
|
||||
AddUsingIfRequired(mappedSourcePropertyType);
|
||||
|
||||
INamedTypeSymbol? namedType;
|
||||
var isEnumerable = IsEnumerable(property, out namedType);
|
||||
|
||||
|
||||
return new MappedMember(
|
||||
property.Name,
|
||||
|
@ -196,6 +205,9 @@ namespace MapTo
|
|||
sourceProperty.Name,
|
||||
ToQualifiedDisplayName(mappedSourcePropertyType),
|
||||
ToQualifiedDisplayName(enumerableTypeArgumentType),
|
||||
property,
|
||||
namedType,
|
||||
isEnumerable,
|
||||
(property as IPropertySymbol).IsReadOnly);
|
||||
;
|
||||
}
|
||||
|
@ -232,6 +244,9 @@ namespace MapTo
|
|||
AddUsingIfRequired(mappedSourcePropertyType);
|
||||
|
||||
|
||||
INamedTypeSymbol? namedType;
|
||||
var isEnumerable = IsEnumerable(property, out namedType);
|
||||
|
||||
return new MappedMember(
|
||||
property.Name,
|
||||
property.GetTypeSymbol().ToString(),
|
||||
|
@ -241,6 +256,9 @@ namespace MapTo
|
|||
sourceProperty.Name,
|
||||
ToQualifiedDisplayName(mappedSourcePropertyType),
|
||||
ToQualifiedDisplayName(enumerableTypeArgumentType),
|
||||
property,
|
||||
namedType,
|
||||
isEnumerable,
|
||||
(property as IFieldSymbol).IsReadOnly);
|
||||
;
|
||||
}
|
||||
|
@ -262,6 +280,8 @@ namespace MapTo
|
|||
AddUsingIfRequired(enumerableTypeArgumentType);
|
||||
AddUsingIfRequired(mappedSourcePropertyType);
|
||||
|
||||
INamedTypeSymbol? namedType;
|
||||
var isEnumerable = IsEnumerable(property, out namedType);
|
||||
|
||||
return new MappedMember(
|
||||
property.Name,
|
||||
|
@ -272,6 +292,9 @@ namespace MapTo
|
|||
property.Name,
|
||||
ToQualifiedDisplayName(mappedSourcePropertyType),
|
||||
ToQualifiedDisplayName(enumerableTypeArgumentType),
|
||||
property,
|
||||
namedType,
|
||||
isEnumerable,
|
||||
(property as IPropertySymbol).IsReadOnly);
|
||||
;
|
||||
}
|
||||
|
@ -299,6 +322,9 @@ namespace MapTo
|
|||
AddUsingIfRequired(enumerableTypeArgumentType);
|
||||
AddUsingIfRequired(mappedSourcePropertyType);
|
||||
|
||||
INamedTypeSymbol? namedType;
|
||||
var isEnumerable = IsEnumerable(property, out namedType);
|
||||
|
||||
|
||||
return new MappedMember(
|
||||
property.Name,
|
||||
|
@ -309,6 +335,9 @@ namespace MapTo
|
|||
property.Name,
|
||||
ToQualifiedDisplayName(mappedSourcePropertyType),
|
||||
ToQualifiedDisplayName(enumerableTypeArgumentType),
|
||||
property,
|
||||
namedType,
|
||||
isEnumerable,
|
||||
(property as IFieldSymbol).IsReadOnly);
|
||||
;
|
||||
}
|
||||
|
@ -403,7 +432,27 @@ namespace MapTo
|
|||
|
||||
return Diagnostics.IsEmpty();
|
||||
}
|
||||
protected bool IsEnumerable(ISymbol property, out INamedTypeSymbol? namedTypeSymbolResult)
|
||||
{
|
||||
|
||||
if (!property.TryGetTypeSymbol(out var propertyType))
|
||||
{
|
||||
AddDiagnostic(DiagnosticsFactory.NoMatchingPropertyTypeFoundError(property));
|
||||
namedTypeSymbolResult = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
propertyType is INamedTypeSymbol namedTypeSymbol &&
|
||||
!propertyType.IsPrimitiveType() &&
|
||||
(Compilation.IsGenericEnumerable(propertyType) || propertyType.AllInterfaces.Any(i => Compilation.IsGenericEnumerable(i))))
|
||||
{
|
||||
namedTypeSymbolResult = namedTypeSymbol;
|
||||
return true;
|
||||
}
|
||||
namedTypeSymbolResult = null;
|
||||
return false;
|
||||
}
|
||||
private static ImmutableArray<string> GetTypeConverterParameters(AttributeData typeConverterAttribute)
|
||||
{
|
||||
var converterParameter = typeConverterAttribute.ConstructorArguments.Skip(1).FirstOrDefault();
|
||||
|
@ -434,6 +483,7 @@ namespace MapTo
|
|||
var sourceTypeIdentifierName = sourceTypeSymbol.Name;
|
||||
var isTypeInheritFromMappedBaseClass = IsTypeInheritFromMappedBaseClass(semanticModel);
|
||||
var isTypeUpdatable = IsTypeUpdatable();
|
||||
var hasJsonExtension = HasJsonExtension();
|
||||
var shouldGenerateSecondaryConstructor = ShouldGenerateSecondaryConstructor(semanticModel, sourceTypeSymbol);
|
||||
|
||||
var mappedProperties = GetSourceMappedProperties(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass);
|
||||
|
@ -460,6 +510,7 @@ namespace MapTo
|
|||
sourceTypeIdentifierName,
|
||||
sourceTypeSymbol.ToDisplayString(),
|
||||
isTypeUpdatable,
|
||||
hasJsonExtension,
|
||||
mappedProperties,
|
||||
allProperties,
|
||||
mappedFields,
|
||||
|
|
|
@ -31,6 +31,9 @@ namespace MapTo
|
|||
string SourcePropertyName,
|
||||
string? MappedSourcePropertyTypeName,
|
||||
string? EnumerableTypeArgument,
|
||||
ISymbol ActualSymbol,
|
||||
INamedTypeSymbol? NamedTypeSymbol,
|
||||
bool isEnumerable,
|
||||
bool isReadOnly)
|
||||
{
|
||||
public bool IsEnumerable => EnumerableTypeArgument is not null;
|
||||
|
@ -46,6 +49,7 @@ namespace MapTo
|
|||
string SourceTypeIdentifierName,
|
||||
string SourceTypeFullName,
|
||||
bool IsTypeUpdatable,
|
||||
bool IsJsonExtension,
|
||||
ImmutableArray<MappedMember> SourceProperties,
|
||||
ImmutableArray<MappedMember> TypeProperties,
|
||||
ImmutableArray<MappedMember> SourceFields,
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace MapTo
|
|||
.OrderByDescending(s => s.Parameters.Length)
|
||||
.First(s => s.Name == ".ctor")
|
||||
.Parameters
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapProperty(sourceTypeSymbol, sourceProperties, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
@ -43,7 +43,7 @@ namespace MapTo
|
|||
.OrderByDescending(s => s.Parameters.Length)
|
||||
.First(s => s.Name == ".ctor")
|
||||
.Parameters
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapProperty(typeSymbol, sourceProperties, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
using static MapTo.Sources.Constants;
|
||||
|
||||
namespace MapTo.Sources
|
||||
{
|
||||
internal static class DictionaryToListAttributeSource
|
||||
{
|
||||
internal const string AttributeName = "DictionaryToList";
|
||||
internal const string AttributeClassName = AttributeName + "Attribute";
|
||||
internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
|
||||
internal const string SourceMemberNameFieldOrPropertyName = "SourcePropertyName";
|
||||
|
||||
internal static SourceCode Generate(SourceGenerationOptions options)
|
||||
{
|
||||
using var builder = new SourceBuilder()
|
||||
.WriteLine(GeneratedFilesHeader)
|
||||
.WriteNullableContextOptionIf(options.SupportNullableReferenceTypes)
|
||||
.WriteLine()
|
||||
.WriteLine("using System;")
|
||||
.WriteLine()
|
||||
.WriteLine($"namespace {RootNamespace}")
|
||||
.WriteOpeningBracket();
|
||||
|
||||
if (options.GenerateXmlDocument)
|
||||
{
|
||||
builder
|
||||
.WriteLine("/// <summary>")
|
||||
.WriteLine("/// Specifies the mapping behavior of the annotated property.")
|
||||
.WriteLine("/// </summary>")
|
||||
.WriteLine("/// <remarks>")
|
||||
.WriteLine($"/// {AttributeClassName} has a number of uses:")
|
||||
.WriteLine("/// <list type=\"bullet\">")
|
||||
.WriteLine("/// <item><description>By default properties with same name will get mapped. This attribute allows the names to be different.</description></item>")
|
||||
.WriteLine("/// <item><description>Indicates that a property should be mapped when member serialization is set to opt-in.</description></item>")
|
||||
.WriteLine("/// </list>")
|
||||
.WriteLine("/// </remarks>");
|
||||
}
|
||||
|
||||
builder
|
||||
.WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]")
|
||||
.WriteLine($"public sealed class {AttributeClassName} : Attribute")
|
||||
.WriteOpeningBracket();
|
||||
|
||||
if (options.GenerateXmlDocument)
|
||||
{
|
||||
builder
|
||||
.WriteLine("/// <summary>")
|
||||
.WriteLine("/// Gets or sets the property name of the object to mapping from.")
|
||||
.WriteLine("/// </summary>");
|
||||
}
|
||||
|
||||
builder
|
||||
.WriteLine($"public string{options.NullableReferenceSyntax} {SourceMemberNameFieldOrPropertyName} {{ get; set; }}")
|
||||
.WriteClosingBracket() // class
|
||||
.WriteClosingBracket(); // namespace
|
||||
|
||||
|
||||
return new(builder.ToString(), $"{AttributeClassName}.g.cs");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace MapTo.Sources
|
||||
{
|
||||
internal static class IgnorePropertyAttributeSource
|
||||
internal static class IgnoreMemberAttributeSource
|
||||
{
|
||||
internal const string AttributeName = "IgnoreProperty";
|
||||
internal const string AttributeName = "IgnoreMemberMapTo";
|
||||
internal const string AttributeClassName = AttributeName + "Attribute";
|
||||
internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace MapTo.Sources
|
|||
}
|
||||
|
||||
builder
|
||||
.WriteLine("[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]")
|
||||
.WriteLine("[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = false)]")
|
||||
.WriteLine($"public sealed class {AttributeClassName} : Attribute {{ }}")
|
||||
.WriteClosingBracket();
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
using static MapTo.Sources.Constants;
|
||||
|
||||
namespace MapTo.Sources
|
||||
{
|
||||
internal static class JsonExtensionAttributeSource
|
||||
{
|
||||
internal const string AttributeName = "JsonExtension";
|
||||
internal const string AttributeClassName = AttributeName + "Attribute";
|
||||
internal const string FullyQualifiedName = RootNamespace + "." + AttributeClassName;
|
||||
|
||||
internal static SourceCode Generate(SourceGenerationOptions options)
|
||||
{
|
||||
using var builder = new SourceBuilder()
|
||||
.WriteLine(GeneratedFilesHeader)
|
||||
.WriteLine("using System;")
|
||||
.WriteLine()
|
||||
.WriteLine($"namespace {RootNamespace}")
|
||||
.WriteOpeningBracket();
|
||||
|
||||
if (options.GenerateXmlDocument)
|
||||
{
|
||||
builder
|
||||
.WriteLine("/// <summary>")
|
||||
.WriteLine("/// Specifies that the annotated class has a json extension.")
|
||||
.WriteLine("/// </summary>");
|
||||
}
|
||||
|
||||
builder
|
||||
.WriteLine("[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]")
|
||||
.WriteLine($"public sealed class {AttributeName}Attribute : Attribute")
|
||||
.WriteOpeningBracket();
|
||||
|
||||
builder
|
||||
.WriteClosingBracket() // class
|
||||
.WriteClosingBracket(); // namespace
|
||||
|
||||
return new(builder.ToString(), $"{AttributeName}Attribute.g.cs");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ namespace MapTo
|
|||
return typeSymbol
|
||||
.GetAllMembers()
|
||||
.OfType<IFieldSymbol>()
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapField(sourceTypeSymbol, sourceProperties, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
@ -31,7 +31,7 @@ namespace MapTo
|
|||
return typeSymbol
|
||||
.GetAllMembers()
|
||||
.OfType<IPropertySymbol>()
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapProperty(sourceTypeSymbol, sourceProperties, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
@ -44,7 +44,7 @@ namespace MapTo
|
|||
return sourceTypeSymbol
|
||||
.GetAllMembers()
|
||||
.OfType<IFieldSymbol>()
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapFieldSimple(typeSymbol, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
@ -57,7 +57,7 @@ namespace MapTo
|
|||
return sourceTypeSymbol
|
||||
.GetAllMembers()
|
||||
.OfType<IPropertySymbol>()
|
||||
.Where(p => !p.HasAttribute(IgnorePropertyAttributeTypeSymbol))
|
||||
.Where(p => !p.HasAttribute(IgnoreMemberAttributeTypeSymbol))
|
||||
.Select(property => MapPropertySimple(typeSymbol, property))
|
||||
.Where(mappedProperty => mappedProperty is not null)
|
||||
.ToImmutableArray()!;
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace BlueWest.Data
|
|||
Sell
|
||||
}
|
||||
|
||||
[JsonExtension]
|
||||
[MapFrom(typeof(FinanceTransactionInsertDto))]
|
||||
public partial struct FinanceTransaction
|
||||
{
|
||||
|
|
|
@ -5,12 +5,12 @@ namespace BlueWest.Data
|
|||
|
||||
public partial struct FinanceTransactionInsertDto
|
||||
{
|
||||
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 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;
|
||||
}
|
||||
}
|
|
@ -9,14 +9,14 @@ namespace BlueWest.Data
|
|||
|
||||
partial struct FinanceTransactionReadDto
|
||||
{
|
||||
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 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 string ReadData { get; }
|
||||
public readonly string ReadData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ using MapTo;
|
|||
namespace BlueWest.Data
|
||||
{
|
||||
[MapFrom(typeof(UserUpdateDto))]
|
||||
[JsonExtension]
|
||||
public partial class User
|
||||
{
|
||||
public readonly int Id;
|
||||
|
|
Loading…
Reference in New Issue