diff --git a/analysis/src/Completion.ml b/analysis/src/Completion.ml index 73c56ee93..ad9b5aca7 100644 --- a/analysis/src/Completion.ml +++ b/analysis/src/Completion.ml @@ -319,13 +319,36 @@ let completionWithParser ~debug ~path ~posCursor ~currentFile ~text = scope := !scope |> Scope.addValue ~name:vd.pval_name.txt ~loc:vd.pval_name.loc in + let rec scopePattern (pat : Parsetree.pattern) = + match pat.ppat_desc with + | Ppat_any -> () + | Ppat_var {txt; loc} -> scope := !scope |> Scope.addValue ~name:txt ~loc + | Ppat_alias (p, asA) -> + scopePattern p; + scope := !scope |> Scope.addValue ~name:asA.txt ~loc:asA.loc + | Ppat_constant _ | Ppat_interval _ -> () + | Ppat_tuple pl -> pl |> List.iter scopePattern + | Ppat_construct (_, None) -> () + | Ppat_construct (_, Some p) -> scopePattern p + | Ppat_variant (_, None) -> () + | Ppat_variant (_, Some p) -> scopePattern p + | Ppat_record (fields, _) -> + fields |> List.iter (fun (_, p) -> scopePattern p) + | Ppat_array pl -> pl |> List.iter scopePattern + | Ppat_or (p1, _) -> scopePattern p1 + | Ppat_constraint (p, _) -> scopePattern p + | Ppat_type _ -> () + | Ppat_lazy p -> scopePattern p + | Ppat_unpack {txt; loc} -> scope := !scope |> Scope.addValue ~name:txt ~loc + | Ppat_exception p -> scopePattern p + | Ppat_extension _ -> () + | Ppat_open (_, p) -> scopePattern p + in + let scopeValueBinding (vb : Parsetree.value_binding) = - match vb.pvb_pat.ppat_desc with - | Ppat_var {txt; loc} - | Ppat_constraint ({ppat_desc = Ppat_var {txt; loc}}, _) -> - scope := !scope |> Scope.addValue ~name:txt ~loc - | _ -> () + scopePattern vb.pvb_pat in + let scopeTypeKind (tk : Parsetree.type_kind) = match tk with | Ptype_variant constrDecls -> @@ -355,6 +378,12 @@ let completionWithParser ~debug ~path ~posCursor ~currentFile ~text = !scope |> Scope.addModule ~name:md.pmd_name.txt ~loc:md.pmd_name.loc in + let case (iterator : Ast_iterator.iterator) (case : Parsetree.case) = + let oldScope = !scope in + scopePattern case.pc_lhs; + Ast_iterator.default_iterator.case iterator case; + scope := oldScope + in let structure (iterator : Ast_iterator.iterator) (structure : Parsetree.structure) = let oldScope = !scope in @@ -713,6 +742,7 @@ let completionWithParser ~debug ~path ~posCursor ~currentFile ~text = { Ast_iterator.default_iterator with attribute; + case; expr; module_expr; module_type; diff --git a/analysis/tests/src/Completion.res b/analysis/tests/src/Completion.res index 1212c78ff..07e14237e 100644 --- a/analysis/tests/src/Completion.res +++ b/analysis/tests/src/Completion.res @@ -238,4 +238,12 @@ let name = "abc" // ^com let notHere = " " -// ^com \ No newline at end of file +// ^com + +let someR = Some(r) +let _ = switch someR { +| Some(_z) => 1 +// + _z. +// ^com +| _ => 3 +} diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index 0f604dfec..5f288f606 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -837,6 +837,11 @@ DocumentSymbol tests/src/Completion.res "name": "notHere", "kind": 15, "location": {"uri": "Completion.res", "range": {"start": {"line": 239, "character": 0}, "end": {"line": 239, "character": 22}}} +}, +{ + "name": "someR", + "kind": 13, + "location": {"uri": "Completion.res", "range": {"start": {"line": 242, "character": 0}, "end": {"line": 242, "character": 19}}} } ] @@ -1316,3 +1321,25 @@ posCursor:[239:17] posNoWhite:[239:14] Found expr:[239:14->239:22] Completable: Cnone [] +Complete tests/src/Completion.res 245:8 +posCursor:[245:8] posNoWhite:[245:7] Found expr:[243:8->248:1] +posCursor:[245:8] posNoWhite:[245:7] Found expr:[244:14->247:8] +posCursor:[245:8] posNoWhite:[245:7] Found expr:[244:14->247:1] +Pexp_apply ...[245:3->245:4] (...[244:14->244:15], ...[245:5->247:1]) +posCursor:[245:8] posNoWhite:[245:7] Found expr:[245:5->247:1] +Pexp_field [245:5->245:7] _:[247:0->247:1] +Completable: Cpath Value[_z]."" +[{ + "label": "x", + "kind": 5, + "tags": [], + "detail": "x: int\n\ntype r = {x: int, y: string}", + "documentation": null + }, { + "label": "y", + "kind": 5, + "tags": [], + "detail": "y: string\n\ntype r = {x: int, y: string}", + "documentation": null + }] +