Getting XML Documentation with Microsoft.CodeAnalysis/Roslyn

298 views Asked by At

I'm trying to to get the XML Documentation of a called method with Microsoft.CodeAnalysis, even if this method is defined in an previously compiled library.

I know how to get the XML Documentation if I have a SymbolAnalysisContext or an ISymbol. ISymbol has the Method GetDocumentationCommentXml() which return the xml string.

My Problem is, that I find no way to get an ISymbol of the called method.
I'm using an operation action to find all expression statements, thats how I get one OperationAnalysisContext for each matching expression.
At this point I'm stucked.

I'm trying to get either an SyntaxTree of the containing class/namespace or directly the symbol. But I'm not sure if this is the right way at all. The XML Documentations are stored in XML Documentation files and not in the (decompiled) assembly. Do you have any suggestions? I don't need a full solution, but some hints how to get there would be very nice.

Update:
After several days of research it seems the roslyn compiler does not care about documentation and that you have to load it manually.
Thats why I started to search for the containing assembly, loading it and using the Assembly.CodeBase property to get the path to the xmldocumentation.
Sadly there is neither a xml file containing documentation next to system assembly nor embedded (e. g. system.private.corelib). System assemblies contain an embedded xml file, but this file does not contain the documentation (root element is not doc, it is linker).

To use the Assembly.CodeBase property I had to upgrade the target framework from .netstandard1.3 to .netstandard1.5.

I updated the code example to represent my current state...

The following is an illustrative example:

Thats my Analyzer:

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class Analyzer: DiagnosticAAnalyzer
{
    private static readonly DiagnnosticDescriptor Rule; // is initialized
    
    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
    {
        get => ImmutableArray.Create(Rule);
    }

    public override void Initialize(AnalysisContext context)
    {
        context.RegisterOperationAction(AnalyzeOperation, OperationKind.ExpressionStatement);
    }
    
    private void AnalyzeOperation(OperationAnalysisContext context)
    {
        if(!(context.Operation is IExpressionStatementOperation expressionStatementOperation))
        {
            throw new InvalidOperationException();
        }

        if(!(expressionStatementOperation.Operation is IInvocationOperation invocationOperation))
        {
            throw new InvalidOperationException();
        }

        IMethodSymbol methodSymbol  = invocationOperation.TargetMethod;

        AssemblyIdentity          identity     = methodSymbol.ContainingAssembly.Identity;
        AssemblyName assemblyName = new AssemblyName
                                    {
                                        Name        = identity.Name,
                                        Version     = identity.Version,
                                        Flags       = identity.Flags,
                                        ContentType = identity.ContentType
                                    };

        Assembly assembly = Assembly.Load(assemblyName);
    }
}

Thats a analysed document:

using System.IO;

namespace myProject
{
    public class MyClass
    {
        public void MyMethod(StreamReader reader)
        {
            reader.ReadToEnd();
        }
    }
}

I'm trying to get the whole XML Documentation of `StreamReader.ReadToEnd()

Edit:
Just now I found the class XmlDocumentationProvider which has two static methods to get an instance either by passing an file or byte, but I don't know how I could use it to achieve my goal...

0

There are 0 answers