Uh oh!
There was an error while loading. Please reload this page.
Add support for <include> XML documentation tag - #19186
Merged
Merged
Conversation
CopilotAI
changed the title
[WIP] Add support for <include> XML documentation tagAdd support for Dec 31, 2025
<include> XML documentation tagContributor
❗ Release notes requiredYou can open this PR in browser to add release notes: open in github.dev
|
Add depth and budget guards for XML doc include expansion, share a per-pass expansion environment across doc-file generation, and memoize resolved include fragments with cloning. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use ordinal include path comparison, remove fragment memoization, and reset include budgets per XML doc comment while preserving the shared per-pass file cache. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Emit the per-document include expansion-budget warning at most once instead of once per over-budget include, avoiding warning spam when a single doc comment contains many more than the budgeted number of includes. Every unexpanded include tag is still preserved. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…tic tests Address Phase 8 review gate: - Move the Roslyn CS1589-style include-error frame into a proper localizable FSComp message (xmlDocIncludeError2, %s %s %s) instead of interpolating it in code, matching the F# diagnostic convention and Roslyn's own localized frame; add matching trans-units to all FSComp .xlf files. Rendered text is unchanged. - Drop the throwaway Result.Error payload in resolveSingleInclude in favour of a plain Some/None resolution. - Assert the 'names both file and xpath' guarantee across the remaining failure classes (circular, depth cap, budget, empty xpath, DTD). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The two 'Fixed' entries described hardening of behavior that never shipped; they are part of delivering the brand-new <include> feature, not fixes to released behavior. Fold into the single Added entry and note that <inheritdoc> remains unsupported. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Fills the last Task 10.1 error-class gap: an external file that is not well-formed XML must not crash the compiler. Asserts a single FS3887 that names both file and xpath, that the unexpanded <include> tag is kept, and that no partial malformed content leaks into the output. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Phase 10 review-gauntlet remediation. Correctness (blocking): classifyInclude matched on LocalName only, so an element named 'include' in a foreign XML namespace (e.g. <include xmlns="urn:...">) was hijacked and expanded. It is now required to be unqualified, matching Roslyn's ElementNameIs (which checks the namespace is empty). A foreign-namespace element is ordinary content and is left untouched. Added a RED->GREEN test; real unqualified includes are unaffected. Compactness: * resolveFilePath collapses to GetFullFilePathInDirectoryShim over GetDirectoryNameShim: the shim already passes rooted paths through and maps an empty/dir-less/"unknown" base name to "." (the current directory), so the hand-rolled IsPathRooted + CurrentDirectory branches were redundant. Drops the now-unused open System.IO. * Removed three unused test-framework helpers (withParamChecking, memberExists, memberXmlAbsent). Include suite 60/60, XmlCommentChecking 15/15. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Convergence-review follow-up. The prior one-line simplification called GetDirectoryNameShim on the base file name unconditionally, which throws for a virtual/sentinel range filename containing an illegal path char (caught and downgraded to 'the file path is invalid'). An absolute include path must not depend on the base file name, so restore the rooted short-circuit. The relative case keeps the compacted form; this is now behaviorally identical to the original for all inputs while still dropping the redundant current-directory fallback branches. Include suite 60/60. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve conflicts and adapt the <include> feature to upstream changes: - ProjectAnalysisTests.fs: trivial comment conflict in the unrelated ProjectActivePatternInSig module; take main's canonical wording. - FSComp.txt: main claimed FS3887 for the new ilCustomAttrInvalidArrayElemType diagnostic, colliding with the <include> feature's original 3887. Renumber the two include messages (xmlDocIncludeError / xmlDocIncludeError2) to the next free number FS3891, matching the shared-number convention of the neighbouring xmlDoc diagnostics (3390). Propagate 3891 to the include test assertions and the FS3887 references in XmlDoc.fs / .fsi comments. Repair several silent auto-merge clobbers where my branch's stale base overwrote content main added since the branch point: - FSharp.Compiler.Service.fsproj: restored 6 dropped <Compile> entries (EncMethodDebugInformation, CheckComputationExpressionsCustomOps, CompilerGeneratedNameMapState, GeneratedNames, SynthesizedTypeMaps) by taking main's project and re-applying only XmlDocIncludeExpander.fsi/.fs. - FSharp.Compiler.ComponentTests.fsproj: restored ~30 dropped test <Compile> entries; re-applied only Miscellaneous/XmlDocInclude.fs. - FSharp.Test.Utilities.fsproj: restored ~92 unrelated changes incl. an OpenTelemetry package downgrade (1.15.3 -> 1.11.2); re-applied only XmlDocIncludeTestFramework.fs. - release-notes/11.0.100.md: restored 105 dropped entries from other contributors; re-applied only the single <include> "Added" entry. xlf trans-units are keyed by identifier (not number) so they are unaffected. Verified: ./build.sh -c Release 0W/0E; include suite 60/60; XmlCommentChecking 23/23; main's FS3887 attribute test 12/12. Total delta vs main is exactly the 26 <include> feature files. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- FSComp.txt: relocate the two xmlDocIncludeError entries (3891) to after 3890 so error codes stay monotonically non-decreasing (FSCompCheck.fsx). - XmlDocIncludeExpander.fs: use persistent Set for the in-progress cycle set (drops the O(n) HashSet clone per recursion descent); use XName.Get instead of !!(XName.op_Implicit ...). - XmlDocIncludeTestFramework.fs: make tryMemberInner private. - Compiler.fs: strip trailing whitespace on the added withXmlDoc helper lines. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
String.Contains(char) only exists on .NET Core 2.1+. FSharp.Test.Utilities also targets net472 on Windows CI, where only Contains(string) is available, so 't.Value.Contains '\n'' failed to compile (FS0001 expected string, got char). The local macOS build only compiles the net10.0 leg, so it was missed. Use string literals, which compile on every target framework. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…to 3892; repair fsproj + release-note clobbers Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
T-Gro
approved these changes
Aug 3, 2026
T-Gro
left a comment
Member
There was a problem hiding this comment.
CI is green and the earlier review comments are addressed. LGTM.
T-Gro
commented
Aug 3, 2026
Member
@abonie this is ready for your review when you have a moment — CI is green, and it's a compile-time-only, text-in/text-out |
RFC FS-1341 / C# XmlFileResolver parity: a relative include file is now resolved next to the including source file first, then against the compiler working directory. Also lock signature-file include resolution with a test. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
main added the record-spread messages (FS3892-FS3904) while this branch was in flight, colliding with the <include> error code. Move both include messages to the next free code (3905) so FSComp.txt stays sorted. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
abonie
approved these changes
Aug 4, 2026
Comment-only follow-up to the 3892->3905 renumber: two doc/inline comments still named the old error code. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Production (src/Compiler/SyntaxTree): - Drop restating/narration comments on the include expander; keep only the two genuine why-comments (evaluateXPath lazy-materialize-inside-try, classifyInclude foreign-namespace parity). Inline pathComparer -> StringComparer.Ordinal. - Trim XmlDoc.Check include comment from 4 lines to 1. Tests: - Collapse repeated [<Fact>] cases into [<Theory>]/[<InlineData>]: DTD/XXE 4->1, inline-selection 2->1, param-validation-warn 4->1 (62 discrete cases preserved). - Move single-consumer verifyXmlDoc*/readEmittedXml out of the shared Compiler.fs into the only test file that uses them; recompose withXmlDoc from existing withOutputDirectory/withOptions; simplify countSubstring; reuse includeWarningCount. Net -188 LOC, no behavior change; XmlDocInclude 62/62 green, build 0W/0E, fantomas clean. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Split(string) is .NET Core-only; the desktop (net472) test legs only have Split(char[]) and Split(string[], StringSplitOptions). Use the latter so the helper compiles on every target framework. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
abonie
approved these changes
Aug 5, 2026
The main merge brought the record-spread feature, which claimed 3905 (with off-by-default handling in CompilerDiagnostics + its own tests). The XML <include> diagnostics also sat at 3905, colliding. Move the two include messages (xmlDocIncludeError/xmlDocIncludeError2) to 3908 so the record-spread block stays contiguous (3902-3907) and the include feature owns its own number. Updated the emitted-warning number in the two production comments and all XmlDocInclude test assertions. .xlf files are keyed by identifier with unchanged source text, so no localization regeneration is needed. Verified: build 0 errors; XmlDocInclude 62/62 green; RecordSpreads 127/127 green. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
abonie
approved these changes
Aug 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Support for the
<include>XML documentation tagImplements the C#-style
<include file="..." path="..."/>XML documentation tag for F# (part of #19175). At compile time, when the XML documentation file is generated (--doc), each<include>directive is replaced by the XML element(s) that its XPath query selects from the referenced external file. This is a text-in / text-out transformation on the generated documentation; it does not affect IDE tooltips (unlike<inheritdoc>, which remains unsupported and out of scope).Design: RFC FS-1341.
Behaviour
file(absolute, or relative to the source file, then the compiler working directory), evaluates thepathXPath against the loaded document, and substitutes the matched elements.<include>directives (chains and diamond DAGs), expanded depth-first.(resolved file, xpath)pair: a self/mutual cycle warns (FS3905) and keeps the unexpanded tag instead of looping.--docwriter path (and, when--warnon:3390is set, the quiet doc-checking validation path). The default type-check / IDE path performs no file IO.