Beispiel #1
0
        private static void BuildReplaceMapForNamespaces(UsingsSorter usingsHelper, Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax> replaceMap, IndentationSettings indentationSettings, bool qualifyNames)
        {
            var usingsPerNamespace = usingsHelper
                                     .GetContainedUsings(TreeTextSpan.Empty)
                                     .GroupBy(ud => ud.Parent)
                                     .Select(gr => gr.ToList());

            foreach (var usingList in usingsPerNamespace)
            {
                if (usingList.Count > 0)
                {
                    // sort the original using declarations on Span.Start, in order to have the correct replace mapping.
                    usingList.Sort(CompareSpanStart);

                    var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, usingList[0].Parent);
                    if (usingList[0].Parent is NamespaceDeclarationSyntax)
                    {
                        indentationSteps++;
                    }

                    var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps);

                    var modifiedUsings = usingsHelper.GenerateGroupedUsings(usingList, indentation, false, qualifyNames);

                    for (var i = 0; i < usingList.Count; i++)
                    {
                        replaceMap.Add(usingList[i], modifiedUsings[i]);
                    }
                }
            }
        }
Beispiel #2
0
        private static void BuildReplaceMapForConditionalDirectives(UsingsSorter usingsHelper, Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax> replaceMap, IndentationSettings indentationSettings, TreeTextSpan rootSpan)
        {
            foreach (var childSpan in rootSpan.Children)
            {
                var originalUsings = usingsHelper.GetContainedUsings(childSpan);
                if (originalUsings.Count > 0)
                {
                    // sort the original using declarations on Span.Start, in order to have the correct replace mapping.
                    originalUsings.Sort(CompareSpanStart);

                    var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, originalUsings[0].Parent);
                    if (originalUsings[0].Parent is NamespaceDeclarationSyntax)
                    {
                        indentationSteps++;
                    }

                    var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps);

                    var modifiedUsings = usingsHelper.GenerateGroupedUsings(childSpan, indentation, false, qualifyNames: false);

                    for (var i = 0; i < originalUsings.Count; i++)
                    {
                        replaceMap.Add(originalUsings[i], modifiedUsings[i]);
                    }
                }

                BuildReplaceMapForConditionalDirectives(usingsHelper, replaceMap, indentationSettings, childSpan);
            }
        }
Beispiel #3
0
        private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            SyntaxToken originalToken = root.FindToken(diagnostic.Location.SourceSpan.Start);

            SyntaxTree tree       = root.SyntaxTree;
            SourceText sourceText = await tree.GetTextAsync(cancellationToken).ConfigureAwait(false);

            TextLine sourceLine = sourceText.Lines.GetLineFromPosition(originalToken.SpanStart);

            string lineText = sourceText.ToString(sourceLine.Span);
            int    indentLength;

            for (indentLength = 0; indentLength < lineText.Length; indentLength++)
            {
                if (!char.IsWhiteSpace(lineText[indentLength]))
                {
                    break;
                }
            }

            var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken);
            SyntaxTriviaList newTrivia =
                SyntaxFactory.TriviaList(
                    SyntaxFactory.CarriageReturnLineFeed,
                    SyntaxFactory.Whitespace(lineText.Substring(0, indentLength) + IndentationHelper.GenerateIndentationString(settings.Indentation, 1)));

            SyntaxToken updatedToken = originalToken.WithLeadingTrivia(originalToken.LeadingTrivia.AddRange(newTrivia));
            SyntaxNode  updatedRoot  = root.ReplaceToken(originalToken, updatedToken);

            return(document.WithSyntaxRoot(updatedRoot));
        }
Beispiel #4
0
        private BlockSyntax ReformatBlock(CodeFixContext context, BlockSyntax block)
        {
            var indentationOptions     = IndentationOptions.FromDocument(context.Document);
            var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, block.Parent);

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

            var newOpenBraceLeadingTrivia = block.OpenBraceToken.LeadingTrivia
                                            .WithoutTrailingWhitespace()
                                            .Add(SyntaxFactory.Whitespace(indentationString));

            var newOpenBraceTrailingTrivia = block.OpenBraceToken.TrailingTrivia
                                             .WithoutTrailingWhitespace()
                                             .Add(SyntaxFactory.CarriageReturnLineFeed);

            var newCloseBraceLeadingTrivia = block.CloseBraceToken.LeadingTrivia
                                             .WithoutTrailingWhitespace()
                                             .Add(SyntaxFactory.Whitespace(indentationString));

            var newCloseBraceTrailingTrivia = block.CloseBraceToken.TrailingTrivia
                                              .WithoutTrailingWhitespace();

            // only add an end-of-line to the close brace if there is none yet.
            if ((newCloseBraceTrailingTrivia.Count == 0) || !newCloseBraceTrailingTrivia.Last().IsKind(SyntaxKind.EndOfLineTrivia))
            {
                newCloseBraceTrailingTrivia = newCloseBraceTrailingTrivia.Add(SyntaxFactory.CarriageReturnLineFeed);
            }

            var openBraceToken = SyntaxFactory.Token(SyntaxKind.OpenBraceToken)
                                 .WithLeadingTrivia(newOpenBraceLeadingTrivia)
                                 .WithTrailingTrivia(newOpenBraceTrailingTrivia);

            var closeBraceToken = SyntaxFactory.Token(SyntaxKind.CloseBraceToken)
                                  .WithLeadingTrivia(newCloseBraceLeadingTrivia)
                                  .WithTrailingTrivia(newCloseBraceTrailingTrivia);

            var statements = SyntaxFactory.List <StatementSyntax>();

            foreach (var statement in block.Statements)
            {
                var newLeadingTrivia = statement.GetLeadingTrivia()
                                       .WithoutTrailingWhitespace()
                                       .Add(SyntaxFactory.Whitespace(statementIndentationString));

                var newTrailingTrivia = statement.GetTrailingTrivia()
                                        .WithoutTrailingWhitespace()
                                        .Add(SyntaxFactory.CarriageReturnLineFeed);

                var modifiedStatement = statement
                                        .WithLeadingTrivia(newLeadingTrivia)
                                        .WithTrailingTrivia(newTrailingTrivia);

                statements = statements.Add(modifiedStatement);
            }

            return(SyntaxFactory.Block(openBraceToken, statements, closeBraceToken));
        }
Beispiel #5
0
        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());
        }
Beispiel #6
0
        private static string DetermineIndentation(CompilationUnitSyntax compilationUnit, IndentationSettings indentationSettings, UsingDirectivesPlacement usingDirectivesPlacement)
        {
            string usingsIndentation;

            if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace)
            {
                var rootNamespace    = compilationUnit.Members.OfType <NamespaceDeclarationSyntax>().First();
                var indentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, rootNamespace);
                usingsIndentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationLevel + 1);
            }
            else
            {
                usingsIndentation = string.Empty;
            }

            return(usingsIndentation);
        }
Beispiel #7
0
        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 string DetermineIndentation(CompilationUnitSyntax compilationUnit, IndentationSettings indentationSettings, UsingDirectivesPlacement usingDirectivesPlacement)
        {
            string usingsIndentation;

            if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace)
            {
                var rootNamespace    = compilationUnit.Members.First(member => BaseNamespaceDeclarationSyntaxWrapper.IsInstance(member));
                var indentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, rootNamespace);
                if (!rootNamespace.IsKind(SyntaxKindEx.FileScopedNamespaceDeclaration))
                {
                    indentationLevel++;
                }

                usingsIndentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationLevel);
            }
            else
            {
                usingsIndentation = string.Empty;
            }

            return(usingsIndentation);
        }
        private static SyntaxNode MoveMember(SyntaxNode syntaxRoot, MemberDeclarationSyntax member, MemberDeclarationSyntax targetMember, IndentationSettings indentationSettings)
        {
            var firstToken = syntaxRoot.GetFirstToken();
            var fileHeader = GetFileHeader(firstToken.LeadingTrivia);

            syntaxRoot = syntaxRoot.TrackNodes(member, targetMember, firstToken.Parent);
            var memberToMove        = syntaxRoot.GetCurrentNode(member);
            var targetMemberTracked = syntaxRoot.GetCurrentNode(targetMember);

            if (!memberToMove.HasLeadingTrivia)
            {
                var targetIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, targetMember);
                var indentationString      = IndentationHelper.GenerateIndentationString(indentationSettings, targetIndentationLevel);
                memberToMove = memberToMove.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString));
            }

            if (!HasLeadingBlankLines(targetMember) &&
                HasLeadingBlankLines(member))
            {
                memberToMove = memberToMove.WithTrailingTrivia(memberToMove.GetTrailingTrivia().Add(SyntaxFactory.CarriageReturnLineFeed));
                memberToMove = memberToMove.WithLeadingTrivia(GetLeadingTriviaWithoutLeadingBlankLines(memberToMove));
            }

            syntaxRoot = syntaxRoot.InsertNodesBefore(targetMemberTracked, new[] { memberToMove });
            var fieldToMoveTracked = syntaxRoot.GetCurrentNodes(member).Last();

            syntaxRoot = syntaxRoot.RemoveNode(fieldToMoveTracked, SyntaxRemoveOptions.KeepNoTrivia);
            if (fileHeader.Any())
            {
                var oldFirstToken = syntaxRoot.GetCurrentNode(firstToken.Parent).ChildTokens().First();
                syntaxRoot = syntaxRoot.ReplaceToken(oldFirstToken, oldFirstToken.WithLeadingTrivia(StripFileHeader(oldFirstToken.LeadingTrivia)));
                var newFirstToken = syntaxRoot.GetFirstToken();
                syntaxRoot = syntaxRoot.ReplaceToken(newFirstToken, newFirstToken.WithLeadingTrivia(fileHeader.AddRange(newFirstToken.LeadingTrivia)));
            }

            return(syntaxRoot);
        }
Beispiel #10
0
        private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var whereToken     = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start);
            var precedingToken = whereToken.GetPreviousToken();
            var endToken       = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.End);
            var afterEndToken  = endToken.GetNextToken();

            var parentIndentation  = GetParentIndentation(whereToken);
            var indentationOptions = IndentationOptions.FromDocument(document);
            var indentationTrivia  = SyntaxFactory.Whitespace(parentIndentation + IndentationHelper.GenerateIndentationString(indentationOptions, 1));

            var replaceMap = new Dictionary <SyntaxToken, SyntaxToken>()
            {
                [precedingToken] = precedingToken.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed),
                [whereToken]     = whereToken.WithLeadingTrivia(indentationTrivia),
                [endToken]       = endToken.WithTrailingTrivia(RemoveUnnecessaryWhitespaceTrivia(endToken).Add(SyntaxFactory.CarriageReturnLineFeed)),
            };

            if (afterEndToken.IsKind(SyntaxKind.EqualsGreaterThanToken))
            {
                replaceMap.Add(afterEndToken, afterEndToken.WithLeadingTrivia(indentationTrivia));
            }
            else if (afterEndToken.IsKind(SyntaxKind.OpenBraceToken))
            {
                replaceMap.Add(afterEndToken, afterEndToken.WithLeadingTrivia(SyntaxFactory.Whitespace(parentIndentation)));
            }
            else if (afterEndToken.IsKind(SyntaxKind.WhereKeyword))
            {
                replaceMap.Add(afterEndToken, afterEndToken.WithLeadingTrivia(indentationTrivia));
            }

            var newSyntaxRoot = syntaxRoot.ReplaceTokens(replaceMap.Keys, (t1, t2) => replaceMap[t1]).WithoutFormatting();

            return(document.WithSyntaxRoot(newSyntaxRoot));
        }
        private SyntaxNode ReformatElement(SyntaxNode syntaxRoot, SyntaxNode element, SyntaxToken openBraceToken, SyntaxToken closeBraceToken, IndentationOptions indentationOptions)
        {
            var tokenSubstitutions = new Dictionary <SyntaxToken, SyntaxToken>();

            var parentLastToken = openBraceToken.GetPreviousToken();
            var parentEndLine   = parentLastToken.GetLineSpan().EndLinePosition.Line;
            var blockStartLine  = openBraceToken.GetLineSpan().StartLinePosition.Line;

            // reformat parent if it is on the same line as the block.
            if (parentEndLine == blockStartLine)
            {
                var newTrailingTrivia = parentLastToken.TrailingTrivia
                                        .WithoutTrailingWhitespace()
                                        .Add(SyntaxFactory.CarriageReturnLineFeed);

                tokenSubstitutions.Add(parentLastToken, parentLastToken.WithTrailingTrivia(newTrailingTrivia));
            }

            var parentIndentationLevel   = IndentationHelper.GetIndentationSteps(indentationOptions, element);
            var indentationString        = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel);
            var contentIndentationString = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel + 1);

            // reformat opening brace
            tokenSubstitutions.Add(openBraceToken, this.FormatBraceToken(openBraceToken, indentationString));

            // reformat start of content
            var startOfContentToken = openBraceToken.GetNextToken();

            if (startOfContentToken != closeBraceToken)
            {
                var newStartOfContentTokenLeadingTrivia = startOfContentToken.LeadingTrivia
                                                          .WithoutTrailingWhitespace()
                                                          .Add(SyntaxFactory.Whitespace(contentIndentationString));

                tokenSubstitutions.Add(startOfContentToken, startOfContentToken.WithLeadingTrivia(newStartOfContentTokenLeadingTrivia));
            }

            // reformat end of content
            var endOfContentToken = closeBraceToken.GetPreviousToken();

            if (endOfContentToken != openBraceToken)
            {
                var newEndOfContentTokenTrailingTrivia = endOfContentToken.TrailingTrivia
                                                         .WithoutTrailingWhitespace()
                                                         .Add(SyntaxFactory.CarriageReturnLineFeed);

                // check if the token already exists (occurs when there is only one token in the block)
                if (tokenSubstitutions.ContainsKey(endOfContentToken))
                {
                    tokenSubstitutions[endOfContentToken] = tokenSubstitutions[endOfContentToken].WithTrailingTrivia(newEndOfContentTokenTrailingTrivia);
                }
                else
                {
                    tokenSubstitutions.Add(endOfContentToken, endOfContentToken.WithTrailingTrivia(newEndOfContentTokenTrailingTrivia));
                }
            }

            // reformat closing brace
            tokenSubstitutions.Add(closeBraceToken, this.FormatBraceToken(closeBraceToken, indentationString));

            var rewriter      = new TokenRewriter(tokenSubstitutions);
            var newSyntaxRoot = rewriter.Visit(syntaxRoot);

            return(newSyntaxRoot);
        }
        private static async Task <Document> GetTransformedDocumentAsync(Document document, SyntaxNode syntaxRoot, CancellationToken cancellationToken)
        {
            var fileHeader      = GetFileHeader(syntaxRoot);
            var compilationUnit = (CompilationUnitSyntax)syntaxRoot;

            var settings      = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken);
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var indentationOptions = IndentationOptions.FromDocument(document);

            var usingsHelper   = new UsingsHelper(settings, semanticModel, compilationUnit, fileHeader);
            var namespaceCount = CountNamespaces(compilationUnit.Members);

            // Only move using declarations inside the namespace when
            // - There are no global attributes
            // - There is only a single namespace declared at the top level
            // - OrderingSettings.UsingDirectivesPlacement is set to InsideNamespace
            UsingDirectivesPlacement usingDirectivesPlacement;

            switch (settings.OrderingRules.UsingDirectivesPlacement)
            {
            case UsingDirectivesPlacement.InsideNamespace:
                if (compilationUnit.AttributeLists.Any() ||
                    compilationUnit.Members.Count > 1 ||
                    namespaceCount > 1)
                {
                    // Override the user's setting with a more conservative one
                    usingDirectivesPlacement = UsingDirectivesPlacement.Preserve;
                }
                else if (namespaceCount == 0)
                {
                    usingDirectivesPlacement = UsingDirectivesPlacement.OutsideNamespace;
                }
                else
                {
                    usingDirectivesPlacement = UsingDirectivesPlacement.InsideNamespace;
                }

                break;

            case UsingDirectivesPlacement.OutsideNamespace:
                usingDirectivesPlacement = UsingDirectivesPlacement.OutsideNamespace;
                break;

            case UsingDirectivesPlacement.Preserve:
            default:
                usingDirectivesPlacement = UsingDirectivesPlacement.Preserve;
                break;
            }

            string usingsIndentation;

            if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace)
            {
                var rootNamespace    = compilationUnit.Members.OfType <NamespaceDeclarationSyntax>().First();
                var indentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, rootNamespace);
                usingsIndentation = IndentationHelper.GenerateIndentationString(indentationOptions, indentationLevel + 1);
            }
            else
            {
                usingsIndentation = string.Empty;
            }

            // - The strategy is to strip all using directive that are not inside a conditional directive and replace them later with a sorted list at the correct spot
            // - The using directives that are inside a conditional directive are replaced (in sorted order) on the spot.
            // - Conditional directives are not moved, as correctly parsing them is too tricky
            // - No using directives will be stripped when there are multiple namespaces. In that case everything is replaced on the spot.
            List <UsingDirectiveSyntax> stripList;
            var replaceMap = new Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax>();

            // When there are multiple namespaces, do not move using statements outside of them, only sort.
            if (usingDirectivesPlacement == UsingDirectivesPlacement.Preserve)
            {
                BuildReplaceMapForNamespaces(usingsHelper, replaceMap, indentationOptions, false);
                stripList = new List <UsingDirectiveSyntax>();
            }
            else
            {
                stripList = usingsHelper.GetContainedUsings(usingsHelper.RootSpan);
            }

            BuildReplaceMapForConditionalDirectives(usingsHelper, replaceMap, indentationOptions, usingsHelper.RootSpan);

            var usingSyntaxRewriter = new UsingSyntaxRewriter(stripList, replaceMap, fileHeader);
            var newSyntaxRoot       = usingSyntaxRewriter.Visit(syntaxRoot);

            if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace)
            {
                newSyntaxRoot = AddUsingsToNamespace(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any());
            }
            else if (usingDirectivesPlacement == UsingDirectivesPlacement.OutsideNamespace)
            {
                newSyntaxRoot = AddUsingsToCompilationRoot(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any());
            }

            // Final cleanup
            newSyntaxRoot = StripMultipleBlankLines(newSyntaxRoot);
            newSyntaxRoot = ReAddFileHeader(newSyntaxRoot, fileHeader);

            var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting());

            return(newDocument);
        }
        private static void ReformatBlock(IndentationSettings indentationSettings, BlockSyntax block, Dictionary <SyntaxToken, SyntaxToken> tokenReplaceMap)
        {
            var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, GetStatementParent(block.Parent));

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

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

            var newOpenBraceLeadingTrivia = block.OpenBraceToken.LeadingTrivia
                                            .WithoutTrailingWhitespace()
                                            .Add(SyntaxFactory.Whitespace(indentationString));

            var newOpenBraceTrailingTrivia = block.OpenBraceToken.TrailingTrivia
                                             .WithoutTrailingWhitespace()
                                             .Add(SyntaxFactory.CarriageReturnLineFeed);

            var newCloseBraceLeadingTrivia = block.CloseBraceToken.LeadingTrivia
                                             .WithoutTrailingWhitespace()
                                             .Add(SyntaxFactory.Whitespace(indentationString));

            var newCloseBraceTrailingTrivia = block.CloseBraceToken.TrailingTrivia
                                              .WithoutTrailingWhitespace();

            bool addNewLineAfterCloseBrace;

            switch (block.CloseBraceToken.GetNextToken().Kind())
            {
            case SyntaxKind.CloseParenToken:
            case SyntaxKind.CommaToken:
            case SyntaxKind.SemicolonToken:
                addNewLineAfterCloseBrace = false;
                break;

            default:
                addNewLineAfterCloseBrace = (newCloseBraceTrailingTrivia.Count == 0) || !newCloseBraceTrailingTrivia.Last().IsKind(SyntaxKind.EndOfLineTrivia);
                break;
            }

            if (addNewLineAfterCloseBrace)
            {
                newCloseBraceTrailingTrivia = newCloseBraceTrailingTrivia.Add(SyntaxFactory.CarriageReturnLineFeed);
            }

            AddToReplaceMap(tokenReplaceMap, block.OpenBraceToken, block.OpenBraceToken.WithLeadingTrivia(newOpenBraceLeadingTrivia).WithTrailingTrivia(newOpenBraceTrailingTrivia));
            AddToReplaceMap(tokenReplaceMap, block.CloseBraceToken, block.CloseBraceToken.WithLeadingTrivia(newCloseBraceLeadingTrivia).WithTrailingTrivia(newCloseBraceTrailingTrivia));

            foreach (var statement in block.Statements)
            {
                var firstToken = statement.GetFirstToken();
                var lastToken  = statement.GetLastToken();

                var newLeadingTrivia = firstToken.LeadingTrivia
                                       .WithoutTrailingWhitespace()
                                       .Add(SyntaxFactory.Whitespace(statementIndentationString));

                var newTrailingTrivia = lastToken.TrailingTrivia
                                        .WithoutTrailingWhitespace()
                                        .Add(SyntaxFactory.CarriageReturnLineFeed);

                AddToReplaceMap(tokenReplaceMap, firstToken, firstToken.WithLeadingTrivia(newLeadingTrivia));
                AddToReplaceMap(tokenReplaceMap, lastToken, lastToken.WithTrailingTrivia(newTrailingTrivia));
            }
        }
        private static BlockSyntax ReformatBlock(Document document, IndentationSettings indentationSettings, BlockSyntax block)
        {
            var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationSettings, GetStatementParent(block.Parent));

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

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

            var newOpenBraceLeadingTrivia = block.OpenBraceToken.LeadingTrivia
                                            .WithoutTrailingWhitespace()
                                            .Add(SyntaxFactory.Whitespace(indentationString));

            var newOpenBraceTrailingTrivia = block.OpenBraceToken.TrailingTrivia
                                             .WithoutTrailingWhitespace()
                                             .Add(SyntaxFactory.CarriageReturnLineFeed);

            var newCloseBraceLeadingTrivia = block.CloseBraceToken.LeadingTrivia
                                             .WithoutTrailingWhitespace()
                                             .Add(SyntaxFactory.Whitespace(indentationString));

            var newCloseBraceTrailingTrivia = block.CloseBraceToken.TrailingTrivia
                                              .WithoutTrailingWhitespace();

            bool addNewLineAfterCloseBrace;

            switch (block.CloseBraceToken.GetNextToken().Kind())
            {
            case SyntaxKind.CloseParenToken:
            case SyntaxKind.CommaToken:
            case SyntaxKind.SemicolonToken:
                addNewLineAfterCloseBrace = false;
                break;

            default:
                addNewLineAfterCloseBrace = (newCloseBraceTrailingTrivia.Count == 0) || !newCloseBraceTrailingTrivia.Last().IsKind(SyntaxKind.EndOfLineTrivia);
                break;
            }

            if (addNewLineAfterCloseBrace)
            {
                newCloseBraceTrailingTrivia = newCloseBraceTrailingTrivia.Add(SyntaxFactory.CarriageReturnLineFeed);
            }

            var openBraceToken = SyntaxFactory.Token(SyntaxKind.OpenBraceToken)
                                 .WithLeadingTrivia(newOpenBraceLeadingTrivia)
                                 .WithTrailingTrivia(newOpenBraceTrailingTrivia);

            var closeBraceToken = SyntaxFactory.Token(SyntaxKind.CloseBraceToken)
                                  .WithLeadingTrivia(newCloseBraceLeadingTrivia)
                                  .WithTrailingTrivia(newCloseBraceTrailingTrivia);

            var statements = SyntaxFactory.List <StatementSyntax>();

            foreach (var statement in block.Statements)
            {
                var newLeadingTrivia = statement.GetLeadingTrivia()
                                       .WithoutTrailingWhitespace()
                                       .Add(SyntaxFactory.Whitespace(statementIndentationString));

                var newTrailingTrivia = statement.GetTrailingTrivia()
                                        .WithoutTrailingWhitespace()
                                        .Add(SyntaxFactory.CarriageReturnLineFeed);

                var modifiedStatement = statement
                                        .WithLeadingTrivia(newLeadingTrivia)
                                        .WithTrailingTrivia(newTrailingTrivia);

                statements = statements.Add(modifiedStatement);
            }

            return(SyntaxFactory.Block(openBraceToken, statements, closeBraceToken));
        }
        private static Task <Document> GetTransformedDocumentAsync(Document document, SyntaxNode syntaxRoot, CancellationToken cancellationToken)
        {
            var compilationUnit = (CompilationUnitSyntax)syntaxRoot;

            var indentationOptions = IndentationOptions.FromDocument(document);

            var usingsHelper   = new UsingsHelper(document, compilationUnit);
            var namespaceCount = CountNamespaces(compilationUnit.Members);

            // Only move using declarations inside the namespace when
            // - SA1200 is enabled
            // - There are no global attributes
            // - There is only a single namespace declared at the top level
            var moveInsideNamespace =
                !document.Project.CompilationOptions.IsAnalyzerSuppressed(SA1200UsingDirectivesMustBePlacedWithinNamespace.DiagnosticId) &&
                !compilationUnit.AttributeLists.Any() &&
                compilationUnit.Members.Count == 1 &&
                namespaceCount == 1;

            string usingsIndentation;

            if (moveInsideNamespace)
            {
                var rootNamespace    = compilationUnit.Members.OfType <NamespaceDeclarationSyntax>().First();
                var indentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, rootNamespace);
                usingsIndentation = IndentationHelper.GenerateIndentationString(indentationOptions, indentationLevel + 1);
            }
            else
            {
                usingsIndentation = string.Empty;
            }

            // - The strategy is to strip all using directive that are not inside a conditional directive and replace them later with a sorted list at the correct spot
            // - The using directives that are inside a conditional directive are replaced (in sorted order) on the spot.
            // - Conditional directives are not moved, as correctly parsing them is too tricky
            // - No using directives will be stripped when there are multiple namespaces. In that case everything is replaced on the spot.
            List <UsingDirectiveSyntax> stripList;
            var replaceMap = new Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax>();

            // When there are multiple namespaces, do not move using statements outside of them, only sort.
            if (namespaceCount > 1)
            {
                BuildReplaceMapForNamespaces(usingsHelper, replaceMap, indentationOptions);
                stripList = new List <UsingDirectiveSyntax>();
            }
            else
            {
                stripList = usingsHelper.GetContainedUsings(usingsHelper.RootSpan);
            }

            BuildReplaceMapForConditionalDirectives(usingsHelper, replaceMap, indentationOptions, usingsHelper.RootSpan);

            var usingSyntaxRewriter = new UsingSyntaxRewriter(stripList, replaceMap);
            var newSyntaxRoot       = usingSyntaxRewriter.Visit(syntaxRoot);

            if (moveInsideNamespace)
            {
                newSyntaxRoot = AddUsingsToNamespace(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any());
            }
            else if (namespaceCount <= 1)
            {
                newSyntaxRoot = AddUsingsToCompilationRoot(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any());
            }

            newSyntaxRoot = ReAddFileHeader(syntaxRoot, newSyntaxRoot);

            var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting());

            return(Task.FromResult(newDocument));
        }