Add MappedSourceType to the list

This commit is contained in:
CodeLiturgy 2022-08-18 16:01:39 +01:00
parent 2cd2a3868c
commit 3a2d3a1b41
6 changed files with 111 additions and 75 deletions

View File

@ -5,7 +5,7 @@ using MapTo;
namespace BlueWest.Data namespace BlueWest.Data
{ {
[MapFrom(typeof(CountryUpdate))] [MapFrom(new [] {typeof(CountryUpdate), typeof(CountryCreate)})]
public partial class Country public partial class Country
{ {
// ISO 3166-1 numeric code // ISO 3166-1 numeric code

View File

@ -30,6 +30,7 @@ namespace MapTo.Extensions
internal static SourceBuilder WriteModelInfo(this SourceBuilder builder, MappingModel model) internal static SourceBuilder WriteModelInfo(this SourceBuilder builder, MappingModel model)
{ {
var targetSourceType = model.MappedSourceTypes[0];
return builder return builder
.WriteLine() .WriteLine()
.WriteComment($" IsTypeUpdatable {model.IsTypeUpdatable}") .WriteComment($" IsTypeUpdatable {model.IsTypeUpdatable}")
@ -38,9 +39,9 @@ namespace MapTo.Extensions
.WriteComment($" Options {model.Options.ToString()}") .WriteComment($" Options {model.Options.ToString()}")
.WriteComment($" Type {model.Type}") .WriteComment($" Type {model.Type}")
.WriteComment($" TypeIdentifierName {model.TypeIdentifierName}") .WriteComment($" TypeIdentifierName {model.TypeIdentifierName}")
.WriteComment($" SourceNamespace {model.SourceNamespace}") .WriteComment($" SourceNamespace {targetSourceType.SourceNamespace}")
.WriteComment($" SourceTypeFullName {model.SourceTypeFullName}") .WriteComment($" SourceTypeFullName {targetSourceType.SourceTypeFullName}")
.WriteComment($" SourceTypeIdentifierName {model.SourceTypeIdentifierName}"); .WriteComment($" SourceTypeIdentifierName {targetSourceType.SourceTypeIdentifierName}");
} }

View File

@ -15,6 +15,8 @@ namespace MapTo.Extensions
{ {
const bool writeDebugInfo = true; const bool writeDebugInfo = true;
var targetSourceType = model.MappedSourceTypes[0];
using var builder = new SourceBuilder() using var builder = new SourceBuilder()
.WriteLine(GeneratedFilesHeader) .WriteLine(GeneratedFilesHeader)
.WriteNullableContextOptionIf(model.Options.SupportNullableReferenceTypes) .WriteNullableContextOptionIf(model.Options.SupportNullableReferenceTypes)
@ -31,16 +33,16 @@ namespace MapTo.Extensions
.WriteLine() .WriteLine()
.WriteComment("Type properties") .WriteComment("Type properties")
.WriteComment() .WriteComment()
.WriteMappedProperties(model.TypeProperties) .WriteMappedProperties(targetSourceType.TypeProperties)
.WriteLine() .WriteLine()
.WriteComment("Source properties") .WriteComment("Source properties")
.WriteLine() .WriteLine()
.WriteComment("Type fields") .WriteComment("Type fields")
.WriteComment() .WriteComment()
.WriteMappedProperties(model.TypeFields) .WriteMappedProperties(targetSourceType.TypeFields)
.WriteLine() .WriteLine()
.WriteComment("Source fields") .WriteComment("Source fields")
.WriteMappedProperties(model.SourceFields) .WriteMappedProperties(targetSourceType.SourceFields)
.WriteLine(); .WriteLine();
builder builder
@ -52,8 +54,8 @@ namespace MapTo.Extensions
.GeneratePublicConstructor(model); .GeneratePublicConstructor(model);
if (model.IsJsonExtension) builder.WriteToJsonMethod(model); if (model.IsJsonExtension) builder.WriteToJsonMethod(model);
if (model.IsTypeUpdatable && model.TypeProperties.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model); if (model.IsTypeUpdatable && targetSourceType.TypeProperties.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model);
if (model.IsTypeUpdatable && model.TypeFields.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model); if (model.IsTypeUpdatable && targetSourceType.TypeFields.GetWritableMappedProperties().Length > 0) builder.GenerateUpdateMethod(model);
builder builder
.WriteLine() .WriteLine()
@ -68,7 +70,8 @@ namespace MapTo.Extensions
private static SourceBuilder GeneratePublicConstructor(this SourceBuilder builder, MappingModel model) private static SourceBuilder GeneratePublicConstructor(this SourceBuilder builder, MappingModel model)
{ {
var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); var targetSourceType = model.MappedSourceTypes[0];
var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase();
const string mappingContextParameterName = "context"; const string mappingContextParameterName = "context";
var baseConstructor = /*model.HasMappedBaseClass ? $" : base({mappingContextParameterName}, {sourceClassParameterName})" :*/ string.Empty; var baseConstructor = /*model.HasMappedBaseClass ? $" : base({mappingContextParameterName}, {sourceClassParameterName})" :*/ string.Empty;
@ -77,9 +80,9 @@ namespace MapTo.Extensions
var otherProperties = new List<MappedMember>(); var otherProperties = new List<MappedMember>();
foreach (var property in model.TypeProperties) foreach (var property in targetSourceType.TypeProperties)
{ {
if (!model.SourceProperties.IsMappedProperty(property)) if (!targetSourceType.SourceProperties.IsMappedProperty(property))
{ {
stringBuilder.Append(", "); stringBuilder.Append(", ");
stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}");
@ -87,9 +90,9 @@ namespace MapTo.Extensions
} }
} }
foreach (var property in model.TypeFields) foreach (var property in targetSourceType.TypeFields)
{ {
if (!model.SourceFields.IsMappedProperty(property)) if (!targetSourceType.SourceFields.IsMappedProperty(property))
{ {
stringBuilder.Append(", "); stringBuilder.Append(", ");
stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}"); stringBuilder.Append($"{property.FullyQualifiedType} {property.SourcePropertyName.ToCamelCase()}");
@ -101,7 +104,7 @@ namespace MapTo.Extensions
var readOnlyPropertiesArguments = stringBuilder.ToString(); var readOnlyPropertiesArguments = stringBuilder.ToString();
builder builder
.WriteLine($"public {model.TypeIdentifierName}({model.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}") .WriteLine($"public {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName}{readOnlyPropertiesArguments}){baseConstructor}")
.WriteOpeningBracket() .WriteOpeningBracket()
.WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false); .WriteAssignmentMethod(model, otherProperties.ToArray().ToImmutableArray(), sourceClassParameterName, mappingContextParameterName, false);
@ -128,7 +131,8 @@ namespace MapTo.Extensions
.WriteLine("var stringBuilder = new System.Text.StringBuilder();") .WriteLine("var stringBuilder = new System.Text.StringBuilder();")
.WriteLine(GetStringBuilderAppendNoInterpolation("{")); .WriteLine(GetStringBuilderAppendNoInterpolation("{"));
foreach (var property in model.TypeProperties) var targetSourceType = model.MappedSourceTypes[0];
foreach (var property in targetSourceType.TypeProperties)
{ {
if (!property.isEnumerable) if (!property.isEnumerable)
HandlePropertyEnumerable(builder, property); HandlePropertyEnumerable(builder, property);
@ -137,7 +141,7 @@ namespace MapTo.Extensions
builder = WriteJsonField(builder, property); builder = WriteJsonField(builder, property);
} }
} }
foreach (var property in model.TypeFields) foreach (var property in targetSourceType.TypeFields)
{ {
if (!property.isEnumerable) if (!property.isEnumerable)
HandleFieldEnumerable(builder, property); HandleFieldEnumerable(builder, property);
@ -227,8 +231,9 @@ namespace MapTo.Extensions
private static SourceBuilder WriteAssignmentMethod(this SourceBuilder builder, MappingModel model, System.Collections.Immutable.ImmutableArray<MappedMember>? 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)
{ {
var targetSourceType = model.MappedSourceTypes[0];
foreach (var property in model.SourceProperties) foreach (var property in targetSourceType.SourceProperties)
{ {
if (property.isReadOnly && fromUpdate) continue; if (property.isReadOnly && fromUpdate) continue;
@ -236,7 +241,7 @@ namespace MapTo.Extensions
} }
foreach (var property in model.SourceFields) foreach (var property in targetSourceType.SourceFields)
{ {
if (property.isReadOnly && fromUpdate) continue; if (property.isReadOnly && fromUpdate) continue;
@ -261,11 +266,12 @@ namespace MapTo.Extensions
private static SourceBuilder GenerateUpdateMethod(this SourceBuilder builder, MappingModel model) private static SourceBuilder GenerateUpdateMethod(this SourceBuilder builder, MappingModel model)
{ {
var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); var targetSourceType = model.MappedSourceTypes[0];
var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase();
builder builder
.GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName) .GenerateUpdaterMethodsXmlDocs(model, sourceClassParameterName)
.WriteLine($"public void Update({model.SourceType} {sourceClassParameterName})") .WriteLine($"public void Update({targetSourceType.SourceType} {sourceClassParameterName})")
.WriteOpeningBracket() .WriteOpeningBracket()
.WriteAssignmentMethod(model, null, sourceClassParameterName, "context", true) .WriteAssignmentMethod(model, null, sourceClassParameterName, "context", true)
.WriteClosingBracket(); .WriteClosingBracket();
@ -280,21 +286,25 @@ namespace MapTo.Extensions
return builder; return builder;
} }
var targetSourceType = model.MappedSourceTypes[0];
return builder return builder
.WriteLine("/// <summary>") .WriteLine("/// <summary>")
.WriteLine($"/// Updates <see cref=\"{model.TypeIdentifierName}\"/> and sets its participating properties") .WriteLine($"/// Updates <see cref=\"{model.TypeIdentifierName}\"/> and sets its participating properties")
.WriteLine($"/// using the property values from <paramref name=\"{sourceClassParameterName}\"/>.") .WriteLine($"/// using the property values from <paramref name=\"{sourceClassParameterName}\"/>.")
.WriteLine("/// </summary>") .WriteLine("/// </summary>")
.WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{model.SourceType}\"/> to use as source.</param>"); .WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{targetSourceType.SourceType}\"/> to use as source.</param>");
} }
private static SourceBuilder GenerateEnumerableJsonSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model) private static SourceBuilder GenerateEnumerableJsonSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model)
{ {
var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); var targetSourceType = model.MappedSourceTypes[0];
var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase();
return builder return builder
.WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]")
.WriteLine($"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static string ToJson(this IEnumerable<{model.SourceType}{model.Options.NullableReferenceSyntax}> {sourceClassParameterName}List)") .WriteLine($"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static string ToJson(this IEnumerable<{targetSourceType.SourceType}{model.Options.NullableReferenceSyntax}> {sourceClassParameterName}List)")
.WriteOpeningBracket() .WriteOpeningBracket()
.WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});") .WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});")
.WriteClosingBracket(); .WriteClosingBracket();

View File

@ -504,21 +504,38 @@ namespace MapTo
return null; return null;
} }
var sourceTypeSymbol = sourceTypeSymbols[0];
// Pick first one to avoid errors. TODO: Make possible to use different source types
_ignoredNamespaces.Add(sourceTypeSymbol.ContainingNamespace.ToDisplayParts().First());
var typeIdentifierName = TypeSyntax.GetIdentifierName(); var typeIdentifierName = TypeSyntax.GetIdentifierName();
var sourceTypeIdentifierName = sourceTypeSymbol.Name;
var isTypeInheritFromMappedBaseClass = IsTypeInheritFromMappedBaseClass(semanticModel); var isTypeInheritFromMappedBaseClass = IsTypeInheritFromMappedBaseClass(semanticModel);
var isTypeUpdatable = false; //IsTypeUpdatable(); var isTypeUpdatable = false; //IsTypeUpdatable();
var hasJsonExtension = false; // HasJsonExtension(); var hasJsonExtension = false; // HasJsonExtension();
var shouldGenerateSecondaryConstructor = ShouldGenerateSecondaryConstructor(semanticModel, sourceTypeSymbol);
var mappedProperties = GetSourceMappedProperties(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass); List<MappedSourceType> mappedSourceTypes = new List<MappedSourceType>();
var mappedFields = GetSourceMappedFields(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass);
foreach (var sourceTypeSymbol in sourceTypeSymbols)
{
_ignoredNamespaces.Add(sourceTypeSymbol.ContainingNamespace.ToDisplayParts().First());
var sourceTypeIdentifierName = sourceTypeSymbol.Name;
var shouldGenerateSecondaryConstructor = ShouldGenerateSecondaryConstructor(semanticModel, sourceTypeSymbol);
var mappedProperties = GetSourceMappedProperties(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass);
var mappedFields = GetSourceMappedFields(typeSymbol, sourceTypeSymbol, isTypeInheritFromMappedBaseClass);
AddUsingIfRequired(mappedProperties.Any(p => p.IsEnumerable), "System.Linq");
var allProperties = GetTypeMappedProperties(sourceTypeSymbol, typeSymbol , isTypeInheritFromMappedBaseClass);
var allFields = GetTypeMappedFields(sourceTypeSymbol, typeSymbol, isTypeInheritFromMappedBaseClass);
mappedSourceTypes.Add(new MappedSourceType(
sourceTypeSymbol.ContainingNamespace.ToDisplayString(),
sourceTypeIdentifierName,
sourceTypeSymbol.ToDisplayString(),
mappedProperties, mappedFields, allProperties, allFields, shouldGenerateSecondaryConstructor));
}
//var sourceTypeSymbol = sourceTypeSymbols[0];
// Pick first one to avoid errors. TODO: Make possible to use different source types
/*if (!mappedProperties.Any()) /*if (!mappedProperties.Any())
{ {
@ -526,29 +543,17 @@ namespace MapTo
return null; return null;
}*/ }*/
AddUsingIfRequired(mappedProperties.Any(p => p.IsEnumerable), "System.Linq");
var allProperties = GetTypeMappedProperties(sourceTypeSymbol, typeSymbol , isTypeInheritFromMappedBaseClass);
var allFields = GetTypeMappedFields(sourceTypeSymbol, typeSymbol, isTypeInheritFromMappedBaseClass);
return new MappingModel( return new MappingModel(
SourceGenerationOptions, SourceGenerationOptions,
TypeSyntax.GetNamespace(), TypeSyntax.GetNamespace(),
TypeSyntax.Modifiers, TypeSyntax.Modifiers,
TypeSyntax.Keyword.Text, TypeSyntax.Keyword.Text,
typeIdentifierName, typeIdentifierName,
sourceTypeSymbol.ContainingNamespace.ToDisplayString(),
sourceTypeIdentifierName,
sourceTypeSymbol.ToDisplayString(),
isTypeUpdatable, isTypeUpdatable,
hasJsonExtension, hasJsonExtension,
mappedProperties, mappedSourceTypes.ToImmutableArray(),
allProperties,
mappedFields,
allFields,
isTypeInheritFromMappedBaseClass, isTypeInheritFromMappedBaseClass,
Usings, Usings);
shouldGenerateSecondaryConstructor);
} }

View File

@ -39,29 +39,35 @@ namespace MapTo
public bool IsEnumerable => EnumerableTypeArgument is not null; public bool IsEnumerable => EnumerableTypeArgument is not null;
} }
internal record MappingModel ( internal record MappedSourceType
SourceGenerationOptions Options, (
string? Namespace,
SyntaxTokenList Modifiers,
string Type,
string TypeIdentifierName,
string SourceNamespace, string SourceNamespace,
string SourceTypeIdentifierName, string SourceTypeIdentifierName,
string SourceTypeFullName, string SourceTypeFullName,
bool IsTypeUpdatable,
bool IsJsonExtension,
ImmutableArray<MappedMember> SourceProperties, ImmutableArray<MappedMember> SourceProperties,
ImmutableArray<MappedMember> TypeProperties,
ImmutableArray<MappedMember> SourceFields, ImmutableArray<MappedMember> SourceFields,
ImmutableArray<MappedMember> TypeProperties,
ImmutableArray<MappedMember> TypeFields, ImmutableArray<MappedMember> TypeFields,
bool HasMappedBaseClass,
ImmutableArray<string> Usings,
bool GenerateSecondaryConstructor bool GenerateSecondaryConstructor
) )
{ {
public string SourceType => SourceTypeFullName; public string SourceType => SourceTypeFullName;
} }
internal record MappingModel(
SourceGenerationOptions Options,
string? Namespace,
SyntaxTokenList Modifiers,
string Type,
string TypeIdentifierName,
bool IsTypeUpdatable,
bool IsJsonExtension,
ImmutableArray<MappedSourceType> MappedSourceTypes,
bool HasMappedBaseClass,
ImmutableArray<string> Usings
);
internal record SourceGenerationOptions( internal record SourceGenerationOptions(
AccessModifier ConstructorAccessModifier, AccessModifier ConstructorAccessModifier,
AccessModifier GeneratedMethodsAccessModifier, AccessModifier GeneratedMethodsAccessModifier,

View File

@ -22,8 +22,10 @@ namespace MapTo.Sources
.WriteLine($"partial record {model.TypeIdentifierName}") .WriteLine($"partial record {model.TypeIdentifierName}")
.WriteOpeningBracket(); .WriteOpeningBracket();
var targetSourceType = model.MappedSourceTypes[0];
// Class body // Class body
if (model.GenerateSecondaryConstructor) if (targetSourceType.GenerateSecondaryConstructor)
{ {
builder builder
.GenerateSecondaryConstructor(model) .GenerateSecondaryConstructor(model)
@ -52,7 +54,9 @@ namespace MapTo.Sources
private static SourceBuilder GenerateSecondaryConstructor(this SourceBuilder builder, MappingModel model) private static SourceBuilder GenerateSecondaryConstructor(this SourceBuilder builder, MappingModel model)
{ {
var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); // grab first data from array
var targetSourceType = model.MappedSourceTypes[0];
var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase();
if (model.Options.GenerateXmlDocument) if (model.Options.GenerateXmlDocument)
{ {
@ -65,17 +69,19 @@ namespace MapTo.Sources
} }
return builder return builder
.WriteLine($"{model.Options.ConstructorAccessModifier.ToLowercaseString()} {model.TypeIdentifierName}({model.SourceType} {sourceClassParameterName})") .WriteLine($"{model.Options.ConstructorAccessModifier.ToLowercaseString()} {model.TypeIdentifierName}({targetSourceType.SourceType} {sourceClassParameterName})")
.WriteLine($" : this(new {MappingContextSource.ClassName}(), {sourceClassParameterName}) {{ }}"); .WriteLine($" : this(new {MappingContextSource.ClassName}(), {sourceClassParameterName}) {{ }}");
} }
private static SourceBuilder GeneratePrivateConstructor(this SourceBuilder builder, MappingModel model) private static SourceBuilder GeneratePrivateConstructor(this SourceBuilder builder, MappingModel model)
{ {
var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); var targetSourceType = model.MappedSourceTypes[0];
var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase();
const string mappingContextParameterName = "context"; const string mappingContextParameterName = "context";
builder builder
.WriteLine($"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {model.SourceType} {sourceClassParameterName})") .WriteLine($"private protected {model.TypeIdentifierName}({MappingContextSource.ClassName} {mappingContextParameterName}, {targetSourceType.SourceType} {sourceClassParameterName})")
.Indent() .Indent()
.Write(": this("). .Write(": this(").
@ -96,9 +102,11 @@ namespace MapTo.Sources
private static SourceBuilder WriteProperties(this SourceBuilder builder, MappingModel model, string sourceClassParameterName, private static SourceBuilder WriteProperties(this SourceBuilder builder, MappingModel model, string sourceClassParameterName,
string mappingContextParameterName) string mappingContextParameterName)
{ {
for (var i = 0; i < model.SourceProperties.Length; i++) var targetSourceType = model.MappedSourceTypes[0];
for (var i = 0; i < targetSourceType.SourceProperties.Length; i++)
{ {
var property = model.SourceProperties[i]; var property = targetSourceType.SourceProperties[i];
if (property.TypeConverter is null) if (property.TypeConverter is null)
{ {
if (property.IsEnumerable) if (property.IsEnumerable)
@ -123,7 +131,7 @@ namespace MapTo.Sources
$"{property.Name}: new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters})"); $"{property.Name}: new {property.TypeConverter}().Convert({sourceClassParameterName}.{property.SourcePropertyName}, {parameters})");
} }
if (i < model.SourceProperties.Length - 1) if (i < targetSourceType.SourceProperties.Length - 1)
{ {
builder.Write(", "); builder.Write(", ");
} }
@ -134,16 +142,17 @@ namespace MapTo.Sources
private static SourceBuilder GenerateFactoryMethod(this SourceBuilder builder, MappingModel model) private static SourceBuilder GenerateFactoryMethod(this SourceBuilder builder, MappingModel model)
{ {
var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); var targetSourceType = model.MappedSourceTypes[0];
var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase();
return builder return builder
.GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName) .GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName)
.WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]")
.WriteLine( .WriteLine(
$"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static {model.TypeIdentifierName}{model.Options.NullableReferenceSyntax} From({model.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})") $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static {model.TypeIdentifierName}{model.Options.NullableReferenceSyntax} From({targetSourceType.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})")
.WriteOpeningBracket() .WriteOpeningBracket()
.WriteLine( .WriteLine(
$"return {sourceClassParameterName} == null ? null : {MappingContextSource.ClassName}.{MappingContextSource.FactoryMethodName}<{model.SourceType}, {model.TypeIdentifierName}>({sourceClassParameterName});") $"return {sourceClassParameterName} == null ? null : {MappingContextSource.ClassName}.{MappingContextSource.FactoryMethodName}<{targetSourceType.SourceType}, {model.TypeIdentifierName}>({sourceClassParameterName});")
.WriteClosingBracket(); .WriteClosingBracket();
} }
@ -153,22 +162,25 @@ namespace MapTo.Sources
{ {
return builder; return builder;
} }
var targetSourceType = model.MappedSourceTypes[0];
return builder return builder
.WriteLine("/// <summary>") .WriteLine("/// <summary>")
.WriteLine($"/// Creates a new instance of <see cref=\"{model.TypeIdentifierName}\"/> and sets its participating properties") .WriteLine($"/// Creates a new instance of <see cref=\"{model.TypeIdentifierName}\"/> and sets its participating properties")
.WriteLine($"/// using the property values from <paramref name=\"{sourceClassParameterName}\"/>.") .WriteLine($"/// using the property values from <paramref name=\"{sourceClassParameterName}\"/>.")
.WriteLine("/// </summary>") .WriteLine("/// </summary>")
.WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{model.SourceType}\"/> to use as source.</param>") .WriteLine($"/// <param name=\"{sourceClassParameterName}\">The instance of <see cref=\"{targetSourceType.SourceType}\"/> to use as source.</param>")
.WriteLine( .WriteLine(
$"/// <returns>A new instance of <see cred=\"{model.TypeIdentifierName}\"/> -or- <c>null</c> if <paramref name=\"{sourceClassParameterName}\"/> is <c>null</c>.</returns>"); $"/// <returns>A new instance of <see cred=\"{model.TypeIdentifierName}\"/> -or- <c>null</c> if <paramref name=\"{sourceClassParameterName}\"/> is <c>null</c>.</returns>");
} }
private static SourceBuilder GenerateSourceTypeExtensionClass(this SourceBuilder builder, MappingModel model) private static SourceBuilder GenerateSourceTypeExtensionClass(this SourceBuilder builder, MappingModel model)
{ {
var targetSourceType = model.MappedSourceTypes[0];
return builder return builder
.WriteLine( .WriteLine(
$"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static partial class {model.SourceTypeIdentifierName}To{model.TypeIdentifierName}Extensions") $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static partial class {targetSourceType.SourceTypeIdentifierName}To{model.TypeIdentifierName}Extensions")
.WriteOpeningBracket() .WriteOpeningBracket()
.GenerateSourceTypeExtensionMethod(model) .GenerateSourceTypeExtensionMethod(model)
.WriteClosingBracket(); .WriteClosingBracket();
@ -176,13 +188,15 @@ namespace MapTo.Sources
private static SourceBuilder GenerateSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model) private static SourceBuilder GenerateSourceTypeExtensionMethod(this SourceBuilder builder, MappingModel model)
{ {
var sourceClassParameterName = model.SourceTypeIdentifierName.ToCamelCase(); var targetSourceType = model.MappedSourceTypes[0];
var sourceClassParameterName = targetSourceType.SourceTypeIdentifierName.ToCamelCase();
return builder return builder
.GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName) .GenerateConvertorMethodsXmlDocs(model, sourceClassParameterName)
.WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]") .WriteLineIf(model.Options.SupportNullableStaticAnalysis, $"[return: NotNullIfNotNull(\"{sourceClassParameterName}\")]")
.WriteLine( .WriteLine(
$"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static {model.TypeIdentifierName}{model.Options.NullableReferenceSyntax} To{model.TypeIdentifierName}(this {model.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})") $"{model.Options.GeneratedMethodsAccessModifier.ToLowercaseString()} static {model.TypeIdentifierName}{model.Options.NullableReferenceSyntax} To{model.TypeIdentifierName}(this {targetSourceType.SourceType}{model.Options.NullableReferenceSyntax} {sourceClassParameterName})")
.WriteOpeningBracket() .WriteOpeningBracket()
.WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});") .WriteLine($"return {sourceClassParameterName} == null ? null : new {model.TypeIdentifierName}({sourceClassParameterName});")
.WriteClosingBracket(); .WriteClosingBracket();