public ObjectCreationExpressionSyntax AddInitializerWithMapping( ObjectCreationExpressionSyntax objectCreationExpression, IMappingSourceFinder mappingSourceFinder, ITypeSymbol createdObjectTyp, MappingPath mappingPath = null) { var propertiesToSet = ObjectHelper.GetFieldsThaCanBeSetPublicly(createdObjectTyp, contextAssembly); var assignments = MapUsingSimpleAssignment(syntaxGenerator, propertiesToSet, mappingSourceFinder, mappingPath); var initializerExpressionSyntax = SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, new SeparatedSyntaxList <ExpressionSyntax>().AddRange(assignments)).FixInitializerExpressionFormatting(objectCreationExpression); return(objectCreationExpression.WithInitializer(initializerExpressionSyntax)); }
public MappingElement MapExpression(MappingElement element, ITypeSymbol targetType, MappingPath mappingPath = null) { if (element == null) { return(null); } if (mappingPath == null) { mappingPath = new MappingPath(); } var sourceType = element.ExpressionType; if (mappingPath.AddToMapped(sourceType) == false) { return(new MappingElement() { ExpressionType = sourceType, Expression = element.Expression.WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursive mapping */")) }); } if (ObjectHelper.IsSimpleType(targetType) && SymbolHelper.IsNullable(sourceType, out var underlyingType)) { element = new MappingElement() { Expression = (ExpressionSyntax)syntaxGenerator.MemberAccessExpression(element.Expression, "Value"), ExpressionType = underlyingType }; } if (IsUnwrappingNeeded(targetType, element)) { return(TryToUnwrap(targetType, element)); } if (ShouldCreateConversionBetweenTypes(targetType, sourceType)) { return(TryToCreateMappingExpression(element, targetType, mappingPath)); } return(element); }
public MappingElement MapExpression(MappingElement element, ITypeSymbol targetType, MappingPath mappingPath = null) { if (element == null) { return(null); } if (mappingPath == null) { mappingPath = new MappingPath(); } var sourceType = element.ExpressionType; if (mappingPath.AddToMapped(sourceType) == false) { return(new MappingElement() { ExpressionType = sourceType, Expression = element.Expression.WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursive mapping */")) }); } if (IsUnwrappingNeeded(targetType, element)) { return(TryToUnwrap(targetType, element)); } if (ShouldCreateConversionBetweenTypes(targetType, sourceType)) { return(TryToCreateMappingExpression(element, targetType, mappingPath)); } return(element); }
internal SyntaxNode GetDefaultExpression(ITypeSymbol type, MappingPath mappingPath) { if (mappingPath.AddToMapped(type) == false) { return(syntaxGenerator.DefaultExpression(type) .WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursive mapping */"))); } if (type.TypeKind == TypeKind.Enum && type is INamedTypeSymbol namedTypeSymbol) { var enumOptions = namedTypeSymbol.MemberNames.ToList(); if (enumOptions.Count > 0) { return(syntaxGenerator.MemberAccessExpression(syntaxGenerator.IdentifierName(namedTypeSymbol.Name), syntaxGenerator.IdentifierName(enumOptions[0]))); } return(syntaxGenerator.DefaultExpression(type)); } if (type.SpecialType == SpecialType.None) { var objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(type); if (MappingHelper.IsCollection(type)) { var isReadonlyCollection = ObjectHelper.IsReadonlyCollection(type); if (type is IArrayTypeSymbol) { objectCreationExpression = SyntaxFactory.ObjectCreationExpression((TypeSyntax)syntaxGenerator.TypeExpression(type)); } else if (type.TypeKind == TypeKind.Interface || isReadonlyCollection) { var namedType = type as INamedTypeSymbol; if (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 <ExpressionSyntax>(); var subTypeDefault = (ExpressionSyntax)GetDefaultExpression(subType, mappingPath.Clone()); if (subTypeDefault != null) { initializationBlockExpressions = initializationBlockExpressions.Add(subTypeDefault); } var initializerExpressionSyntax = SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, initializationBlockExpressions).FixInitializerExpressionFormatting(objectCreationExpression); return(objectCreationExpression .WithInitializer(initializerExpressionSyntax) .WrapInReadonlyCollectionIfNecessary(isReadonlyCollection, syntaxGenerator)); } { var nt = type as INamedTypeSymbol; if (nt.TypeKind == TypeKind.Interface) { var implementations = SymbolFinder.FindImplementationsAsync(nt, this._document.Project.Solution).Result; var firstImplementation = implementations.FirstOrDefault(); if (firstImplementation is INamedTypeSymbol == false) { return(syntaxGenerator.DefaultExpression(nt) .WithTrailingTrivia(SyntaxFactory.Comment($" /* Cannot find any type implementing {nt.Name} */"))); } nt = firstImplementation as INamedTypeSymbol; objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(nt); } var hasDefaultConstructor = nt.Constructors.Any(x => x.Parameters.Length == 0); if (hasDefaultConstructor == false && nt.Constructors.Length > 0) { var randomConstructor = nt.Constructors.First(); var constructorArguments = randomConstructor.Parameters.Select(p => GetDefaultExpression(p.Type, mappingPath.Clone())).ToList(); objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(nt, constructorArguments); } var fields = ObjectHelper.GetFieldsThaCanBeSetPublicly(nt); var assignments = fields.Select(x => { var identifier = (ExpressionSyntax)(SyntaxFactory.IdentifierName(x.Name)); return((ExpressionSyntax)syntaxGenerator.AssignmentStatement(identifier, this.FindMappingSource(x.Type, mappingPath.Clone()).Expression)); }).ToList(); if (assignments.Count == 0) { return(objectCreationExpression); } var initializerExpressionSyntax = SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, new SeparatedSyntaxList <ExpressionSyntax>().AddRange(assignments)).FixInitializerExpressionFormatting(objectCreationExpression); return(objectCreationExpression.WithInitializer(initializerExpressionSyntax)); } } switch (type.SpecialType) { case SpecialType.System_Boolean: return(syntaxGenerator.LiteralExpression(true)); case SpecialType.System_SByte: return(syntaxGenerator.LiteralExpression(1)); case SpecialType.System_Int16: return(syntaxGenerator.LiteralExpression(16)); case SpecialType.System_Int32: return(syntaxGenerator.LiteralExpression(32)); case SpecialType.System_Int64: return(syntaxGenerator.LiteralExpression(64)); case SpecialType.System_Byte: return(syntaxGenerator.LiteralExpression(1)); case SpecialType.System_UInt16: return(syntaxGenerator.LiteralExpression(16u)); case SpecialType.System_UInt32: return(syntaxGenerator.LiteralExpression(32u)); case SpecialType.System_UInt64: return(syntaxGenerator.LiteralExpression(64u)); case SpecialType.System_Single: return(syntaxGenerator.LiteralExpression(1.0f)); case SpecialType.System_Double: return(syntaxGenerator.LiteralExpression(1.0)); case SpecialType.System_Char: return(syntaxGenerator.LiteralExpression('a')); case SpecialType.System_String: return(syntaxGenerator.LiteralExpression("lorem ipsum")); case SpecialType.System_Decimal: return(syntaxGenerator.LiteralExpression(2.0m)); case SpecialType.System_Object: return(SyntaxFactory.ObjectCreationExpression((TypeSyntax)syntaxGenerator.TypeExpression(type), SyntaxFactory.ArgumentList(), default(InitializerExpressionSyntax))); default: return(syntaxGenerator.LiteralExpression("ccc")); } }
internal SyntaxNode GetDefaultExpression(ITypeSymbol type, MappingPath mappingPath) { if (mappingPath.AddToMapped(type) == false) { return(syntaxGenerator.DefaultExpression(type) .WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursive mapping */"))); } if (SymbolHelper.IsNullable(type, out var underlyingType)) { type = underlyingType; } if (type.TypeKind == TypeKind.Enum && type is INamedTypeSymbol namedTypeSymbol) { var enumOptions = namedTypeSymbol.MemberNames.Where(x => x != "value__" && x != ".ctor").ToList(); if (enumOptions.Count > 0) { return(syntaxGenerator.MemberAccessExpression(syntaxGenerator.IdentifierName(namedTypeSymbol.Name), syntaxGenerator.IdentifierName(enumOptions[0]))); } return(syntaxGenerator.DefaultExpression(type)); } if (type.SpecialType == SpecialType.None) { var objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(type); if (MappingHelper.IsCollection(type)) { var isReadonlyCollection = ObjectHelper.IsReadonlyCollection(type); if (type is IArrayTypeSymbol) { objectCreationExpression = SyntaxFactory.ObjectCreationExpression((TypeSyntax)syntaxGenerator.TypeExpression(type)); } else if (type.TypeKind == TypeKind.Interface || isReadonlyCollection) { var namedType = type as INamedTypeSymbol; if (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 <ExpressionSyntax>(); var subTypeDefault = (ExpressionSyntax)GetDefaultExpression(subType, mappingPath.Clone()); if (subTypeDefault != null) { initializationBlockExpressions = initializationBlockExpressions.Add(subTypeDefault); } 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) { return(GetDefaultForUnknown(type, SyntaxFactory.ParseTypeName("object"))); } 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)); } 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 = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(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) { nt = randomDerived; objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(nt); } } var publicConstructors = nt.Constructors.Where(x => x.DeclaredAccessibility == Accessibility.Public || (x.DeclaredAccessibility == Accessibility.Internal && x.ContainingAssembly.IsSameAssemblyOrHasFriendAccessTo(_contextAssembly))).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, mappingPath.Clone())).ToList(); objectCreationExpression = (ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(nt, constructorArguments); } var fields = ObjectHelper.GetFieldsThaCanBeSetPublicly(nt, _contextAssembly); var assignments = fields.Select(x => { var identifier = (ExpressionSyntax)(SyntaxFactory.IdentifierName(x.Name)); return((ExpressionSyntax)syntaxGenerator.AssignmentStatement(identifier, this.FindMappingSource(x.Type, mappingPath.Clone()).Expression)); }).ToList(); if (assignments.Count == 0) { return(objectCreationExpression); } var initializerExpressionSyntax = SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, new SeparatedSyntaxList <ExpressionSyntax>().AddRange(assignments)).FixInitializerExpressionFormatting(objectCreationExpression); return(objectCreationExpression.WithInitializer(initializerExpressionSyntax)); } } return(GetDefaultForSpecialType(type)); }
protected virtual MappingElement TryToCreateMappingExpression(MappingElement source, ITypeSymbol targetType, MappingPath mappingPath) { //TODO: If source expression is method or constructor invocation then we should extract local variable and use it im mappings as a reference var namedTargetType = targetType as INamedTypeSymbol; if (namedTargetType != null) { var directlyMappingConstructor = namedTargetType.Constructors.FirstOrDefault(c => c.Parameters.Length == 1 && c.Parameters[0].Type.Equals(source.ExpressionType)); if (directlyMappingConstructor != null) { var constructorParameters = SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(source.Expression)); var creationExpression = syntaxGenerator.ObjectCreationExpression(targetType, constructorParameters.Arguments); return(new MappingElement() { ExpressionType = targetType, Expression = (ExpressionSyntax)creationExpression }); } } if (MappingHelper.IsMappingBetweenCollections(targetType, source.ExpressionType)) { return(new MappingElement() { ExpressionType = targetType, Expression = MapCollections(source.Expression, source.ExpressionType, targetType, mappingPath.Clone()) as ExpressionSyntax }); } var subMappingSourceFinder = new ObjectMembersMappingSourceFinder(source.ExpressionType, source.Expression, syntaxGenerator); if (namedTargetType != null) { //maybe there is constructor that accepts parameter matching source properties var constructorOverloadParameterSets = namedTargetType.Constructors.Select(x => x.Parameters); var matchedOverload = MethodHelper.FindBestParametersMatch(subMappingSourceFinder, constructorOverloadParameterSets); if (matchedOverload != null) { var creationExpression = syntaxGenerator.ObjectCreationExpression(targetType, matchedOverload.ToArgumentListSyntax(this).Arguments); return(new MappingElement() { ExpressionType = targetType, Expression = (ExpressionSyntax)creationExpression }); } } var objectCreationExpressionSyntax = ((ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(targetType)); return(new MappingElement() { ExpressionType = targetType, Expression = AddInitializerWithMapping(objectCreationExpressionSyntax, subMappingSourceFinder, targetType, mappingPath) }); }
public SyntaxNode CreateMappingLambda(string lambdaParameterName, ITypeSymbol sourceListElementType, ITypeSymbol targetListElementType, MappingPath mappingPath) { var listElementMappingStm = MapExpression(new MappingElement() { ExpressionType = sourceListElementType, Expression = syntaxGenerator.IdentifierName(lambdaParameterName) as ExpressionSyntax }, targetListElementType, mappingPath); return(syntaxGenerator.ValueReturningLambdaExpression(lambdaParameterName, listElementMappingStm.Expression)); }
private SyntaxNode MapCollections(SyntaxNode sourceAccess, ITypeSymbol sourceListType, ITypeSymbol targetListType, MappingPath mappingPath) { var isReadonlyCollection = ObjectHelper.IsReadonlyCollection(targetListType); var sourceListElementType = MappingHelper.GetElementType(sourceListType); var targetListElementType = MappingHelper.GetElementType(targetListType); if (ShouldCreateConversionBetweenTypes(targetListElementType, sourceListElementType)) { var selectAccess = syntaxGenerator.MemberAccessExpression(sourceAccess, "Select"); var lambdaParameterName = NameHelper.CreateLambdaParameterName(sourceAccess); var mappingLambda = CreateMappingLambda(lambdaParameterName, sourceListElementType, targetListElementType, mappingPath); var selectInvocation = syntaxGenerator.InvocationExpression(selectAccess, mappingLambda); var toList = AddMaterializeCollectionInvocation(syntaxGenerator, selectInvocation, targetListType); return(MappingHelper.WrapInReadonlyCollectionIfNecessary(toList, isReadonlyCollection, syntaxGenerator)); } var toListInvocation = AddMaterializeCollectionInvocation(syntaxGenerator, sourceAccess, targetListType); return(MappingHelper.WrapInReadonlyCollectionIfNecessary(toListInvocation, isReadonlyCollection, syntaxGenerator)); }
protected override MappingElement TryToCreateMappingExpression(MappingElement source, ITypeSymbol targetType, MappingPath mappingPath) { //TODO: check if source is not null (conditional member access) if (mappingPath.Length > 1 && source.ExpressionType.AllInterfaces.Any(x => x.Name == "ICloneable") && source.ExpressionType.SpecialType != SpecialType.System_Array) { var invokeClone = syntaxGenerator.InvocationExpression(syntaxGenerator.MemberAccessExpression(source.Expression, "Clone")); var cloneMethods = targetType.GetMembers("Clone"); if (cloneMethods.Any(IsGenericCloneMethod)) { return(new MappingElement() { ExpressionType = targetType, Expression = invokeClone as ExpressionSyntax }); } var objectClone = cloneMethods.FirstOrDefault(x => x is IMethodSymbol md && md.Parameters.Length == 0); if (objectClone != null) { var objectCLoneMethod = (IMethodSymbol)objectClone; if (CanBeAccessedInCurrentContext(objectCLoneMethod)) { return(new MappingElement() { ExpressionType = targetType, Expression = syntaxGenerator.TryCastExpression(invokeClone, targetType) as ExpressionSyntax }); } } var implicitClone = targetType.GetMembers("System.ICloneable.Clone").FirstOrDefault(); if (implicitClone != null) { var castedOnICloneable = syntaxGenerator.CastExpression(SyntaxFactory.ParseTypeName("ICloneable"), source.Expression); return(new MappingElement() { ExpressionType = targetType, Expression = syntaxGenerator.TryCastExpression(syntaxGenerator.InvocationExpression(syntaxGenerator.MemberAccessExpression(castedOnICloneable, "Clone")), targetType) as ExpressionSyntax }); } } return(base.TryToCreateMappingExpression(source, targetType, mappingPath)); }
public MappingElement MapExpression(MappingElement element, ITypeSymbol targetType, MappingPath mappingPath = null) { if (element == null) { return(null); } if (mappingPath == null) { mappingPath = new MappingPath(); } if (mappingPath.AddToMapped(element.ExpressionType) == false) { return(new MappingElement() { ExpressionType = element.ExpressionType, Expression = element.Expression.WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursing mapping */")) }); } if (IsUnrappingNeeded(targetType, element)) { return(TryToUnwrapp(targetType, element)); } if (element.ExpressionType.Equals(targetType) == false && ObjectHelper.IsSimpleType(targetType) == false && ObjectHelper.IsSimpleType(element.ExpressionType) == false) { return(TryToCreateMappingExpression(element, targetType, mappingPath)); } return(element); }
private SyntaxNode MapCollections(SyntaxNode sourceAccess, ITypeSymbol sourceListType, ITypeSymbol targetListType, MappingPath mappingPath) { var isReadolyCollection = targetListType.Name == "ReadOnlyCollection"; var sourceListElementType = MappingHelper.GetElementType(sourceListType); var targetListElementType = MappingHelper.GetElementType(targetListType); if (ObjectHelper.IsSimpleType(sourceListElementType) || sourceListElementType.Equals(targetListElementType)) { var toListInvocation = AddMaterializeCollectionInvocation(syntaxGenerator, sourceAccess, targetListType); return(WrapInReadonlyCollectionIfNecessary(isReadolyCollection, toListInvocation, syntaxGenerator)); } var selectAccess = syntaxGenerator.MemberAccessExpression(sourceAccess, "Select"); var lambdaParameterName = CreateLambdaParameterName(sourceAccess); var listElementMappingStm = MapExpression(new MappingElement() { ExpressionType = sourceListElementType, Expression = syntaxGenerator.IdentifierName(lambdaParameterName) as ExpressionSyntax }, targetListElementType, mappingPath); var selectInvocation = syntaxGenerator.InvocationExpression(selectAccess, syntaxGenerator.ValueReturningLambdaExpression(lambdaParameterName, listElementMappingStm.Expression)); var toList = AddMaterializeCollectionInvocation(syntaxGenerator, selectInvocation, targetListType); return(WrapInReadonlyCollectionIfNecessary(isReadolyCollection, toList, syntaxGenerator)); }