/// <summary>
        /// Creates a new document with preprocessor directives of the specified kind removed.
        /// </summary>
        /// <param name="document"></param>
        /// <param name="directiveFilter"></param>
        /// <param name="cancellationToken"></param>
        public static async Task <Document> RemovePreprocessorDirectivesAsync(
            this Document document,
            PreprocessorDirectiveFilter directiveFilter,
            CancellationToken cancellationToken = default)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            SourceText newSourceText = RemovePreprocessorDirectives(sourceText, root.DescendantPreprocessorDirectives(), directiveFilter);

            return(document.WithText(newSourceText));
        }
        private static SourceText RemovePreprocessorDirectives(
            SourceText sourceText,
            IEnumerable <DirectiveTriviaSyntax> directives,
            PreprocessorDirectiveFilter directiveFilter)
        {
            return(sourceText.WithChanges(GetTextChanges()));

            IEnumerable <TextChange> GetTextChanges()
            {
                TextLineCollection lines = sourceText.Lines;

                foreach (DirectiveTriviaSyntax directive in directives)
                {
                    if (ShouldRemoveDirective(directive))
                    {
                        int startLine = directive.GetSpanStartLine();

                        yield return(new TextChange(lines[startLine].SpanIncludingLineBreak, ""));
                    }
                }
            }

            bool ShouldRemoveDirective(DirectiveTriviaSyntax directive)
            {
                switch (directive.Kind())
                {
                case SyntaxKind.IfDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.If) != 0);

                case SyntaxKind.ElifDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Elif) != 0);

                case SyntaxKind.ElseDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Else) != 0);

                case SyntaxKind.EndIfDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.EndIf) != 0);

                case SyntaxKind.RegionDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Region) != 0);

                case SyntaxKind.EndRegionDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.EndRegion) != 0);

                case SyntaxKind.DefineDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Define) != 0);

                case SyntaxKind.UndefDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Undef) != 0);

                case SyntaxKind.ErrorDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Error) != 0);

                case SyntaxKind.WarningDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Warning) != 0);

                case SyntaxKind.LineDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Line) != 0);

                case SyntaxKind.PragmaWarningDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.PragmaWarning) != 0);

                case SyntaxKind.PragmaChecksumDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.PragmaChecksum) != 0);

                case SyntaxKind.ReferenceDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Reference) != 0);

                case SyntaxKind.BadDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Bad) != 0);

                case SyntaxKind.ShebangDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Shebang) != 0);

                case SyntaxKind.LoadDirectiveTrivia:
                    return((directiveFilter & PreprocessorDirectiveFilter.Load) != 0);
                }

                Debug.Fail(directive.Kind().ToString());
                return(false);
            }
        }