public SyntaxNode ReplaceDeconstructions(SyntaxNode root, SemanticModel model)
        {
            var assignments = root
                              .DescendantNodes()
                              .OfType <AssignmentExpressionSyntax>()
                              .Where(ae => ae.Left is TupleExpressionSyntax || ae.Left is DeclarationExpressionSyntax de && de.Designation is ParenthesizedVariableDesignationSyntax);

            Dictionary <AssignmentExpressionSyntax, DeconstructionInfo> infos = new Dictionary <AssignmentExpressionSyntax, DeconstructionInfo>();
            List <AssignmentExpressionSyntax> nodes = new List <AssignmentExpressionSyntax>();

            foreach (var assignment in assignments)
            {
                var deconstructionInfo = model.GetDeconstructionInfo(assignment);
                infos.Add(assignment, deconstructionInfo);
                nodes.Add(assignment);
            }

            if (nodes.Count > 0)
            {
                root = root.ReplaceNodes(nodes, (n1, n2) =>
                {
                    var assignment         = n2;
                    var deconstructionInfo = infos[n1];


                    var tuple = assignment.Left;
                    var obj   = assignment.Right;

                    return(DeconstructionToMethod(tuple, obj, deconstructionInfo));
                });
            }

            return(root);
        }
Exemplo n.º 2
0
        public SyntaxNode ReplaceForeachDeconstructions(SyntaxNode root, SemanticModel model)
        {
            var loops = root
                        .DescendantNodes()
                        .OfType <ForEachVariableStatementSyntax>()
                        .Where(forEach => forEach.Variable is TupleExpressionSyntax || forEach.Variable is DeclarationExpressionSyntax de && de.Designation is ParenthesizedVariableDesignationSyntax);

            if (loops.Any())
            {
                Dictionary <ForEachVariableStatementSyntax, DeconstructionInfo> infos = new Dictionary <ForEachVariableStatementSyntax, DeconstructionInfo>();

                foreach (var loop in loops)
                {
                    try
                    {
                        var deconstructionInfo = model.GetDeconstructionInfo(loop);
                        infos.Add(loop, deconstructionInfo);
                    }
                    catch (Exception e)
                    {
                        throw new ReplacerException(loop, e);
                    }
                }

                var tempIndex = 0;
                root = root.ReplaceNodes(loops, (n1, n2) => {
                    var variable = n2.Variable;

                    string instance = "_d" + ++tempIndex;
                    if (n1.Parent != null)
                    {
                        var info = LocalUsageGatherer.GatherInfo(model, n1.Parent);

                        while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance))
                        {
                            instance = "_d" + ++tempIndex;
                        }
                    }

                    var newloop = SyntaxFactory.ForEachStatement(SyntaxFactory.IdentifierName("var"), SyntaxFactory.Identifier(instance), n2.Expression, n2.Statement)
                                  .WithLeadingTrivia(n2.GetLeadingTrivia())
                                  .WithTrailingTrivia(n2.GetTrailingTrivia());

                    var deconstructionInfo = infos[n1];
                    var invocation         = DeconstructionToMethod(variable, SyntaxFactory.IdentifierName(instance), deconstructionInfo);

                    if (newloop.Statement is BlockSyntax b)
                    {
                        foreach (var statement in b.Statements)
                        {
                            try
                            {
                                if (statement.ContainsAnnotations)
                                {
                                    var annotaions = statement.GetAnnotations("last_variable");
                                    if (annotaions != null && annotaions.Any())
                                    {
                                        newloop = newloop.InsertNodesAfter(statement, new[] { SyntaxFactory.ExpressionStatement(invocation) });
                                        break;
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                throw new ReplacerException(statement, e);
                            }
                        }
                    }

                    return(newloop.NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")));
                });
            }

            return(root);
        }