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); }
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); }