private static Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode syntaxRoot, CancellationToken cancellationToken)
        {
            var compilationUnit = (CompilationUnitSyntax)syntaxRoot;

            var indentationOptions = IndentationOptions.FromDocument(document);

            var usingsHelper = new UsingsHelper(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.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);
        }
            public UsingsHelper(Document document, CompilationUnitSyntax compilationUnit)
            {
                this.conditionalDirectiveTree = DirectiveSpan.BuildConditionalDirectiveTree(compilationUnit);
                this.separateSystemDirectives = !document.IsAnalyzerSuppressed(SA1208SystemUsingDirectivesMustBePlacedBeforeOtherUsingDirectives.DiagnosticId);

                this.ProcessUsingDirectives(compilationUnit.Usings);
                this.ProcessMembers(compilationUnit.Members);
            }