Summary
In API docs, postfix FSharp.Core type constructors such as list, option, voption and seq are rendered as plain text in type signatures, while other types get a link. For example the "Abbreviation For" line of MarkdownSpans renders as
<a href="../reference/fsharp-formatting-markdown-markdownspan.html">MarkdownSpan</a> list
MarkdownSpan is linked, list is not. It would be nice if list linked to https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-list-1.html, the way FSharpList already does when it shows up under its compiled name.
The same applies wherever a type is formatted: member signatures, record fields, union case fields, return types.
Cause
formatTyconRefAsHtml in src/FSharp.Formatting.ApiDocs/TypeFormatter.fs calls CrossReferenceResolver.TryResolveEntity on the type constructor. For int list the type constructor reported by FSharp.Compiler.Service is FSharp.Core's list<'T> abbreviation entity (IsFSharpAbbreviation = true), not FSharpList<'T>. For that entity TryFullName is None, so tryResolveCrossReferenceForEntity returns None and the formatter falls back to plain text.
Quick check with FCS 43.12.401 on type B = int option:
tcref=option IsFSharpAbbreviation=true TryFullName=None
Suggested fix
In tryResolveCrossReferenceForEntity, when the entity is not registered and is an F# abbreviation with no full name, resolve the link through the abbreviated type's definition (entity.AbbreviatedType.TypeDefinition, here FSharpList1) while keeping the abbreviation's display name (list) as the link text. externalDocsLinkalready mapsFSharpListto the fsharp-core-docs URL above andFSharpOptiontooption`, so only the entity lookup needs to change.
Follow-up from #1314.
Summary
In API docs, postfix FSharp.Core type constructors such as
list,option,voptionandseqare rendered as plain text in type signatures, while other types get a link. For example the "Abbreviation For" line ofMarkdownSpansrenders asMarkdownSpanis linked,listis not. It would be nice iflistlinked to https://fsharp.github.io/fsharp-core-docs/reference/fsharp-collections-list-1.html, the wayFSharpListalready does when it shows up under its compiled name.The same applies wherever a type is formatted: member signatures, record fields, union case fields, return types.
Cause
formatTyconRefAsHtmlinsrc/FSharp.Formatting.ApiDocs/TypeFormatter.fscallsCrossReferenceResolver.TryResolveEntityon the type constructor. Forint listthe type constructor reported by FSharp.Compiler.Service is FSharp.Core'slist<'T>abbreviation entity (IsFSharpAbbreviation = true), notFSharpList<'T>. For that entityTryFullNameisNone, sotryResolveCrossReferenceForEntityreturnsNoneand the formatter falls back to plain text.Quick check with FCS 43.12.401 on
type B = int option:Suggested fix
In
tryResolveCrossReferenceForEntity, when the entity is not registered and is an F# abbreviation with no full name, resolve the link through the abbreviated type's definition (entity.AbbreviatedType.TypeDefinition, hereFSharpList1) while keeping the abbreviation's display name (list) as the link text.externalDocsLinkalready mapsFSharpListto the fsharp-core-docs URL above andFSharpOptiontooption`, so only the entity lookup needs to change.Follow-up from #1314.