diff --git a/CHANGELOG.md b/CHANGELOG.md index 752439edc..1c6897820 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ #### :bug: Bug Fix - Highlight `catch` like a keyword https://github.com/rescript-lang/rescript-vscode/pull/677 +- Make signature help work in calls nested inside of other calls. https://github.com/rescript-lang/rescript-vscode/pull/687 ## v1.10.0 diff --git a/analysis/src/SignatureHelp.ml b/analysis/src/SignatureHelp.ml index 5b6390a20..a31140320 100644 --- a/analysis/src/SignatureHelp.ml +++ b/analysis/src/SignatureHelp.ml @@ -179,10 +179,19 @@ let signatureHelp ~path ~pos ~currentFile ~debug = let supportsMarkdownLinks = true in let foundFunctionApplicationExpr = ref None in let setFound r = - if !foundFunctionApplicationExpr = None then + (* Because we want to handle both piped and regular function calls, and in + the case of piped calls the iterator will process both the pipe and the + regular call (even though it's piped), we need to ensure that we don't + re-save the same expression (but unpiped, even though it's actually piped). *) + match (!foundFunctionApplicationExpr, r) with + | Some (_, alreadyFoundExp, _), (_, newExp, _) + when alreadyFoundExp.Parsetree.pexp_loc <> newExp.Parsetree.pexp_loc + -> foundFunctionApplicationExpr := Some r + | None, _ -> foundFunctionApplicationExpr := Some r + | Some _, _ -> () in - let searchForArgWithCursor ~isPipeExpr ~args ~exp = + let searchForArgWithCursor ~isPipeExpr ~args = let extractedArgs = extractExpApplyArgs ~args in let argAtCursor = let firstArgIndex = if isPipeExpr then 1 else 0 in @@ -246,7 +255,7 @@ let signatureHelp ~path ~pos ~currentFile ~debug = else 0)) | v -> v in - setFound (argAtCursor, exp, extractedArgs) + (argAtCursor, extractedArgs) in let expr (iterator : Ast_iterator.iterator) (expr : Parsetree.expression) = @@ -269,7 +278,10 @@ let signatureHelp ~path ~pos ~currentFile ~debug = when pexp_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor == HasCursor -> - searchForArgWithCursor ~isPipeExpr:true ~args ~exp + let argAtCursor, extractedArgs = + searchForArgWithCursor ~isPipeExpr:true ~args + in + setFound (argAtCursor, exp, extractedArgs) (* Look for applying idents, like someIdent(...) *) | { pexp_desc = Pexp_apply (({pexp_desc = Pexp_ident _} as exp), args); @@ -278,7 +290,10 @@ let signatureHelp ~path ~pos ~currentFile ~debug = when pexp_loc |> CursorPosition.classifyLoc ~pos:posBeforeCursor == HasCursor -> - searchForArgWithCursor ~isPipeExpr:false ~args ~exp + let argAtCursor, extractedArgs = + searchForArgWithCursor ~isPipeExpr:false ~args + in + setFound (argAtCursor, exp, extractedArgs) | _ -> ()); Ast_iterator.default_iterator.expr iterator expr in diff --git a/analysis/tests/src/SignatureHelp.res b/analysis/tests/src/SignatureHelp.res index 8fa6c4020..41d2b8cfb 100644 --- a/analysis/tests/src/SignatureHelp.res +++ b/analysis/tests/src/SignatureHelp.res @@ -68,3 +68,9 @@ let fn = (age: int, name: string, year: int) => { // let _ = fn(12, "hello", ) // ^she + +// let _ = fn({ iAmSoSpecial() }) +// ^she + +// let _ = fn({ iAmSoSpecial({ someFunc() }) }) +// ^she diff --git a/analysis/tests/src/expected/SignatureHelp.res.txt b/analysis/tests/src/expected/SignatureHelp.res.txt index f6b960ff5..802874b2f 100644 --- a/analysis/tests/src/expected/SignatureHelp.res.txt +++ b/analysis/tests/src/expected/SignatureHelp.res.txt @@ -266,3 +266,45 @@ extracted params: "activeParameter": 2 } +Signature help src/SignatureHelp.res 71:29 +posCursor:[71:28] posNoWhite:[71:27] Found expr:[71:11->71:33] +Pexp_apply ...[71:11->71:13] (...[71:16->71:30]) +posCursor:[71:28] posNoWhite:[71:27] Found expr:[71:16->71:30] +Pexp_apply ...[71:16->71:28] (...[71:29->71:30]) +posCursor:[71:28] posNoWhite:[71:27] Found expr:[71:16->71:28] +Pexp_ident iAmSoSpecial:[71:16->71:28] +argAtCursor: unlabelled<0> +extracted params: +[string] +{ + "signatures": [{ + "label": "string => unit", + "parameters": [{"label": [0, 6], "documentation": {"kind": "markdown", "value": "```rescript\nstring\n```"}}] + }], + "activeSignature": 0, + "activeParameter": 0 +} + +Signature help src/SignatureHelp.res 74:40 +posCursor:[74:39] posNoWhite:[74:38] Found expr:[74:11->74:47] +Pexp_apply ...[74:11->74:13] (...[74:16->74:44]) +posCursor:[74:39] posNoWhite:[74:38] Found expr:[74:16->74:44] +Pexp_apply ...[74:16->74:28] (...[74:31->74:41]) +posCursor:[74:39] posNoWhite:[74:38] Found expr:[74:31->74:41] +Pexp_apply ...[74:31->74:39] (...[74:40->74:41]) +posCursor:[74:39] posNoWhite:[74:38] Found expr:[74:31->74:39] +Pexp_ident someFunc:[74:31->74:39] +argAtCursor: unlabelled<0> +extracted params: +[( + int, ~two: string=?, ~three: unit => unit, ~four: someVariant, unit] +{ + "signatures": [{ + "label": "(\n int,\n ~two: string=?,\n ~three: unit => unit,\n ~four: someVariant,\n unit,\n) => unit", + "parameters": [{"label": [0, 7], "documentation": {"kind": "markdown", "value": "```rescript\nint\n```"}}, {"label": [11, 25], "documentation": {"kind": "markdown", "value": "```rescript\noption\n```"}}, {"label": [29, 49], "documentation": {"kind": "markdown", "value": ""}}, {"label": [53, 71], "documentation": {"kind": "markdown", "value": "```rescript\nsomeVariant\n```\n```rescript\ntype someVariant = One | Two | Three\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22SignatureHelp.res%22%2C0%2C0%5D)"}}, {"label": [75, 79], "documentation": {"kind": "markdown", "value": "```rescript\nint\n```"}}], + "documentation": {"kind": "markdown", "value": " Does stuff. "} + }], + "activeSignature": 0, + "activeParameter": 0 +} +