From 66992874962b6d7e5a5ada482ded44d411af907d Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 25 Sep 2023 18:03:49 +0200 Subject: [PATCH 1/2] complete for builtin types, and enable completion for types when coercing --- .vscode/settings.json | 24 ++-- analysis/src/CompletionBackEnd.ml | 24 +++- analysis/src/CompletionFrontEnd.ml | 4 + analysis/src/Utils.ml | 5 + analysis/tests/src/Completion.res | 6 + .../tests/src/expected/Completion.res.txt | 105 +++++++++++++++++- 6 files changed, 153 insertions(+), 15 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 11909bf1d..fed2e87a0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,13 +1,13 @@ { - "editor.insertSpaces": false, - "tslint.enable": true, - "typescript.tsc.autoDetect": "off", - "typescript.preferences.quoteStyle": "single", - "editor.codeActionsOnSave": { - "source.fixAll.eslint": true - }, - "ocaml.sandbox": { - "kind": "opam", - "switch": "${workspaceFolder:rescript-vscode}/analysis" - } -} \ No newline at end of file + "editor.insertSpaces": false, + "tslint.enable": true, + "typescript.tsc.autoDetect": "off", + "typescript.preferences.quoteStyle": "single", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "ocaml.sandbox": { + "kind": "opam", + "switch": "4.14.0" + } +} diff --git a/analysis/src/CompletionBackEnd.ml b/analysis/src/CompletionBackEnd.ml index 61acb9d08..2db69a7f3 100644 --- a/analysis/src/CompletionBackEnd.ml +++ b/analysis/src/CompletionBackEnd.ml @@ -373,6 +373,26 @@ let getItemsFromOpens ~opens ~localTables ~prefix ~exact ~completionContext = completionsFromThisOpen @ results) [] +let builtinTypes = + [ + ("string", "string"); + ("int", "int"); + ("float", "float"); + ("bool", "bool"); + ("option", "option<${1:_}>"); + ("array", "array<${1:_}>"); + ("promise", "promise<${1:_}>"); + ("result", "result<${1:_}, ${2:_}>"); + ] + +let getTypesFromBuiltins ~env ~prefix ~exact = + builtinTypes + |> List.filter (fun (typeName, _) -> + if exact then typeName == prefix else Utils.startsWith typeName prefix) + |> List.map (fun (typeName, template) -> + Completion.createWithSnippet ~name:typeName ~insertText:template ~env + ~kind:(Completion.Label typeName) ()) + let findLocalCompletionsForValuesAndConstructors ~(localTables : LocalTables.t) ~env ~prefix ~exact ~opens ~scope = localTables |> LocalTables.populateValues ~env; @@ -442,6 +462,7 @@ let findLocalCompletionsForTypes ~(localTables : LocalTables.t) ~env ~prefix let valuesFromOpens = getItemsFromOpens ~opens ~localTables ~prefix ~exact ~completionContext:Type in + let typesFromBuiltins = getTypesFromBuiltins ~env ~prefix ~exact in scope |> Scope.iterTypesAfterFirstOpen @@ -449,7 +470,7 @@ let findLocalCompletionsForTypes ~(localTables : LocalTables.t) ~env ~prefix scope |> Scope.iterModulesAfterFirstOpen (processLocalModule ~prefix ~exact ~env ~localTables); - List.rev_append localTables.resultRev valuesFromOpens + List.rev_append localTables.resultRev (valuesFromOpens @ typesFromBuiltins) let findLocalCompletionsForModules ~(localTables : LocalTables.t) ~env ~prefix ~exact ~opens ~scope = @@ -745,6 +766,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact | Some (Tpromise (env, typ), _env) -> [Completion.create "dummy" ~env ~kind:(Completion.Value typ)] | _ -> []) + | CPId ([], Type) -> getTypesFromBuiltins ~env ~prefix:"" ~exact | CPId (path, completionContext) -> path |> getCompletionsForPath ~debug ~package ~opens ~full ~pos ~exact diff --git a/analysis/src/CompletionFrontEnd.ml b/analysis/src/CompletionFrontEnd.ml index 70ce8eda5..caecf6d4e 100644 --- a/analysis/src/CompletionFrontEnd.ml +++ b/analysis/src/CompletionFrontEnd.ml @@ -819,6 +819,10 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor in typedCompletionExpr expr; match expr.pexp_desc with + | Pexp_coerce (_e, _, typ) + when expr.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor + && Utils.isTypeHole typ -> + setResult (Cpath (CPId ([], Type))) | Pexp_match (expr, cases) when cases <> [] -> let ctxPath = exprToContextPath expr in let oldCtxPath = !currentCtxPath in diff --git a/analysis/src/Utils.ml b/analysis/src/Utils.ml index e548457f2..903e1ded6 100644 --- a/analysis/src/Utils.ml +++ b/analysis/src/Utils.ml @@ -216,3 +216,8 @@ let rec lastElements list = let lowercaseFirstChar s = if String.length s = 0 then s else String.mapi (fun i c -> if i = 0 then Char.lowercase_ascii c else c) s + +let isTypeHole typ = + match typ.Parsetree.ptyp_desc with + | Ptyp_extension ({txt = "rescript.typehole"}, _) -> true + | _ -> false diff --git a/analysis/tests/src/Completion.res b/analysis/tests/src/Completion.res index 153e6d237..fcb046d80 100644 --- a/analysis/tests/src/Completion.res +++ b/analysis/tests/src/Completion.res @@ -462,3 +462,9 @@ type withUncurried = { // let f: withUncurried = {fn: } // ^com + +// let a = (fff :> ) +// ^com + +// let a = (fff :> boo) +// ^com diff --git a/analysis/tests/src/expected/Completion.res.txt b/analysis/tests/src/expected/Completion.res.txt index aef3b28be..76192e18d 100644 --- a/analysis/tests/src/expected/Completion.res.txt +++ b/analysis/tests/src/expected/Completion.res.txt @@ -1323,6 +1323,14 @@ Path s "tags": [], "detail": "type someLocalVariant = SomeLocalVariantItem", "documentation": null + }, { + "label": "string", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "insertText": "string", + "insertTextFormat": 2 }] Complete src/Completion.res 291:30 @@ -1950,8 +1958,8 @@ Path red }] Complete src/Completion.res 405:22 -posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->465:0] -Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->423:17], ...[428:0->465:0]) +posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->471:0] +Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->423:17], ...[428:0->471:0]) posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:11->423:17] Pexp_apply ...__ghost__[0:-1->0:-1] (...[405:11->405:19], ...[405:21->423:17]) posCursor:[405:22] posNoWhite:[405:21] Found expr:[405:21->423:17] @@ -2206,3 +2214,96 @@ Path withUncurried "insertTextFormat": 2 }] +Complete src/Completion.res 465:19 +XXX Not found! +Completable: Cpath Type[] +Raw opens: 2 Shadow.B.place holder ... Shadow.A.place holder +Package opens Pervasives.JsxModules.place holder +Resolved opens 3 Completion.res Completion.res pervasives +ContextPath Type[] +[{ + "label": "string", + "kind": 4, + "tags": [], + "detail": "string", + "documentation": null, + "insertText": "string", + "insertTextFormat": 2 + }, { + "label": "int", + "kind": 4, + "tags": [], + "detail": "int", + "documentation": null, + "insertText": "int", + "insertTextFormat": 2 + }, { + "label": "float", + "kind": 4, + "tags": [], + "detail": "float", + "documentation": null, + "insertText": "float", + "insertTextFormat": 2 + }, { + "label": "bool", + "kind": 4, + "tags": [], + "detail": "bool", + "documentation": null, + "insertText": "bool", + "insertTextFormat": 2 + }, { + "label": "option", + "kind": 4, + "tags": [], + "detail": "option", + "documentation": null, + "insertText": "option<${1:_}>", + "insertTextFormat": 2 + }, { + "label": "array", + "kind": 4, + "tags": [], + "detail": "array", + "documentation": null, + "insertText": "array<${1:_}>", + "insertTextFormat": 2 + }, { + "label": "promise", + "kind": 4, + "tags": [], + "detail": "promise", + "documentation": null, + "insertText": "promise<${1:_}>", + "insertTextFormat": 2 + }, { + "label": "result", + "kind": 4, + "tags": [], + "detail": "result", + "documentation": null, + "insertText": "result<${1:_}, ${2:_}>", + "insertTextFormat": 2 + }] + +Complete src/Completion.res 468:22 +posCursor:[468:22] posNoWhite:[468:21] Found expr:[468:12->468:22] +posCursor:[468:22] posNoWhite:[468:21] Found type:[468:19->468:22] +Ptyp_constr boo:[468:19->468:22] +Completable: Cpath Type[boo] +Raw opens: 2 Shadow.B.place holder ... Shadow.A.place holder +Package opens Pervasives.JsxModules.place holder +Resolved opens 3 Completion.res Completion.res pervasives +ContextPath Type[boo] +Path boo +[{ + "label": "bool", + "kind": 4, + "tags": [], + "detail": "bool", + "documentation": null, + "insertText": "bool", + "insertTextFormat": 2 + }] + From 4b9f612da89fdfb5a1f67662b998b1dbc4117a1a Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 25 Sep 2023 22:13:29 +0200 Subject: [PATCH 2/2] revert --- .vscode/settings.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index fed2e87a0..11909bf1d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,13 +1,13 @@ { - "editor.insertSpaces": false, - "tslint.enable": true, - "typescript.tsc.autoDetect": "off", - "typescript.preferences.quoteStyle": "single", - "editor.codeActionsOnSave": { - "source.fixAll.eslint": true - }, - "ocaml.sandbox": { - "kind": "opam", - "switch": "4.14.0" - } -} + "editor.insertSpaces": false, + "tslint.enable": true, + "typescript.tsc.autoDetect": "off", + "typescript.preferences.quoteStyle": "single", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "ocaml.sandbox": { + "kind": "opam", + "switch": "${workspaceFolder:rescript-vscode}/analysis" + } +} \ No newline at end of file