/// <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(); }