Use fully qualified name of the source type instead of adding usings if necessary.
This commit is contained in:
parent
aced7d749d
commit
0ad89b0d6b
|
@ -11,8 +11,11 @@ namespace MapTo
|
|||
{
|
||||
internal abstract class MappingContext
|
||||
{
|
||||
private readonly List<string> _ignoredNamespaces;
|
||||
|
||||
protected MappingContext(Compilation compilation, SourceGenerationOptions sourceGenerationOptions, TypeDeclarationSyntax typeSyntax)
|
||||
{
|
||||
_ignoredNamespaces = new();
|
||||
Diagnostics = ImmutableArray<Diagnostic>.Empty;
|
||||
Usings = ImmutableArray.Create("System", Constants.RootNamespace);
|
||||
SourceGenerationOptions = sourceGenerationOptions;
|
||||
|
@ -77,7 +80,10 @@ namespace MapTo
|
|||
|
||||
protected void AddUsingIfRequired(bool condition, string? ns)
|
||||
{
|
||||
if (condition && ns is not null && ns != TypeSyntax.GetNamespace() && !Usings.Contains(ns))
|
||||
if (condition && ns is not null &&
|
||||
ns != TypeSyntax.GetNamespace() &&
|
||||
!_ignoredNamespaces.Contains(ns) &&
|
||||
!Usings.Contains(ns))
|
||||
{
|
||||
Usings = Usings.Add(ns);
|
||||
}
|
||||
|
@ -145,7 +151,6 @@ namespace MapTo
|
|||
}
|
||||
|
||||
AddUsingIfRequired(propertyType);
|
||||
AddUsingIfRequired(sourceTypeSymbol);
|
||||
AddUsingIfRequired(enumerableTypeArgumentType);
|
||||
AddUsingIfRequired(mappedSourcePropertyType);
|
||||
|
||||
|
@ -155,8 +160,8 @@ namespace MapTo
|
|||
converterFullyQualifiedName,
|
||||
converterParameters.ToImmutableArray(),
|
||||
sourceProperty.Name,
|
||||
mappedSourcePropertyType?.Name,
|
||||
enumerableTypeArgumentType?.Name);
|
||||
ToQualifiedDisplayName(mappedSourcePropertyType),
|
||||
ToQualifiedDisplayName(enumerableTypeArgumentType));
|
||||
}
|
||||
|
||||
protected bool TryGetMapTypeConverter(ISymbol property, IPropertySymbol sourceProperty, out string? converterFullyQualifiedName,
|
||||
|
@ -171,7 +176,7 @@ namespace MapTo
|
|||
}
|
||||
|
||||
var typeConverterAttribute = property.GetAttribute(MapTypeConverterAttributeTypeSymbol);
|
||||
if (!(typeConverterAttribute?.ConstructorArguments.First().Value is INamedTypeSymbol converterTypeSymbol))
|
||||
if (typeConverterAttribute?.ConstructorArguments.First().Value is not INamedTypeSymbol converterTypeSymbol)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -248,6 +253,9 @@ namespace MapTo
|
|||
return null;
|
||||
}
|
||||
|
||||
var sourceTypeNamespace = sourceTypeSymbol.ContainingNamespace.ToDisplayString();
|
||||
_ignoredNamespaces.Add(sourceTypeNamespace);
|
||||
|
||||
var typeIdentifierName = TypeSyntax.GetIdentifierName();
|
||||
var sourceTypeIdentifierName = sourceTypeSymbol.Name;
|
||||
var isTypeInheritFromMappedBaseClass = IsTypeInheritFromMappedBaseClass(semanticModel);
|
||||
|
@ -260,7 +268,6 @@ namespace MapTo
|
|||
return null;
|
||||
}
|
||||
|
||||
AddUsingIfRequired(sourceTypeSymbol);
|
||||
AddUsingIfRequired(mappedProperties.Any(p => p.IsEnumerable), "System.Linq");
|
||||
|
||||
return new MappingModel(
|
||||
|
@ -269,7 +276,7 @@ namespace MapTo
|
|||
TypeSyntax.Modifiers,
|
||||
TypeSyntax.Keyword.Text,
|
||||
typeIdentifierName,
|
||||
sourceTypeSymbol.ContainingNamespace.ToString(),
|
||||
sourceTypeNamespace,
|
||||
sourceTypeIdentifierName,
|
||||
sourceTypeSymbol.ToDisplayString(),
|
||||
mappedProperties,
|
||||
|
@ -316,5 +323,16 @@ namespace MapTo
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
private string? ToQualifiedDisplayName(ISymbol? typeSymbol)
|
||||
{
|
||||
if (typeSymbol is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var typeNamespace = typeSymbol.ContainingNamespace.ToDisplayString();
|
||||
return _ignoredNamespaces.Contains(typeNamespace) ? typeSymbol.ToDisplayString() : typeSymbol.Name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ namespace MapTo
|
|||
bool GenerateSecondaryConstructor
|
||||
)
|
||||
{
|
||||
public string SourceType => SourceTypeIdentifierName == TypeIdentifierName ? SourceTypeFullName : SourceTypeIdentifierName;
|
||||
public string SourceType => SourceTypeFullName;
|
||||
}
|
||||
|
||||
internal record SourceGenerationOptions(
|
||||
|
|
|
@ -172,6 +172,142 @@ namespace SaleModel
|
|||
diagnostics.ShouldBeSuccessful();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(SameSourceAndDestinationTypeNameData))]
|
||||
public void When_SourceAndDestinationNamesAreTheSame_Should_MapAccordingly(string source, LanguageVersion languageVersion)
|
||||
{
|
||||
// Arrange
|
||||
source = source.Trim();
|
||||
|
||||
// Act
|
||||
var (_, diagnostics) = CSharpGenerator.GetOutputCompilation(source, analyzerConfigOptions: DefaultAnalyzerOptions, languageVersion: languageVersion);
|
||||
|
||||
// Assert
|
||||
diagnostics.ShouldBeSuccessful();
|
||||
}
|
||||
|
||||
public static IEnumerable<object> SameSourceAndDestinationTypeNameData => new List<object>
|
||||
{
|
||||
new object[]
|
||||
{
|
||||
@"
|
||||
namespace Test
|
||||
{
|
||||
public class TypeName { public int Prop2 { get; set; } }
|
||||
}
|
||||
|
||||
namespace Test2
|
||||
{
|
||||
using MapTo;
|
||||
|
||||
[MapFrom(typeof(Test.TypeName))]
|
||||
public partial class TypeName
|
||||
{
|
||||
[MapProperty(SourcePropertyName=""Prop2"")]
|
||||
public int Prop1 { get; set; }
|
||||
}
|
||||
}",
|
||||
LanguageVersion.CSharp7_3
|
||||
},
|
||||
new object[]
|
||||
{
|
||||
@"
|
||||
namespace Test
|
||||
{
|
||||
public record TypeName(int Prop2);
|
||||
}
|
||||
|
||||
namespace Test2
|
||||
{
|
||||
using MapTo;
|
||||
|
||||
[MapFrom(typeof(Test.TypeName))]
|
||||
public partial record TypeName([MapProperty(SourcePropertyName=""Prop2"")] int Prop1);
|
||||
}",
|
||||
LanguageVersion.CSharp9
|
||||
},
|
||||
new object[]
|
||||
{
|
||||
@"
|
||||
namespace Test
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class SourceType2 { public int Id { get; set; } }
|
||||
public class SourceType
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public List<SourceType2> Prop1 { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
namespace Test2
|
||||
{
|
||||
using MapTo;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[MapFrom(typeof(Test.SourceType2))]
|
||||
public partial class SourceType2 { public int Id { get; set; } }
|
||||
|
||||
[MapFrom(typeof(Test.SourceType))]
|
||||
public partial class SourceType
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public IReadOnlyList<SourceType2> Prop1 { get; set; }
|
||||
}
|
||||
}",
|
||||
LanguageVersion.CSharp7_3
|
||||
},
|
||||
new object[]
|
||||
{
|
||||
@"
|
||||
namespace Test
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
public record SourceType(int Id, List<SourceType2> Prop1);
|
||||
public record SourceType2(int Id);
|
||||
}
|
||||
|
||||
namespace Test2
|
||||
{
|
||||
using MapTo;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[MapFrom(typeof(Test.SourceType2))]
|
||||
public partial record SourceType2(int Id);
|
||||
|
||||
[MapFrom(typeof(Test.SourceType))]
|
||||
public partial record SourceType(int Id, IReadOnlyList<SourceType2> Prop1);
|
||||
}",
|
||||
LanguageVersion.CSharp9
|
||||
},
|
||||
new object[]
|
||||
{
|
||||
@"
|
||||
namespace Test
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
public record SourceType1(int Id);
|
||||
public record SourceType2(int Id, List<SourceType1> Prop1);
|
||||
}
|
||||
|
||||
namespace Test
|
||||
{
|
||||
using MapTo;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[MapFrom(typeof(Test.SourceType1))]
|
||||
public partial record SourceType3(int Id);
|
||||
|
||||
[MapFrom(typeof(Test.SourceType2))]
|
||||
public partial record SourceType4(int Id, IReadOnlyList<SourceType3> Prop1);
|
||||
}",
|
||||
LanguageVersion.CSharp9
|
||||
}
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(VerifyMappedTypesData))]
|
||||
public void VerifyMappedTypes(string[] sources, LanguageVersion languageVersion)
|
||||
|
|
Loading…
Reference in New Issue