diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md index 6a2048ef27a..a10c2fd1568 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md @@ -13,6 +13,7 @@ ### Added * Add FSharpCodeCompletionOptions ([PR #19030](https://github.com/dotnet/fsharp/pull/19030)) +* Debugger: provide breakpoint ranges for short lambdas ([#19067](https://github.com/dotnet/fsharp/pull/19067)) ### Changed diff --git a/src/Compiler/Service/FSharpParseFileResults.fs b/src/Compiler/Service/FSharpParseFileResults.fs index f5c1d978447..07eb010a767 100644 --- a/src/Compiler/Service/FSharpParseFileResults.fs +++ b/src/Compiler/Service/FSharpParseFileResults.fs @@ -525,7 +525,6 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, match expr with | SynExpr.ArbitraryAfterError _ | SynExpr.LongIdent _ - | SynExpr.DotLambda _ | SynExpr.LibraryOnlyILAssembly _ | SynExpr.LibraryOnlyStaticOptimization _ | SynExpr.Null _ @@ -762,6 +761,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, yield! walkExpr false e2 yield! walkExpr false e3 + | SynExpr.DotLambda(_, m, _) -> yield! checkRange m + ] // Process a class declaration or F# type declaration diff --git a/tests/FSharp.Compiler.Service.Tests/BreakpointLocationTests.fs b/tests/FSharp.Compiler.Service.Tests/BreakpointLocationTests.fs new file mode 100644 index 00000000000..04c508d6730 --- /dev/null +++ b/tests/FSharp.Compiler.Service.Tests/BreakpointLocationTests.fs @@ -0,0 +1,57 @@ +module FSharp.Compiler.Service.Tests.BreakpointLocationTests + +open FSharp.Compiler.Text +open FSharp.Compiler.Text.Range +open FSharp.Test.Assert +open Xunit + +let assertBreakpointRange ((startLine, startCol), (endLine, endCol)) markedSource = + let context, parseResults = Checker.getParseResultsWithContext markedSource + let breakpointRange = parseResults.ValidateBreakpointLocation(context.CaretPos).Value + + let startPos = Position.mkPos startLine startCol + let endPod = Position.mkPos endLine endCol + let expectedRange = mkFileIndexRange breakpointRange.FileIndex startPos endPod + + breakpointRange |> shouldEqual expectedRange + +[] +let ``Let - Function - Body 01`` () = + assertBreakpointRange ((3, 4), (3, 5)) """ +let f () = + 1{caret} +""" + +[] +let ``Seq 01`` () = + assertBreakpointRange ((3, 4), (3, 5)) """ +do + 1{caret} + 2 +""" + +[] +let ``Seq 02`` () = + assertBreakpointRange ((4, 4), (4, 5)) """ +do + 1 + 2{caret} +""" + +[] +let ``Lambda 01`` () = + assertBreakpointRange ((2, 27), (2, 35)) """ +[""] |> List.map (fun s -> s.Lenght{caret}) +""" + +[] +let ``Dot lambda 01`` () = + assertBreakpointRange ((2, 17), (2, 25)) """ +[""] |> List.map _.Lenght{caret} +""" + +[] +let ``Dot lambda 02`` () = + assertBreakpointRange ((2, 17), (2, 36)) """ +[""] |> List.map _.ToString().Length{caret} +""" diff --git a/tests/FSharp.Compiler.Service.Tests/Checker.fs b/tests/FSharp.Compiler.Service.Tests/Checker.fs index 82b015f4bd1..5d16f87783d 100644 --- a/tests/FSharp.Compiler.Service.Tests/Checker.fs +++ b/tests/FSharp.Compiler.Service.Tests/Checker.fs @@ -147,6 +147,11 @@ module Checker = let names = plid.QualifyingIdents @ [plid.PartialIdent] { SourceContext = context; Pos = context.CaretPos; PartialIdentifier = plid } + let getParseResultsWithContext (markedSource: string) = + let context = SourceContext.fromMarkedSource markedSource + let parseResults = getParseFileResults "Test.fsx" context.Source + context, parseResults + let getCheckedResolveContext (markedSource: string) = let context = getResolveContext markedSource let _, checkResults = getParseAndCheckResults context.Source diff --git a/tests/FSharp.Compiler.Service.Tests/Common.fs b/tests/FSharp.Compiler.Service.Tests/Common.fs index db316223e68..e54541c0444 100644 --- a/tests/FSharp.Compiler.Service.Tests/Common.fs +++ b/tests/FSharp.Compiler.Service.Tests/Common.fs @@ -188,7 +188,7 @@ let parseAndCheckScript50 (file, input) = parseAndCheckScriptWithOptions (file, let parseAndCheckScript70 (file, input) = parseAndCheckScriptWithOptions (file, input, [| "--langversion:7.0" |]) let parseAndCheckScriptPreview (file, input) = parseAndCheckScriptWithOptions (file, input, [| "--langversion:preview" |]) -let parseSourceCode (name: string, code: string) = +let getParseFileResults (name: string) (code: string) = let location = Path.Combine(Path.GetTempPath(),"test"+string(hash (name, code))) try Directory.CreateDirectory(location) |> ignore with _ -> () let filePath = Path.Combine(location, name) @@ -197,6 +197,10 @@ let parseSourceCode (name: string, code: string) = let options, _errors = checker.GetParsingOptionsFromCommandLineArgs(List.ofArray args) let parseResults = checker.ParseFile(filePath, SourceText.ofString code, options) |> Async.RunImmediate Range.setTestSource filePath code + parseResults + +let parseSourceCode (name: string, code: string) : ParsedInput = + let parseResults = getParseFileResults name code parseResults.ParseTree let matchBraces (name: string, code: string) = diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj index d411f07b520..1244517a4c9 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj @@ -28,6 +28,7 @@ +