Skip to content

Commit 3792cff

Browse files
authored
Improve completions for union field patterns (#15754)
1 parent c65a076 commit 3792cff

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

src/Compiler/Service/ServiceParsedInputOps.fs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,20 +1269,29 @@ module ParsedInput =
12691269
else
12701270
let context = Some(PatternContext.NamedUnionCaseField(patId.idText, id.Range))
12711271
TryGetCompletionContextInPattern suppressIdentifierCompletions pat context pos)
1272-
| SynPat.LongIdent (argPats = SynArgPats.Pats pats; longDotId = id) ->
1272+
| SynPat.LongIdent (argPats = SynArgPats.Pats pats; longDotId = id; range = m) when rangeContainsPos m pos ->
12731273
match pats with
1274-
| [ SynPat.Named _ as pat ] ->
1275-
TryGetCompletionContextInPattern false pat (Some(PatternContext.PositionalUnionCaseField(None, id.Range))) pos
1274+
1275+
// fun (Some v| ) ->
1276+
| [ SynPat.Named _ ] -> Some(CompletionContext.Pattern(PatternContext.PositionalUnionCaseField(None, id.Range)))
1277+
1278+
// fun (Case (| )) ->
1279+
| [ SynPat.Paren (SynPat.Const (SynConst.Unit, _), m) ] when rangeContainsPos m pos ->
1280+
Some(CompletionContext.Pattern(PatternContext.PositionalUnionCaseField(Some 0, id.Range)))
1281+
1282+
// fun (Case (a| , b)) ->
12761283
| [ SynPat.Paren (SynPat.Tuple _ | SynPat.Named _ as pat, _) ] ->
12771284
TryGetCompletionContextInPattern false pat (Some(PatternContext.PositionalUnionCaseField(Some 0, id.Range))) pos
1285+
|> Option.orElseWith (fun () -> Some CompletionContext.Invalid)
1286+
12781287
| _ ->
12791288
pats
12801289
|> List.tryPick (fun pat -> TryGetCompletionContextInPattern false pat None pos)
12811290
| SynPat.Ands (pats = pats)
12821291
| SynPat.ArrayOrList (elementPats = pats) ->
12831292
pats
12841293
|> List.tryPick (fun pat -> TryGetCompletionContextInPattern suppressIdentifierCompletions pat None pos)
1285-
| SynPat.Tuple (elementPats = pats) ->
1294+
| SynPat.Tuple (elementPats = pats; commaRanges = commas; range = m) ->
12861295
pats
12871296
|> List.indexed
12881297
|> List.tryPick (fun (i, pat) ->
@@ -1295,6 +1304,15 @@ module ParsedInput =
12951304
None
12961305

12971306
TryGetCompletionContextInPattern suppressIdentifierCompletions pat context pos)
1307+
|> Option.orElseWith (fun () ->
1308+
// Last resort - check for fun (Case (a, | )) ->
1309+
// That is, pos is after the last comma and before the end of the tuple
1310+
match previousContext, List.tryLast commas with
1311+
| Some (PatternContext.PositionalUnionCaseField (_, caseIdRange)), Some mComma when
1312+
rangeBeforePos mComma pos && rangeContainsPos m pos
1313+
->
1314+
Some(CompletionContext.Pattern(PatternContext.PositionalUnionCaseField(Some(pats.Length - 1), caseIdRange)))
1315+
| _ -> None)
12981316
| SynPat.Named (range = m) when rangeContainsPos m pos ->
12991317
if suppressIdentifierCompletions then
13001318
Some CompletionContext.Invalid
@@ -1312,7 +1330,7 @@ module ParsedInput =
13121330
TryGetCompletionContextInPattern suppressIdentifierCompletions pat1 None pos
13131331
|> Option.orElseWith (fun () -> TryGetCompletionContextInPattern suppressIdentifierCompletions pat2 None pos)
13141332
| SynPat.IsInst (_, m) when rangeContainsPos m pos -> Some CompletionContext.Type
1315-
| SynPat.Wild m when rangeContainsPos m pos -> Some CompletionContext.Invalid
1333+
| SynPat.Wild m when rangeContainsPos m pos && m.StartColumn <> m.EndColumn -> Some CompletionContext.Invalid
13161334
| SynPat.Typed (pat = pat; targetType = synType) ->
13171335
if rangeContainsPos pat.Range pos then
13181336
TryGetCompletionContextInPattern suppressIdentifierCompletions pat previousContext pos

vsintegration/tests/FSharp.Editor.Tests/CompletionProviderTests.fs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,6 +1674,22 @@ let x (du: Du list) =
16741674
VerifyCompletionList(fileContents, "| [ C (first, rest); C (f", [ "option" ], [ "first" ])
16751675
VerifyCompletionList(fileContents, "| [ C (first, rest); C (f, l", [ "list" ], [ "rest" ])
16761676

1677+
[<Fact>]
1678+
let ``Completion list contains relevant items for the correct union case field pattern before its identifier has been typed`` () =
1679+
let fileContents =
1680+
"""
1681+
type Du =
1682+
| C of first: Du * second: Result<int, string>
1683+
1684+
let x du =
1685+
match du with
1686+
| C () -> ()
1687+
| C (first, ) -> ()
1688+
"""
1689+
1690+
VerifyCompletionList(fileContents, "| C (", [ "first"; "du" ], [ "second"; "result" ])
1691+
VerifyCompletionList(fileContents, "| C (first, ", [ "second"; "result" ], [ "first"; "du" ])
1692+
16771693
[<Fact>]
16781694
let ``Completion list contains suggested names for union case field pattern in a let binding, lambda and member`` () =
16791695
let fileContents =

0 commit comments

Comments
 (0)