diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md index 29d414d88f4..460e58b0fdc 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md @@ -16,7 +16,8 @@ * Enforce AttributeTargets on let values and functions. ([PR #16692](https://github.com/dotnet/fsharp/pull/16692)) * Enforce AttributeTargets on union case declarations. ([PR #16764](https://github.com/dotnet/fsharp/pull/16764)) * Disallow using base to invoke an abstract base method. ([Issue #13926](https://github.com/dotnet/fsharp/issues/13926), [PR #16773](https://github.com/dotnet/fsharp/pull/16773)) -* Fix broken code completion after a record type declaration ([PR #16813]([Title](https://github.com/dotnet/fsharp/pull/16813))) +* Parser: fix pattern range for idents with trivia ([PR #16824](https://github.com/dotnet/fsharp/pull/16824)) +* Fix broken code completion after a record type declaration ([PR #16813](https://github.com/dotnet/fsharp/pull/16813)) ### Added diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index 8b034740be4..a97976bee5c 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -16,7 +16,19 @@ type Ident(text: string, range: range) = member _.idRange = range override _.ToString() = text -type SynIdent = SynIdent of ident: Ident * trivia: IdentTrivia option +type SynIdent = + | SynIdent of ident: Ident * trivia: IdentTrivia option + + member this.Range = + match this with + | SynIdent(ident, trivia) -> + match trivia with + | Some value -> + match value with + | IdentTrivia.OriginalNotationWithParen(leftParen, _, rightParen) + | IdentTrivia.HasParenthesis(leftParen, rightParen) -> unionRanges leftParen rightParen + | _ -> ident.idRange + | None -> ident.idRange type LongIdent = Ident list diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 3d9ef06dcad..fa88b48004d 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -16,7 +16,10 @@ type Ident = member idRange: range /// Represents an identifier with potentially additional trivia information. -type SynIdent = SynIdent of ident: Ident * trivia: IdentTrivia option +type SynIdent = + | SynIdent of ident: Ident * trivia: IdentTrivia option + + member Range: range /// Represents a long identifier e.g. 'A.B.C' type LongIdent = Ident list diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 4080fc7ec8b..b33d55722a5 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -3627,8 +3627,7 @@ atomicPattern: mkSynPatMaybeVar lidwd vis (lhs parseState) else let synIdent = List.head lidwd.IdentsWithTrivia - let (SynIdent(id, _)) = synIdent - SynPat.Named(synIdent, false, vis, id.idRange) } + SynPat.Named(synIdent, false, vis, synIdent.Range) } | constant { SynPat.Const(fst $1, snd $1) } diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index cdbdb81bda0..9dda7f12180 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -7534,6 +7534,8 @@ FSharp.Compiler.Syntax.SynField: System.String ToString() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident get_ident() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident ident FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.SynIdent NewSynIdent(FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia]) +FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Text.Range Range +FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynIdent: Int32 Tag FSharp.Compiler.Syntax.SynIdent: Int32 get_Tag() FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] get_trivia() diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index cdbdb81bda0..9dda7f12180 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -7534,6 +7534,8 @@ FSharp.Compiler.Syntax.SynField: System.String ToString() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident get_ident() FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.Ident ident FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Syntax.SynIdent NewSynIdent(FSharp.Compiler.Syntax.Ident, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia]) +FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Text.Range Range +FSharp.Compiler.Syntax.SynIdent: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynIdent: Int32 Tag FSharp.Compiler.Syntax.SynIdent: Int32 get_Tag() FSharp.Compiler.Syntax.SynIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.SyntaxTrivia.IdentTrivia] get_trivia() diff --git a/tests/service/data/SyntaxTree/ModuleMember/Let 05.fs b/tests/service/data/SyntaxTree/ModuleMember/Let 05.fs new file mode 100644 index 00000000000..3d306418d47 --- /dev/null +++ b/tests/service/data/SyntaxTree/ModuleMember/Let 05.fs @@ -0,0 +1,3 @@ +let (|AP|) + +() diff --git a/tests/service/data/SyntaxTree/ModuleMember/Let 05.fs.bsl b/tests/service/data/SyntaxTree/ModuleMember/Let 05.fs.bsl new file mode 100644 index 00000000000..684cfa3cfb0 --- /dev/null +++ b/tests/service/data/SyntaxTree/ModuleMember/Let 05.fs.bsl @@ -0,0 +1,28 @@ +ImplFile + (ParsedImplFileInput + ("/root/ModuleMember/Let 05.fs", false, QualifiedNameOfFile Let 05, [], [], + [SynModuleOrNamespace + ([Let 05], false, AnonModule, + [Let + (false, + [SynBinding + (None, Normal, false, false, [], + PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), + SynValData + (None, SynValInfo ([], SynArgInfo ([], false, None)), None), + Named + (SynIdent + (|AP|, Some (HasParenthesis ((1,4--1,5), (1,9--1,10)))), + false, None, (1,4--1,10)), None, + ArbitraryAfterError ("localBinding2", (1,10--1,10)), + (1,4--1,10), Yes (1,0--1,10), + { LeadingKeyword = Let (1,0--1,3) + InlineKeyword = None + EqualsRange = None })], (1,0--1,10)); + Expr (Const (Unit, (3,0--3,2)), (3,0--3,2))], PreXmlDocEmpty, [], + None, (1,0--3,2), { LeadingKeyword = None })], (true, true), + { ConditionalDirectives = [] + CodeComments = [] }, set [])) + +(3,0)-(3,1) parse error Incomplete structured construct at or before this point in binding. Expected '=' or other token. +(1,0)-(2,0) parse warning The declarations in this file will be placed in an implicit module 'Let 05' based on the file name 'Let 05.fs'. However this is not a valid F# identifier, so the contents will not be accessible from other files. Consider renaming the file or adding a 'module' or 'namespace' declaration at the top of the file. diff --git a/tests/service/data/SyntaxTree/OperatorName/PartialActivePatternDefinitionWithoutParameters.fs.bsl b/tests/service/data/SyntaxTree/OperatorName/PartialActivePatternDefinitionWithoutParameters.fs.bsl index d3f6d9d59f8..be0b81e8577 100644 --- a/tests/service/data/SyntaxTree/OperatorName/PartialActivePatternDefinitionWithoutParameters.fs.bsl +++ b/tests/service/data/SyntaxTree/OperatorName/PartialActivePatternDefinitionWithoutParameters.fs.bsl @@ -16,12 +16,12 @@ ImplFile (SynIdent (|Boolean|_|, Some (HasParenthesis ((2,4--2,5), (2,16--2,17)))), false, - None, (2,5--2,16)), None, + None, (2,4--2,17)), None, LongIdent (false, SynLongIdent ([Boolean; parse], [(2,27--2,28)], [None; None]), None, - (2,20--2,33)), (2,5--2,16), Yes (2,0--2,33), + (2,20--2,33)), (2,4--2,17), Yes (2,0--2,33), { LeadingKeyword = Let (2,0--2,3) InlineKeyword = None EqualsRange = Some (2,18--2,19) })], (2,0--2,33))],