From 94d21e03f590e84a28f9fa313c45f35bcffba28c Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Wed, 22 Feb 2017 13:45:57 -0800 Subject: [PATCH] Fixing support for XML docs in OOP The issue here is that the OOP host doesn't yet have support for documentation, it will just return null. Fixing this code to look for the documentation after we get the descriptors back into VS. I tested this and confirmed that it works with TagHelpers in dlls + xml file documenation as well as TagHelpers compiled in the project itself. --- .../DefaultTagHelperResolver.cs | 2 +- .../XmlMemberDocumentation.cs | 3 +- .../DefaultTagHelperResolver.cs | 46 +++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperResolver.cs b/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperResolver.cs index a3fa319388..f9a6d66a23 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperResolver.cs +++ b/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperResolver.cs @@ -3,9 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.AspNetCore.Razor.Evolution; using Microsoft.AspNetCore.Razor.Evolution.Legacy; -using System.Linq; namespace Microsoft.CodeAnalysis.Razor { diff --git a/src/Microsoft.CodeAnalysis.Razor/XmlMemberDocumentation.cs b/src/Microsoft.CodeAnalysis.Razor/XmlMemberDocumentation.cs index 63685166cd..cec3ebed7f 100644 --- a/src/Microsoft.CodeAnalysis.Razor/XmlMemberDocumentation.cs +++ b/src/Microsoft.CodeAnalysis.Razor/XmlMemberDocumentation.cs @@ -23,9 +23,8 @@ namespace Microsoft.CodeAnalysis.Razor } // the structure of the XML is defined by: https://msdn.microsoft.com/en-us/library/fsbx0t7x.aspx - // we expect the root node of the content we are passed to always be 'member'. + // we expect the root node of the content we are passed to always be 'member' or 'doc'. _element = XElement.Parse(content); - Debug.Assert(_element.Name == "member"); } /// diff --git a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperResolver.cs b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperResolver.cs index 5b6b44a57a..5ae954eceb 100644 --- a/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperResolver.cs +++ b/src/Microsoft.VisualStudio.LanguageServices.Razor/DefaultTagHelperResolver.cs @@ -4,8 +4,10 @@ using System; using System.Collections.Generic; using System.Composition; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Evolution; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Razor; @@ -33,6 +35,12 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor using (var session = await client.CreateSessionAsync(project.Solution)) { var result = await session.InvokeAsync("GetTagHelpersAsync", new object[] { project.Id.Id, "Foo", assemblyNameFilters, }).ConfigureAwait(false); + + // Per https://github.com/dotnet/roslyn/issues/12770 - there's currently no support for documentation in the OOP host + // until that's available we add the documentation on the VS side by looking up each symbol again. + var compilation = await project.GetCompilationAsync().ConfigureAwait(false); + AddXmlDocumentation(compilation, result.Descriptors); + return result; } } @@ -44,5 +52,43 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor exception); } } + + private void AddXmlDocumentation(Compilation compilation, IReadOnlyList tagHelpers) + { + for (var i = 0; i < tagHelpers.Count; i++) + { + var tagHelper = tagHelpers[i]; + tagHelper.DesignTimeDescriptor = tagHelper.DesignTimeDescriptor ?? new TagHelperDesignTimeDescriptor(); + + var symbol = compilation.GetTypeByMetadataName(tagHelper.TypeName); + if (symbol != null) + { + var xml = symbol.GetDocumentationCommentXml(); + if (!string.IsNullOrEmpty(xml)) + { + var documentation = new XmlMemberDocumentation(xml); + tagHelper.DesignTimeDescriptor.Summary = documentation.GetSummary(); + tagHelper.DesignTimeDescriptor.Remarks = documentation.GetRemarks(); + } + + foreach (var attribute in tagHelper.Attributes) + { + attribute.DesignTimeDescriptor = attribute.DesignTimeDescriptor ?? new TagHelperAttributeDesignTimeDescriptor(); + + var attributeSymbol = symbol.GetMembers(attribute.PropertyName).FirstOrDefault(); + if (attributeSymbol != null) + { + xml = attributeSymbol.GetDocumentationCommentXml(); + if (!string.IsNullOrEmpty(xml)) + { + var documentation = new XmlMemberDocumentation(xml); + tagHelper.DesignTimeDescriptor.Summary = documentation.GetSummary(); + tagHelper.DesignTimeDescriptor.Remarks = documentation.GetRemarks(); + } + } + } + } + } + } } }