Skip to content

Commit d332f85

Browse files
authored
Fix nested pattern completion with trailing comma (#906)
* only check for pattern completions if the associated expression does not have the cursor * changelog
1 parent 4653a00 commit d332f85

File tree

5 files changed

+76
-10
lines changed

5 files changed

+76
-10
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
- Prefer Core's `RegExp` when Core is open and completing for regexp functions. https://github.com/rescript-lang/rescript-vscode/pull/903
1818
- Add `%re("")` to the completions list when completing in a position where a regexp value is expected. https://github.com/rescript-lang/rescript-vscode/pull/903
1919

20+
#### :bug: Bug Fix
21+
22+
- Fix issue with completion in nested patterns that would make it not possible to complete for new record fields via trailing commas in certain situations. https://github.com/rescript-lang/rescript-vscode/pull/906
23+
2024
## 1.36.0
2125

2226
#### :bug: Bug Fix

analysis/src/CompletionFrontEnd.ml

+6-2
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
494494
contextPath )
495495
with
496496
| Some (prefix, nestedPattern), Some ctxPath ->
497+
if Debug.verbose () then
498+
Printf.printf "[completePattern] found pattern that can be completed\n";
497499
setResult
498500
(Completable.Cpattern
499501
{
@@ -910,7 +912,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
910912
cases
911913
|> List.iter (fun (case : Parsetree.case) ->
912914
let oldScope = !scope in
913-
completePattern ?contextPath:ctxPath case.pc_lhs;
915+
if locHasCursor case.pc_rhs.pexp_loc = false then
916+
completePattern ?contextPath:ctxPath case.pc_lhs;
914917
scopePattern ?contextPath:ctxPath case.pc_lhs;
915918
Ast_iterator.default_iterator.case iterator case;
916919
scope := oldScope);
@@ -1182,7 +1185,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
11821185
(match defaultExpOpt with
11831186
| None -> ()
11841187
| Some defaultExp -> iterator.expr iterator defaultExp);
1185-
completePattern ?contextPath:argContextPath pat;
1188+
if locHasCursor e.pexp_loc = false then
1189+
completePattern ?contextPath:argContextPath pat;
11861190
scopePattern ?contextPath:argContextPath pat;
11871191
iterator.pat iterator pat;
11881192
iterator.expr iterator e;

analysis/src/CompletionPatterns.ml

+25-8
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,14 @@ let rec traverseTupleItems tupleItems ~nextPatternPath ~resultFromFoundItemNum
3535

3636
and traversePattern (pat : Parsetree.pattern) ~patternPath ~locHasCursor
3737
~firstCharBeforeCursorNoWhite ~posBeforeCursor =
38-
let someIfHasCursor v =
39-
if locHasCursor pat.Parsetree.ppat_loc then Some v else None
38+
let someIfHasCursor v debugId =
39+
if locHasCursor pat.Parsetree.ppat_loc then (
40+
if Debug.verbose () then
41+
Printf.printf
42+
"[traversePattern:someIfHasCursor] '%s' has cursor, returning \n"
43+
debugId;
44+
Some v)
45+
else None
4046
in
4147
match pat.ppat_desc with
4248
| Ppat_constant _ | Ppat_interval _ -> None
@@ -57,21 +63,28 @@ and traversePattern (pat : Parsetree.pattern) ~patternPath ~locHasCursor
5763
~firstCharBeforeCursorNoWhite ~posBeforeCursor)
5864
in
5965
match orPatWithItem with
60-
| None when isPatternHole p1 || isPatternHole p2 -> Some ("", patternPath)
66+
| None when isPatternHole p1 || isPatternHole p2 ->
67+
if Debug.verbose () then
68+
Printf.printf
69+
"[traversePattern] found or-pattern that was pattern hole\n";
70+
Some ("", patternPath)
6171
| v -> v)
6272
| Ppat_any ->
6373
(* We treat any `_` as an empty completion. This is mainly because we're
6474
inserting `_` in snippets and automatically put the cursor there. So
6575
letting it trigger an empty completion improves the ergonomics by a
6676
lot. *)
67-
someIfHasCursor ("", patternPath)
68-
| Ppat_var {txt} -> someIfHasCursor (txt, patternPath)
77+
someIfHasCursor ("", patternPath) "Ppat_any"
78+
| Ppat_var {txt} -> someIfHasCursor (txt, patternPath) "Ppat_var"
6979
| Ppat_construct ({txt = Lident "()"}, None) ->
7080
(* switch s { | (<com>) }*)
71-
someIfHasCursor ("", patternPath @ [Completable.NTupleItem {itemNum = 0}])
81+
someIfHasCursor
82+
("", patternPath @ [Completable.NTupleItem {itemNum = 0}])
83+
"Ppat_construct()"
7284
| Ppat_construct ({txt = Lident prefix}, None) ->
73-
someIfHasCursor (prefix, patternPath)
74-
| Ppat_variant (prefix, None) -> someIfHasCursor ("#" ^ prefix, patternPath)
85+
someIfHasCursor (prefix, patternPath) "Ppat_construct(Lident)"
86+
| Ppat_variant (prefix, None) ->
87+
someIfHasCursor ("#" ^ prefix, patternPath) "Ppat_variant"
7588
| Ppat_array arrayPatterns ->
7689
let nextPatternPath = [Completable.NArray] @ patternPath in
7790
if List.length arrayPatterns = 0 && locHasCursor pat.ppat_loc then
@@ -94,6 +107,7 @@ and traversePattern (pat : Parsetree.pattern) ~patternPath ~locHasCursor
94107
(* Empty fields means we're in a record body `{}`. Complete for the fields. *)
95108
someIfHasCursor
96109
("", [Completable.NRecordBody {seenFields = []}] @ patternPath)
110+
"Ppat_record(empty)"
97111
| Ppat_record (fields, _) -> (
98112
let fieldWithCursor = ref None in
99113
let fieldWithPatHole = ref None in
@@ -125,10 +139,12 @@ and traversePattern (pat : Parsetree.pattern) ~patternPath ~locHasCursor
125139
( "",
126140
[Completable.NFollowRecordField {fieldName = fname}] @ patternPath
127141
)
142+
"patternhole"
128143
| Ppat_var {txt} ->
129144
(* A var means `{s}` or similar. Complete for fields. *)
130145
someIfHasCursor
131146
(txt, [Completable.NRecordBody {seenFields}] @ patternPath)
147+
"Ppat_var #2"
132148
| _ ->
133149
f
134150
|> traversePattern
@@ -145,6 +161,7 @@ and traversePattern (pat : Parsetree.pattern) ~patternPath ~locHasCursor
145161
| Some ',' ->
146162
someIfHasCursor
147163
("", [Completable.NRecordBody {seenFields}] @ patternPath)
164+
"firstCharBeforeCursorNoWhite:,"
148165
| _ -> None))
149166
| Ppat_construct
150167
( {txt},

analysis/tests/src/CompletionPattern.res

+11
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,14 @@ let res: result<someVariant, somePolyVariant> = Ok(One)
219219

220220
// switch res { | Error() }
221221
// ^com
222+
223+
@react.component
224+
let make = (~thing: result<someVariant, unit>) => {
225+
switch thing {
226+
| Ok(Three(r, _)) =>
227+
let _x = r
228+
// switch r { | {first, }}
229+
// ^com
230+
| _ => ()
231+
}
232+
}

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

+30
Original file line numberDiff line numberDiff line change
@@ -1177,3 +1177,33 @@ Path res
11771177
"insertTextFormat": 2
11781178
}]
11791179

1180+
Complete src/CompletionPattern.res 227:25
1181+
posCursor:[227:25] posNoWhite:[227:24] Found expr:[223:11->231:1]
1182+
posCursor:[227:25] posNoWhite:[227:24] Found expr:[223:12->231:1]
1183+
posCursor:[227:25] posNoWhite:[227:24] Found expr:[226:4->227:28]
1184+
posCursor:[227:25] posNoWhite:[227:24] Found pattern:[227:18->227:27]
1185+
Completable: Cpattern Value[r]->recordBody
1186+
Package opens Pervasives.JsxModules.place holder
1187+
Resolved opens 1 pervasives
1188+
ContextPath Value[r]
1189+
Path r
1190+
[{
1191+
"label": "second",
1192+
"kind": 5,
1193+
"tags": [],
1194+
"detail": "second: (bool, option<someRecord>)\n\nsomeRecord",
1195+
"documentation": null
1196+
}, {
1197+
"label": "optThird",
1198+
"kind": 5,
1199+
"tags": [],
1200+
"detail": "optThird: option<[#first | #second(someRecord)]>\n\nsomeRecord",
1201+
"documentation": null
1202+
}, {
1203+
"label": "nest",
1204+
"kind": 5,
1205+
"tags": [],
1206+
"detail": "nest: nestedRecord\n\nsomeRecord",
1207+
"documentation": null
1208+
}]
1209+

0 commit comments

Comments
 (0)