Open astrohart opened 3 years ago
Having generics formatted like that would sure be nice.
I tried to have a look to see if it's a simple fix I could quickly create a PR for but nope. I'm already side-tracked from my main project so I'll just leave what I found for reference.
The effect @astrohart described is caused by how the xml docs represent generics:
Arguments that represent generic types have an appended ` (backtick) character followed by the number of type parameters Arguments having the out or ref modifier have an @ following their type name. Arguments passed by value or via params have no special notation. Arguments that are arrays are represented as [lowerbound:size, ... , lowerbound:size] where the number of commas is the rank less one, and the lower bounds and size of each dimension, if known, are represented in decimal. If a lower bound or size is not specified, it is omitted. If the lower bound and size for a particular dimension are omitted, the : is omitted as well. Jagged arrays are represented by one [] per level. Arguments that have pointer types other than void are represented using a * following the type name. A void pointer is represented using a type name of System.Void. Arguments that refer to generic type parameters defined on types are encoded using the ` (backtick) character followed by the zero-based index of the type parameter. Arguments that use generic type parameters defined in methods use a double-backtick `` instead of the ` used for types. Arguments that refer to constructed generic types are encoded using the generic type, followed by {, followed by a comma-separated list of type arguments, followed by }.
This is where it goes wrong:
It looks to me that the in fixing this; you want to know the name of the generic types in the method, you'd somehow need to get information from all the relevant TypeparamUnits
I guess just sending them as the third parameter to the MemberName constructor would work, just like params are passed along: https://github.com/lijunle/Vsxmd/blob/master/Vsxmd/Units/MemberUnit.cs#L34
There is another problem with generic type parameters. When generating links, the backticks often don't get escaped properly, leading to invalid markdown. Once generic type parameters are rendered as desccribed by OP, this problem should also be fixed, so I don't think it's worth a separate issue.
I have made a little minimum effort fix that will automatically escape the backticks inside the links, so it will at least generate valid markdown. It's a little bit clunky and slow, but it does the job. I thought I'd share it here.
Define a task in your project file (or Directory.Build.targets):
<UsingTask TaskName="FixGeneratedXmlDocMarkdown" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<MarkdownFile ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Text.RegularExpressions" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Regex regex = new Regex(@"(\]\([^\)]*[^\\])`");
string text = File.ReadAllText(MarkdownFile);
while (regex.IsMatch(text))
{
text = regex.Replace(text, "$1\\`");
}
File.WriteAllText(MarkdownFile, text);
]]>
</Code>
</Task>
</UsingTask>
and add a build target to run this after build:
<Target Name="AfterBuildStep" AfterTargets="Build">
<FixGeneratedXmlDocMarkdown MarkdownFile="$(DocumentationMarkdown)" />
</Target>
I have a generic interface
and another generic interface
These are generated in the Markdown with a
1 for the `IFloatyThing` interface, and a
2 for theIRockCandy
interface. The output isThe desired result is
To reproduce, make interfaces such as above in a new C# class library project with this NuGet package, and then build it, and then look at the generated Markdown.