Skip to content

Commit 8ff4bd7

Browse files
committed
special handling of optional fields when destructuring
1 parent 4919335 commit 8ff4bd7

File tree

5 files changed

+61
-11
lines changed

5 files changed

+61
-11
lines changed

analysis/src/CompletionBackEnd.ml

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,10 +1047,10 @@ let printConstructorArgs argsLen ~asSnippet =
10471047
if List.length !args > 0 then "(" ^ (!args |> String.concat ", ") ^ ")"
10481048
else ""
10491049

1050-
type completionMode = Pattern | Expression
1050+
type completionMode = Pattern of Completable.patternMode option | Expression
10511051

1052-
let rec completeTypedValue (t : SharedTypes.completionType) ~full ~prefix
1053-
~completionContext ~mode =
1052+
let rec completeTypedValue ~full ~prefix ~completionContext ~mode
1053+
(t : SharedTypes.completionType) =
10541054
match t with
10551055
| Tbool env ->
10561056
[
@@ -1142,10 +1142,23 @@ let rec completeTypedValue (t : SharedTypes.completionType) ~full ~prefix
11421142
|> List.filter (fun (field : field) ->
11431143
List.mem field.fname.txt seenFields = false)
11441144
|> List.map (fun (field : field) ->
1145-
Completion.create field.fname.txt
1146-
~kind:
1147-
(Field (field, TypeUtils.extractedTypeToString extractedType))
1148-
~env)
1145+
match (field.optional, mode) with
1146+
| true, Pattern (Some Destructuring) ->
1147+
Completion.create ("?" ^ field.fname.txt)
1148+
~docstring:
1149+
[
1150+
field.fname.txt
1151+
^ " is an optional field, and needs to be destructured \
1152+
using '?'.";
1153+
]
1154+
~kind:
1155+
(Field (field, TypeUtils.extractedTypeToString extractedType))
1156+
~env
1157+
| _ ->
1158+
Completion.create field.fname.txt
1159+
~kind:
1160+
(Field (field, TypeUtils.extractedTypeToString extractedType))
1161+
~env)
11491162
|> filterItems ~prefix
11501163
| None ->
11511164
if prefix = "" then
@@ -1157,7 +1170,7 @@ let rec completeTypedValue (t : SharedTypes.completionType) ~full ~prefix
11571170
(ExtractedType
11581171
( extractedType,
11591172
match mode with
1160-
| Pattern -> `Type
1173+
| Pattern _ -> `Type
11611174
| Expression -> `Value ))
11621175
~env ();
11631176
]
@@ -1190,7 +1203,7 @@ let rec completeTypedValue (t : SharedTypes.completionType) ~full ~prefix
11901203
(ExtractedType
11911204
( typ,
11921205
match mode with
1193-
| Pattern -> `Type
1206+
| Pattern _ -> `Type
11941207
| Expression -> `Value ))
11951208
~env ();
11961209
]
@@ -1360,7 +1373,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover
13601373
Utils.startsWith name prefix
13611374
&& (forHover || not (List.mem name identsSeen)))
13621375
|> List.map mkLabel
1363-
| Cpattern {contextPath; prefix; nested; fallback} -> (
1376+
| Cpattern {contextPath; prefix; nested; fallback; patternMode} -> (
13641377
let fallbackOrEmpty ?items () =
13651378
match (fallback, items) with
13661379
| Some fallback, (None | Some []) ->
@@ -1385,7 +1398,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover
13851398
| Some (typ, _env, completionContext) ->
13861399
let items =
13871400
typ
1388-
|> completeTypedValue ~mode:Pattern ~full ~prefix ~completionContext
1401+
|> completeTypedValue ~mode:(Pattern patternMode) ~full ~prefix
1402+
~completionContext
13891403
in
13901404
fallbackOrEmpty ~items ())
13911405
| None -> fallbackOrEmpty ())

analysis/src/CompletionFrontEnd.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
317317
prefix;
318318
nested = List.rev nestedPattern;
319319
fallback = None;
320+
patternMode = None;
320321
})
321322
| _ -> ()
322323
in
@@ -391,6 +392,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
391392
nested = [];
392393
prefix = "";
393394
fallback = None;
395+
patternMode = None;
394396
}))
395397
| Pexp_match (exp, cases) -> (
396398
(* If there's more than one case, or the case isn't a pattern hole, figure out if we're completing another
@@ -423,6 +425,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
423425
nested = [];
424426
prefix = "";
425427
fallback = None;
428+
patternMode = None;
426429
})
427430
| false, false -> ()))
428431
| _ -> unsetLookingForPat ()
@@ -524,6 +527,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
524527
prefix;
525528
nested = List.rev nested;
526529
fallback = None;
530+
patternMode = Some Destructuring;
527531
})
528532
| _ -> ())
529533
| _ -> ());

analysis/src/SharedTypes.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,8 @@ module Completable = struct
631631
^ ")"
632632
| NArray -> "array"
633633

634+
type patternMode = Destructuring
635+
634636
type t =
635637
| Cdecorator of string (** e.g. @module *)
636638
| CnamedArg of contextPath * string * string list
@@ -648,6 +650,7 @@ module Completable = struct
648650
contextPath: contextPath;
649651
nested: nestedPath list;
650652
prefix: string;
653+
patternMode: patternMode option;
651654
fallback: t option;
652655
}
653656
| CexhaustiveSwitch of {contextPath: contextPath; exprLoc: Location.t}

analysis/tests/src/Destructuring.res

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,15 @@ let f2 = (x: x) => {
1919
// ^com
2020
ignore(x)
2121
}
22+
23+
type recordWithOptField = {
24+
someField: int,
25+
someOptField?: bool
26+
}
27+
28+
let x: recordWithOptField = {
29+
someField: 123
30+
}
31+
32+
// let {} = x
33+
// ^com

analysis/tests/src/expected/Destructuring.res.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,20 @@ Completable: Cpattern Value[x]->recordBody
5858
"documentation": null
5959
}]
6060

61+
Complete src/Destructuring.res 31:8
62+
posCursor:[31:8] posNoWhite:[31:7] Found pattern:[31:7->31:9]
63+
Completable: Cpattern Value[x]->recordBody
64+
[{
65+
"label": "someField",
66+
"kind": 5,
67+
"tags": [],
68+
"detail": "someField: int\n\nrecordWithOptField",
69+
"documentation": null
70+
}, {
71+
"label": "?someOptField",
72+
"kind": 5,
73+
"tags": [],
74+
"detail": "?someOptField: option<bool>\n\nrecordWithOptField",
75+
"documentation": {"kind": "markdown", "value": "someOptField is an optional field, and needs to be destructured using '?'."}
76+
}]
77+

0 commit comments

Comments
 (0)