diff --git a/CHANGELOG.md b/CHANGELOG.md index f097e5d66..be71a6f22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Add completion to top level decorators. https://github.com/rescript-lang/rescript-vscode/pull/799 - Add code action for wrapping patterns where option is expected with `Some`. https://github.com/rescript-lang/rescript-vscode/pull/806 - Better completion from identifiers with inferred types. https://github.com/rescript-lang/rescript-vscode/pull/808 +- Make suggested template functions async when the target function returns a promise. https://github.com/rescript-lang/rescript-vscode/pull/816 #### :nail_care: Polish diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 15db181c1..61acb9d08 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -1382,8 +1382,8 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode ~env (); ] else [] - | Tfunction {env; typ; args; uncurried} when prefix = "" && mode = Expression - -> + | Tfunction {env; typ; args; uncurried; returnType} + when prefix = "" && mode = Expression -> let shouldPrintAsUncurried = uncurried && !Config.uncurried <> Uncurried in let mkFnArgs ~asSnippet = match args with @@ -1419,11 +1419,18 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode in "(" ^ if shouldPrintAsUncurried then ". " else "" ^ argsText ^ ")" in + let isAsync = + match TypeUtils.extractType ~env ~package:full.package returnType with + | Some (Tpromise _) -> true + | _ -> false + in + let asyncPrefix = if isAsync then "async " else "" in [ Completion.createWithSnippet - ~name:(mkFnArgs ~asSnippet:false ^ " => {}") + ~name:(asyncPrefix ^ mkFnArgs ~asSnippet:false ^ " => {}") ~insertText: - (mkFnArgs ~asSnippet:!Cfg.supportsSnippets + (asyncPrefix + ^ mkFnArgs ~asSnippet:!Cfg.supportsSnippets ^ " => " ^ if !Cfg.supportsSnippets then "{$0}" else "{}") ~sortText:"A" ~kind:(Value typ) ~env (); diff --git a/analysis/src/SharedTypes.ml b/analysis/src/SharedTypes.ml index aee6e046b..7ee60c8e8 100644 --- a/analysis/src/SharedTypes.ml +++ b/analysis/src/SharedTypes.ml @@ -343,6 +343,7 @@ and completionType = args: typedFnArg list; typ: Types.type_expr; uncurried: bool; + returnType: Types.type_expr; } module Env = struct diff --git a/analysis/src/TypeUtils.ml b/analysis/src/TypeUtils.ml index d8da5bc8f..a0ea3210a 100644 --- a/analysis/src/TypeUtils.ml +++ b/analysis/src/TypeUtils.ml @@ -125,8 +125,8 @@ let rec extractType ~env ~package (t : Types.type_expr) = | Tconstr (Pident {name = "function$"}, [t; _], _) -> ( (* Uncurried functions. *) match extractFunctionType t ~env ~package with - | args, _tRet when args <> [] -> - Some (Tfunction {env; args; typ = t; uncurried = true}) + | args, tRet when args <> [] -> + Some (Tfunction {env; args; typ = t; uncurried = true; returnType = tRet}) | _args, _tRet -> None) | Tconstr (path, typeArgs, _) -> ( match References.digConstructor ~env ~package path with @@ -168,8 +168,9 @@ let rec extractType ~env ~package (t : Types.type_expr) = Some (Tpolyvariant {env; constructors; typeExpr = t}) | Tarrow _ -> ( match extractFunctionType t ~env ~package with - | args, _tRet when args <> [] -> - Some (Tfunction {env; args; typ = t; uncurried = false}) + | args, tRet when args <> [] -> + Some + (Tfunction {env; args; typ = t; uncurried = false; returnType = tRet}) | _args, _tRet -> None) | _ -> None diff --git a/analysis/tests/src/CompletionExpressions.res b/analysis/tests/src/CompletionExpressions.res index d61259101..cbd9aef1b 100644 --- a/analysis/tests/src/CompletionExpressions.res +++ b/analysis/tests/src/CompletionExpressions.res @@ -250,3 +250,10 @@ external commitLocalUpdate: (~updater: RecordSourceSelectorProxy.t => unit) => u // commitLocalUpdate(~updater=) // ^com + +let fnTakingAsyncCallback = (cb: unit => promise) => { + let _ = cb +} + +// fnTakingAsyncCallback() +// ^com diff --git a/analysis/tests/src/expected/CompletionExpressions.res.txt b/analysis/tests/src/expected/CompletionExpressions.res.txt index 2be6098fd..e3363eb27 100644 --- a/analysis/tests/src/expected/CompletionExpressions.res.txt +++ b/analysis/tests/src/expected/CompletionExpressions.res.txt @@ -1074,3 +1074,23 @@ Path commitLocalUpdate "insertTextFormat": 2 }] +Complete src/CompletionExpressions.res 257:25 +posCursor:[257:25] posNoWhite:[257:24] Found expr:[257:3->257:26] +Pexp_apply ...[257:3->257:24] (...[257:25->257:26]) +Completable: Cexpression CArgument Value[fnTakingAsyncCallback]($0) +Package opens Pervasives.JsxModules.place holder +Resolved opens 1 pervasives +ContextPath CArgument Value[fnTakingAsyncCallback]($0) +ContextPath Value[fnTakingAsyncCallback] +Path fnTakingAsyncCallback +[{ + "label": "async () => {}", + "kind": 12, + "tags": [], + "detail": "unit => promise", + "documentation": null, + "sortText": "A", + "insertText": "async () => {$0}", + "insertTextFormat": 2 + }] +