Skip to content

Commit 34c4a3b

Browse files
authored
Extend code action that expands catch all (#988)
* handle ppat_or and guards in code action for expanding catch alls * set mode properly
1 parent 0f2ab3b commit 34c4a3b

File tree

3 files changed

+169
-40
lines changed

3 files changed

+169
-40
lines changed

analysis/src/Xform.ml

+21-31
Original file line numberDiff line numberDiff line change
@@ -392,15 +392,28 @@ module ExpandCatchAllForVariants = struct
392392
if Debug.verbose () then
393393
print_endline
394394
"[codeAction - ExpandCatchAllForVariants] Found target switch";
395-
let currentConstructorNames =
395+
let rec findAllConstructorNames ?(mode : [`option | `default] = `default)
396+
?(constructorNames = []) (p : Parsetree.pattern) =
397+
match p.ppat_desc with
398+
| Ppat_construct ({txt = Lident "Some"}, Some payload)
399+
when mode = `option ->
400+
findAllConstructorNames ~mode ~constructorNames payload
401+
| Ppat_construct ({txt}, _) -> Longident.last txt :: constructorNames
402+
| Ppat_variant (name, _) -> name :: constructorNames
403+
| Ppat_or (a, b) ->
404+
findAllConstructorNames ~mode ~constructorNames a
405+
@ findAllConstructorNames ~mode ~constructorNames b
406+
@ constructorNames
407+
| _ -> constructorNames
408+
in
409+
let getCurrentConstructorNames ?mode cases =
396410
cases
397-
|> List.filter_map (fun (c : Parsetree.case) ->
398-
match c with
399-
| {pc_lhs = {ppat_desc = Ppat_construct ({txt}, _)}} ->
400-
Some (Longident.last txt)
401-
| {pc_lhs = {ppat_desc = Ppat_variant (name, _)}} -> Some name
402-
| _ -> None)
411+
|> List.map (fun (c : Parsetree.case) ->
412+
if Option.is_some c.pc_guard then []
413+
else findAllConstructorNames ?mode c.pc_lhs)
414+
|> List.flatten
403415
in
416+
let currentConstructorNames = getCurrentConstructorNames cases in
404417
match
405418
switchExpr
406419
|> extractTypeFromExpr ~debug ~path ~currentFile ~full
@@ -469,30 +482,7 @@ module ExpandCatchAllForVariants = struct
469482
match innerType with
470483
| Some ((Tvariant _ | Tpolyvariant _) as variant) ->
471484
let currentConstructorNames =
472-
cases
473-
|> List.filter_map (fun (c : Parsetree.case) ->
474-
match c with
475-
| {
476-
pc_lhs =
477-
{
478-
ppat_desc =
479-
Ppat_construct
480-
( {txt = Lident "Some"},
481-
Some {ppat_desc = Ppat_construct ({txt}, _)} );
482-
};
483-
} ->
484-
Some (Longident.last txt)
485-
| {
486-
pc_lhs =
487-
{
488-
ppat_desc =
489-
Ppat_construct
490-
( {txt = Lident "Some"},
491-
Some {ppat_desc = Ppat_variant (name, _)} );
492-
};
493-
} ->
494-
Some name
495-
| _ -> None)
485+
getCurrentConstructorNames ~mode:`option cases
496486
in
497487
let hasNoneCase =
498488
cases

analysis/tests/src/Xform.res

+37
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,19 @@ let _x = switch variant {
8282
// ^xfm
8383
}
8484

85+
let _x = switch variant {
86+
| First | Second => "first"
87+
| _ => "other"
88+
// ^xfm
89+
}
90+
91+
let _x = switch variant {
92+
| First if 1 > 2 => "first"
93+
| Second => "second"
94+
| _ => "other"
95+
// ^xfm
96+
}
97+
8598
let polyvariant: [#first | #second | #"illegal identifier" | #third(int)] = #first
8699

87100
let _y = switch polyvariant {
@@ -90,6 +103,12 @@ let _y = switch polyvariant {
90103
// ^xfm
91104
}
92105

106+
let _y = switch polyvariant {
107+
| #first | #second => "first"
108+
| _ => "other"
109+
// ^xfm
110+
}
111+
93112
let variantOpt = Some(variant)
94113

95114
let _x = switch variantOpt {
@@ -98,6 +117,18 @@ let _x = switch variantOpt {
98117
// ^xfm
99118
}
100119

120+
let _x = switch variantOpt {
121+
| Some(First) | Some(Second) => "first"
122+
| _ => "other"
123+
// ^xfm
124+
}
125+
126+
let _x = switch variantOpt {
127+
| Some(First | Second) => "first"
128+
| _ => "other"
129+
// ^xfm
130+
}
131+
101132
let polyvariantOpt = Some(polyvariant)
102133

103134
let _x = switch polyvariantOpt {
@@ -106,3 +137,9 @@ let _x = switch polyvariantOpt {
106137
| _ => "other"
107138
// ^xfm
108139
}
140+
141+
let _x = switch polyvariantOpt {
142+
| Some(#first | #second) => "first"
143+
| _ => "other"
144+
// ^xfm
145+
}

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

+111-9
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,42 @@ newText:
206206
<--here
207207
Second | Third | Fourth(_)
208208

209-
Xform src/Xform.res 88:4
210-
posCursor:[86:16] posNoWhite:[86:14] Found expr:[86:9->90:1]
209+
Xform src/Xform.res 86:4
210+
posCursor:[84:16] posNoWhite:[84:14] Found expr:[84:9->88:1]
211+
Completable: Cpath Value[variant]
212+
Package opens Pervasives.JsxModules.place holder
213+
Resolved opens 1 pervasives
214+
ContextPath Value[variant]
215+
Path variant
216+
Package opens Pervasives.JsxModules.place holder
217+
Resolved opens 1 pervasives
218+
Hit: Expand catch-all
219+
220+
TextDocumentEdit: Xform.res
221+
{"start": {"line": 86, "character": 2}, "end": {"line": 86, "character": 3}}
222+
newText:
223+
<--here
224+
Third | Fourth(_)
225+
226+
Xform src/Xform.res 93:4
227+
posCursor:[90:16] posNoWhite:[90:14] Found expr:[90:9->95:1]
228+
Completable: Cpath Value[variant]
229+
Package opens Pervasives.JsxModules.place holder
230+
Resolved opens 1 pervasives
231+
ContextPath Value[variant]
232+
Path variant
233+
Package opens Pervasives.JsxModules.place holder
234+
Resolved opens 1 pervasives
235+
Hit: Expand catch-all
236+
237+
TextDocumentEdit: Xform.res
238+
{"start": {"line": 93, "character": 2}, "end": {"line": 93, "character": 3}}
239+
newText:
240+
<--here
241+
First | Third | Fourth(_)
242+
243+
Xform src/Xform.res 101:4
244+
posCursor:[99:16] posNoWhite:[99:14] Found expr:[99:9->103:1]
211245
Completable: Cpath Value[polyvariant]
212246
Package opens Pervasives.JsxModules.place holder
213247
Resolved opens 1 pervasives
@@ -218,13 +252,30 @@ Resolved opens 1 pervasives
218252
Hit: Expand catch-all
219253

220254
TextDocumentEdit: Xform.res
221-
{"start": {"line": 88, "character": 2}, "end": {"line": 88, "character": 3}}
255+
{"start": {"line": 101, "character": 2}, "end": {"line": 101, "character": 3}}
222256
newText:
223257
<--here
224258
#second | #"illegal identifier" | #third(_)
225259

226-
Xform src/Xform.res 96:4
227-
posCursor:[94:16] posNoWhite:[94:14] Found expr:[94:9->98:1]
260+
Xform src/Xform.res 107:4
261+
posCursor:[105:16] posNoWhite:[105:14] Found expr:[105:9->109:1]
262+
Completable: Cpath Value[polyvariant]
263+
Package opens Pervasives.JsxModules.place holder
264+
Resolved opens 1 pervasives
265+
ContextPath Value[polyvariant]
266+
Path polyvariant
267+
Package opens Pervasives.JsxModules.place holder
268+
Resolved opens 1 pervasives
269+
Hit: Expand catch-all
270+
271+
TextDocumentEdit: Xform.res
272+
{"start": {"line": 107, "character": 2}, "end": {"line": 107, "character": 3}}
273+
newText:
274+
<--here
275+
#"illegal identifier" | #third(_)
276+
277+
Xform src/Xform.res 115:4
278+
posCursor:[113:16] posNoWhite:[113:14] Found expr:[113:9->117:1]
228279
Completable: Cpath Value[variantOpt]
229280
Package opens Pervasives.JsxModules.place holder
230281
Resolved opens 1 pervasives
@@ -235,13 +286,47 @@ Resolved opens 1 pervasives
235286
Hit: Expand catch-all
236287

237288
TextDocumentEdit: Xform.res
238-
{"start": {"line": 96, "character": 2}, "end": {"line": 96, "character": 3}}
289+
{"start": {"line": 115, "character": 2}, "end": {"line": 115, "character": 3}}
239290
newText:
240291
<--here
241292
Some(Second | Third | Fourth(_)) | None
242293

243-
Xform src/Xform.res 105:4
244-
posCursor:[102:16] posNoWhite:[102:14] Found expr:[102:9->107:1]
294+
Xform src/Xform.res 121:4
295+
posCursor:[119:16] posNoWhite:[119:14] Found expr:[119:9->123:1]
296+
Completable: Cpath Value[variantOpt]
297+
Package opens Pervasives.JsxModules.place holder
298+
Resolved opens 1 pervasives
299+
ContextPath Value[variantOpt]
300+
Path variantOpt
301+
Package opens Pervasives.JsxModules.place holder
302+
Resolved opens 1 pervasives
303+
Hit: Expand catch-all
304+
305+
TextDocumentEdit: Xform.res
306+
{"start": {"line": 121, "character": 2}, "end": {"line": 121, "character": 3}}
307+
newText:
308+
<--here
309+
Some(Third | Fourth(_)) | None
310+
311+
Xform src/Xform.res 127:4
312+
posCursor:[125:16] posNoWhite:[125:14] Found expr:[125:9->129:1]
313+
Completable: Cpath Value[variantOpt]
314+
Package opens Pervasives.JsxModules.place holder
315+
Resolved opens 1 pervasives
316+
ContextPath Value[variantOpt]
317+
Path variantOpt
318+
Package opens Pervasives.JsxModules.place holder
319+
Resolved opens 1 pervasives
320+
Hit: Expand catch-all
321+
322+
TextDocumentEdit: Xform.res
323+
{"start": {"line": 127, "character": 2}, "end": {"line": 127, "character": 3}}
324+
newText:
325+
<--here
326+
Some(Third | Fourth(_)) | None
327+
328+
Xform src/Xform.res 136:4
329+
posCursor:[133:16] posNoWhite:[133:14] Found expr:[133:9->138:1]
245330
Completable: Cpath Value[polyvariantOpt]
246331
Package opens Pervasives.JsxModules.place holder
247332
Resolved opens 1 pervasives
@@ -252,8 +337,25 @@ Resolved opens 1 pervasives
252337
Hit: Expand catch-all
253338

254339
TextDocumentEdit: Xform.res
255-
{"start": {"line": 105, "character": 2}, "end": {"line": 105, "character": 3}}
340+
{"start": {"line": 136, "character": 2}, "end": {"line": 136, "character": 3}}
256341
newText:
257342
<--here
258343
Some(#"illegal identifier" | #second | #third(_))
259344

345+
Xform src/Xform.res 142:4
346+
posCursor:[140:16] posNoWhite:[140:14] Found expr:[140:9->144:1]
347+
Completable: Cpath Value[polyvariantOpt]
348+
Package opens Pervasives.JsxModules.place holder
349+
Resolved opens 1 pervasives
350+
ContextPath Value[polyvariantOpt]
351+
Path polyvariantOpt
352+
Package opens Pervasives.JsxModules.place holder
353+
Resolved opens 1 pervasives
354+
Hit: Expand catch-all
355+
356+
TextDocumentEdit: Xform.res
357+
{"start": {"line": 142, "character": 2}, "end": {"line": 142, "character": 3}}
358+
newText:
359+
<--here
360+
Some(#"illegal identifier" | #third(_)) | None
361+

0 commit comments

Comments
 (0)