Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue where completion inside of switch expr would not work #936

Merged
merged 3 commits into from
Mar 1, 2024
Merged
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
Next Next commit
fix issue where completion inside of switch expr would not work
zth committed Feb 29, 2024
commit 4201b1a2ee0a7fa10027058807b92d4a383e51aa
35 changes: 28 additions & 7 deletions analysis/src/CompletionFrontEnd.ml
Original file line number Diff line number Diff line change
@@ -549,18 +549,26 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
let inJsxContext = ref false in
(* Identifies expressions where we can do typed pattern or expr completion. *)
let typedCompletionExpr (exp : Parsetree.expression) =
if exp.pexp_loc |> CursorPosition.locHasCursor ~pos:posBeforeCursor then
if exp.pexp_loc |> CursorPosition.locHasCursor ~pos:posBeforeCursor then (
if Debug.verbose () then print_endline "[typedCompletionExpr] Has cursor";
match exp.pexp_desc with
(* No cases means there's no `|` yet in the switch *)
| Pexp_match (({pexp_desc = Pexp_ident _} as expr), []) -> (
if locHasCursor expr.pexp_loc then
| Pexp_match (({pexp_desc = Pexp_ident _} as expr), []) ->
if Debug.verbose () then
print_endline "[typedCompletionExpr] No cases, with ident";
if locHasCursor expr.pexp_loc then (
if Debug.verbose () then
print_endline "[typedCompletionExpr] No cases - has cursor";
(* We can do exhaustive switch completion if this is an ident we can
complete from. *)
match exprToContextPath expr with
| None -> ()
| Some contextPath ->
setResult (CexhaustiveSwitch {contextPath; exprLoc = exp.pexp_loc}))
| Pexp_match (_expr, []) -> ()
| Pexp_match (_expr, []) ->
if Debug.verbose () then
print_endline "[typedCompletionExpr] No cases, rest";
()
| Pexp_match
( exp,
[
@@ -586,11 +594,16 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
patternMode = Default;
}))
| Pexp_match (exp, cases) -> (
if Debug.verbose () then print_endline "[typedCompletionExpr] Has cases";
(* If there's more than one case, or the case isn't a pattern hole, figure out if we're completing another
broken parser case (`switch x { | true => () | <com> }` for example). *)
match exp |> exprToContextPath with
| None -> ()
| None ->
if Debug.verbose () then
print_endline "[typedCompletionExpr] Has cases - no ctx path"
| Some ctxPath -> (
if Debug.verbose () then
print_endline "[typedCompletionExpr] Has cases - has ctx path";
let hasCaseWithCursor =
cases
|> List.find_opt (fun case ->
@@ -603,6 +616,11 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
locIsEmpty case.Parsetree.pc_lhs.ppat_loc)
|> Option.is_some
in
if Debug.verbose () then
Printf.printf
"[typedCompletionExpr] Has cases - has ctx path - \
hasCaseWithEmptyLoc: %b, hasCaseWithCursor: %b\n"
hasCaseWithEmptyLoc hasCaseWithCursor;
match (hasCaseWithEmptyLoc, hasCaseWithCursor) with
| _, true ->
(* Always continue if there's a case with the cursor *)
@@ -619,7 +637,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
patternMode = Default;
})
| false, false -> ()))
| _ -> ()
| _ -> ())
in
let structure (iterator : Ast_iterator.iterator)
(structure : Parsetree.structure) =
@@ -977,7 +995,10 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
in
typedCompletionExpr expr;
match expr.pexp_desc with
| Pexp_match (expr, cases) when cases <> [] ->
| Pexp_match (expr, cases)
when cases <> [] && locHasCursor expr.pexp_loc = false ->
if Debug.verbose () then
print_endline "[completionFrontend] Checking each case";
let ctxPath = exprToContextPath expr in
let oldCtxPath = !currentCtxPath in
cases
5 changes: 5 additions & 0 deletions analysis/tests/src/CompletionExpressions.res
Original file line number Diff line number Diff line change
@@ -357,3 +357,8 @@ let labeledTArgCompletionTestFn = (~tVal: Money.t) => ()

// labeledTArgCompletionTestFn(~tVal=)
// ^com

let someTyp: someTyp = {test: true}

// switch someTyp. { | _ => () }
// ^com
29 changes: 29 additions & 0 deletions analysis/tests/src/expected/CompletionExpressions.res.txt
Original file line number Diff line number Diff line change
@@ -1404,3 +1404,32 @@ Path labeledTArgCompletionTestFn
"insertTextFormat": 2
}]


Complete src/CompletionExpressions.res 363:18
[typedCompletionExpr] Has cursor
[typedCompletionExpr] Has cases
[typedCompletionExpr] Has cases - has ctx path
[typedCompletionExpr] Has cases - has ctx path - hasCaseWithEmptyLoc: false, hasCaseWithCursor: false
posCursor:[363:18] posNoWhite:[363:17] Found expr:[363:3->363:32]
[typedCompletionExpr] Has cursor
posCursor:[363:18] posNoWhite:[363:17] Found expr:[363:10->363:18]
Pexp_field [363:10->363:17] _:[363:19->363:18]
[set_result] set new result to Cpath Value[someTyp].""
Completable: Cpath Value[someTyp].""
Raw opens: 1 CompletionSupport.place holder
Package opens Pervasives.JsxModules.place holder
Resolved opens 2 pervasives CompletionSupport.res
ContextPath Value[someTyp].""
[ctx_path]--> CPField
ContextPath Value[someTyp]
[ctx_path]--> CPId
Path someTyp
[{
"label": "test",
"kind": 5,
"tags": [],
"detail": "test: bool\n\ntype someTyp = {test: bool}",
"documentation": null
}]