private async Task <Document> IntroduceLocalDeclarationIntoBlockAsync( SemanticDocument document, BlockSyntax block, ExpressionSyntax expression, NameSyntax newLocalName, LocalDeclarationStatementSyntax declarationStatement, bool allOccurrences, CancellationToken cancellationToken) { declarationStatement = declarationStatement.WithAdditionalAnnotations(Formatter.Annotation); SyntaxNode scope = block; // If we're within a non-static local function, our scope for the new local declaration is expanded to include the enclosing member. var localFunction = block.GetAncestor <LocalFunctionStatementSyntax>(); if (localFunction != null && !localFunction.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.StaticKeyword))) { scope = block.GetAncestor <MemberDeclarationSyntax>(); } var matches = FindMatches(document, expression, document, scope, allOccurrences, cancellationToken); Debug.Assert(matches.Contains(expression)); (document, matches) = await ComplexifyParentingStatementsAsync(document, matches, cancellationToken).ConfigureAwait(false); // Our original expression should have been one of the matches, which were tracked as part // of complexification, so we can retrieve the latest version of the expression here. expression = document.Root.GetCurrentNode(expression); var root = document.Root; ISet <StatementSyntax> allAffectedStatements = new HashSet <StatementSyntax>(matches.SelectMany(expr => GetApplicableStatementAncestors(expr))); SyntaxNode innermostCommonBlock; var innermostStatements = new HashSet <StatementSyntax>(matches.Select(expr => GetApplicableStatementAncestors(expr).First())); if (innermostStatements.Count == 1) { // if there was only one match, or all the matches came from the same statement var statement = innermostStatements.Single(); // and the statement is an embedded statement without a block, we want to generate one // around this statement rather than continue going up to find an actual block if (!IsBlockLike(statement.Parent)) { root = root.TrackNodes(allAffectedStatements.Concat(new SyntaxNode[] { expression, statement })); root = root.ReplaceNode(root.GetCurrentNode(statement), SyntaxFactory.Block(root.GetCurrentNode(statement)).WithAdditionalAnnotations(Formatter.Annotation)); expression = root.GetCurrentNode(expression); allAffectedStatements = allAffectedStatements.Select(root.GetCurrentNode).ToSet(); statement = root.GetCurrentNode(statement); } innermostCommonBlock = statement.Parent; } else { innermostCommonBlock = innermostStatements.FindInnermostCommonNode(IsBlockLike); } var firstStatementAffectedIndex = GetFirstStatementAffectedIndex(innermostCommonBlock, matches, GetStatements(innermostCommonBlock).IndexOf(allAffectedStatements.Contains)); var newInnerMostBlock = Rewrite( document, expression, newLocalName, document, innermostCommonBlock, allOccurrences, cancellationToken); var statements = InsertWithinTriviaOfNext(GetStatements(newInnerMostBlock), declarationStatement, firstStatementAffectedIndex); var finalInnerMostBlock = WithStatements(newInnerMostBlock, statements); var newRoot = root.ReplaceNode(innermostCommonBlock, finalInnerMostBlock); return(document.Document.WithSyntaxRoot(newRoot)); }