Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
extend to work on options
  • Loading branch information
zth committed May 25, 2024
commit d7c91f5e1aeb3d0c0527cf29f7a046683e43f02a
93 changes: 93 additions & 0 deletions analysis/src/Xform.ml
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,99 @@ module ExpandCatchAllForVariants = struct
in
codeActions := codeAction :: !codeActions
else ()
| Some (Toption (env, innerType)) -> (
if Debug.verbose () then
print_endline
"[codeAction - ExpandCatchAllForVariants] Found option type";
let innerType =
match innerType with
| ExtractedType t -> Some t
| TypeExpr t -> (
match TypeUtils.extractType ~env ~package:full.package t with
| None -> None
| Some (t, _) -> Some t)
in
match innerType with
| Some ((Tvariant _ | Tpolyvariant _) as variant) ->
let currentConstructorNames =
cases
|> List.filter_map (fun (c : Parsetree.case) ->
match c with
| {
pc_lhs =
{
ppat_desc =
Ppat_construct
( {txt = Lident "Some"},
Some {ppat_desc = Ppat_construct ({txt}, _)} );
};
} ->
Some (Longident.last txt)
| {
pc_lhs =
{
ppat_desc =
Ppat_construct
( {txt = Lident "Some"},
Some {ppat_desc = Ppat_variant (name, _)} );
};
} ->
Some name
| _ -> None)
in
let hasNoneCase =
cases
|> List.exists (fun (c : Parsetree.case) ->
match c.pc_lhs.ppat_desc with
| Ppat_construct ({txt = Lident "None"}, _) -> true
| _ -> false)
in
let missingConstructors =
match variant with
| Tvariant {constructors} ->
constructors
|> List.filter_map (fun (c : SharedTypes.Constructor.t) ->
if currentConstructorNames |> List.mem c.cname.txt = false
then
Some
( c.cname.txt,
match c.args with
| Args [] -> false
| _ -> true )
else None)
| Tpolyvariant {constructors} ->
constructors
|> List.filter_map
(fun (c : SharedTypes.polyVariantConstructor) ->
if currentConstructorNames |> List.mem c.name = false then
Some
( Res_printer.polyVarIdentToString c.name,
match c.args with
| [] -> false
| _ -> true )
else None)
| _ -> []
in
if List.length missingConstructors > 0 || not hasNoneCase then
let newText =
"Some("
^ (missingConstructors
|> List.map (fun (name, hasArgs) ->
name ^ if hasArgs then "" else "(_)")
|> String.concat " | ")
^ ")"
in
let newText =
if hasNoneCase then newText else newText ^ " | None"
in
let range = rangeOfLoc catchAllCase.pc_lhs.ppat_loc in
let codeAction =
CodeActions.make ~title:"Expand catch-all" ~kind:RefactorRewrite
~uri:path ~newText ~range
in
codeActions := codeAction :: !codeActions
else ()
| _ -> ())
| _ -> ())
end

Expand Down
17 changes: 17 additions & 0 deletions analysis/tests/src/Xform.res
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,20 @@ let _y = switch polyvariant {
| _ => "other"
// ^xfm
}

let variantOpt = Some(variant)

let _x = switch variantOpt {
| Some(First) => "first"
| _ => "other"
// ^xfm
}

let polyvariantOpt = Some(polyvariant)

let _x = switch polyvariantOpt {
| Some(#first) => "first"
| None => "nothing"
| _ => "other"
// ^xfm
}
34 changes: 34 additions & 0 deletions analysis/tests/src/expected/Xform.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,37 @@ newText:
<--here
#second | #"illegal identifier" | #third(_)

Xform src/Xform.res 96:4
posCursor:[94:16] posNoWhite:[94:14] Found expr:[94:9->98:1]
Completable: Cpath Value[variantOpt]
Package opens Pervasives.JsxModules.place holder
Resolved opens 1 pervasives
ContextPath Value[variantOpt]
Path variantOpt
Package opens Pervasives.JsxModules.place holder
Resolved opens 1 pervasives
Hit: Expand catch-all

TextDocumentEdit: Xform.res
{"start": {"line": 96, "character": 2}, "end": {"line": 96, "character": 3}}
newText:
<--here
Some(Second(_) | Third(_) | Fourth) | None

Xform src/Xform.res 105:4
posCursor:[102:16] posNoWhite:[102:14] Found expr:[102:9->107:1]
Completable: Cpath Value[polyvariantOpt]
Package opens Pervasives.JsxModules.place holder
Resolved opens 1 pervasives
ContextPath Value[polyvariantOpt]
Path polyvariantOpt
Package opens Pervasives.JsxModules.place holder
Resolved opens 1 pervasives
Hit: Expand catch-all

TextDocumentEdit: Xform.res
{"start": {"line": 105, "character": 2}, "end": {"line": 105, "character": 3}}
newText:
<--here
Some(#"illegal identifier"(_) | #second(_) | #third)