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