Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5c1cb81
Initial plan
Copilot Sep 8, 2025
1713662
Add basic XML doc comment position warning - initial implementation
Copilot Sep 8, 2025
8698eef
Add warning for XML documentation comments not positioned as first no…
Copilot Sep 8, 2025
21333cf
Fix XML doc comment position check to analyze actual line content ins…
Copilot Sep 8, 2025
7d2be7e
Address feedback by disabling hardcoded column limit approach tempora…
Copilot Sep 8, 2025
6413c55
Merge branch 'main' into copilot/fix-920e1d4e-0c13-4c25-8d7b-183dbc29…
T-Gro Sep 18, 2025
92f2c02
Address feedback: remove hardcoded column limit, disable warning temp…
Copilot Sep 19, 2025
e12e8cc
Implement XML doc comment position check in LexFilter instead of lexe…
Copilot Sep 19, 2025
fb42cf8
Merge branch 'main' into copilot/fix-920e1d4e-0c13-4c25-8d7b-183dbc29…
T-Gro Sep 22, 2025
28a6204
Fix type constraint mismatch in FSComp.SR.xmlDocNotFirstOnLine() usage
Copilot Sep 22, 2025
56607de
Fix unused variable warning in LexFilter pattern match
Copilot Sep 22, 2025
9d9a664
Merge branch 'main' into copilot/fix-920e1d4e-0c13-4c25-8d7b-183dbc29…
T-Gro Oct 17, 2025
83a3454
Update xlf localization files for xmlDocNotFirstOnLine entry
Copilot Nov 30, 2025
bd22c0e
Add lexer-level tracking for XML doc comment position warning
Copilot Dec 2, 2025
3070e3d
Fix incorrect /// comment usage in infos.fs - should be //
Copilot Dec 2, 2025
1f45f17
Disable XML doc position warning - implementation too aggressive
Copilot Dec 3, 2025
4ac9a26
Re-implement XML doc comment position warning using token position tr…
Copilot Dec 3, 2025
a560672
Add token position tracking to more token types and start updating tests
Copilot Dec 3, 2025
3f936f2
Update XmlDocTests to expect FS3879 warning for misplaced /// comments
Copilot Dec 3, 2025
df81dfb
Fix remaining test failures: update neg45.bsl baseline and type membe…
Copilot Dec 3, 2025
fc51e55
Fix code formatting in LexHelpers.fs and LexHelpers.fsi
Copilot Dec 3, 2025
4b58239
Merge branch 'main' into copilot/fix-920e1d4e-0c13-4c25-8d7b-183dbc29…
abonie Dec 5, 2025
c24643d
Update neg45.bsl baseline with all three FS3879 warnings
Copilot Dec 5, 2025
c2736dc
Fix /// comment in Trimming/Program.fs that was causing build failures
Copilot Dec 5, 2025
e171853
Change triple slash to regular comments
abonie Dec 8, 2025
b4a85cb
Fix XML documentation comment parse errors
abonie Dec 8, 2025
b3984a0
Undo changes to neg45.bsl
abonie Dec 8, 2025
0c6e957
Suppress FS3879 warning in AOT trimming test projects
Copilot Dec 9, 2025
d4b6661
Add release notes entry for FS3879 warning
Copilot Dec 9, 2025
c2112c5
Add test for DU cases with /// after case definition
Copilot Dec 9, 2025
2faae14
Fix DU test - use correct lambda signature (fun _ -> ()) instead of (…
Copilot Dec 10, 2025
4d16c5b
Fix DU test expected column positions - CaseB line should be Col 12, …
Copilot Dec 10, 2025
1006511
Rewrite XML doc position warning using LexFilter approach
Copilot Dec 31, 2025
337178d
Merge branch 'main' into copilot/fix-920e1d4e-0c13-4c25-8d7b-183dbc29…
T-Gro Jan 2, 2026
250ed38
Move release notes entry to 10.0.200.md as requested
Copilot Jan 2, 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
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/10.0.200.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
### Added

* FSharpDiagnostic: add default severity ([#19152](https://github.com/dotnet/fsharp/pull/19152))
* Add warning FS3879 for XML documentation comments not positioned as first non-whitespace on line. ([PR #18891](https://github.com/dotnet/fsharp/pull/18891))

### Breaking Changes

Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/infos.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1516,7 +1516,7 @@ type ILFieldInfo =
match x with
| ILFieldInfo(tinfo, _) -> tinfo.TypeInstOfRawMetadata
#if !NO_TYPEPROVIDERS
| ProvidedField _ -> [] /// GENERIC TYPE PROVIDERS
| ProvidedField _ -> [] // GENERIC TYPE PROVIDERS
#endif

/// Get the name of the field
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1813,4 +1813,5 @@ featureAllowLetOrUseBangTypeAnnotationWithoutParens,"Allow let! and use! type an
3876,lexWarnDirectivesMustMatch,"There is another %s for this warning already in line %d."
3877,lexLineDirectiveMappingIsNotUnique,"The file '%s' was also pointed to in a line directive in '%s'. Proper warn directive application may not be possible."
3878,tcAttributeIsNotValidForUnionCaseWithFields,"This attribute is not valid for use on union cases with fields."
3879,xmlDocNotFirstOnLine,"XML documentation comments should be the first non-whitespace text on a line."
featureReturnFromFinal,"Support for ReturnFromFinal/YieldFromFinal in computation expressions to enable tailcall optimization when available on the builder."
19 changes: 19 additions & 0 deletions src/Compiler/SyntaxTree/LexFilter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,14 @@
savedLexbufState <- tokenLexbufState
haveLexbufState <- true

// Track the last non-comment token position for XML doc comment validation
match token with
| LINE_COMMENT _ -> ()
| BLOCK_COMMENT _

Check failure on line 679 in src/Compiler/SyntaxTree/LexFilter.fs

View workflow job for this annotation

GitHub Actions / copilot

The two sides of this 'or' pattern bind different sets of variables

Check failure on line 679 in src/Compiler/SyntaxTree/LexFilter.fs

View workflow job for this annotation

GitHub Actions / copilot

The two sides of this 'or' pattern bind different sets of variables

Check failure on line 679 in src/Compiler/SyntaxTree/LexFilter.fs

View workflow job for this annotation

GitHub Actions / copilot

The pattern discriminator 'BLOCK_COMMENT' is not defined.
| BLOCK_COMMENT_OPEN

Check warning on line 680 in src/Compiler/SyntaxTree/LexFilter.fs

View workflow job for this annotation

GitHub Actions / copilot

Uppercase variable identifiers should not generally be used in patterns, and may indicate a missing open declaration or a misspelt pattern name.
| WHITESPACE _ -> ()
| _ -> XmlDocStore.SetLastNonCommentTokenLine lexbuf tokenLexbufState.EndPos.Line

Check warning on line 682 in src/Compiler/SyntaxTree/LexFilter.fs

View workflow job for this annotation

GitHub Actions / copilot

This rule will never be matched

Check failure on line 682 in src/Compiler/SyntaxTree/LexFilter.fs

View workflow job for this annotation

GitHub Actions / copilot

The value, constructor, namespace or type 'SetLastNonCommentTokenLine' is not defined.

let tokenTup = pool.Rent()
tokenTup.Token <- token
tokenTup.LexbufState <- tokenLexbufState
Expand Down Expand Up @@ -2628,6 +2636,17 @@
true

and rulesForBothSoftWhiteAndHardWhite(tokenTup: TokenTup) =
// Check if XML doc comment (///) appears after other code on the same line
match tokenTup.Token with
| LINE_COMMENT comment when comment.StartsWithOrdinal("///") ->

Check failure on line 2641 in src/Compiler/SyntaxTree/LexFilter.fs

View workflow job for this annotation

GitHub Actions / copilot

The type 'LexerContinuation' does not define the field, constructor or member 'StartsWithOrdinal'.
let commentStartLine = tokenTup.StartPos.Line
let lastNonCommentLine = XmlDocStore.GetLastNonCommentTokenLine lexbuf

Check failure on line 2643 in src/Compiler/SyntaxTree/LexFilter.fs

View workflow job for this annotation

GitHub Actions / copilot

The value, constructor, namespace or type 'GetLastNonCommentTokenLine' is not defined.
if lastNonCommentLine = commentStartLine then
// XML doc comment appears on same line as previous non-comment token
let m = mkFileIndexRange tokenTup.LexbufState.FileIndex tokenTup.StartPos (tokenTup.StartPos.ShiftColumnBy(3))

Check failure on line 2646 in src/Compiler/SyntaxTree/LexFilter.fs

View workflow job for this annotation

GitHub Actions / copilot

The value or constructor 'mkFileIndexRange' is not defined.
warning(Error(FSComp.SR.xmlDocNotFirstOnLine(), m))
| _ -> ()

match tokenTup.Token with
| HASH_IDENT ident ->
let hashPos = LexbufState(tokenTup.StartPos, tokenTup.StartPos.ShiftColumnBy(1), false)
Expand Down
7 changes: 4 additions & 3 deletions src/Compiler/SyntaxTree/LexHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
open System.Text

open Internal.Utilities
open Internal.Utilities.Library
open Internal.Utilities.Text.Lexing

open FSharp.Compiler.DiagnosticsLogger
Expand Down Expand Up @@ -395,7 +396,7 @@
(*------- for prototyping and explaining offside rule *)
FSHARP, "__token_OBLOCKSEP", OBLOCKSEP
FSHARP, "__token_OWITH", OWITH
FSHARP, "__token_ODECLEND", ODECLEND(range0, false)
FSHARP, "__token_ODECLEND", ODECLEND range0

Check failure on line 399 in src/Compiler/SyntaxTree/LexHelpers.fs

View workflow job for this annotation

GitHub Actions / copilot

This expression was expected to have type� 'range * bool' �but here has type� 'range'
FSHARP, "__token_OTHEN", OTHEN
FSHARP, "__token_OELSE", OELSE
FSHARP, "__token_OEND", OEND
Expand Down Expand Up @@ -451,7 +452,7 @@
| true, v ->
match v with
| RESERVED ->
warning (ReservedKeyword(FSComp.SR.lexhlpIdentifierReserved s, lexbuf.LexemeRange))
warning (ReservedKeyword(FSComp.SR.lexhlpIdentifierReserved (s), lexbuf.LexemeRange))
IdentifierToken args lexbuf s
| _ ->
match s with
Expand All @@ -462,7 +463,7 @@
| "lsr"
| "asr" ->
if lexbuf.SupportsFeature LanguageFeature.MLCompatRevisions then
mlCompatWarning (FSComp.SR.mlCompatKeyword s) lexbuf.LexemeRange
mlCompatWarning (FSComp.SR.mlCompatKeyword (s)) lexbuf.LexemeRange
| _ -> ()

v
Expand Down
8 changes: 8 additions & 0 deletions src/Compiler/SyntaxTree/LexerStore.fs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@
let collector = getCollector lexbuf
collector.CheckInvalidXmlDocPositions()

let SetLastNonCommentTokenLine (lexbuf: Lexbuf) (line: int) =
let collector = getCollector lexbuf
collector.SetLastNonCommentTokenLine(line)

Check failure on line 69 in src/Compiler/SyntaxTree/LexerStore.fs

View workflow job for this annotation

GitHub Actions / copilot

The type 'XmlDocCollector' does not define the field, constructor or member 'SetLastNonCommentTokenLine'.

let GetLastNonCommentTokenLine (lexbuf: Lexbuf) =
let collector = getCollector lexbuf
collector.LastNonCommentTokenLine

Check failure on line 73 in src/Compiler/SyntaxTree/LexerStore.fs

View workflow job for this annotation

GitHub Actions / copilot

The type 'XmlDocCollector' does not define the field, constructor or member 'LastNonCommentTokenLine'.

//------------------------------------------------------------------------
// Storage to hold the current accumulated ConditionalDirectiveTrivia, and related types and access functions
//------------------------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions src/Compiler/SyntaxTree/XmlDoc.fs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ type XmlDocCollector() =
let mutable savedGrabPoints = Dictionary<pos, struct (int * int * bool)>()
let mutable currentGrabPointCommentsCount = 0
let mutable delayedGrabPoint = ValueNone
let mutable lastNonCommentTokenLine = 0

member _.AddGrabPoint(pos: pos) =
if currentGrabPointCommentsCount = 0 then
Expand Down Expand Up @@ -187,6 +188,11 @@ type XmlDocCollector() =
member _.HasComments grabPointPos =
savedGrabPoints.TryGetValue grabPointPos |> fst

member _.SetLastNonCommentTokenLine(line: int) =
lastNonCommentTokenLine <- line

member _.LastNonCommentTokenLine = lastNonCommentTokenLine

member _.CheckInvalidXmlDocPositions() =
let comments = ResizeArray<range>(savedLines.Count)

Expand Down
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.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<TargetFrameworks>net9.0</TargetFrameworks>
<LangVersion>preview</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>3879</NoWarn>
</PropertyGroup>

<PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion tests/AheadOfTime/Trimming/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8262,7 +8262,7 @@ let func7000()=
test "test7935" (lazy(sprintf "%+0G" -10.0M)) "-10"
test "test7936" (lazy(sprintf "%+05G" -10.0M)) "-0010"// "00-10"
test "test7937" (lazy(sprintf "%+01G" -10.0M)) "-10"
test "test7938" (lazy(sprintf "%+0*G" 7 -10.0M)) "-000010"/// "0000-10"
test "test7938" (lazy(sprintf "%+0*G" 7 -10.0M)) "-000010"// "0000-10"
test "test7939" (lazy(sprintf "%+0.5G" -10.0M)) "-10"
test "test7940" (lazy(sprintf "%+0.*G" 4 -10.0M)) "-10"
test "test7941" (lazy(sprintf "%+0*.*G" 5 4 -10.0M)) "-0010"// "00-10"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<TargetFrameworks>net9.0</TargetFrameworks>
<LangVersion>preview</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>3879</NoWarn>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<TargetFrameworks>net9.0</TargetFrameworks>
<LangVersion>preview</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>3879</NoWarn>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
<OtherFlags>--standalone</OtherFlags>
</PropertyGroup>
Expand Down
Loading
Loading