public static async Task <Document> FixInvocationWithParameters(Document document,
                                                                        IInvocation invocation,
                                                                        bool generateNamedParameters,
                                                                        SemanticModel semanticModel,
                                                                        IMappingSourceFinder mappingSourceFinder,
                                                                        CancellationToken cancellationToken)
        {
            var syntaxGenerator       = SyntaxGenerator.GetGenerator(document);
            var overloadParameterSets = invocation.GetOverloadParameterSets(semanticModel);

            if (overloadParameterSets != null)
            {
                var contextAssembly = semanticModel.FindContextAssembly(invocation.SourceNode);
                var mappingEngine   = new MappingEngine(semanticModel, syntaxGenerator, contextAssembly);
                var parametersMatch = MethodHelper.FindBestParametersMatch(mappingSourceFinder, overloadParameterSets);
                if (parametersMatch != null)
                {
                    var argumentList = parametersMatch.ToArgumentListSyntax(mappingEngine, generateNamedParameters);
                    return(await document.ReplaceNodes(invocation.SourceNode, invocation.WithArgumentList(argumentList), cancellationToken));
                }
            }

            return(document);
        }
Beispiel #2
0
        private string GetArgumentListWithLocalVariables(Document document, IInvocation invocation, bool generateNamedParameters, SemanticModel semanticModel)
        {
            var mappingSourceFinder = new LocalScopeMappingSourceFinder(semanticModel, invocation.SourceNode, AllowedSymbolsForCompletion)
            {
                AllowMatchOnlyByTypeWhenSingleCandidate = true
            };
            var syntaxGenerator       = SyntaxGenerator.GetGenerator(document);
            var overloadParameterSets = invocation.GetOverloadParameterSets(semanticModel);

            if (overloadParameterSets != null)
            {
                var contextAssembly = semanticModel.FindContextAssembly(invocation.SourceNode);
                var mappingEngine   = new MappingEngine(semanticModel, syntaxGenerator, contextAssembly);
                var parametersMatch = MethodHelper.FindBestParametersMatch(mappingSourceFinder, overloadParameterSets);
                if (parametersMatch != null)
                {
                    var argumentList = parametersMatch.ToArgumentListSyntax(mappingEngine, generateNamedParameters);
                    var chunks       = argumentList.Arguments.Select(a => a.ToString());
                    return(string.Join(", ", chunks));
                }
            }

            return(null);
        }
        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 = ((ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(targetType, matchedOverload.ToArgumentListSyntax(this).Arguments));
                    var matchedSources     = matchedOverload.GetMatchedSources();
                    var restSourceFinder   = new IgnorableMappingSourceFinder(subMappingSourceFinder, foundElement =>
                    {
                        return(matchedSources.Any(x => x.Expression.IsEquivalentTo(foundElement.Expression)));
                    });
                    return(new MappingElement()
                    {
                        ExpressionType = targetType,
                        Expression = AddInitializerWithMapping(creationExpression, restSourceFinder, targetType, mappingPath)
                    });
                }
            }


            var objectCreationExpressionSyntax = ((ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(targetType));

            return(new MappingElement()
            {
                ExpressionType = targetType,
                Expression = AddInitializerWithMapping(objectCreationExpressionSyntax, subMappingSourceFinder, targetType, mappingPath)
            });
        }