Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ce6fd0d
Initial plan
Copilot Jan 2, 2026
20291f3
WIP: Add XML documentation infrastructure (incomplete - needs more work)
Copilot Jan 2, 2026
0916227
Add initial infrastructure for `<inheritdoc>` XML documentation support
Copilot Jan 2, 2026
8882d88
Merge branch 'main' into copilot/support-xmldoc-inherit-element
T-Gro Jan 6, 2026
f0471a5
Fix build warnings: parameter name mismatch and unused parameter
Copilot Jan 6, 2026
d01033e
Fix unused parameter error: mark infoReader as intentionally unused
Copilot Jan 6, 2026
7fb1835
Fix FS3218 warning: update signature to match implementation with _m …
Copilot Jan 7, 2026
0d42ef3
Add detailed SPEC-TODO.MD with implementation checklist based on MS L…
Copilot Jan 7, 2026
1cf9a6c
Impl added
T-Gro Jan 8, 2026
5aa295b
next batch of impls
T-Gro Jan 12, 2026
ddee485
inherits impl
T-Gro Jan 12, 2026
1b8e242
Deduplicate with go to definition
T-Gro Jan 13, 2026
14a1f05
fixing warnings
T-Gro Jan 13, 2026
e1fb343
Apply patch from /run xlf
actions-user Jan 13, 2026
c685017
Merge branch 'main' into copilot/support-xmldoc-inherit-element
T-Gro Jan 13, 2026
5ab6249
Apply suggestions from code review
T-Gro Jan 13, 2026
b06ccdd
Apply suggestions from code review
T-Gro Jan 14, 2026
d509cb6
Update Range.Zero to Range.range0 in XmlDoc tests
T-Gro Jan 15, 2026
b525f97
Merge branch 'main' into copilot/support-xmldoc-inherit-element
T-Gro Jan 15, 2026
5c8f7e3
Merge branch 'main' into copilot/support-xmldoc-inherit-element
T-Gro Jan 16, 2026
f79cbcd
Apply patch from /run fantomas
actions-user Jan 16, 2026
d96f3d2
Apply patch from /run test-baseline
actions-user Jan 16, 2026
2846e4e
Apply patch from /run ilverify
actions-user Jan 16, 2026
6a1b5da
Implement `<inheritdoc>` XML documentation support for F#
Copilot Jan 16, 2026
22f088c
Merge branch 'main' into copilot/support-xmldoc-inherit-element
T-Gro Jan 19, 2026
39a9cdb
Non hardcoded resolution of external assembly ref sigs
T-Gro Jan 19, 2026
1bce792
Merge branch 'main' into copilot/support-xmldoc-inherit-element
T-Gro Jan 19, 2026
b368155
FIx resolution of external .xml files for .dll imports
T-Gro Jan 19, 2026
34be62d
Adjust tests
T-Gro Jan 20, 2026
ac0806f
Apply patch from /run fantomas
actions-user Jan 20, 2026
c1b885a
Merge branch 'main' into copilot/support-xmldoc-inherit-element
T-Gro Jan 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Compiler/Driver/XmlDocFileWriter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module internal FSharp.Compiler.XmlDocFileWriter

open System.IO
open FSharp.Compiler.DiagnosticsLogger
open FSharp.Compiler.InfoReader
open FSharp.Compiler.IO
open FSharp.Compiler.Text
open FSharp.Compiler.Xml
Expand Down Expand Up @@ -77,7 +78,7 @@ module XmlDocWriter =

doModuleSig None generatedCcu.Contents

let WriteXmlDocFile (g, assemblyName, generatedCcu: CcuThunk, xmlFile) =
let WriteXmlDocFile (g, _infoReader: InfoReader, assemblyName, generatedCcu: CcuThunk, xmlFile) =
if not (FileSystemUtils.checkSuffix xmlFile "xml") then
error (Error(FSComp.SR.docfileNoXmlSuffix (), Range.rangeStartup))

Expand Down
3 changes: 2 additions & 1 deletion src/Compiler/Driver/XmlDocFileWriter.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

module internal FSharp.Compiler.XmlDocFileWriter

open FSharp.Compiler.InfoReader
open FSharp.Compiler.TypedTree
open FSharp.Compiler.TcGlobals

Expand All @@ -15,4 +16,4 @@ module XmlDocWriter =

/// Writes the XmlDocSig property of each element (field, union case, etc)
/// of the specified compilation unit to an XML document in a new text file.
val WriteXmlDocFile: g: TcGlobals * assemblyName: string * generatedCcu: CcuThunk * xmlFile: string -> unit
val WriteXmlDocFile: g: TcGlobals * _infoReader: InfoReader * assemblyName: string * generatedCcu: CcuThunk * xmlFile: string -> unit
3 changes: 2 additions & 1 deletion src/Compiler/Driver/fsc.fs
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,8 @@ let main2
tcConfig.xmlDocOutputFile
|> Option.iter (fun xmlFile ->
let xmlFile = tcConfig.MakePathAbsolute xmlFile
XmlDocWriter.WriteXmlDocFile(tcGlobals, assemblyName, generatedCcu, xmlFile))
let infoReader = InfoReader(tcGlobals, tcImports.GetImportMap())
XmlDocWriter.WriteXmlDocFile(tcGlobals, infoReader, assemblyName, generatedCcu, xmlFile))

// Pass on only the minimum information required for the next phase
Args(
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1684,6 +1684,7 @@ forFormatInvalidForInterpolated4,"Interpolated strings used as type IFormattable
3390,xmlDocDuplicateParameter,"This XML comment is invalid: multiple documentation entries for parameter '%s'"
3390,xmlDocUnresolvedCrossReference,"This XML comment is invalid: unresolved cross-reference '%s'"
3390,xmlDocMissingParameter,"This XML comment is incomplete: no documentation for parameter '%s'"
3390,xmlDocInheritDocError,"XML documentation inheritdoc error: %s"
3391,tcImplicitConversionUsedForNonMethodArg,"This expression uses the implicit conversion '%s' to convert type '%s' to type '%s'. See https://aka.ms/fsharp-implicit-convs. This warning may be disabled using '#nowarn \"3391\"."
3392,containerDeprecated,"The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead."
3393,containerSigningUnsupportedOnThisPlatform,"Key container signing is not supported on this platform."
Expand Down
4 changes: 4 additions & 0 deletions src/Compiler/FSharp.Compiler.Service.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,10 @@
<Compile Include="Driver\fsc.fs" />

<!-- the symbol API. -->
<Compile Include="Symbols\XmlDocSigParser.fsi" />
<Compile Include="Symbols\XmlDocSigParser.fs" />
<Compile Include="Symbols\XmlDocInheritance.fsi" />
<Compile Include="Symbols\XmlDocInheritance.fs" />
<Compile Include="Symbols\SymbolHelpers.fsi" />
<Compile Include="Symbols\SymbolHelpers.fs" />
<Compile Include="Symbols\Symbols.fsi" />
Expand Down
18 changes: 18 additions & 0 deletions src/Compiler/Symbols/XmlDocInheritance.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

module internal FSharp.Compiler.Symbols.XmlDocInheritance

open FSharp.Compiler.Text
open FSharp.Compiler.Xml

/// Expands `<inheritdoc>` elements in XML documentation (currently a placeholder)
/// Returns the original documentation unchanged
/// TODO: Implement full inheritdoc expansion
let expandInheritDoc (_m: range) (doc: XmlDoc) : XmlDoc =
// Placeholder implementation - just return the original doc
// Full implementation would:
// 1. Check for <inheritdoc> elements in the XML
// 2. Resolve the target (from cref or implicit from override/interface)
// 3. Retrieve and merge the inherited documentation
// 4. Apply path filters if specified
doc
10 changes: 10 additions & 0 deletions src/Compiler/Symbols/XmlDocInheritance.fsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

module internal FSharp.Compiler.Symbols.XmlDocInheritance

open FSharp.Compiler.Text
open FSharp.Compiler.Xml

/// Expands `<inheritdoc>` elements in XML documentation (currently a placeholder)
/// Returns the original documentation unchanged
val expandInheritDoc: _m: range -> doc: XmlDoc -> XmlDoc
89 changes: 89 additions & 0 deletions src/Compiler/Symbols/XmlDocSigParser.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace FSharp.Compiler.Symbols

open System.Text.RegularExpressions

/// Represents the kind of element in a documentation comment ID
[<RequireQualifiedAccess>]
type DocCommentIdKind =
| Type
| Method
| Property
| Field
| Event
| Namespace
| Unknown

/// Represents a parsed documentation comment ID (cref format)
[<RequireQualifiedAccess>]
type ParsedDocCommentId =
/// Type reference (T:Namespace.Type)
| Type of path: string list
/// Member reference (M:, P:, E:) with type path, member name, generic arity, and kind
| Member of typePath: string list * memberName: string * genericArity: int * kind: DocCommentIdKind
/// Field reference (F:Namespace.Type.field)
| Field of typePath: string list * fieldName: string
/// Invalid or unparseable ID
| None

module XmlDocSigParser =
/// Parse a documentation comment ID string (e.g., "M:Namespace.Type.Method(System.String)")
let parseDocCommentId (docCommentId: string) =
// Regex to match documentation comment IDs
// Groups: kind (T/M/P/F/E/N), entity (dotted path), optional args, optional return type
let docCommentIdRx =
Regex(@"^(?<kind>\w):(?<entity>[\w\d#`.]+)(?<args>\(.+\))?(?:~([\w\d.]+))?$", RegexOptions.Compiled)

// Parse generic args count from function name (e.g., MethodName``1)
let fnGenericArgsRx =
Regex(@"^(?<entity>.+)``(?<typars>\d+)$", RegexOptions.Compiled)

let m = docCommentIdRx.Match(docCommentId)
let kindStr = m.Groups["kind"].Value

match m.Success, kindStr with
| true, ("M" | "P" | "E") ->
let parts = m.Groups["entity"].Value.Split('.')
if parts.Length < 2 then
ParsedDocCommentId.None
else
let entityPath = parts[.. (parts.Length - 2)] |> List.ofArray
let memberOrVal = parts[parts.Length - 1]

// Try and parse generic params count from the name
let genericM = fnGenericArgsRx.Match(memberOrVal)

let (memberOrVal, genericParametersCount) =
if genericM.Success then
(genericM.Groups["entity"].Value, int genericM.Groups["typars"].Value)
else
memberOrVal, 0

let kind =
match kindStr with
| "M" -> DocCommentIdKind.Method
| "P" -> DocCommentIdKind.Property
| "E" -> DocCommentIdKind.Event
| _ -> DocCommentIdKind.Unknown

// Handle constructor name conversion (#ctor in doc comments, .ctor in F#)
let finalMemberName =
if memberOrVal = "#ctor" then ".ctor" else memberOrVal

ParsedDocCommentId.Member(entityPath, finalMemberName, genericParametersCount, kind)

| true, "T" ->
let entityPath = m.Groups["entity"].Value.Split('.') |> List.ofArray
ParsedDocCommentId.Type entityPath

| true, "F" ->
let parts = m.Groups["entity"].Value.Split('.')
if parts.Length < 2 then
ParsedDocCommentId.None
else
let entityPath = parts[.. (parts.Length - 2)] |> List.ofArray
let memberOrVal = parts[parts.Length - 1]
ParsedDocCommentId.Field(entityPath, memberOrVal)

| _ -> ParsedDocCommentId.None
30 changes: 30 additions & 0 deletions src/Compiler/Symbols/XmlDocSigParser.fsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace FSharp.Compiler.Symbols

/// Represents the kind of element in a documentation comment ID
[<RequireQualifiedAccess>]
type DocCommentIdKind =
| Type
| Method
| Property
| Field
| Event
| Namespace
| Unknown

/// Represents a parsed documentation comment ID (cref format)
[<RequireQualifiedAccess>]
type ParsedDocCommentId =
/// Type reference (T:Namespace.Type)
| Type of path: string list
/// Member reference (M:, P:, E:) with type path, member name, generic arity, and kind
| Member of typePath: string list * memberName: string * genericArity: int * kind: DocCommentIdKind
/// Field reference (F:Namespace.Type.field)
| Field of typePath: string list * fieldName: string
/// Invalid or unparseable ID
| None

module XmlDocSigParser =
/// Parse a documentation comment ID string (e.g., "M:Namespace.Type.Method(System.String)")
val parseDocCommentId: docCommentId: string -> ParsedDocCommentId
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.zh-Hant.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading