Skip to content

Commit 34dbfc1

Browse files
authored
Code completion: fix getting qualifier expression in do statements in type decls (#18524)
1 parent cf6b53e commit 34dbfc1

File tree

4 files changed

+92
-34
lines changed

4 files changed

+92
-34
lines changed

docs/release-notes/.FSharp.Compiler.Service/9.0.300.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
* Allow `_` in `use!` bindings values (lift FS1228 restriction) ([PR #18487](https://github.com/dotnet/fsharp/pull/18487))
2929
* Make `[<CallerMemberName; Struct>]` combination work([PR #18444](https://github.com/dotnet/fsharp/pull/18444/))
3030
* Fix code completion considers types from own namespace non-imported ([PR #18518](https://github.com/dotnet/fsharp/issues/18518))
31+
* Code completion: fix getting qualifier expression in do statements in type decls ([PR #18524](https://github.com/dotnet/fsharp/pull/18524))
3132

3233
### Added
3334
* Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241))

src/Compiler/Service/ServiceParseTreeWalk.fs

+2
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,8 @@ module SyntaxTraversal =
10141014
let path = SyntaxNode.SynBinding b :: origPath
10151015

10161016
match b with
1017+
| SynBinding(kind = SynBindingKind.Do; expr = expr) -> traverseSynExpr path expr
1018+
10171019
| SynBinding(headPat = synPat; expr = synExpr; attributes = attributes; range = m) ->
10181020
[
10191021
yield! attributeApplicationDives path attributes

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

+10
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,16 @@ let rec allSymbolsInEntities compGen (entities: IList<FSharpEntity>) =
342342
yield! allSymbolsInEntities compGen entity.NestedEntities ]
343343

344344

345+
let getCursorPosAndPrepareSource (source: string) : string * string * pos =
346+
let lines = source.Split([|"\r\n"; "\n"|], StringSplitOptions.None)
347+
let line = lines |> Seq.findIndex _.Contains("{caret}")
348+
let lineText = lines[line]
349+
let column = lineText.IndexOf("{caret}")
350+
351+
let source = source.Replace("{caret}", "")
352+
let lineText = lineText.Replace("{caret}", "")
353+
source, lineText, Position.mkPos (line + 1) (column - 1)
354+
345355
let getParseResults (source: string) =
346356
parseSourceCode("Test.fsx", source)
347357

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

+79-34
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ open FSharp.Compiler.Service.Tests.Common
44
open FSharp.Compiler.EditorServices
55
open Xunit
66

7-
let getCompletionInfo lineText (line, column) source =
7+
let getCompletionInfo source =
8+
let source, lineText, pos = getCursorPosAndPrepareSource source
89
let parseResults, checkResults = getParseAndCheckResultsPreview source
9-
let plid = QuickParse.GetPartialLongNameEx(lineText, column)
10-
checkResults.GetDeclarationListInfo(Some parseResults, line, lineText, plid)
10+
let plid = QuickParse.GetPartialLongNameEx(lineText, pos.Column)
11+
checkResults.GetDeclarationListInfo(Some parseResults, pos.Line, lineText, plid)
1112

1213
let getCompletionItemNames (completionInfo: DeclarationListInfo) =
1314
completionInfo.Items |> Array.map (fun item -> item.NameInCode)
@@ -19,92 +20,100 @@ let assertHasItemWithNames names (completionInfo: DeclarationListInfo) =
1920
Assert.True(Set.contains name itemNames, $"{name} not found in {itemNames}")
2021

2122
[<Fact>]
22-
let ``Expr - After record decl`` () =
23-
let info = getCompletionInfo "{ Fi }" (4, 0) """
23+
let ``Expr - After record decl 01`` () =
24+
let info = getCompletionInfo """
2425
type Record = { Field: int }
2526
27+
{ Fi{caret} }
28+
"""
29+
assertHasItemWithNames ["ignore"] info
2630

31+
[<Fact>]
32+
let ``Expr - After record decl 02`` () =
33+
let info = getCompletionInfo """
34+
type Record = { Field: int }
35+
36+
{caret}
2737
"""
2838
assertHasItemWithNames ["ignore"] info
2939

3040
[<Fact>]
3141
let ``Expr - record - field 01 - anon module`` () =
32-
let info = getCompletionInfo "{ Fi }" (4, 3) """
42+
let info = getCompletionInfo """
3343
type Record = { Field: int }
3444
35-
{ Fi }
45+
{ Fi{caret} }
3646
"""
3747
assertHasItemWithNames ["Field"] info
3848

3949
[<Fact>]
4050
let ``Expr - record - field 02 - anon module`` () =
41-
let info = getCompletionInfo "{ Fi }" (6, 3) """
51+
let info = getCompletionInfo """
4252
type Record = { Field: int }
4353
4454
let record = { Field = 1 }
4555
46-
{ Fi }
56+
{ Fi{caret} }
4757
"""
4858
assertHasItemWithNames ["Field"] info
4959

5060
[<Fact>]
5161
let ``Expr - record - empty 01`` () =
52-
let info = getCompletionInfo "{ }" (4, 2) """
62+
let info = getCompletionInfo """
5363
type Record = { Field: int }
5464
55-
{ }
65+
{ {caret} }
5666
"""
5767
assertHasItemWithNames ["Field"] info
5868

5969
[<Fact>]
6070
let ``Expr - record - empty 02`` () =
61-
let info = getCompletionInfo "{ }" (6, 2) """
71+
let info = getCompletionInfo """
6272
type Record = { Field: int }
6373
6474
let record = { Field = 1 }
6575
66-
{ }
76+
{ {caret} }
6777
"""
6878
assertHasItemWithNames ["Field"; "record"] info
6979

7080
[<Fact>]
7181
let ``Underscore dot lambda - completion`` () =
72-
let info = getCompletionInfo " |> _.Len" (4, 11) """
82+
let info = getCompletionInfo """
7383
let myFancyFunc (x:string) =
7484
x
75-
|> _.Len"""
85+
|> _.Len{caret}"""
7686
assertHasItemWithNames ["Length"] info
7787

7888
[<Fact>]
7989
let ``Underscore dot lambda - method completion`` () =
80-
let info = getCompletionInfo " |> _.ToL" (4, 11) """
90+
let info = getCompletionInfo """
8191
let myFancyFunc (x:string) =
8292
x
83-
|> _.ToL"""
93+
|> _.ToL{caret}"""
8494
assertHasItemWithNames ["ToLower"] info
8595

8696
[<Fact>]
8797
let ``Underscore dot lambda - No prefix`` () =
88-
let info = getCompletionInfo "[s] |> List.map _. " (3, 18) """
98+
let info = getCompletionInfo """
8999
let s = ""
90-
[s] |> List.map _.
100+
[s] |> List.map _.{caret}
91101
"""
92102
assertHasItemWithNames ["Length"] info
93103

94104
[<Fact>]
95105
let ``Type decl - Record - Field type 01`` () =
96-
let info = getCompletionInfo "type Record = { Field: }" (2, 23) """
97-
type Record = { Field: }
106+
let info = getCompletionInfo """
107+
type Record = { Field: {caret} }
98108
"""
99109
assertHasItemWithNames ["string"] info
100110

101111

102112
[<Fact>]
103113
let ``Expr - Qualifier 01`` () =
104-
let info =
105-
getCompletionInfo "s.Trim(). " (3, 13) """
114+
let info = getCompletionInfo """
106115
let f (s: string) =
107-
s.Trim().
116+
s.Trim().{caret}
108117
s.Trim()
109118
s.Trim()
110119
()
@@ -114,10 +123,10 @@ let f (s: string) =
114123
[<Fact>]
115124
let ``Expr - Qualifier 02`` () =
116125
let info =
117-
getCompletionInfo "s.Trim(). " (4, 13) """
126+
getCompletionInfo """
118127
let f (s: string) =
119128
s.Trim()
120-
s.Trim().
129+
s.Trim().{caret}
121130
s.Trim()
122131
()
123132
"""
@@ -126,20 +135,56 @@ let f (s: string) =
126135
[<Fact>]
127136
let ``Expr - Qualifier 03`` () =
128137
let info =
129-
getCompletionInfo "s.Trim(). " (5, 13) """
138+
getCompletionInfo """
130139
let f (s: string) =
131140
s.Trim()
132141
s.Trim()
133-
s.Trim().
142+
s.Trim().{caret}
134143
()
135144
"""
136145
assertHasItemWithNames ["Length"] info
137146

147+
[<Fact>]
148+
let ``Expr - Qualifier 04`` () =
149+
let info =
150+
getCompletionInfo """
151+
type T() =
152+
do
153+
System.String.Empty.ToString().L{caret}
154+
"""
155+
assertHasItemWithNames ["Length"] info
156+
157+
[<Fact>]
158+
let ``Expr - Qualifier 05`` () =
159+
let info =
160+
getCompletionInfo """
161+
System.String.Empty.ToString().{caret}
162+
"""
163+
assertHasItemWithNames ["Length"] info
164+
165+
[<Fact>]
166+
let ``Expr - Qualifier 06`` () =
167+
let info =
168+
getCompletionInfo """
169+
System.String.Empty.ToString().L{caret}
170+
"""
171+
assertHasItemWithNames ["Length"] info
172+
173+
[<Fact>]
174+
let ``Expr - Qualifier 07`` () =
175+
let info =
176+
getCompletionInfo """
177+
type T() =
178+
do
179+
System.String.Empty.ToString().L{caret}
180+
()
181+
"""
182+
assertHasItemWithNames ["Length"] info
138183

139184
[<Fact>]
140185
let ``Import - Ns 01`` () =
141186
let info =
142-
getCompletionInfo "let _: R " (14, 12) """
187+
getCompletionInfo """
143188
namespace Ns
144189
145190
type Rec1 = { F: int }
@@ -153,14 +198,14 @@ module M =
153198
154199
type Rec3 = { F: int }
155200
156-
let _: R = ()
201+
let _: R{caret} = ()
157202
"""
158203
assertHasItemWithNames ["Rec1"; "Rec2"; "Rec3"] info
159204

160205
[<Fact>]
161206
let ``Import - Ns 02 - Rec`` () =
162207
let info =
163-
getCompletionInfo "let _: R " (14, 12) """
208+
getCompletionInfo """
164209
namespace Ns
165210
166211
type Rec1 = { F: int }
@@ -174,14 +219,14 @@ module M =
174219
175220
type Rec3 = { F: int }
176221
177-
let _: R = ()
222+
let _: R{caret} = ()
178223
"""
179224
assertHasItemWithNames ["Rec1"; "Rec2"; "Rec3"] info
180225

181226
[<Fact>]
182227
let ``Import - Ns 03 - Rec`` () =
183228
let info =
184-
getCompletionInfo "let _: R " (14, 12) """
229+
getCompletionInfo """
185230
namespace Ns
186231
187232
type Rec1 = { F: int }
@@ -195,6 +240,6 @@ module rec M =
195240
196241
type Rec3 = { F: int }
197242
198-
let _: R = ()
243+
let _: R{caret} = ()
199244
"""
200245
assertHasItemWithNames ["Rec1"; "Rec2"; "Rec3"] info

0 commit comments

Comments
 (0)