예제 #1
0
        private void AddEmbeddedStatementsIndentationOperation(List <IndentBlockOperation> list, StatementSyntax statement)
        {
            var firstToken = statement.GetFirstToken(includeZeroWidth: true);
            var lastToken  = statement.GetLastToken(includeZeroWidth: true);

            if (lastToken.IsMissing)
            {
                // embedded statement is not done, consider following as part of embedded statement
                AddIndentBlockOperation(list, firstToken, lastToken);
            }
            else
            {
                // embedded statement is done
                AddIndentBlockOperation(list, firstToken, lastToken, TextSpan.FromBounds(firstToken.FullSpan.Start, lastToken.FullSpan.End));
            }
        }
예제 #2
0
        public static bool StatementNeedsWrapping(StatementSyntax statement)
        {
            // Statement has to be parented by another statement (or an else-clause) to count.
            var parent             = statement.Parent;
            var parentIsElseClause = parent.IsKind(SyntaxKind.ElseClause);

            if (!(parent is StatementSyntax || parentIsElseClause))
            {
                return(false);
            }

            // `else if` is always allowed.
            if (statement.IsKind(SyntaxKind.IfStatement) && parentIsElseClause)
            {
                return(false);
            }

            var statementStartToken = statement.GetFirstToken();

            // we have to have a newline between the start of this statement and the previous statement.
            if (ContainsEndOfLineBetween(statementStartToken.GetPreviousToken(), statementStartToken))
            {
                return(false);
            }

            // Looks like a statement that might need wrapping.  However, we do suppress wrapping for a few well known
            // acceptable cases.

            if (parent.IsKind(SyntaxKind.Block))
            {
                // Blocks can be on a single line if parented by a member/accessor/lambda.
                // And if they only contain a single statement at most within them.
                var blockParent = parent.Parent;
                if (blockParent is MemberDeclarationSyntax or
                    AccessorDeclarationSyntax or
                    AnonymousFunctionExpressionSyntax)
                {
                    if (parent.DescendantNodes().OfType <StatementSyntax>().Count() <= 1)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
예제 #3
0
        private bool CheckStatementSyntax(SyntaxTreeAnalysisContext context, ReportDiagnostic severity, StatementSyntax statement)
        {
            if (!StatementNeedsWrapping(statement))
            {
                return(false);
            }

            var additionalLocations = ImmutableArray.Create(statement.GetLocation());

            context.ReportDiagnostic(DiagnosticHelper.Create(
                                         this.Descriptor,
                                         statement.GetFirstToken().GetLocation(),
                                         severity,
                                         additionalLocations,
                                         properties: null));
            return(true);
        }
예제 #4
0
        public static bool StatementNeedsWrapping(StatementSyntax statement)
        {
            // Statement has to be parented by another statement (or an else-clause) to count.
            var parent             = statement.Parent;
            var parentIsElseClause = parent.IsKind(SyntaxKind.ElseClause);

            if (!(parent is StatementSyntax || parentIsElseClause))
            {
                return(false);
            }

            // `else if` is always allowed.
            if (statement.IsKind(SyntaxKind.IfStatement) && parentIsElseClause)
            {
                return(false);
            }

            if (parent.IsKind(SyntaxKind.Block))
            {
                // Blocks can be on a single line if parented by a member/accessor/lambda.
                var blockParent = parent.Parent;
                if (blockParent is MemberDeclarationSyntax or
                    AccessorDeclarationSyntax or
                    AnonymousFunctionExpressionSyntax)
                {
                    return(false);
                }
            }

            var statementStartToken = statement.GetFirstToken();
            var previousToken       = statementStartToken.GetPreviousToken();

            // we have to have a newline between the start of this statement and the previous statement.
            if (ContainsEndOfLine(previousToken.TrailingTrivia) ||
                ContainsEndOfLine(statementStartToken.LeadingTrivia))
            {
                return(false);
            }

            return(true);
        }
        private static void CheckChildStatement(SyntaxNodeAnalysisContext context, SyntaxNode node, StatementSyntax childStatement)
        {
            if (childStatement == null || childStatement.IsMissing)
            {
                return;
            }

            if (childStatement is BlockSyntax)
            {
                // BlockSyntax child statements are handled by HandleBlock
                return;
            }

            // We are only interested in the first instance of this violation on a line.
            if (!node.GetFirstToken().IsFirstInLine())
            {
                return;
            }

            // We are only interested in the case where statement and childStatement start on the same line. Use
            // IsFirstInLine to detect this condition easily.
            SyntaxToken firstChildToken = childStatement.GetFirstToken();

            if (firstChildToken.IsMissingOrDefault() || firstChildToken.IsFirstInLine())
            {
                return;
            }

            if (!context.IsAnalyzerSuppressed(SA1519CurlyBracketsMustNotBeOmittedFromMultiLineChildStatement.DiagnosticId))
            {
                // diagnostics for multi-line statements is handled by SA1519, as long as it's not suppressed
                FileLinePositionSpan lineSpan = childStatement.GetLineSpan();
                if (lineSpan.StartLinePosition.Line != lineSpan.EndLinePosition.Line)
                {
                    return;
                }
            }

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, childStatement.GetLocation()));
        }
        private static void CheckChildStatement(SyntaxNodeAnalysisContext context, StatementSyntax childStatement)
        {
            bool reportAsHidden = false;

            if (childStatement == null || childStatement.IsMissing)
            {
                return;
            }

            if (childStatement is BlockSyntax)
            {
                // BlockSyntax child statements are handled by HandleBlock
                return;
            }

            // We are only interested in the case where statement and childStatement start on the same line. Use
            // IsFirstInLine to detect this condition easily.
            SyntaxToken firstChildToken = childStatement.GetFirstToken();

            if (firstChildToken.IsMissingOrDefault() || firstChildToken.IsFirstInLine())
            {
                return;
            }

            if (!context.IsAnalyzerSuppressed(SA1519BracesMustNotBeOmittedFromMultiLineChildStatement.Descriptor))
            {
                // diagnostics for multi-line statements is handled by SA1519, as long as it's not suppressed
                FileLinePositionSpan lineSpan = childStatement.GetLineSpan();
                if (lineSpan.StartLinePosition.Line != lineSpan.EndLinePosition.Line)
                {
                    reportAsHidden = true;
                }
            }

            ReportDiagnostic(context, childStatement.GetLocation(), reportAsHidden);
        }
예제 #7
0
        private static SyntaxToken GetFirstIncludedToken(StatementSyntax statement)
        {
            Debug.Assert(statement != null);
            switch (statement.Kind())
            {
            case SyntaxKind.Block:
                return(((BlockSyntax)statement).OpenBraceToken);

            case SyntaxKind.BreakStatement:
                return(((BreakStatementSyntax)statement).BreakKeyword);

            case SyntaxKind.CheckedStatement:
            case SyntaxKind.UncheckedStatement:
                return(((CheckedStatementSyntax)statement).Keyword);

            case SyntaxKind.ContinueStatement:
                return(((ContinueStatementSyntax)statement).ContinueKeyword);

            case SyntaxKind.ExpressionStatement:
            case SyntaxKind.LocalDeclarationStatement:
                return(statement.GetFirstToken());

            case SyntaxKind.DoStatement:
                return(((DoStatementSyntax)statement).DoKeyword);

            case SyntaxKind.EmptyStatement:
                return(default(SyntaxToken));    //The caller will have to check for this.

            case SyntaxKind.FixedStatement:
                return(((FixedStatementSyntax)statement).FixedKeyword);

            case SyntaxKind.ForEachStatement:
            case SyntaxKind.ForEachVariableStatement:
                return(((CommonForEachStatementSyntax)statement).OpenParenToken.GetNextToken());

            case SyntaxKind.ForStatement:
                return(((ForStatementSyntax)statement).OpenParenToken.GetNextToken());

            case SyntaxKind.GotoDefaultStatement:
            case SyntaxKind.GotoCaseStatement:
            case SyntaxKind.GotoStatement:
                return(((GotoStatementSyntax)statement).GotoKeyword);

            case SyntaxKind.IfStatement:
                return(((IfStatementSyntax)statement).IfKeyword);

            case SyntaxKind.LabeledStatement:
                return(((LabeledStatementSyntax)statement).Identifier);

            case SyntaxKind.LockStatement:
                return(((LockStatementSyntax)statement).LockKeyword);

            case SyntaxKind.ReturnStatement:
                return(((ReturnStatementSyntax)statement).ReturnKeyword);

            case SyntaxKind.SwitchStatement:
                return(((SwitchStatementSyntax)statement).Expression.GetFirstToken());

            case SyntaxKind.ThrowStatement:
                return(((ThrowStatementSyntax)statement).ThrowKeyword);

            case SyntaxKind.TryStatement:
                return(((TryStatementSyntax)statement).TryKeyword);

            case SyntaxKind.UnsafeStatement:
                return(((UnsafeStatementSyntax)statement).UnsafeKeyword);

            case SyntaxKind.UsingStatement:
                return(((UsingStatementSyntax)statement).UsingKeyword);

            case SyntaxKind.WhileStatement:
                return(((WhileStatementSyntax)statement).WhileKeyword);

            case SyntaxKind.YieldReturnStatement:
            case SyntaxKind.YieldBreakStatement:
                return(((YieldStatementSyntax)statement).YieldKeyword);

            case SyntaxKind.LocalFunctionStatement:
                return(statement.GetFirstToken());

            default:
                throw ExceptionUtilities.UnexpectedValue(statement.Kind());
            }
        }
예제 #8
0
        private static SyntaxToken GetFirstIncludedToken(StatementSyntax statement, bool inRecursiveCall = false)
        {
            Debug.Assert(statement != null);
            switch (statement.Kind())
            {
            case SyntaxKind.Block:
                return(((BlockSyntax)statement).OpenBraceToken);

            case SyntaxKind.BreakStatement:
                return(((BreakStatementSyntax)statement).BreakKeyword);

            case SyntaxKind.CheckedStatement:
            case SyntaxKind.UncheckedStatement:
                return(((CheckedStatementSyntax)statement).Keyword);

            case SyntaxKind.ContinueStatement:
                return(((ContinueStatementSyntax)statement).ContinueKeyword);

            case SyntaxKind.ExpressionStatement:
            case SyntaxKind.LocalDeclarationStatement:
                return(statement.GetFirstToken());

            case SyntaxKind.DoStatement:
                return(((DoStatementSyntax)statement).DoKeyword);

            case SyntaxKind.EmptyStatement:
                return(default(SyntaxToken));    //The caller will have to check for this.

            case SyntaxKind.FixedStatement:
                return(((FixedStatementSyntax)statement).FixedKeyword);

            case SyntaxKind.ForEachStatement:
                // NB: iteration variable is only in scope in body.
                ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)statement;
                if (inRecursiveCall)
                {
                    return(forEachSyntax.ForEachKeyword);
                }
                return(GetFirstIncludedToken(forEachSyntax.Statement, inRecursiveCall: true));

            case SyntaxKind.ForStatement:
                // Section 8.8.3 of the spec says that the scope of the loop variable starts at
                // its declaration.  If it's not there, then the scope we are interested in is
                // the loop body.
                ForStatementSyntax forSyntax = (ForStatementSyntax)statement;
                if (inRecursiveCall)
                {
                    return(forSyntax.ForKeyword);
                }
                VariableDeclarationSyntax declOpt = forSyntax.Declaration;
                return(declOpt == null?GetFirstIncludedToken(forSyntax.Statement, inRecursiveCall : true) : declOpt.GetFirstToken());

            case SyntaxKind.GotoDefaultStatement:
            case SyntaxKind.GotoCaseStatement:
            case SyntaxKind.GotoStatement:
                return(((GotoStatementSyntax)statement).GotoKeyword);

            case SyntaxKind.IfStatement:
                return(((IfStatementSyntax)statement).IfKeyword);

            case SyntaxKind.LabeledStatement:
                return(((LabeledStatementSyntax)statement).Identifier);

            case SyntaxKind.LockStatement:
                return(((LockStatementSyntax)statement).LockKeyword);

            case SyntaxKind.ReturnStatement:
                return(((ReturnStatementSyntax)statement).ReturnKeyword);

            case SyntaxKind.SwitchStatement:
                return(((SwitchStatementSyntax)statement).OpenBraceToken);

            case SyntaxKind.ThrowStatement:
                return(((ThrowStatementSyntax)statement).ThrowKeyword);

            case SyntaxKind.TryStatement:
                return(((TryStatementSyntax)statement).TryKeyword);

            case SyntaxKind.UnsafeStatement:
                return(((UnsafeStatementSyntax)statement).UnsafeKeyword);

            case SyntaxKind.UsingStatement:
                return(((UsingStatementSyntax)statement).UsingKeyword);

            case SyntaxKind.WhileStatement:
                return(((WhileStatementSyntax)statement).WhileKeyword);

            case SyntaxKind.YieldReturnStatement:
            case SyntaxKind.YieldBreakStatement:
                return(((YieldStatementSyntax)statement).YieldKeyword);

            default:
                throw ExceptionUtilities.UnexpectedValue(statement.Kind());
            }
        }
예제 #9
0
        private void AddEmbeddedStatementsIndentationOperation(List<IndentBlockOperation> list, StatementSyntax statement)
        {
            var firstToken = statement.GetFirstToken(includeZeroWidth: true);
            var lastToken = statement.GetLastToken(includeZeroWidth: true);

            if (lastToken.IsMissing)
            {
                // embedded statement is not done, consider following as part of embedded statement
                AddIndentBlockOperation(list, firstToken, lastToken);
            }
            else
            {
                // embedded statement is done
                AddIndentBlockOperation(list, firstToken, lastToken, TextSpan.FromBounds(firstToken.FullSpan.Start, lastToken.FullSpan.End));
            }
        }
        private static void CheckChildStatement(SyntaxNodeAnalysisContext context, SyntaxNode node, StatementSyntax childStatement)
        {
            if (childStatement == null || childStatement.IsMissing)
            {
                return;
            }

            if (childStatement is BlockSyntax)
            {
                // BlockSyntax child statements are handled by HandleBlock
                return;
            }

            // We are only interested in the first instance of this violation on a line.
            if (!node.GetFirstToken().IsFirstInLine())
            {
                return;
            }

            // We are only interested in the case where statement and childStatement start on the same line. Use
            // IsFirstInLine to detect this condition easily.
            SyntaxToken firstChildToken = childStatement.GetFirstToken();
            if (firstChildToken.IsMissingOrDefault() || firstChildToken.IsFirstInLine())
            {
                return;
            }

            if (!context.IsAnalyzerSuppressed(SA1519CurlyBracketsMustNotBeOmittedFromMultiLineChildStatement.DiagnosticId))
            {
                // diagnostics for multi-line statements is handled by SA1519, as long as it's not suppressed
                FileLinePositionSpan lineSpan = childStatement.GetLineSpan();
                if (lineSpan.StartLinePosition.Line != lineSpan.EndLinePosition.Line)
                {
                    return;
                }
            }

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, childStatement.GetLocation()));
        }
예제 #11
0
 private static SyntaxToken GetFirstIncludedToken(StatementSyntax statement, bool inRecursiveCall = false)
 {
     Debug.Assert(statement != null);
     switch (statement.Kind)
     {
         case SyntaxKind.Block:
             return ((BlockSyntax)statement).OpenBraceToken;
         case SyntaxKind.BreakStatement:
             return ((BreakStatementSyntax)statement).BreakKeyword;
         case SyntaxKind.CheckedStatement:
         case SyntaxKind.UncheckedStatement:
             return ((CheckedStatementSyntax)statement).Keyword;
         case SyntaxKind.ContinueStatement:
             return ((ContinueStatementSyntax)statement).ContinueKeyword;
         case SyntaxKind.ExpressionStatement:
         case SyntaxKind.LocalDeclarationStatement:
             return statement.GetFirstToken();
         case SyntaxKind.DoStatement:
             return ((DoStatementSyntax)statement).DoKeyword;
         case SyntaxKind.EmptyStatement:
             return default(SyntaxToken); //The caller will have to check for this.
         case SyntaxKind.FixedStatement:
             return ((FixedStatementSyntax)statement).FixedKeyword;
         case SyntaxKind.ForEachStatement:
             // NB: iteration variable is only in scope in body.
             ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)statement;
             if (inRecursiveCall)
             {
                 return forEachSyntax.ForEachKeyword;
             }
             return GetFirstIncludedToken(forEachSyntax.Statement, inRecursiveCall: true);
         case SyntaxKind.ForStatement:
             // Section 8.8.3 of the spec says that the scope of the loop variable starts at 
             // its declaration.  If it's not there, then the scope we are interested in is
             // the loop body.
             ForStatementSyntax forSyntax = (ForStatementSyntax)statement;
             if (inRecursiveCall)
             {
                 return forSyntax.ForKeyword;
             }
             VariableDeclarationSyntax declOpt = forSyntax.Declaration;
             return declOpt == null ? GetFirstIncludedToken(forSyntax.Statement, inRecursiveCall: true) : declOpt.GetFirstToken();
         case SyntaxKind.GotoDefaultStatement:
         case SyntaxKind.GotoCaseStatement:
         case SyntaxKind.GotoStatement:
             return ((GotoStatementSyntax)statement).GotoKeyword;
         case SyntaxKind.IfStatement:
             return ((IfStatementSyntax)statement).IfKeyword;
         case SyntaxKind.LabeledStatement:
             return ((LabeledStatementSyntax)statement).Identifier;
         case SyntaxKind.LockStatement:
             return ((LockStatementSyntax)statement).LockKeyword;
         case SyntaxKind.ReturnStatement:
             return ((ReturnStatementSyntax)statement).ReturnKeyword;
         case SyntaxKind.SwitchStatement:
             return ((SwitchStatementSyntax)statement).OpenBraceToken;
         case SyntaxKind.ThrowStatement:
             return ((ThrowStatementSyntax)statement).ThrowKeyword;
         case SyntaxKind.TryStatement:
             return ((TryStatementSyntax)statement).TryKeyword;
         case SyntaxKind.UnsafeStatement:
             return ((UnsafeStatementSyntax)statement).UnsafeKeyword;
         case SyntaxKind.UsingStatement:
             return ((UsingStatementSyntax)statement).UsingKeyword;
         case SyntaxKind.WhileStatement:
             return ((WhileStatementSyntax)statement).WhileKeyword;
         case SyntaxKind.YieldReturnStatement:
         case SyntaxKind.YieldBreakStatement:
             return ((YieldStatementSyntax)statement).YieldKeyword;
         default:
             throw ExceptionUtilities.UnexpectedValue(statement.Kind);
     }
 }
예제 #12
0
 private static SyntaxToken GetFirstIncludedToken(StatementSyntax statement)
 {
     Debug.Assert(statement != null);
     switch (statement.Kind())
     {
         case SyntaxKind.Block:
             return ((BlockSyntax)statement).OpenBraceToken;
         case SyntaxKind.BreakStatement:
             return ((BreakStatementSyntax)statement).BreakKeyword;
         case SyntaxKind.CheckedStatement:
         case SyntaxKind.UncheckedStatement:
             return ((CheckedStatementSyntax)statement).Keyword;
         case SyntaxKind.ContinueStatement:
             return ((ContinueStatementSyntax)statement).ContinueKeyword;
         case SyntaxKind.ExpressionStatement:
         case SyntaxKind.LocalDeclarationStatement:
         case SyntaxKind.DeconstructionDeclarationStatement:
             return statement.GetFirstToken();
         case SyntaxKind.DoStatement:
             return ((DoStatementSyntax)statement).DoKeyword;
         case SyntaxKind.EmptyStatement:
             return default(SyntaxToken); //The caller will have to check for this.
         case SyntaxKind.FixedStatement:
             return ((FixedStatementSyntax)statement).FixedKeyword;
         case SyntaxKind.ForEachStatement:
         case SyntaxKind.ForEachComponentStatement:
             return ((CommonForEachStatementSyntax)statement).OpenParenToken.GetNextToken();
         case SyntaxKind.ForStatement:
             return ((ForStatementSyntax)statement).OpenParenToken.GetNextToken();
         case SyntaxKind.GotoDefaultStatement:
         case SyntaxKind.GotoCaseStatement:
         case SyntaxKind.GotoStatement:
             return ((GotoStatementSyntax)statement).GotoKeyword;
         case SyntaxKind.IfStatement:
             return ((IfStatementSyntax)statement).IfKeyword;
         case SyntaxKind.LabeledStatement:
             return ((LabeledStatementSyntax)statement).Identifier;
         case SyntaxKind.LockStatement:
             return ((LockStatementSyntax)statement).LockKeyword;
         case SyntaxKind.ReturnStatement:
             return ((ReturnStatementSyntax)statement).ReturnKeyword;
         case SyntaxKind.SwitchStatement:
             return ((SwitchStatementSyntax)statement).Expression.GetFirstToken();
         case SyntaxKind.ThrowStatement:
             return ((ThrowStatementSyntax)statement).ThrowKeyword;
         case SyntaxKind.TryStatement:
             return ((TryStatementSyntax)statement).TryKeyword;
         case SyntaxKind.UnsafeStatement:
             return ((UnsafeStatementSyntax)statement).UnsafeKeyword;
         case SyntaxKind.UsingStatement:
             return ((UsingStatementSyntax)statement).UsingKeyword;
         case SyntaxKind.WhileStatement:
             return ((WhileStatementSyntax)statement).WhileKeyword;
         case SyntaxKind.YieldReturnStatement:
         case SyntaxKind.YieldBreakStatement:
             return ((YieldStatementSyntax)statement).YieldKeyword;
         case SyntaxKind.LocalFunctionStatement:
             return statement.GetFirstToken();
         default:
             throw ExceptionUtilities.UnexpectedValue(statement.Kind());
     }
 }
        private static StatementSyntax ReformatStatement(Document document, StatementSyntax statement)
        {
            var indentationOptions = IndentationOptions.FromDocument(document);
            var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, GetStatementParent(statement.Parent));

            // use one additional step of indentation for lambdas / anonymous methods
            switch (statement.Parent.Kind())
            {
            case SyntaxKind.AnonymousMethodExpression:
            case SyntaxKind.SimpleLambdaExpression:
            case SyntaxKind.ParenthesizedLambdaExpression:
                parentIndentationLevel++;
                break;
            }

            var statementIndentationString = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel + 1);

            var newFirstTokenLeadingTrivia = statement.GetFirstToken().LeadingTrivia
                .WithoutTrailingWhitespace()
                .Add(SyntaxFactory.Whitespace(statementIndentationString));

            var newLastTokenTrailingTrivia = statement.GetLastToken().TrailingTrivia
                .WithoutTrailingWhitespace()
                .Add(SyntaxFactory.CarriageReturnLineFeed);

            var firstToken = statement.GetFirstToken().WithLeadingTrivia(newFirstTokenLeadingTrivia);
            var lastToken = statement.GetLastToken().WithTrailingTrivia(newLastTokenTrailingTrivia);

            return statement.ReplaceTokens(
                new[] { statement.GetFirstToken(), statement.GetLastToken() },
                (originalToken, rewrittenToken) =>
                {
                    if (originalToken == statement.GetFirstToken())
                    {
                        return firstToken;
                    }
                    else if (originalToken == statement.GetLastToken())
                    {
                        return lastToken;
                    }
                    else
                    {
                        return rewrittenToken;
                    }
                });
        }
        private static SyntaxNode ReformatStatementAndParent(Document document, SyntaxNode syntaxRoot, StatementSyntax statement)
        {
            var parentLastToken = statement.GetFirstToken().GetPreviousToken();

            var parentEndLine = parentLastToken.GetEndLine();
            var statementStartLine = statement.GetFirstToken().GetLine();

            var newParentLastToken = parentLastToken;
            if (parentEndLine == statementStartLine)
            {
                var newTrailingTrivia = parentLastToken.TrailingTrivia
                    .WithoutTrailingWhitespace()
                    .Add(SyntaxFactory.CarriageReturnLineFeed);

                newParentLastToken = newParentLastToken.WithTrailingTrivia(newTrailingTrivia);
            }

            var parentNextToken = statement.GetLastToken().GetNextToken();

            var nextTokenLine = parentNextToken.GetLine();
            var statementCloseLine = statement.GetLastToken().GetEndLine();

            var newParentNextToken = parentNextToken;
            if (nextTokenLine == statementCloseLine)
            {
                var indentationOptions = IndentationOptions.FromDocument(document);
                var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, GetStatementParent(statement.Parent));
                var indentationString = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel);
                newParentNextToken = newParentNextToken.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString));
            }

            var newStatement = ReformatStatement(document, statement);
            var newSyntaxRoot = syntaxRoot.ReplaceSyntax(
                new[] { statement },
                (originalNode, rewrittenNode) => originalNode == statement ? newStatement : rewrittenNode,
                new[] { parentLastToken, parentNextToken },
                (originalToken, rewrittenToken) =>
                {
                    if (originalToken == parentLastToken)
                    {
                        return newParentLastToken;
                    }
                    else if (originalToken == parentNextToken)
                    {
                        return newParentNextToken;
                    }
                    else
                    {
                        return rewrittenToken;
                    }
                },
                Enumerable.Empty<SyntaxTrivia>(),
                (originalTrivia, rewrittenTrivia) => rewrittenTrivia);

            return newSyntaxRoot.WithoutFormatting();
        }