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

Signature help for constructors in patterns #954

Merged
merged 2 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#### :rocket: New Feature

- Extend signature help to work on constructor payloads as well. Can be turned off if wanted through settings. https://github.com/rescript-lang/rescript-vscode/pull/947
- Extend signature help to work on constructor payloads in both expressions and patterns as well. Can be turned off if wanted through settings. https://github.com/rescript-lang/rescript-vscode/pull/947 https://github.com/rescript-lang/rescript-vscode/pull/954
- Show module docs for file modules. https://github.com/rescript-lang/rescript-vscode/pull/952

#### :nail_care: Polish
Expand Down
73 changes: 63 additions & 10 deletions analysis/src/SignatureHelp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,13 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
let result = ref None in
let printThing thg =
match thg with
| `Constructor _ -> "Constructor"
| `ConstructorExpr _ -> "Constructor(expr)"
| `ConstructorPat _ -> "Constructor(pat)"
| `FunctionCall _ -> "FunctionCall"
in
let setResult (loc, thing) =
match (thing, allowForConstructorPayloads) with
| `Constructor _, false -> ()
| (`ConstructorExpr _ | `ConstructorPat _), false -> ()
| _ -> (
match !result with
| None ->
Expand Down Expand Up @@ -364,11 +365,20 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
|| CompletionExpressions.isExprHole payloadExp
&& locHasCursor pexp_loc ->
(* Constructor payloads *)
setResult (lid.loc, `Constructor (lid, payloadExp))
setResult (lid.loc, `ConstructorExpr (lid, payloadExp))
| _ -> ());
Ast_iterator.default_iterator.expr iterator expr
in
let iterator = {Ast_iterator.default_iterator with expr} in
let pat (iterator : Ast_iterator.iterator) (pat : Parsetree.pattern) =
(match pat with
| {ppat_desc = Ppat_construct (lid, Some payloadPat)}
when locHasCursor payloadPat.ppat_loc ->
(* Constructor payloads *)
setResult (lid.loc, `ConstructorPat (lid, payloadPat))
| _ -> ());
Ast_iterator.default_iterator.pat iterator pat
in
let iterator = {Ast_iterator.default_iterator with expr; pat} in
let parser =
Res_driver.parsingEngine.parseImplementation ~forPrinter:false
in
Expand Down Expand Up @@ -474,9 +484,10 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
| activeParameter -> activeParameter);
}
| _ -> None)
| Some (_, `Constructor (lid, expr)) -> (
| Some (_, ((`ConstructorExpr (lid, _) | `ConstructorPat (lid, _)) as cs))
-> (
if Debug.verbose () then
Printf.printf "[signature_help] Found constructor expr!\n";
Printf.printf "[signature_help] Found constructor!\n";
match Cmt.loadFullCmtFromPath ~path with
| None ->
if Debug.verbose () then
Expand Down Expand Up @@ -560,8 +571,8 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
^ ")"
in
let activeParameter =
match expr with
| {pexp_desc = Pexp_tuple items} -> (
match cs with
| `ConstructorExpr (_, {pexp_desc = Pexp_tuple items}) -> (
let idx = ref 0 in
let tupleItemWithCursor =
items
Expand All @@ -574,7 +585,7 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
match tupleItemWithCursor with
| None -> -1
| Some i -> i)
| {pexp_desc = Pexp_record (fields, _)} -> (
| `ConstructorExpr (_, {pexp_desc = Pexp_record (fields, _)}) -> (
let fieldNameWithCursor =
fields
|> List.find_map
Expand Down Expand Up @@ -602,7 +613,49 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
else ());
!fieldIndex
| _ -> -1)
| _ when locHasCursor expr.pexp_loc -> 0
| `ConstructorExpr (_, expr) when locHasCursor expr.pexp_loc -> 0
| `ConstructorPat (_, {ppat_desc = Ppat_tuple items}) -> (
let idx = ref 0 in
let tupleItemWithCursor =
items
|> List.find_map (fun (item : Parsetree.pattern) ->
let currentIndex = !idx in
idx := currentIndex + 1;
if locHasCursor item.ppat_loc then Some currentIndex
else None)
in
match tupleItemWithCursor with
| None -> -1
| Some i -> i)
| `ConstructorPat (_, {ppat_desc = Ppat_record (fields, _)}) -> (
let fieldNameWithCursor =
fields
|> List.find_map
(fun
(({loc; txt}, pat) :
Longident.t Location.loc * Parsetree.pattern)
->
if
posBeforeCursor >= Pos.ofLexing loc.loc_start
&& posBeforeCursor
<= Pos.ofLexing pat.ppat_loc.loc_end
then Some (Longident.last txt)
else None)
in
match (fieldNameWithCursor, argParts) with
| Some fieldName, Some (`InlineRecord fields) ->
let idx = ref 0 in
let fieldIndex = ref (-1) in
fields
|> List.iter (fun (_, field, _) ->
idx := !idx + 1;
let currentIndex = !idx in
if fieldName = field.fname.txt then
fieldIndex := currentIndex
else ());
!fieldIndex
| _ -> -1)
| `ConstructorPat (_, pat) when locHasCursor pat.ppat_loc -> 0
| _ -> -1
in

Expand Down
13 changes: 13 additions & 0 deletions analysis/tests/src/SignatureHelp.res
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,16 @@ let _ = stuffers({}, One)

let _ = stuffers({}, One)
// ^she

let _ = switch _one {
| One({hit: _hit}) => ""
// ^she
| One(_a) => ""
// ^she
| Two(_ms) => ""
// ^she
| Three(_a, []) => ""
// ^she
| Three(_, _b) => ""
// ^she
}
55 changes: 55 additions & 0 deletions analysis/tests/src/expected/SignatureHelp.res.txt
Original file line number Diff line number Diff line change
Expand Up @@ -505,3 +505,58 @@ extracted params:
"activeParameter": 1
}

Signature help src/SignatureHelp.res 143:8
{
"signatures": [{
"label": "One({miss?: bool, hit?: bool, stuff?: string})",
"parameters": [{"label": [0, 0], "documentation": {"kind": "markdown", "value": ""}}, {"label": [5, 16], "documentation": {"kind": "markdown", "value": ""}}, {"label": [18, 28], "documentation": {"kind": "markdown", "value": ""}}, {"label": [30, 44], "documentation": {"kind": "markdown", "value": ""}}],
"documentation": {"kind": "markdown", "value": " One is cool. "}
}],
"activeSignature": 0,
"activeParameter": 2
}

Signature help src/SignatureHelp.res 145:7
{
"signatures": [{
"label": "One({miss?: bool, hit?: bool, stuff?: string})",
"parameters": [{"label": [0, 0], "documentation": {"kind": "markdown", "value": ""}}, {"label": [5, 16], "documentation": {"kind": "markdown", "value": ""}}, {"label": [18, 28], "documentation": {"kind": "markdown", "value": ""}}, {"label": [30, 44], "documentation": {"kind": "markdown", "value": ""}}],
"documentation": {"kind": "markdown", "value": " One is cool. "}
}],
"activeSignature": 0,
"activeParameter": 0
}

Signature help src/SignatureHelp.res 147:7
{
"signatures": [{
"label": "Two(mySpecialThing)",
"parameters": [{"label": [4, 18], "documentation": {"kind": "markdown", "value": "```rescript\ntype mySpecialThing = string\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22SignatureHelp.res%22%2C78%2C0%5D)"}}],
"documentation": {"kind": "markdown", "value": " Two is fun! "}
}],
"activeSignature": 0,
"activeParameter": 0
}

Signature help src/SignatureHelp.res 149:9
{
"signatures": [{
"label": "Three(mySpecialThing, array<option<string>>)",
"parameters": [{"label": [6, 20], "documentation": {"kind": "markdown", "value": "```rescript\ntype mySpecialThing = string\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22SignatureHelp.res%22%2C78%2C0%5D)"}}, {"label": [22, 43], "documentation": {"kind": "markdown", "value": ""}}],
"documentation": {"kind": "markdown", "value": " Three is... three "}
}],
"activeSignature": 0,
"activeParameter": 0
}

Signature help src/SignatureHelp.res 151:12
{
"signatures": [{
"label": "Three(mySpecialThing, array<option<string>>)",
"parameters": [{"label": [6, 20], "documentation": {"kind": "markdown", "value": "```rescript\ntype mySpecialThing = string\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22SignatureHelp.res%22%2C78%2C0%5D)"}}, {"label": [22, 43], "documentation": {"kind": "markdown", "value": ""}}],
"documentation": {"kind": "markdown", "value": " Three is... three "}
}],
"activeSignature": 0,
"activeParameter": 1
}