diff --git a/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTestCases.Designer.cs b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTestCases.Designer.cs
index 082143d..6982fc2 100644
--- a/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTestCases.Designer.cs
+++ b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTestCases.Designer.cs
@@ -81,10 +81,10 @@ internal EmptyInitializationBlockTestCases() {
/// var firstName = "Cezary";
/// var lastName = "Piatek";
///
- /// var x = new UserDTO()
+ /// var x = new UserDTO
/// [|{
///
- /// [rest of string was truncated]";.
+ /// } [rest of string was truncated]";.
///
internal static string _001_CompleteInitializationBlockWithLocals {
get {
@@ -113,9 +113,9 @@ internal static string _001_CompleteInitializationBlockWithLocals {
/// var firstName = "Cezary";
/// var lastName = "Piatek";
///
- /// var x = new UserDTO()
+ /// var x = new UserDTO
/// {
- /// [rest of string was truncated]";.
+ /// F [rest of string was truncated]";.
///
internal static string _001_CompleteInitializationBlockWithLocals_FIXED {
get {
@@ -195,14 +195,14 @@ internal static string _002_CompleteInitializationBlockWithLambdaParameter_FIXED
/// {
/// public IList<UserDTO> Map(IList<UserEntity> entities)
/// {
- /// return entities.Select((UserEntity x) => new UserDTO() [|{ }|]).ToList();
+ /// return entities.Select((UserEntity x) => new UserDTO [|{ }|]).ToList();
/// }
/// }
///
/// public class UserDTO
/// {
/// public string FirstName { get; set; }
- /// public string LastName { get; se [rest of string was truncated]";.
+ /// public string LastName { get; set; [rest of string was truncated]";.
///
internal static string _003_CompleteInitializationBlockWithSompleLambdaParameter {
get {
@@ -222,13 +222,13 @@ internal static string _003_CompleteInitializationBlockWithSompleLambdaParameter
/// {
/// public IList<UserDTO> Map(IList<UserEntity> entities)
/// {
- /// return entities.Select((UserEntity x) => new UserDTO()
+ /// return entities.Select((UserEntity x) => new UserDTO
/// {
/// FirstName = x.FirstName,
/// LastName = x.LastName,
/// Age = x.Age
/// }).ToList();
- /// [rest of string was truncated]";.
+ /// } [rest of string was truncated]";.
///
internal static string _003_CompleteInitializationBlockWithSompleLambdaParameter_FIXED {
get {
@@ -280,10 +280,10 @@ internal static string _004_CompleteInitializationBlockWithSampleDataRecursiveTy
/// return new Tree
/// {
/// Name = "lorem ipsum",
- /// Left = new Tree()
+ /// Left = new Tree
/// {
/// Name = "lorem ipsum",
- /// Left = null /* Stop recursive mappin [rest of string was truncated]";.
+ /// Left = null /* Stop recursive mapping [rest of string was truncated]";.
///
internal static string _004_CompleteInitializationBlockWithSampleDataRecursiveType_FIXED {
get {
@@ -365,7 +365,7 @@ internal static string _005_CompleteInitializationBlockWithSampleDatComplexType_
/// var users = new List<User>();
/// var query = from p in users
/// where p.FirstName !=""
- /// select new UserDTO()
+ /// select new UserDTO
/// {
/// [||]
/// };
@@ -376,7 +376,7 @@ internal static string _005_CompleteInitializationBlockWithSampleDatComplexType_
/// class User
/// {
/// public string FirstName { get; set; }
- /// public st [rest of string was truncated]";.
+ /// public stri [rest of string was truncated]";.
///
internal static string _006_SelectInSimpleLinq {
get {
@@ -398,7 +398,7 @@ internal static string _006_SelectInSimpleLinq {
/// var users = new List<User>();
/// var query = from p in users
/// where p.FirstName !=""
- /// select new UserDTO()
+ /// select new UserDTO
/// {
/// FirstName = p.FirstName,
/// LastName = p.LastName
@@ -409,7 +409,7 @@ internal static string _006_SelectInSimpleLinq {
///
/// class User
/// {
- /// [rest of string was truncated]";.
+ /// [rest of string was truncated]";.
///
internal static string _006_SelectInSimpleLinqFixed {
get {
@@ -718,10 +718,10 @@ internal static string _010_GroupByInLinq_txt_FIXED {
/// var firstName = "Cezary";
/// var lastName = "Piatek";
///
- /// var user = new UserDTO()
+ /// var user = new UserDTO
/// [|{
///
- /// }|] [rest of string was truncated]";.
+ /// }|];
/// [rest of string was truncated]";.
///
internal static string _011_CompleteInitializationBlockWithLocals {
get {
@@ -750,14 +750,64 @@ internal static string _011_CompleteInitializationBlockWithLocals {
/// var firstName = "Cezary";
/// var lastName = "Piatek";
///
- /// var user = new UserDTO()
+ /// var user = new UserDTO
/// {
- /// Fir [rest of string was truncated]";.
+ /// First [rest of string was truncated]";.
///
internal static string _011_CompleteInitializationBlockWithLocals_FIXED {
get {
return ResourceManager.GetString("_011_CompleteInitializationBlockWithLocals_FIXED", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to #nullable enable
+ ///using System;
+ ///using System.Collections.Generic;
+ ///using System.Text;
+ ///using System.Collections.ObjectModel;
+ ///using System.Collections.Immutable;
+ ///using System.Linq;
+ ///
+ ///namespace MappingGenerator.Test.MappingGenerator.TestCaseData
+ ///{
+ /// public class TestMapper
+ /// {
+ /// public static UserDTO Map(UserEntity? entity)
+ /// {
+ /// return entity != null ? new UserDTO
+ /// [|{
+ /// }|] : throw new ArgumentNullException(nameof(entity), "The value of 'entity' sho [rest of string was truncated]";.
+ ///
+ internal static string _012_ScaffoldingWithNonNullable {
+ get {
+ return ResourceManager.GetString("_012_ScaffoldingWithNonNullable", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to #nullable enable
+ ///using System;
+ ///using System.Collections.Generic;
+ ///using System.Text;
+ ///using System.Collections.ObjectModel;
+ ///using System.Collections.Immutable;
+ ///using System.Linq;
+ ///
+ ///namespace MappingGenerator.Test.MappingGenerator.TestCaseData
+ ///{
+ /// public class TestMapper
+ /// {
+ /// public static UserDTO Map(UserEntity? entity)
+ /// {
+ /// return entity != null ? new UserDTO
+ /// [|{
+ /// }|] : throw new ArgumentNullException(nameof(entity), "The value of 'entity' sho [rest of string was truncated]";.
+ ///
+ internal static string _012_ScaffoldingWithNonNullable_FIXED {
+ get {
+ return ResourceManager.GetString("_012_ScaffoldingWithNonNullable_FIXED", resourceCulture);
+ }
+ }
}
}
diff --git a/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTestCases.resx b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTestCases.resx
index be9e4e8..fdcf732 100644
--- a/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTestCases.resx
+++ b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTestCases.resx
@@ -184,4 +184,10 @@
TestCasesData\011_CompleteInitializationBlockWithLocals_FIXED.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
+ TestCasesData\012_ScaffoldingWithNonNullable.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
+
+ TestCasesData\012_ScaffoldingWithNonNullable_FIXED.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
+
\ No newline at end of file
diff --git a/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTests.cs b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTests.cs
index cbc20a6..f912c2f 100644
--- a/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTests.cs
+++ b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/EmptyInitializationBlockTests.cs
@@ -98,6 +98,15 @@ public void should_not_initialized_using_itself()
var fixedCode = EmptyInitializationBlockTestCases._011_CompleteInitializationBlockWithLocals_FIXED;
TestCodeRefactoring(test, fixedCode, 0);
}
+
+
+ [Test]
+ public void should_scaffold_init_block_with_non_nullable_references()
+ {
+ var test = EmptyInitializationBlockTestCases._012_ScaffoldingWithNonNullable;
+ var fixedCode = EmptyInitializationBlockTestCases._012_ScaffoldingWithNonNullable_FIXED;
+ TestCodeRefactoring(test, fixedCode, 1);
+ }
protected override string LanguageName => LanguageNames.CSharp;
protected override CodeRefactoringProvider CreateProvider()
diff --git a/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/TestCasesData/012_ScaffoldingWithNonNullable.txt b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/TestCasesData/012_ScaffoldingWithNonNullable.txt
new file mode 100644
index 0000000..e204b80
--- /dev/null
+++ b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/TestCasesData/012_ScaffoldingWithNonNullable.txt
@@ -0,0 +1,132 @@
+#nullable enable
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace MappingGenerator.Test.MappingGenerator.TestCaseData
+{
+ public class TestMapper
+ {
+ public static UserDTO Map(UserEntity? entity)
+ {
+ return entity != null ? new UserDTO
+ [|{
+ }|] : throw new ArgumentNullException(nameof(entity), "The value of 'entity' should not be null");
+ }
+ }
+
+ public class UserDTO
+ {
+ public int Id {get; set;}
+ public string FirstName { get; set; }
+ public string? MiddleName { get; set; }
+ public string LastName { get; set; }
+ public int Age { get; set; }
+ public AccountDTO? Account { get; set; }
+ public AccountDTO Account2 { get; set; }
+ public List? Debs { get; set; }
+ public List Debs2 { get; set; }
+ public string AddressCity { get; set; }
+ public string AddressZipCode { get; set; }
+ public string AddressStreet { get; set; }
+ public string? AddressFlatNo { get; set; }
+ public string AddressBuildingNo { get; set; }
+ public AddressDTO Address1 { get; set; }
+ public AddressDTO? Address2 { get; set; }
+ public List Address3 { get; set; }
+ public List Address4 { get; set; }
+ public List Address5 { get; set; }
+ public List Address6 { get; set; }
+ public int Total { get; set; }
+ public int UnitId { get; set; }
+ public UserSourceDTO Source { get; set; }
+ }
+
+ public class AccountDTO
+ {
+ public string BankName { get; set; }
+ public string Number { get; set; }
+ }
+
+ public class AddressDTO
+ {
+ public string City { get; set; }
+ public string ZipCode { get; set; }
+ public string Street { get; set; }
+ public string FlatNo { get; set; }
+ public string BuildingNo { get; set; }
+
+ public AddressDTO(AddressEntity entity)
+ {
+ }
+ }
+
+ public class UserSourceDTO
+ {
+ public string ProviderName { get; set; }
+ public string ProviderAddress { get; set; }
+ public bool IsActive {get; set;}
+
+ public UserSourceDTO(string providerName, string providerAddress, bool isActive)
+ {
+ ProviderName = providerName;
+ ProviderAddress = providerAddress;
+ IsActive = isActive;
+ }
+ }
+
+ //---- Entities
+
+ public class UserEntity
+ {
+ public int Id {get; set;}
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public string? MiddleName { get; set; }
+ public int Age { get; set; }
+ public AccountEntity? Account { get; set; }
+ public AccountEntity? Account2 { get; set; }
+ public List? Debs { get; set; }
+ public List? Debs2 { get; set; }
+ public AddressEntity? Address { get; set; }
+ public AddressEntity? Address1 { get; set; }
+ public AddressEntity? Address2 { get; set; }
+ public List Address3 { get; set; }
+ public List Address4 { get; set; }
+ public List? Address5 { get; set; }
+ public List? Address6 { get; set; }
+ public int? GetTotal() => throw new Exception();
+ public UnitEntity? Unit { get; set; }
+ public UserSourceEntity Source { get; set; }
+ }
+
+ public class AccountEntity
+ {
+ public string BankName { get; set; }
+ public string Number { get; set; }
+ }
+
+ public class AddressEntity
+ {
+ public string City { get; set; }
+ public string ZipCode { get; set; }
+ public string Street { get; set; }
+ public string FlatNo { get; set; }
+ public string BuildingNo { get; set; }
+ }
+
+ public class UnitEntity
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+
+ public class UserSourceEntity
+ {
+ public string ProviderName { get; set; }
+ public string? ProviderAddress { get; set; }
+ public bool? IsActive {get; set;}
+ }
+}
\ No newline at end of file
diff --git a/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/TestCasesData/012_ScaffoldingWithNonNullable_FIXED.txt b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/TestCasesData/012_ScaffoldingWithNonNullable_FIXED.txt
new file mode 100644
index 0000000..4b74c69
--- /dev/null
+++ b/MappingGenerator/MappingGenerator/MappingGenerator.Test/EmptyInitializationBlock/TestCasesData/012_ScaffoldingWithNonNullable_FIXED.txt
@@ -0,0 +1,278 @@
+#nullable enable
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace MappingGenerator.Test.MappingGenerator.TestCaseData
+{
+ public class TestMapper
+ {
+ public static UserDTO Map(UserEntity? entity)
+ {
+ return entity != null ? new UserDTO
+ {
+ Id = 32,
+ FirstName = "lorem ipsum",
+ MiddleName = "lorem ipsum",
+ LastName = "lorem ipsum",
+ Age = 32,
+ Account = new AccountDTO
+ {
+ BankName = "lorem ipsum",
+ Number = "lorem ipsum"
+ },
+ Account2 = new AccountDTO
+ {
+ BankName = "lorem ipsum",
+ Number = "lorem ipsum"
+ },
+ Debs = new List()
+ {
+ new AccountDTO
+ {
+ BankName = "lorem ipsum",
+ Number = "lorem ipsum"
+ }
+ },
+ Debs2 = new List()
+ {
+ new AccountDTO
+ {
+ BankName = "lorem ipsum",
+ Number = "lorem ipsum"
+ }
+ },
+ AddressCity = "lorem ipsum",
+ AddressZipCode = "lorem ipsum",
+ AddressStreet = "lorem ipsum",
+ AddressFlatNo = "lorem ipsum",
+ AddressBuildingNo = "lorem ipsum",
+ Address1 = new AddressDTO(new AddressEntity
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ })
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ },
+ Address2 = new AddressDTO(new AddressEntity
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ })
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ },
+ Address3 = new List()
+ {
+ new AddressDTO(new AddressEntity
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ })
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ }
+ },
+ Address4 = new List()
+ {
+ new AddressDTO(new AddressEntity
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ })
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ }
+ },
+ Address5 = new List()
+ {
+ new AddressDTO(new AddressEntity
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ })
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ }
+ },
+ Address6 = new List()
+ {
+ new AddressDTO(new AddressEntity
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ })
+ {
+ City = "lorem ipsum",
+ ZipCode = "lorem ipsum",
+ Street = "lorem ipsum",
+ FlatNo = "lorem ipsum",
+ BuildingNo = "lorem ipsum"
+ }
+ },
+ Total = 32,
+ UnitId = 32,
+ Source = new UserSourceDTO("lorem ipsum", "lorem ipsum", true)
+ {
+ ProviderName = "lorem ipsum",
+ ProviderAddress = "lorem ipsum",
+ IsActive = true
+ }
+ } : throw new ArgumentNullException(nameof(entity), "The value of 'entity' should not be null");
+ }
+ }
+
+ public class UserDTO
+ {
+ public int Id {get; set;}
+ public string FirstName { get; set; }
+ public string? MiddleName { get; set; }
+ public string LastName { get; set; }
+ public int Age { get; set; }
+ public AccountDTO? Account { get; set; }
+ public AccountDTO Account2 { get; set; }
+ public List? Debs { get; set; }
+ public List Debs2 { get; set; }
+ public string AddressCity { get; set; }
+ public string AddressZipCode { get; set; }
+ public string AddressStreet { get; set; }
+ public string? AddressFlatNo { get; set; }
+ public string AddressBuildingNo { get; set; }
+ public AddressDTO Address1 { get; set; }
+ public AddressDTO? Address2 { get; set; }
+ public List Address3 { get; set; }
+ public List Address4 { get; set; }
+ public List Address5 { get; set; }
+ public List Address6 { get; set; }
+ public int Total { get; set; }
+ public int UnitId { get; set; }
+ public UserSourceDTO Source { get; set; }
+ }
+
+ public class AccountDTO
+ {
+ public string BankName { get; set; }
+ public string Number { get; set; }
+ }
+
+ public class AddressDTO
+ {
+ public string City { get; set; }
+ public string ZipCode { get; set; }
+ public string Street { get; set; }
+ public string FlatNo { get; set; }
+ public string BuildingNo { get; set; }
+
+ public AddressDTO(AddressEntity entity)
+ {
+ }
+ }
+
+ public class UserSourceDTO
+ {
+ public string ProviderName { get; set; }
+ public string ProviderAddress { get; set; }
+ public bool IsActive {get; set;}
+
+ public UserSourceDTO(string providerName, string providerAddress, bool isActive)
+ {
+ ProviderName = providerName;
+ ProviderAddress = providerAddress;
+ IsActive = isActive;
+ }
+ }
+
+ //---- Entities
+
+ public class UserEntity
+ {
+ public int Id {get; set;}
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public string? MiddleName { get; set; }
+ public int Age { get; set; }
+ public AccountEntity? Account { get; set; }
+ public AccountEntity? Account2 { get; set; }
+ public List? Debs { get; set; }
+ public List? Debs2 { get; set; }
+ public AddressEntity? Address { get; set; }
+ public AddressEntity? Address1 { get; set; }
+ public AddressEntity? Address2 { get; set; }
+ public List Address3 { get; set; }
+ public List Address4 { get; set; }
+ public List? Address5 { get; set; }
+ public List? Address6 { get; set; }
+ public int? GetTotal() => throw new Exception();
+ public UnitEntity? Unit { get; set; }
+ public UserSourceEntity Source { get; set; }
+ }
+
+ public class AccountEntity
+ {
+ public string BankName { get; set; }
+ public string Number { get; set; }
+ }
+
+ public class AddressEntity
+ {
+ public string City { get; set; }
+ public string ZipCode { get; set; }
+ public string Street { get; set; }
+ public string FlatNo { get; set; }
+ public string BuildingNo { get; set; }
+ }
+
+ public class UnitEntity
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ }
+
+ public class UserSourceEntity
+ {
+ public string ProviderName { get; set; }
+ public string? ProviderAddress { get; set; }
+ public bool? IsActive {get; set;}
+ }
+}
\ No newline at end of file
diff --git a/MappingGenerator/MappingGenerator/MappingGenerator/Mappings/MappingImplementors/MultiParameterPureMappingMethodImplementor.cs b/MappingGenerator/MappingGenerator/MappingGenerator/Mappings/MappingImplementors/MultiParameterPureMappingMethodImplementor.cs
index 359fb4b..831ef63 100644
--- a/MappingGenerator/MappingGenerator/MappingGenerator/Mappings/MappingImplementors/MultiParameterPureMappingMethodImplementor.cs
+++ b/MappingGenerator/MappingGenerator/MappingGenerator/Mappings/MappingImplementors/MultiParameterPureMappingMethodImplementor.cs
@@ -21,7 +21,7 @@ public IEnumerable GenerateImplementation(IMethodSymbol methodSymbol
var mappingEngine = new MappingEngine(semanticModel, generator);
var targetType = methodSymbol.ReturnType;
var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol);
- var objectCreationExpressionSyntax = (ObjectCreationExpressionSyntax)generator.ObjectCreationExpression(targetType);
+ var objectCreationExpressionSyntax = (ObjectCreationExpressionSyntax)generator.ObjectCreationExpression(targetType.StripNullability());
var newExpression = mappingEngine.AddInitializerWithMapping(objectCreationExpressionSyntax, new SingleSourceMatcher(sourceFinder), targetType, mappingContext);
return new[] { generator.ReturnStatement(newExpression).WithAdditionalAnnotations(Formatter.Annotation) };
}
diff --git a/MappingGenerator/MappingGenerator/MappingGenerator/Mappings/SourceFinders/ScaffoldingSourceFinder.cs b/MappingGenerator/MappingGenerator/MappingGenerator/Mappings/SourceFinders/ScaffoldingSourceFinder.cs
index 1bdf1c6..f206989 100644
--- a/MappingGenerator/MappingGenerator/MappingGenerator/Mappings/SourceFinders/ScaffoldingSourceFinder.cs
+++ b/MappingGenerator/MappingGenerator/MappingGenerator/Mappings/SourceFinders/ScaffoldingSourceFinder.cs
@@ -1,3 +1,5 @@
+using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using MappingGenerator.RoslynHelpers;
@@ -34,6 +36,8 @@ private MappingElement FindMappingSource(AnnotatedType targetType, MappingContex
};
}
+ private ConcurrentDictionary cache = new ConcurrentDictionary();
+
internal SyntaxNode GetDefaultExpression(ITypeSymbol type, MappingContext mappingContext, MappingPath mappingPath)
{
if (mappingPath.AddToMapped(type) == false)
@@ -42,132 +46,145 @@ internal SyntaxNode GetDefaultExpression(ITypeSymbol type, MappingContext mappin
.WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursive mapping */"));
}
- if (SymbolHelper.IsNullable(type, out var underlyingType))
+ return cache.GetOrAdd(type.ToDisplayString().TrimEnd('?'), _ =>
{
- type = underlyingType;
- }
-
- if (type.TypeKind == TypeKind.Enum && type is INamedTypeSymbol namedTypeSymbol)
- {
- var enumOptions = namedTypeSymbol.MemberNames.Where(x=>x!="value__" && x!=".ctor").OrderBy(x=>x).ToList();
- if (enumOptions.Count > 0)
+ if (SymbolHelper.IsNullable(type, out var underlyingType))
{
- return syntaxGenerator.MemberAccessExpression(syntaxGenerator.IdentifierName(namedTypeSymbol.Name), syntaxGenerator.IdentifierName(enumOptions[0]));
+ type = underlyingType;
}
- return syntaxGenerator.DefaultExpression(type);
- }
-
- if (type.SpecialType == SpecialType.None)
- {
- var objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(type);
-
- if (MappingHelper.IsCollection(type))
+ if (type.TypeKind == TypeKind.Enum && type is INamedTypeSymbol namedTypeSymbol)
{
- var isReadonlyCollection = ObjectHelper.IsReadonlyCollection(type);
-
- if (type is IArrayTypeSymbol)
+ var enumOptions = namedTypeSymbol.MemberNames.Where(x => x != "value__" && x != ".ctor").OrderBy(x => x).ToList();
+ if (enumOptions.Count > 0)
{
- objectCreationExpression = SyntaxFactory.ObjectCreationExpression((TypeSyntax)syntaxGenerator.TypeExpression(type));
+ return SyntaxFactoryExtensions.CreateMemberAccessExpression(SyntaxFactory.IdentifierName(namedTypeSymbol.Name), false, enumOptions[0]);
}
- else if (type.TypeKind == TypeKind.Interface || isReadonlyCollection)
+ return syntaxGenerator.DefaultExpression(type);
+ }
+
+ if (type.SpecialType == SpecialType.None)
+ {
+
+
+ ObjectCreationExpressionSyntax objectCreationExpression = null;
+
+ if (MappingHelper.IsCollection(type))
{
- var namedType = type as INamedTypeSymbol;
- if (namedType.IsGenericType)
+ var isReadonlyCollection = ObjectHelper.IsReadonlyCollection(type);
+
+ if (type is IArrayTypeSymbol)
{
- var typeArgumentListSyntax = SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(namedType.TypeArguments.Select(x=> syntaxGenerator.TypeExpression(x))));
- var newType = SyntaxFactory.GenericName(SyntaxFactory.Identifier("List"), typeArgumentListSyntax);
- objectCreationExpression = SyntaxFactory.ObjectCreationExpression(newType, SyntaxFactory.ArgumentList(), default(InitializerExpressionSyntax));
+ objectCreationExpression = CreateObject(type);
}
- else
+ else if (type.TypeKind == TypeKind.Interface || isReadonlyCollection)
{
- var newType = SyntaxFactory. ParseTypeName("ArrayList");
- objectCreationExpression = SyntaxFactory.ObjectCreationExpression(newType, SyntaxFactory.ArgumentList(), default(InitializerExpressionSyntax));
+ if (type is INamedTypeSymbol namedType && namedType.IsGenericType)
+ {
+ var typeArgumentListSyntax = SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(namedType.TypeArguments.Select(x => syntaxGenerator.TypeExpression(x))));
+ var newType = SyntaxFactory.GenericName(SyntaxFactory.Identifier("List"), typeArgumentListSyntax);
+ objectCreationExpression = SyntaxFactory.ObjectCreationExpression(newType, SyntaxFactory.ArgumentList(), default(InitializerExpressionSyntax));
+ }
+ else
+ {
+ var newType = SyntaxFactory.ParseTypeName("ArrayList");
+ objectCreationExpression = SyntaxFactory.ObjectCreationExpression(newType, SyntaxFactory.ArgumentList(), default(InitializerExpressionSyntax));
+ }
}
- }
- var subType = MappingHelper.GetElementType(type);
- var initializationBlockExpressions = new SeparatedSyntaxList();
- var subTypeDefault = (ExpressionSyntax)GetDefaultExpression(subType.Type, mappingContext, mappingPath.Clone());
- if (subTypeDefault != null)
- {
- initializationBlockExpressions = initializationBlockExpressions.Add(subTypeDefault);
- }
+ objectCreationExpression ??= CreateObject(type, Array.Empty());
- var initializerExpressionSyntax = SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, initializationBlockExpressions).FixInitializerExpressionFormatting(objectCreationExpression);
- return objectCreationExpression
- .WithInitializer(initializerExpressionSyntax)
- .WrapInReadonlyCollectionIfNecessary(isReadonlyCollection, syntaxGenerator);
- }
-
- {
- var nt = type as INamedTypeSymbol;
-
- if (nt == null)
- {
- var genericTypeConstraints = type.UnwrapGeneric().ToList();
- if (genericTypeConstraints.Any() == false)
+ var subType = MappingHelper.GetElementType(type);
+ var initializationBlockExpressions = new SeparatedSyntaxList();
+ var subTypeDefault = (ExpressionSyntax)GetDefaultExpression(subType.Type, mappingContext, mappingPath.Clone());
+ if (subTypeDefault != null)
{
- return GetDefaultForUnknown(type, ObjectType);
+ initializationBlockExpressions = initializationBlockExpressions.Add(subTypeDefault);
}
- nt = genericTypeConstraints.FirstOrDefault(x=>x.TypeKind == TypeKind.Class) as INamedTypeSymbol ??
- genericTypeConstraints.FirstOrDefault(x => x.TypeKind == TypeKind.Interface) as INamedTypeSymbol;
- }
- if (nt == null)
- {
- return GetDefaultForUnknownType(type);
+ var initializerExpressionSyntax = SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, initializationBlockExpressions).FixInitializerExpressionFormatting(objectCreationExpression);
+ return objectCreationExpression
+ .WithInitializer(initializerExpressionSyntax)
+ .WrapInReadonlyCollectionIfNecessary(isReadonlyCollection, syntaxGenerator);
}
- if (nt.TypeKind == TypeKind.Interface)
{
- var implementations = SymbolFinder.FindImplementationsAsync(type, this._document.Project.Solution).Result;
- var firstImplementation = implementations.FirstOrDefault();
- if (firstImplementation is INamedTypeSymbol == false)
+ var nt = type as INamedTypeSymbol;
+ if (nt == null)
+ {
+ var genericTypeConstraints = type.UnwrapGeneric().ToList();
+ if (genericTypeConstraints.Any() == false)
+ {
+ return GetDefaultForUnknown(type, ObjectType);
+ }
+ nt = genericTypeConstraints.FirstOrDefault(x => x.TypeKind == TypeKind.Class) as INamedTypeSymbol ??
+ genericTypeConstraints.FirstOrDefault(x => x.TypeKind == TypeKind.Interface) as INamedTypeSymbol;
+ }
+
+ if (nt == null)
{
return GetDefaultForUnknownType(type);
}
- nt = firstImplementation as INamedTypeSymbol;
- objectCreationExpression = (ObjectCreationExpressionSyntax) syntaxGenerator.ObjectCreationExpression(nt);
+ if (nt.TypeKind == TypeKind.Interface)
+ {
+ var implementations = SymbolFinder.FindImplementationsAsync(type, this._document.Project.Solution).Result;
+ var firstImplementation = implementations.FirstOrDefault();
+ if (firstImplementation is INamedTypeSymbol == false)
+ {
+ return GetDefaultForUnknownType(type);
+ }
+
+ nt = firstImplementation as INamedTypeSymbol;
+ objectCreationExpression = CreateObject(nt);
- }else if (nt.TypeKind == TypeKind.Class && nt.IsAbstract)
- {
- var randomDerived = SymbolFinder.FindDerivedClassesAsync(nt, this._document.Project.Solution).Result
- .FirstOrDefault(x => x.IsAbstract == false);
-
- if (randomDerived != null)
+ }
+ else if (nt.TypeKind == TypeKind.Class && nt.IsAbstract)
{
- nt = randomDerived;
- objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(nt);
+ var randomDerived = SymbolFinder.FindDerivedClassesAsync(nt, this._document.Project.Solution).Result
+ .FirstOrDefault(x => x.IsAbstract == false);
+
+ if (randomDerived != null)
+ {
+ nt = randomDerived;
+ objectCreationExpression = CreateObject(nt);
+ }
}
- }
- var publicConstructors = nt.Constructors.Where(x => mappingContext.AccessibilityHelper.IsSymbolAccessible(x, nt)).ToList();
- var hasDefaultConstructor = publicConstructors.Any(x => x.Parameters.Length == 0);
- if (hasDefaultConstructor == false && publicConstructors.Count > 0)
- {
- var randomConstructor = publicConstructors.First();
- var constructorArguments = randomConstructor.Parameters.Select(p => GetDefaultExpression(p.Type, mappingContext, mappingPath.Clone())).ToList();
- objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(nt, constructorArguments);
- }
+ var publicConstructors = nt.Constructors.Where(x => mappingContext.AccessibilityHelper.IsSymbolAccessible(x, nt)).ToList();
+ var hasDefaultConstructor = publicConstructors.Any(x => x.Parameters.Length == 0);
+ if (hasDefaultConstructor == false && publicConstructors.Count > 0)
+ {
+ var randomConstructor = publicConstructors.First();
+ var constructorArguments = randomConstructor.Parameters.Select(p => GetDefaultExpression(p.Type, mappingContext, mappingPath.Clone())).Select(x=> SyntaxFactory.Argument((ExpressionSyntax) x)) .ToList();
+ objectCreationExpression = CreateObject(nt, constructorArguments);
+ }
- var fields = MappingTargetHelper.GetFieldsThaCanBeSetPublicly(nt, mappingContext);
- var assignments = fields.Select(x =>
- {
- var identifier = (ExpressionSyntax)(SyntaxFactory.IdentifierName(x.Name));
- var mappingSource = this.FindMappingSource(x.Type, mappingContext, mappingPath.Clone());
- return (ExpressionSyntax)syntaxGenerator.AssignmentStatement(identifier, mappingSource.Expression);
- }).ToList();
+ var fields = MappingTargetHelper.GetFieldsThaCanBeSetPublicly(nt, mappingContext);
+ var assignments = fields.Select(x =>
+ {
+ var identifier = (ExpressionSyntax)(SyntaxFactory.IdentifierName(x.Name));
+ var mappingSource = this.FindMappingSource(x.Type, mappingContext, mappingPath.Clone());
+ return (ExpressionSyntax)syntaxGenerator.AssignmentStatement(identifier, mappingSource.Expression);
+ }).ToList();
+ if (objectCreationExpression == null)
+ {
+ objectCreationExpression = CreateObject(type);
+ }
- return SyntaxFactoryExtensions.WithMembersInitialization(objectCreationExpression, assignments);
+ return SyntaxFactoryExtensions.WithMembersInitialization(objectCreationExpression, assignments);
+ }
}
- }
-
+ return GetDefaultForSpecialType(type);
+ });
+ }
- return GetDefaultForSpecialType(type);
+ private ObjectCreationExpressionSyntax CreateObject(ITypeSymbol type, IReadOnlyList constructorArguments = null)
+ {
+ var argumentListSyntax = constructorArguments == null ? null : SyntaxFactory.ArgumentList(new SeparatedSyntaxList().AddRange(constructorArguments));
+ return SyntaxFactory.ObjectCreationExpression((TypeSyntax)syntaxGenerator.TypeExpression(type.StripNullability())).WithArgumentList(argumentListSyntax);
}