private StatementSyntax LinkAssignment(AssignmentExpressionSyntax assignment, InvocationExpressionSyntax success, InvocationExpressionSyntax failure, Dictionary <string, TypeSyntax> assignments) { var leftString = assignment.Left.ToString(); var leftType = Roslyn.SymbolTypeSyntax(_model, assignment.Left); Debug.Assert(assignment.Left is IdentifierNameSyntax); Debug.Assert(!assignments.ContainsKey(leftString)); Debug.Assert(leftType != null); //td: error assignments[leftString] = leftType; var emptyAssignments = new Dictionary <string, TypeSyntax>(); var right = LinkOperand(assignment.Right, success, failure, emptyAssignments); Debug.Assert(right != null); Debug.Assert(!emptyAssignments.Any()); //there are 2 scenarios, first, the right operand was a concurrent expression //in which case it would have a success function var successFunc = right .DescendantNodes() .OfType <ParenthesizedLambdaExpressionSyntax>() .Where(fn => fn .ParameterList .Parameters .Any(p => p.Identifier.ToString() == "__res")) .SingleOrDefault(); if (successFunc != null) { return(right.ReplaceNode(successFunc, successFunc .WithBody(CSharp.Block(new[] { Templates .ExpressionAssigment .Get <StatementSyntax>(assignment.Left, leftType) } .Union(successFunc.Body is BlockSyntax ? (successFunc.Body as BlockSyntax) .Statements .AsEnumerable() : new[] { successFunc.Body as StatementSyntax }) .ToArray())))); } //else, we need to substitute the actual Right expr by //an assignment. var rightString = assignment.Right.ToString(); return(right.ReplaceNodes(right. DescendantNodes() .OfType <ExpressionSyntax>() .Where(node => node.ToString().Equals(rightString)), (on, nn) => CSharp.AssignmentExpression( assignment.Kind(), Templates .ExpressionProperty .Get <ExpressionSyntax>(assignment.Left), nn))); }
public override SyntaxNode VisitTryStatement(TryStatementSyntax node) { _trysInStack++; try { var newNode = (TryStatementSyntax)base.VisitTryStatement(node); if (_tryConcurrent) { var variableName = "__try" + _trysInStack; _tryVariables.Add(variableName); //we can only split on expressions directly on the try level //i.e. no try { if () { EXPRESSION }} if (_trysInStack > 1 && !(newNode.Parent.Parent is TryStatementSyntax)) { Debug.Assert(false); //td: error return(newNode); } var statements = new List <StatementSyntax>(newNode.Block.Statements); var newStatements = new List <StatementSyntax>(); var currentIndex = 0; while (currentIndex < statements.Count) { var oldIndex = currentIndex; for (int i = oldIndex; i < statements.Count; i++, currentIndex++) { var statement = statements[i]; if (statement is YieldStatementSyntax) { newStatements.Add(newNode .WithBlock(CSharp.Block( statements .Skip(oldIndex) .Take(currentIndex - oldIndex - 1)))); //variable and return yield //td: assert newStatements.Add(statements[currentIndex - 1]); newStatements.Add(statements[currentIndex++]); break; } //must make variables available to later code, unless it precedes a yield var yieldNext = statements.Count > i + 1 && statements[i + 1] is YieldStatementSyntax; if (statement is LocalDeclarationStatementSyntax && !yieldNext) { var decl = statement as LocalDeclarationStatementSyntax; var varType = decl.Declaration.Type; if (varType == null || varType.Kind() == SyntaxKind.TypeVarKeyword) { varType = Roslyn.SymbolTypeSyntax(_model, decl .Declaration .Variables[0] .Initializer .Value); } Debug.Assert(varType != null, "Untyped local variable on try fix"); var assignmentStatements = new List <StatementSyntax>(); newStatements.Add(decl .WithDeclaration(decl.Declaration .WithType(varType) .WithVariables(CSharp.SeparatedList( decl .Declaration .Variables .Select(v => { assignmentStatements.Add(CSharp.ExpressionStatement( CSharp.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, CSharp.IdentifierName(v.Identifier), v.Initializer.Value))); return(v.WithInitializer(v .Initializer .WithValue(Templates .DefaultValue .Get <ExpressionSyntax>(varType)))); }))))); //once moved the variables "up" scope //we must keep the assignments Debug.Assert(assignmentStatements.Any()); statements.RemoveAt(i); statements.InsertRange(i, assignmentStatements); } } } Debug.Assert(newStatements.Any()); return(LinkTryStatements(newStatements, variableName)); } return(newNode); } finally { _trysInStack--; } }