Skip to content

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

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

Merged
merged 3 commits into from
Mar 1, 2024
Merged
Changes from all commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -12,6 +12,10 @@

## master

#### :bug: Bug Fix

- Fix issue where completion inside of switch expression would not work in some cases. https://github.com/rescript-lang/rescript-vscode/pull/936

## 1.40.0

#### :nail_care: Polish
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
9 changes: 7 additions & 2 deletions analysis/tests/src/CompletionExpressions.res
Original file line number Diff line number Diff line change
@@ -348,12 +348,17 @@ module Money: {
let plus = (m1, _) => m1
}

let tArgCompletionTestFn = (tVal: Money.t) => ()
let tArgCompletionTestFn = (_tVal: Money.t) => ()

// tArgCompletionTestFn()
// ^com

let labeledTArgCompletionTestFn = (~tVal: Money.t) => ()
let labeledTArgCompletionTestFn = (~tVal as _: Money.t) => ()

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

let someTyp: someTyp = {test: true}

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

Complete src/CompletionExpressions.res 362:18
posCursor:[362:18] posNoWhite:[362:17] Found expr:[362:3->362:32]
posCursor:[362:18] posNoWhite:[362:17] Found expr:[362:10->362:18]
Pexp_field [362:10->362:17] _:[362:19->362:18]
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].""
ContextPath Value[someTyp]
Path someTyp
[{
"label": "test",
"kind": 5,
"tags": [],
"detail": "test: bool\n\ntype someTyp = {test: bool}",
"documentation": null
}]