Skip to content

Commit 69bfb26

Browse files
authored
Signature help for constructors in patterns (#954)
* signature help for constructors in patterns * changelog
1 parent 9dd6d1d commit 69bfb26

File tree

4 files changed

+132
-11
lines changed

4 files changed

+132
-11
lines changed

Diff for: CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
#### :rocket: New Feature
1616

17-
- 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
17+
- 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
1818
- Show module docs for file modules. https://github.com/rescript-lang/rescript-vscode/pull/952
1919

2020
#### :nail_care: Polish

Diff for: analysis/src/SignatureHelp.ml

+63-10
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,13 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
229229
let result = ref None in
230230
let printThing thg =
231231
match thg with
232-
| `Constructor _ -> "Constructor"
232+
| `ConstructorExpr _ -> "Constructor(expr)"
233+
| `ConstructorPat _ -> "Constructor(pat)"
233234
| `FunctionCall _ -> "FunctionCall"
234235
in
235236
let setResult (loc, thing) =
236237
match (thing, allowForConstructorPayloads) with
237-
| `Constructor _, false -> ()
238+
| (`ConstructorExpr _ | `ConstructorPat _), false -> ()
238239
| _ -> (
239240
match !result with
240241
| None ->
@@ -364,11 +365,20 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
364365
|| CompletionExpressions.isExprHole payloadExp
365366
&& locHasCursor pexp_loc ->
366367
(* Constructor payloads *)
367-
setResult (lid.loc, `Constructor (lid, payloadExp))
368+
setResult (lid.loc, `ConstructorExpr (lid, payloadExp))
368369
| _ -> ());
369370
Ast_iterator.default_iterator.expr iterator expr
370371
in
371-
let iterator = {Ast_iterator.default_iterator with expr} in
372+
let pat (iterator : Ast_iterator.iterator) (pat : Parsetree.pattern) =
373+
(match pat with
374+
| {ppat_desc = Ppat_construct (lid, Some payloadPat)}
375+
when locHasCursor payloadPat.ppat_loc ->
376+
(* Constructor payloads *)
377+
setResult (lid.loc, `ConstructorPat (lid, payloadPat))
378+
| _ -> ());
379+
Ast_iterator.default_iterator.pat iterator pat
380+
in
381+
let iterator = {Ast_iterator.default_iterator with expr; pat} in
372382
let parser =
373383
Res_driver.parsingEngine.parseImplementation ~forPrinter:false
374384
in
@@ -474,9 +484,10 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
474484
| activeParameter -> activeParameter);
475485
}
476486
| _ -> None)
477-
| Some (_, `Constructor (lid, expr)) -> (
487+
| Some (_, ((`ConstructorExpr (lid, _) | `ConstructorPat (lid, _)) as cs))
488+
-> (
478489
if Debug.verbose () then
479-
Printf.printf "[signature_help] Found constructor expr!\n";
490+
Printf.printf "[signature_help] Found constructor!\n";
480491
match Cmt.loadFullCmtFromPath ~path with
481492
| None ->
482493
if Debug.verbose () then
@@ -560,8 +571,8 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
560571
^ ")"
561572
in
562573
let activeParameter =
563-
match expr with
564-
| {pexp_desc = Pexp_tuple items} -> (
574+
match cs with
575+
| `ConstructorExpr (_, {pexp_desc = Pexp_tuple items}) -> (
565576
let idx = ref 0 in
566577
let tupleItemWithCursor =
567578
items
@@ -574,7 +585,7 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
574585
match tupleItemWithCursor with
575586
| None -> -1
576587
| Some i -> i)
577-
| {pexp_desc = Pexp_record (fields, _)} -> (
588+
| `ConstructorExpr (_, {pexp_desc = Pexp_record (fields, _)}) -> (
578589
let fieldNameWithCursor =
579590
fields
580591
|> List.find_map
@@ -602,7 +613,49 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
602613
else ());
603614
!fieldIndex
604615
| _ -> -1)
605-
| _ when locHasCursor expr.pexp_loc -> 0
616+
| `ConstructorExpr (_, expr) when locHasCursor expr.pexp_loc -> 0
617+
| `ConstructorPat (_, {ppat_desc = Ppat_tuple items}) -> (
618+
let idx = ref 0 in
619+
let tupleItemWithCursor =
620+
items
621+
|> List.find_map (fun (item : Parsetree.pattern) ->
622+
let currentIndex = !idx in
623+
idx := currentIndex + 1;
624+
if locHasCursor item.ppat_loc then Some currentIndex
625+
else None)
626+
in
627+
match tupleItemWithCursor with
628+
| None -> -1
629+
| Some i -> i)
630+
| `ConstructorPat (_, {ppat_desc = Ppat_record (fields, _)}) -> (
631+
let fieldNameWithCursor =
632+
fields
633+
|> List.find_map
634+
(fun
635+
(({loc; txt}, pat) :
636+
Longident.t Location.loc * Parsetree.pattern)
637+
->
638+
if
639+
posBeforeCursor >= Pos.ofLexing loc.loc_start
640+
&& posBeforeCursor
641+
<= Pos.ofLexing pat.ppat_loc.loc_end
642+
then Some (Longident.last txt)
643+
else None)
644+
in
645+
match (fieldNameWithCursor, argParts) with
646+
| Some fieldName, Some (`InlineRecord fields) ->
647+
let idx = ref 0 in
648+
let fieldIndex = ref (-1) in
649+
fields
650+
|> List.iter (fun (_, field, _) ->
651+
idx := !idx + 1;
652+
let currentIndex = !idx in
653+
if fieldName = field.fname.txt then
654+
fieldIndex := currentIndex
655+
else ());
656+
!fieldIndex
657+
| _ -> -1)
658+
| `ConstructorPat (_, pat) when locHasCursor pat.ppat_loc -> 0
606659
| _ -> -1
607660
in
608661

Diff for: analysis/tests/src/SignatureHelp.res

+13
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,16 @@ let _ = stuffers({}, One)
139139

140140
let _ = stuffers({}, One)
141141
// ^she
142+
143+
let _ = switch _one {
144+
| One({hit: _hit}) => ""
145+
// ^she
146+
| One(_a) => ""
147+
// ^she
148+
| Two(_ms) => ""
149+
// ^she
150+
| Three(_a, []) => ""
151+
// ^she
152+
| Three(_, _b) => ""
153+
// ^she
154+
}

Diff for: analysis/tests/src/expected/SignatureHelp.res.txt

+55
Original file line numberDiff line numberDiff line change
@@ -505,3 +505,58 @@ extracted params:
505505
"activeParameter": 1
506506
}
507507

508+
Signature help src/SignatureHelp.res 143:8
509+
{
510+
"signatures": [{
511+
"label": "One({miss?: bool, hit?: bool, stuff?: string})",
512+
"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": ""}}],
513+
"documentation": {"kind": "markdown", "value": " One is cool. "}
514+
}],
515+
"activeSignature": 0,
516+
"activeParameter": 2
517+
}
518+
519+
Signature help src/SignatureHelp.res 145:7
520+
{
521+
"signatures": [{
522+
"label": "One({miss?: bool, hit?: bool, stuff?: string})",
523+
"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": ""}}],
524+
"documentation": {"kind": "markdown", "value": " One is cool. "}
525+
}],
526+
"activeSignature": 0,
527+
"activeParameter": 0
528+
}
529+
530+
Signature help src/SignatureHelp.res 147:7
531+
{
532+
"signatures": [{
533+
"label": "Two(mySpecialThing)",
534+
"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)"}}],
535+
"documentation": {"kind": "markdown", "value": " Two is fun! "}
536+
}],
537+
"activeSignature": 0,
538+
"activeParameter": 0
539+
}
540+
541+
Signature help src/SignatureHelp.res 149:9
542+
{
543+
"signatures": [{
544+
"label": "Three(mySpecialThing, array<option<string>>)",
545+
"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": ""}}],
546+
"documentation": {"kind": "markdown", "value": " Three is... three "}
547+
}],
548+
"activeSignature": 0,
549+
"activeParameter": 0
550+
}
551+
552+
Signature help src/SignatureHelp.res 151:12
553+
{
554+
"signatures": [{
555+
"label": "Three(mySpecialThing, array<option<string>>)",
556+
"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": ""}}],
557+
"documentation": {"kind": "markdown", "value": " Three is... three "}
558+
}],
559+
"activeSignature": 0,
560+
"activeParameter": 1
561+
}
562+

0 commit comments

Comments
 (0)