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)
            });
        }
Exemple #2
0
        private static IEnumerable<SyntaxNode> GenerateMappingCode(IMethodSymbol methodSymbol, SyntaxGenerator generator, SemanticModel semanticModel)
        {
            var mappingEngine = new MappingEngine(semanticModel, generator);

            if (SymbolHelper.IsPureMappingFunction(methodSymbol))
            {
                var source = methodSymbol.Parameters[0];
                var targetType = methodSymbol.ReturnType;
                var newExpression = mappingEngine.MapExpression((ExpressionSyntax)generator.IdentifierName(source.Name), source.Type, targetType);
                return new[] { generator.ReturnStatement(newExpression) };
            }

            //TODO: Pure mapping with multiple parameters

            if (SymbolHelper.IsUpdateParameterFunction(methodSymbol))
            {
                var source = methodSymbol.Parameters[0];
                var target = methodSymbol.Parameters[1];
                var targets = ObjectHelper.GetFieldsThaCanBeSetPublicly(target.Type);
                var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator);
                return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder, globalTargetAccessor: generator.IdentifierName(target.Name));
            }

            if (SymbolHelper.IsUpdateThisObjectFunction(methodSymbol))
            {
                var source = methodSymbol.Parameters[0];
                var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator);
                var targets = ObjectHelper.GetFieldsThaCanBeSetPrivately(methodSymbol.ContainingType);
                return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder);
            }

            if (SymbolHelper.IsMultiParameterUpdateThisObjectFunction(methodSymbol))
            {
                var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol.Parameters);
                var targets = ObjectHelper.GetFieldsThaCanBeSetPrivately(methodSymbol.ContainingType);
                return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder);
            }

            if (SymbolHelper.IsMappingConstructor(methodSymbol))
            {
                var source = methodSymbol.Parameters[0];
                var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator);
                var targets = ObjectHelper.GetFieldsThaCanBeSetFromConstructor(methodSymbol.ContainingType);
                return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder);
            }

            if (SymbolHelper.IsMultiParameterMappingConstructor(methodSymbol))
            {
                var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol.Parameters);
                var targets = ObjectHelper.GetFieldsThaCanBeSetFromConstructor(methodSymbol.ContainingType);
                return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder);
            }
            return Enumerable.Empty<SyntaxNode>();
        }
        private async Task <Document> InitizalizeWithLambdaParameter(Document document, LambdaExpressionSyntax lambdaSyntax, InitializerExpressionSyntax objectInitializer, CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken);

            var generator = SyntaxGenerator.GetGenerator(document);

            var lambdaSymbol        = semanticModel.GetSymbolInfo(lambdaSyntax).Symbol as IMethodSymbol;
            var firstArgument       = lambdaSymbol.Parameters.First();
            var mappingSourceFinder = new ObjectMembersMappingSourceFinder(firstArgument.Type, generator.IdentifierName(firstArgument.Name), generator);

            return(await ReplaceEmptyInitializationBlock(document, objectInitializer, cancellationToken, semanticModel, mappingSourceFinder, generator));
        }
        public IEnumerable <SyntaxNode> MapTypes(ITypeSymbol sourceType, ITypeSymbol targetType,
                                                 SyntaxNode globalSourceAccessor, SyntaxNode globbalTargetAccessor = null, bool targetExists = false,
                                                 bool generatorContext     = false,
                                                 bool isConstructorContext = 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 ObjectMembersMappingSourceFinder(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 (CanBeSet(targetProperty, globbalTargetAccessor, isConstructorContext) == false)
                {
                    continue;
                }

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

                var mappingTarget = new MappingElement()
                {
                    Expression     = (ExpressionSyntax)generator.MemberAccessExpression(localTargetIdentifier, targetProperty.Name),
                    ExpressionType = targetProperty.Type
                };

                foreach (var syntaxNode in Map(mappingSource, mappingTarget))
                {
                    yield return(syntaxNode);
                }
            }

            if (globbalTargetAccessor == null)
            {
                yield return(generator.ContextualReturnStatement(localTargetIdentifier, generatorContext));
            }
            else if (targetExists == false)
            {
                yield return(generator.CompleteAssignmentStatement(globbalTargetAccessor, localTargetIdentifier));
            }
        }
 private ArgumentListSyntax FindMappingConstructorParameters(ITypeSymbol targetType, ITypeSymbol sourceType, ObjectMembersMappingSourceFinder mappingSourceFinder, ExpressionSyntax globalSourceAccessor)
 {
     if (targetType is INamedTypeSymbol namedType)
     {
         var directlyMappingConstructor = namedType.Constructors.FirstOrDefault(c => c.Parameters.Length == 1 && c.Parameters[0].Type == sourceType);
         if (directlyMappingConstructor != null)
         {
             return(SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(globalSourceAccessor)));
         }
         var constructorOverloadParameterSets = namedType.Constructors.Select(x => x.Parameters);
         return(MethodHelper.FindBestParametersMatch(mappingSourceFinder, constructorOverloadParameterSets)?.ToArgumentListSyntax(generator));
     }
     return(null);
 }
Exemple #6
0
        private static IEnumerable <SyntaxNode> GenerateMappingCode(IMethodSymbol methodSymbol, SyntaxGenerator generator, SemanticModel semanticModel)
        {
            if (SymbolHelper.IsIdentityMappingFunction(methodSymbol))
            {
                var cloneMappingEngine = new CloneMappingEngine(semanticModel, generator, methodSymbol.ContainingAssembly);
                var source             = methodSymbol.Parameters[0];
                var targetType         = methodSymbol.ReturnType;
                var newExpression      = cloneMappingEngine.MapExpression((ExpressionSyntax)generator.IdentifierName(source.Name), source.Type, targetType);
                return(new[] { generator.ReturnStatement(newExpression).WithAdditionalAnnotations(Formatter.Annotation) });
            }

            var mappingEngine = new MappingEngine(semanticModel, generator, methodSymbol.ContainingAssembly);

            if (SymbolHelper.IsPureMappingFunction(methodSymbol))
            {
                var source        = methodSymbol.Parameters[0];
                var targetType    = methodSymbol.ReturnType;
                var newExpression = mappingEngine.MapExpression((ExpressionSyntax)generator.IdentifierName(source.Name), source.Type, targetType);
                return(new[] { generator.ReturnStatement(newExpression).WithAdditionalAnnotations(Formatter.Annotation) });
            }

            if (SymbolHelper.IsMultiParameterPureFunction(methodSymbol))
            {
                var targetType    = methodSymbol.ReturnType;
                var sourceFinder  = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol);
                var newExpression = mappingEngine.AddInitializerWithMapping((ObjectCreationExpressionSyntax)generator.ObjectCreationExpression(targetType), sourceFinder, targetType);
                return(new[] { generator.ReturnStatement(newExpression).WithAdditionalAnnotations(Formatter.Annotation) });
            }

            if (SymbolHelper.IsUpdateParameterFunction(methodSymbol))
            {
                var source       = methodSymbol.Parameters[0];
                var target       = methodSymbol.Parameters[1];
                var targets      = ObjectHelper.GetFieldsThaCanBeSetPublicly(target.Type, methodSymbol.ContainingAssembly);
                var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator);
                return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder, globalTargetAccessor: generator.IdentifierName(target.Name)));
            }

            if (SymbolHelper.IsUpdateThisObjectFunction(methodSymbol))
            {
                var source       = methodSymbol.Parameters[0];
                var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator);
                var targets      = ObjectHelper.GetFieldsThaCanBeSetPrivately(methodSymbol.ContainingType);
                return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder));
            }

            if (SymbolHelper.IsMultiParameterUpdateThisObjectFunction(methodSymbol))
            {
                var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol.Parameters);
                var targets      = ObjectHelper.GetFieldsThaCanBeSetPrivately(methodSymbol.ContainingType);
                return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder));
            }

            if (SymbolHelper.IsMappingConstructor(methodSymbol))
            {
                var source       = methodSymbol.Parameters[0];
                var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator);
                var targets      = ObjectHelper.GetFieldsThaCanBeSetFromConstructor(methodSymbol.ContainingType);
                return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder));
            }

            if (SymbolHelper.IsMultiParameterMappingConstructor(methodSymbol))
            {
                var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol.Parameters);
                var targets      = ObjectHelper.GetFieldsThaCanBeSetFromConstructor(methodSymbol.ContainingType);
                return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder));
            }
            return(Enumerable.Empty <SyntaxNode>());
        }