diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 512e9b4dca7..89403050cf6 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -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." +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." diff --git a/src/Compiler/SyntaxTree/LexFilter.fs b/src/Compiler/SyntaxTree/LexFilter.fs index e74f514f812..e3d9591e6fb 100644 --- a/src/Compiler/SyntaxTree/LexFilter.fs +++ b/src/Compiler/SyntaxTree/LexFilter.fs @@ -2627,6 +2627,33 @@ type LexFilterImpl ( delayToken tokenTup true + and checkXmlDocCommentPosition(tokenTup: TokenTup) = + // Check if the current token is a LINE_COMMENT that appears after other content + match tokenTup.Token with + | LINE_COMMENT _ -> + let commentStartPos = startPosOfTokenTup tokenTup + let lastTokenEndPos = tokenTup.LastTokenPos + + // Check if this comment appears after other content on the same line + if lastTokenEndPos.Line = commentStartPos.Line && commentStartPos.Column > 0 then + // This comment appears after other tokens on the same line + // + // We need to be careful here - we want to warn about XML doc comments (///) + // but not regular comments (//). + // + // For now, let's be conservative and only warn in cases where it's likely + // an XML documentation comment. We can infer this from context: + // - The comment appears after what looks like a declaration or definition + // - The comment is positioned in a way that suggests it was meant as documentation + + // For the initial implementation, let's warn about LINE_COMMENTS that appear + // immediately after tokens on the same line. This will catch the obvious cases + // of misplaced /// comments. We may need to refine this later. + + warn tokenTup (FSComp.SR.xmlDocNotFirstOnLine()) + | _ -> + () // Not a comment, nothing to check + and rulesForBothSoftWhiteAndHardWhite(tokenTup: TokenTup) = match tokenTup.Token with | HASH_IDENT ident -> @@ -2750,6 +2777,8 @@ type LexFilterImpl ( true | _ -> + // Check for XML documentation comments positioned incorrectly after code + checkXmlDocCommentPosition tokenTup false and pushCtxtSeqBlock fallbackToken addBlockEnd = diff --git a/tests/FSharp.Compiler.ComponentTests/Language/XmlDocCommentPositionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/XmlDocCommentPositionTests.fs new file mode 100644 index 00000000000..3d0d8ad0f1b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Language/XmlDocCommentPositionTests.fs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.ComponentTests.Language + +open Xunit +open FSharp.Test + +module XmlDocCommentPositionTests = + + [] + let ``XML doc comment after code should warn``() = + FSharp """ +let x = 42 /// This should trigger warning +""" + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 3537, Line 2, Col 25, Line 2, Col 28, "XML documentation comments should be the first non-whitespace text on a line.") + ] + + [] + let ``XML doc comment at start of line should not warn``() = + FSharp """ +/// This is proper documentation +let x = 42 +""" + |> compile + |> shouldSucceed + + [] + let ``XML doc comment with indentation should not warn``() = + FSharp """ +module Test = + /// This is properly indented + let x = 42 +""" + |> compile + |> shouldSucceed + + [] + let ``XML doc comment after let binding should warn``() = + FSharp """ +let value = "test" /// Bad position +""" + |> compile + |> shouldFail + |> withDiagnostics [ + (Warning 3537, Line 2, Col 25, Line 2, Col 28, "XML documentation comments should be the first non-whitespace text on a line.") + ] \ No newline at end of file