从 MetadataReference 获取 ISymbol 的文档
Fetching documentation of ISymbol from MetadataReference
我最近开始学习 Roslyn 代码分析。我浏览了提供的示例代码。我的问题如下:
有没有办法获取 XML 从引用库加载的符号的文档注释?
我使用的示例代码是 FAQ(7)
。目标是获取 Console.Write
函数的文档注释。
public void GetWriteXmlComment()
{
var project1Id = ProjectId.CreateNewId();
var document1Id = DocumentId.CreateNewId(project1Id);
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var solution = new AdhocWorkspace().CurrentSolution
.AddProject(project1Id, "Project1", "Project1", LanguageNames.CSharp)
.AddMetadataReference(project1Id, mscorlib);
var declarations = SymbolFinder.FindDeclarationsAsync(solution.Projects.First(), "Write", true).Result;
var decFirst = declarations.First();
var commentXml = decFirst.GetDocumentationCommentXml();
}
示例代码适用于某些方法 - 它获取文档文本。但是对于方法,例如 Console.Write
,它使用 NullDocumentationProvider
,因此 returns 空字符串。
更新
我发现我可以使用 TestDocumentationProvider
实例加载 MetadataReference
,如下所示:
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location,
default(MetadataReferenceProperties), new TestDocumentationProvider());
其中 TestDocumentationProvider
实现 Microsoft.CodeAnalysis DocumentationProvider
抽象 class。
private class TestDocumentationProvider : DocumentationProvider
{
protected override string GetDocumentationForSymbol(string documentationMemberID, CultureInfo preferredCulture, CancellationToken cancellationToken = default(CancellationToken))
{
// To-Be-Done
}
}
现在问题缩小到如何使用documentationMemberID
阅读文档?
更新:在 Roslyn 2.0 中,您可以使用 XmlDocumentationProvider.CreateFromFile
。
我能想到的唯一方法是使用反射创建一个 FileBasedXmlDocumentationProvider
(或者从 GitHub 复制它的实现)。您还需要搜索参考程序集,因为框架程序集的加载位置不包含文档。
private static MetadataReference FromType(Type type)
{
var path = type.Assembly.Location;
return MetadataReference.CreateFromFile(path, documentation: GetDocumentationProvider(path));
}
private static string GetReferenceAssembliesPath()
{
var programFiles =
Environment.GetFolderPath(Environment.Is64BitOperatingSystem
? Environment.SpecialFolder.ProgramFilesX86
: Environment.SpecialFolder.ProgramFiles);
var path = Path.Combine(programFiles, @"Reference Assemblies\Microsoft\Framework\.NETFramework");
if (Directory.Exists(path))
{
var directories = Directory.EnumerateDirectories(path).OrderByDescending(Path.GetFileName);
return directories.FirstOrDefault();
}
return null;
}
private static DocumentationProvider GetDocumentationProvider(string location)
{
var referenceLocation = Path.ChangeExtension(location, "xml");
if (File.Exists(referenceLocation))
{
return GetXmlDocumentationProvider(referenceLocation);
}
var referenceAssembliesPath = GetReferenceAssembliesPath();
if (referenceAssembliesPath != null)
{
var fileName = Path.GetFileName(location);
referenceLocation = Path.ChangeExtension(Path.Combine(referenceAssembliesPath, fileName), "xml");
if (File.Exists(referenceLocation))
{
return GetXmlDocumentationProvider(referenceLocation);
}
}
return null;
}
private static DocumentationProvider GetXmlDocumentationProvider(string location)
{
return (DocumentationProvider)Activator.CreateInstance(Type.GetType(
"Microsoft.CodeAnalysis.FileBasedXmlDocumentationProvider, Microsoft.CodeAnalysis.Workspaces.Desktop"),
location);
}
我在 RoslynPad 中使用过类似的东西。
我最近开始学习 Roslyn 代码分析。我浏览了提供的示例代码。我的问题如下:
有没有办法获取 XML 从引用库加载的符号的文档注释?
我使用的示例代码是 FAQ(7)
。目标是获取 Console.Write
函数的文档注释。
public void GetWriteXmlComment()
{
var project1Id = ProjectId.CreateNewId();
var document1Id = DocumentId.CreateNewId(project1Id);
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var solution = new AdhocWorkspace().CurrentSolution
.AddProject(project1Id, "Project1", "Project1", LanguageNames.CSharp)
.AddMetadataReference(project1Id, mscorlib);
var declarations = SymbolFinder.FindDeclarationsAsync(solution.Projects.First(), "Write", true).Result;
var decFirst = declarations.First();
var commentXml = decFirst.GetDocumentationCommentXml();
}
示例代码适用于某些方法 - 它获取文档文本。但是对于方法,例如 Console.Write
,它使用 NullDocumentationProvider
,因此 returns 空字符串。
更新
我发现我可以使用 TestDocumentationProvider
实例加载 MetadataReference
,如下所示:
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location,
default(MetadataReferenceProperties), new TestDocumentationProvider());
其中 TestDocumentationProvider
实现 Microsoft.CodeAnalysis DocumentationProvider
抽象 class。
private class TestDocumentationProvider : DocumentationProvider
{
protected override string GetDocumentationForSymbol(string documentationMemberID, CultureInfo preferredCulture, CancellationToken cancellationToken = default(CancellationToken))
{
// To-Be-Done
}
}
现在问题缩小到如何使用documentationMemberID
阅读文档?
更新:在 Roslyn 2.0 中,您可以使用 XmlDocumentationProvider.CreateFromFile
。
我能想到的唯一方法是使用反射创建一个 FileBasedXmlDocumentationProvider
(或者从 GitHub 复制它的实现)。您还需要搜索参考程序集,因为框架程序集的加载位置不包含文档。
private static MetadataReference FromType(Type type)
{
var path = type.Assembly.Location;
return MetadataReference.CreateFromFile(path, documentation: GetDocumentationProvider(path));
}
private static string GetReferenceAssembliesPath()
{
var programFiles =
Environment.GetFolderPath(Environment.Is64BitOperatingSystem
? Environment.SpecialFolder.ProgramFilesX86
: Environment.SpecialFolder.ProgramFiles);
var path = Path.Combine(programFiles, @"Reference Assemblies\Microsoft\Framework\.NETFramework");
if (Directory.Exists(path))
{
var directories = Directory.EnumerateDirectories(path).OrderByDescending(Path.GetFileName);
return directories.FirstOrDefault();
}
return null;
}
private static DocumentationProvider GetDocumentationProvider(string location)
{
var referenceLocation = Path.ChangeExtension(location, "xml");
if (File.Exists(referenceLocation))
{
return GetXmlDocumentationProvider(referenceLocation);
}
var referenceAssembliesPath = GetReferenceAssembliesPath();
if (referenceAssembliesPath != null)
{
var fileName = Path.GetFileName(location);
referenceLocation = Path.ChangeExtension(Path.Combine(referenceAssembliesPath, fileName), "xml");
if (File.Exists(referenceLocation))
{
return GetXmlDocumentationProvider(referenceLocation);
}
}
return null;
}
private static DocumentationProvider GetXmlDocumentationProvider(string location)
{
return (DocumentationProvider)Activator.CreateInstance(Type.GetType(
"Microsoft.CodeAnalysis.FileBasedXmlDocumentationProvider, Microsoft.CodeAnalysis.Workspaces.Desktop"),
location);
}
我在 RoslynPad 中使用过类似的东西。