diff --git a/CHANGELOG.md b/CHANGELOG.md index db909de33..e4533fff9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 5c0ebc3af..30709170a 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -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 => () | }` 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 diff --git a/analysis/tests/src/CompletionExpressions.res b/analysis/tests/src/CompletionExpressions.res index c4f14d6ee..78186f18d 100644 --- a/analysis/tests/src/CompletionExpressions.res +++ b/analysis/tests/src/CompletionExpressions.res @@ -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 diff --git a/analysis/tests/src/expected/CompletionExpressions.res.txt b/analysis/tests/src/expected/CompletionExpressions.res.txt index a95c7ed00..8dd98de70 100644 --- a/analysis/tests/src/expected/CompletionExpressions.res.txt +++ b/analysis/tests/src/expected/CompletionExpressions.res.txt @@ -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 + }] +