Skip to content

Commit c2b8620

Browse files
committed
Tests/source context: allow specifying selection
1 parent 9425e4d commit c2b8620

File tree

1 file changed

+80
-11
lines changed

1 file changed

+80
-11
lines changed

tests/FSharp.Compiler.Service.Tests/Checker.fs

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@ open System
44
open FSharp.Compiler.CodeAnalysis
55
open FSharp.Compiler.EditorServices
66
open FSharp.Compiler.Text
7+
open FSharp.Compiler.Text.Range
78
open FSharp.Compiler.Tokenization
89

910
type SourceContext =
1011
{ Source: string
1112
LineText: string
12-
CaretPos: pos }
13+
CaretPos: pos
14+
SelectedRange: range option }
1315

1416
type ResolveContext =
1517
{ SourceContext: SourceContext
1618
Pos: pos
17-
Names: string list }
19+
Names: string list
20+
SelectedRange: range option }
1821

1922
member this.Source = this.SourceContext.Source
2023
member this.LineText = this.SourceContext.LineText
@@ -29,16 +32,82 @@ type CodeCompletionContext =
2932

3033
[<RequireQualifiedAccess>]
3134
module SourceContext =
35+
let private markers = ["{caret}"; "{selstart}"; "{selend}"]
36+
37+
let getLines (source: string) =
38+
source.Split([|"\r\n"; "\n"|], StringSplitOptions.None)
39+
40+
let rec private extractMarkersOnLine markersAcc (line, lineText: string) =
41+
let markersOnLine =
42+
markers
43+
|> List.choose (fun (marker: string) ->
44+
match lineText.IndexOf(marker) with
45+
| -1 -> None
46+
| column -> Some(marker, column)
47+
)
48+
49+
if markersOnLine.IsEmpty then
50+
markersAcc
51+
else
52+
let marker, column = List.minBy snd markersOnLine
53+
54+
let markerPos =
55+
let column =
56+
match marker with
57+
| "{caret}" -> column - 1
58+
| _ -> column
59+
60+
Position.mkPos (line + 1) column
61+
62+
if markersAcc |> List.map fst |> List.contains marker then
63+
failwith $"Duplicate marker: {marker}"
64+
65+
let markersAcc = (marker, markerPos) :: markersAcc
66+
let lineText = lineText.Replace(marker, "")
67+
68+
extractMarkersOnLine markersAcc (line, lineText)
69+
3270
let fromMarkedSource (markedSource: string) : SourceContext =
33-
let lines = markedSource.Split([|"\r\n"; "\n"|], StringSplitOptions.None)
34-
let line = lines |> Seq.findIndex _.Contains("{caret}")
35-
let lineText = lines[line]
36-
let column = lineText.IndexOf("{caret}")
71+
let markerPositions =
72+
getLines markedSource
73+
|> Seq.indexed
74+
|> Seq.fold extractMarkersOnLine []
75+
76+
let source =
77+
markerPositions
78+
|> List.map fst
79+
|> List.fold (fun (source: string) marker -> source.Replace(marker, "")) markedSource
80+
81+
let markerPositions = markerPositions |> dict
82+
83+
let tryGetPos marker =
84+
match markerPositions.TryGetValue(marker) with
85+
| true, pos -> Some pos
86+
| _ -> None
87+
88+
let caretPos, selectedRange =
89+
match tryGetPos "{caret}", tryGetPos "{selstart}", tryGetPos "{selend}" with
90+
| Some caretPos, None, None ->
91+
caretPos, None
92+
93+
| Some caretPos, Some startPos, Some endPos ->
94+
let selectedRange = mkRange "Test.fsx" startPos endPos
95+
caretPos, Some selectedRange
96+
97+
| None, Some startPos, Some endPos ->
98+
let selectedRange = mkRange "Test.fsx" startPos endPos
99+
let caretPos = Position.mkPos endPos.Line (endPos.Column - 1)
100+
caretPos, Some selectedRange
101+
102+
| _, None, Some _ -> failwith "Missing selected range start"
103+
| _, Some _, None -> failwith "Missing selected range end"
104+
105+
| None, None, None -> failwith "Missing caret marker"
106+
107+
let lines = getLines source
108+
let lineText = Array.get lines (caretPos.Line - 1)
37109

38-
let source = markedSource.Replace("{caret}", "")
39-
let pos = Position.mkPos (line + 1) (column - 1)
40-
let lineText = lineText.Replace("{caret}", "")
41-
{ Source = source; CaretPos = pos; LineText = lineText }
110+
{ Source = source; CaretPos = caretPos; LineText = lineText; SelectedRange = selectedRange }
42111

43112

44113
[<AutoOpen>]
@@ -70,7 +139,7 @@ module Checker =
70139

71140
let plid = QuickParse.GetPartialLongNameEx(context.LineText, pos.Column - 1)
72141
let names = plid.QualifyingIdents @ [plid.PartialIdent]
73-
{ SourceContext = context; Pos = pos; Names = names }
142+
{ SourceContext = context; Pos = pos; Names = names; SelectedRange = context.SelectedRange }
74143

75144
let getCompletionContext (markedSource: string) =
76145
let context = SourceContext.fromMarkedSource markedSource

0 commit comments

Comments
 (0)