/// <summary>
        /// Traverses the symbol table processing XML documentation comments and optionally writing them to
        /// a provided stream.
        /// </summary>
        /// <param name="compilation">Compilation that owns the symbol table.</param>
        /// <param name="assemblyName">Assembly name override, if specified. Otherwise the <see cref="ISymbol.Name"/> of the source assembly is used.</param>
        /// <param name="xmlDocStream">Stream to which XML will be written, if specified.</param>
        /// <param name="diagnostics">Will be supplemented with documentation comment diagnostics.</param>
        /// <param name="cancellationToken">To stop traversing the symbol table early.</param>
        /// <param name="filterTree">Only report diagnostics from this syntax tree, if non-null.</param>
        /// <param name="filterSpanWithinTree">If <paramref name="filterTree"/> and filterSpanWithinTree is non-null, report diagnostics within this span in the <paramref name="filterTree"/>.</param>
        public static void WriteDocumentationCommentXml(CSharpCompilation compilation, string assemblyName, Stream xmlDocStream, DiagnosticBag diagnostics, CancellationToken cancellationToken, SyntaxTree filterTree = null, TextSpan? filterSpanWithinTree = null)
        {
            StreamWriter writer = null;
            if (xmlDocStream != null && xmlDocStream.CanWrite)
            {
                writer = new StreamWriter(
                    stream: xmlDocStream,
                    encoding: new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false),
                    bufferSize: 0x400, // Default.
                    leaveOpen: true); // Don't close caller's stream.
            }

            using (writer)
            {
                var compiler = new DocumentationCommentCompiler(assemblyName ?? compilation.SourceAssembly.Name, compilation, writer, filterTree, filterSpanWithinTree,
                    processIncludes: true, isForSingleSymbol: false, diagnostics: diagnostics, cancellationToken: cancellationToken);
                compiler.Visit(compilation.SourceAssembly.GlobalNamespace);
                Debug.Assert(compiler._indentDepth == 0);
            }

            if (filterTree != null)
            {
                // Will respect the DocumentationMode.
                UnprocessedDocumentationCommentFinder.ReportUnprocessed(filterTree, filterSpanWithinTree, diagnostics, cancellationToken);
            }
            else
            {
                foreach (SyntaxTree tree in compilation.SyntaxTrees)
                {
                    // Will respect the DocumentationMode.
                    UnprocessedDocumentationCommentFinder.ReportUnprocessed(tree, null, diagnostics, cancellationToken);
                }
            }
        }
        /// <summary>
        /// Gets the XML that would be written to the documentation comment file for this assembly.
        /// </summary>
        /// <param name="symbol">The symbol for which to retrieve documentation comments.</param>
        /// <param name="processIncludes">True to treat includes as semantically meaningful (pull in contents from other files and bind crefs, etc).</param>
        /// <param name="cancellationToken">To stop traversing the symbol table early.</param>
        internal static string GetDocumentationCommentXml(Symbol symbol, bool processIncludes, CancellationToken cancellationToken)
        {
            Debug.Assert(
                symbol.Kind == SymbolKind.Event ||
                symbol.Kind == SymbolKind.Field ||
                symbol.Kind == SymbolKind.Method ||
                symbol.Kind == SymbolKind.NamedType ||
                symbol.Kind == SymbolKind.Property);

            CSharpCompilation compilation = symbol.DeclaringCompilation;
            Debug.Assert(compilation != null);

            PooledStringBuilder pooled = PooledStringBuilder.GetInstance();
            StringWriter writer = new StringWriter(pooled.Builder);
            DiagnosticBag discardedDiagnostics = DiagnosticBag.GetInstance();

            var compiler = new DocumentationCommentCompiler(
                assemblyName: null,
                compilation: compilation,
                writer: writer,
                filterTree: null,
                filterSpanWithinTree: null,
                processIncludes: processIncludes,
                isForSingleSymbol: true,
                diagnostics: discardedDiagnostics,
                cancellationToken: cancellationToken);
            compiler.Visit(symbol);
            Debug.Assert(compiler._indentDepth == 0);

            discardedDiagnostics.Free();
            writer.Dispose();
            return pooled.ToStringAndFree();
        }