diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index eee350c40..0d28404c9 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -317,7 +317,26 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = in let scopeValueBinding (vb : Parsetree.value_binding) = scopePattern vb.pvb_pat; - completePattern vb.pvb_pat + (* Identify relevant destructures for completion, like `let {} = someVar` or `let (true, false) = someFn()`. *) + match vb with + | {pvb_pat; pvb_expr} when locHasCursor pvb_pat.ppat_loc -> ( + match + ( pvb_pat + |> CompletionPatterns.traversePattern ~patternPath:[] ~locHasCursor + ~firstCharBeforeCursorNoWhite ~posBeforeCursor, + exprToContextPath pvb_expr ) + with + | Some (prefix, nestedPattern), Some ctxPath -> + setResult + (Completable.Cpattern + { + contextPath = ctxPath; + prefix; + nested = List.rev nestedPattern; + fallback = None; + }) + | _ -> ()) + | _ -> () in let scopeTypeKind (tk : Parsetree.type_kind) = match tk with @@ -446,13 +465,6 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text = scope := !scope |> Scope.addOpen ~lid:popen_lid.txt | Pstr_primitive vd -> scopeValueDescription vd | Pstr_value (recFlag, bindings) -> - (* Identify relevant destructures for completion, like `let {} = someVar` or `let (true, false) = someFn()`. *) - (match bindings with - | [{pvb_pat = {ppat_desc = Ppat_record _ | Ppat_tuple _}; pvb_expr}] -> ( - match exprToContextPath pvb_expr with - | None -> () - | Some ctxPath -> setLookingForPat ctxPath) - | _ -> ()); if recFlag = Recursive then bindings |> List.iter scopeValueBinding; bindings |> List.iter (fun vb -> iterator.value_binding iterator vb); if recFlag = Nonrecursive then bindings |> List.iter scopeValueBinding; diff --git a/analysis/tests/src/Destructuring.res b/analysis/tests/src/Destructuring.res new file mode 100644 index 000000000..2a9c59359 --- /dev/null +++ b/analysis/tests/src/Destructuring.res @@ -0,0 +1,21 @@ +type x = {name: string, age: int} + +let x = {name: "123", age: 12} + +let {name, } = x +// ^com + +// let {} = x +// ^com + +let f = (x: x) => { + let {name, } = x + // ^com + name +} + +let f2 = (x: x) => { + // let {} = x + // ^com + ignore(x) +} diff --git a/analysis/tests/src/expected/Destructuring.res.txt b/analysis/tests/src/expected/Destructuring.res.txt new file mode 100644 index 000000000..dbb31578d --- /dev/null +++ b/analysis/tests/src/expected/Destructuring.res.txt @@ -0,0 +1,60 @@ +Complete src/Destructuring.res 4:11 +posCursor:[4:11] posNoWhite:[4:9] Found pattern:[4:4->4:12] +Completable: Cpattern Value[x]->recordBody +[{ + "label": "age", + "kind": 5, + "tags": [], + "detail": "age: int\n\nx", + "documentation": null + }] + +Complete src/Destructuring.res 7:8 +posCursor:[7:8] posNoWhite:[7:7] Found pattern:[7:7->7:9] +Completable: Cpattern Value[x]->recordBody +[{ + "label": "name", + "kind": 5, + "tags": [], + "detail": "name: string\n\nx", + "documentation": null + }, { + "label": "age", + "kind": 5, + "tags": [], + "detail": "age: int\n\nx", + "documentation": null + }] + +Complete src/Destructuring.res 11:13 +posCursor:[11:13] posNoWhite:[11:11] Found expr:[10:8->14:1] +posCursor:[11:13] posNoWhite:[11:11] Found expr:[11:2->13:6] +posCursor:[11:13] posNoWhite:[11:11] Found pattern:[11:6->11:14] +Completable: Cpattern Value[x]->recordBody +[{ + "label": "age", + "kind": 5, + "tags": [], + "detail": "age: int\n\nx", + "documentation": null + }] + +Complete src/Destructuring.res 17:10 +posCursor:[17:10] posNoWhite:[17:9] Found expr:[16:9->20:1] +posCursor:[17:10] posNoWhite:[17:9] Found expr:[17:5->19:11] +posCursor:[17:10] posNoWhite:[17:9] Found pattern:[17:9->17:11] +Completable: Cpattern Value[x]->recordBody +[{ + "label": "name", + "kind": 5, + "tags": [], + "detail": "name: string\n\nx", + "documentation": null + }, { + "label": "age", + "kind": 5, + "tags": [], + "detail": "age: int\n\nx", + "documentation": null + }] +