Пример #1
0
        private MappingElement FindSubPropertySource(string targetName, ITypeSymbol containingType, IEnumerable <IPropertySymbol> properties, SyntaxNode currentAccessor, string prefix = null)
        {
            if (ObjectHelper.IsSimpleType(containingType))
            {
                return(null);
            }

            var subProperty = properties.FirstOrDefault(x => targetName.StartsWith($"{prefix}{x.Name}", StringComparison.OrdinalIgnoreCase));

            if (subProperty != null)
            {
                var currentNamePart     = $"{prefix}{subProperty.Name}";
                var subPropertyAccessor = (ExpressionSyntax)generator.MemberAccessExpression(currentAccessor, subProperty.Name);
                if (targetName.Equals(currentNamePart, StringComparison.OrdinalIgnoreCase))
                {
                    return(new MappingElement()
                    {
                        Expression = subPropertyAccessor,
                        ExpressionType = subProperty.Type
                    });
                }
                return(FindSubPropertySource(targetName, subProperty.Type, ObjectHelper.GetPublicPropertySymbols(subProperty.Type), subPropertyAccessor, currentNamePart));
            }
            return(null);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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));
        }
        protected override bool ShouldCreateConversionBetweenTypes(ITypeSymbol targetType, ITypeSymbol sourceType)
        {
            if (targetType.Equals(sourceType) && SymbolHelper.IsNullable(targetType, out _))
            {
                return(false);
            }

            return(ObjectHelper.IsSimpleType(targetType) == false && ObjectHelper.IsSimpleType(sourceType) == false);
        }
Пример #5
0
        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);
        }
Пример #6
0
        private SyntaxNode MapCollections(SyntaxNode sourceAccess, ITypeSymbol sourceListType, ITypeSymbol targetListType)
        {
            var isReadolyCollection   = targetListType.Name == "ReadOnlyCollection";
            var sourceListElementType = GetElementType(sourceListType);
            var targetListElementType = GetElementType(targetListType);

            if (ObjectHelper.IsSimpleType(sourceListElementType) || sourceListElementType == targetListElementType)
            {
                var toListInvocation = AddMaterializeCollectionInvocation(generator, sourceAccess, targetListType);
                return(WrapInReadonlyCollectionIfNecessary(isReadolyCollection, toListInvocation, generator));
            }
            var selectAccess           = generator.MemberAccessExpression(sourceAccess, "Select");
            var lambdaParameterName    = ToSingularLocalVariableName(ToLocalVariableName(sourceListElementType.Name));
            var listElementMappingStms = MapTypes(sourceListElementType, targetListElementType, generator.IdentifierName(lambdaParameterName));
            var selectInvocation       = generator.InvocationExpression(selectAccess, generator.ValueReturningLambdaExpression(lambdaParameterName, listElementMappingStms));
            var toList = AddMaterializeCollectionInvocation(generator, selectInvocation, targetListType);

            return(WrapInReadonlyCollectionIfNecessary(isReadolyCollection, toList, generator));
        }
Пример #7
0
        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 (ObjectHelper.IsSimpleType(sourceListElementType) || sourceListElementType.Equals(targetListElementType))
            {
                var toListInvocation = AddMaterializeCollectionInvocation(syntaxGenerator, sourceAccess, targetListType);
                return(MappingHelper.WrapInReadonlyCollectionIfNecessary(toListInvocation, isReadonlyCollection, syntaxGenerator));
            }
            var selectAccess        = syntaxGenerator.MemberAccessExpression(sourceAccess, "Select");
            var lambdaParameterName = 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));
        }
Пример #8
0
 public IEnumerable <SyntaxNode> Map(MappingElement source, MappingElement target)
 {
     if (IsMappingBetweenCollections(target.ExpressionType, source.ExpressionType))
     {
         var collectionMapping = MapCollections(source.Expression, source.ExpressionType, target.ExpressionType);
         yield return(generator.CompleteAssignmentStatement(target.Expression, collectionMapping));
     }
     else if (ObjectHelper.IsSimpleType(target.ExpressionType) == false)
     {
         //TODO: What if both sides has the same type?
         //TODO: Reverse flattening
         foreach (var complexPropertyMappingNode in MapTypes(source.ExpressionType, target.ExpressionType, source.Expression, target.Expression))
         {
             yield return(complexPropertyMappingNode);
         }
     }
     else
     {
         yield return(generator.CompleteAssignmentStatement(target.Expression, source.Expression));
     }
 }
Пример #9
0
 protected virtual bool ShouldCreateConversionBetweenTypes(ITypeSymbol targetType, ITypeSymbol sourceType)
 {
     return((sourceType.Equals(targetType) == false) && ObjectHelper.IsSimpleType(targetType) == false && ObjectHelper.IsSimpleType(sourceType) == false);
 }
Пример #10
0
 private bool IsUnwrappingNeeded(ITypeSymbol targetType, MappingElement element)
 {
     return(targetType != element.ExpressionType && ObjectHelper.IsSimpleType(targetType));
 }
Пример #11
0
        public IEnumerable <SyntaxNode> MapTypes(ITypeSymbol sourceType, ITypeSymbol targetType,
                                                 SyntaxNode globalSourceAccessor, SyntaxNode globbalTargetAccessor = null, bool targetExists = false,
                                                 bool generatorContext = false)
        {
            if (IsMappingBetweenCollections(targetType, sourceType))
            {
                var collectionMapping = MapCollections(globalSourceAccessor, sourceType, targetType);
                if (globbalTargetAccessor == null)
                {
                    yield return(generator.ContextualReturnStatement(collectionMapping, generatorContext));
                }
                else if (targetExists == false)
                {
                    yield return(generator.CompleteAssignmentStatement(globbalTargetAccessor, collectionMapping));
                }
                yield break;
            }

            var targetLocalVariableName = globbalTargetAccessor == null?ToLocalVariableName(targetType.Name) : ToLocalVariableName(globbalTargetAccessor.ToFullString());

            var mappingSourceFinder = new MappingSourceFinder(sourceType, globalSourceAccessor, generator, semanticModel);

            if (targetExists == false)
            {
                var mappingConstructorParameters = FindMappingConstructorParameters(targetType, sourceType, mappingSourceFinder, (ExpressionSyntax)globalSourceAccessor);
                if (mappingConstructorParameters != null)
                {
                    var init = generator.ObjectCreationExpression(targetType, mappingConstructorParameters.Arguments);
                    if (globbalTargetAccessor == null)
                    {
                        yield return(generator.ContextualReturnStatement(init, generatorContext));
                    }
                    else
                    {
                        yield return(generator.CompleteAssignmentStatement(globbalTargetAccessor, init));
                    }
                    yield break;
                }
                else
                {
                    var init = generator.ObjectCreationExpression(targetType);
                    yield return(generator.LocalDeclarationStatement(targetLocalVariableName, init));
                }
            }

            var localTargetIdentifier = targetExists? globbalTargetAccessor: generator.IdentifierName(targetLocalVariableName);

            foreach (var targetProperty in ObjectHelper.GetPublicPropertySymbols(targetType))
            {
                if (targetProperty.SetMethod.DeclaredAccessibility != Accessibility.Public && globbalTargetAccessor.Kind() != SyntaxKind.ThisExpression)
                {
                    continue;
                }

                var mappingSource = mappingSourceFinder.FindMappingSource(targetProperty.Name, targetProperty.Type);
                if (mappingSource == null)
                {
                    continue;
                }

                if (IsMappingBetweenCollections(targetProperty.Type, mappingSource.ExpressionType))
                {
                    var targetAccess      = generator.MemberAccessExpression(localTargetIdentifier, targetProperty.Name);
                    var collectionMapping = MapCollections(mappingSource.Expression, mappingSource.ExpressionType, targetProperty.Type);
                    yield return(generator.CompleteAssignmentStatement(targetAccess, collectionMapping));
                }
                else if (ObjectHelper.IsSimpleType(targetProperty.Type) == false)
                {
                    //TODO: What if both sides has the same type?
                    //TODO: Reverse flattening
                    var targetAccess = generator.MemberAccessExpression(localTargetIdentifier, targetProperty.Name);
                    foreach (var complexPropertyMappingNode in MapTypes(mappingSource.ExpressionType, targetProperty.Type, mappingSource.Expression, targetAccess))
                    {
                        yield return(complexPropertyMappingNode);
                    }
                }
                else
                {
                    var targetAccess = generator.MemberAccessExpression(localTargetIdentifier, targetProperty.Name);
                    yield return(generator.CompleteAssignmentStatement(targetAccess, mappingSource.Expression));
                }
            }

            if (globbalTargetAccessor == null)
            {
                yield return(generator.ContextualReturnStatement(localTargetIdentifier, generatorContext));
            }
            else if (targetExists == false)
            {
                yield return(generator.CompleteAssignmentStatement(globbalTargetAccessor, localTargetIdentifier));
            }
        }
 private static bool IsUnrappingNeeded(ITypeSymbol targetType, MappingSource mappingSource)
 {
     return(targetType != mappingSource.ExpressionType && ObjectHelper.IsSimpleType(targetType));
 }
 protected override bool ShouldCreateConversionBetweenTypes(ITypeSymbol targetType, ITypeSymbol sourceType)
 {
     return(ObjectHelper.IsSimpleType(targetType) == false && ObjectHelper.IsSimpleType(sourceType) == false);
 }
Пример #14
0
 private bool IsUnwrappingNeeded(ITypeSymbol targetType, MappingElement element)
 {
     return(targetType.Equals(element.ExpressionType) == false && (ObjectHelper.IsSimpleType(targetType) || SymbolHelper.IsNullable(targetType, out _)));
 }