From 84fa4ddf689bc7eedaca72c77fd5a4599f22c0fc Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 10 Jun 2022 20:39:00 -0300 Subject: [PATCH 01/42] feat(inlayHint): basic support --- analysis/src/Cli.ml | 4 + analysis/src/Commands.ml | 6 + analysis/src/Hint.ml | 290 ++++++++++++ analysis/src/Protocol.ml | 14 + analysis/tests/src/InlayHint.res | 40 ++ client/package-lock.json | 70 +-- client/package.json | 2 +- client/src/client.ts | 45 ++ client/src/extension.ts | 276 ++++-------- package-lock.json | 28 +- package.json | 23 +- server/package-lock.json | 731 +++++++++++++++---------------- server/package.json | 38 +- server/src/server.ts | 121 +++-- 14 files changed, 1003 insertions(+), 685 deletions(-) create mode 100644 analysis/src/Hint.ml create mode 100644 analysis/tests/src/InlayHint.res create mode 100644 client/src/client.ts diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index a49326d92..89f73ebb5 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -84,6 +84,10 @@ let main () = Commands.hover ~path ~pos:(int_of_string line, int_of_string col) ~currentFile ~debug:false + | [_; "inlayHint"; path; line_start; line_end] -> + Commands.inlayhint ~path + ~pos:(int_of_string line_start, int_of_string line_end) + ~debug:false | [_; "codeAction"; path; line; col; currentFile] -> Commands.codeAction ~path ~pos:(int_of_string line, int_of_string col) diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 65066f8a8..db6e7b669 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -28,6 +28,12 @@ let completion ~debug ~path ~pos ~currentFile = |> List.map Protocol.stringifyCompletionItem |> Protocol.array) +let inlayhint ~path ~pos ~debug = + let result = match Hint.inlay ~path ~debug with + | [] -> Protocol.null + | hints -> "[\n" ^ String.concat ",\n" hints ^ "\n]" in + print_endline result + let hover ~path ~pos ~currentFile ~debug = let result = match Cmt.fullFromPath ~path with diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml new file mode 100644 index 000000000..8cfe1f405 --- /dev/null +++ b/analysis/src/Hint.ml @@ -0,0 +1,290 @@ +open SharedTypes + +type kind = + | Module + | Property + | Constructor + | Function + | Variable + | Constant + | String + | Number + | EnumMember + | TypeParameter + +let hintPrefix label = Printf.sprintf ": %s" label +let hintkindNumber = function TypeParameter | EnumMember -> 2 | _ -> 1 + +let locItemToTypeHint ~full:{file; package} locItem = + match locItem.locType with + (* | TypeDefinition (name, decl, _stamp) -> *) + (* let typeDef = Shared.declToString name decl in *) + (* Some (hintPrefix typeDef) *) + (* | LModule (Definition (stamp, _tip)) | LModule (LocalReference (stamp, _tip)) *) + (* -> ( *) + (* match Stamps.findModule file.stamps stamp with *) + (* | None -> None *) + (* | Some md -> ( *) + (* match References.resolveModuleReference ~file ~package md with *) + (* | None -> None *) + (* | Some (file, declared) -> *) + (* let name, docstring = *) + (* match declared with *) + (* | Some d -> (d.name.txt, d.docstring) *) + (* | None -> (file.moduleName, file.structure.docstring) *) + (* in *) + (* Hover.showModule ~docstring ~name ~file declared)) *) + (* | LModule (GlobalReference (moduleName, path, tip)) -> ( *) + (* match ProcessCmt.fileForModule ~package moduleName with *) + (* | None -> None *) + (* | Some file -> ( *) + (* let env = QueryEnv.fromFile file in *) + (* match ResolvePath.resolvePath ~env ~path ~package with *) + (* | None -> None *) + (* | Some (env, name) -> ( *) + (* match References.exportedForTip ~env name tip with *) + (* | None -> None *) + (* | Some stamp -> ( *) + (* match Stamps.findModule file.stamps stamp with *) + (* | None -> None *) + (* | Some md -> ( *) + (* match References.resolveModuleReference ~file ~package md with *) + (* | None -> None *) + (* | Some (file, declared) -> *) + (* let name, docstring = *) + (* match declared with *) + (* | Some d -> (d.name.txt, d.docstring) *) + (* | None -> (file.moduleName, file.structure.docstring) *) + (* in *) + (* Hover.showModule ~docstring ~name ~file declared))))) *) + | LModule NotFound -> None + (* | TopLevelModule name -> ( *) + (* match ProcessCmt.fileForModule ~package name with *) + (* | None -> None *) + (* | Some file -> *) + (* Hover.showModule ~docstring:file.structure.docstring ~name:file.moduleName *) + (* ~file None) *) + | Typed (_, _, Definition (_, (Field _ | Constructor _))) -> None + | Constant t -> + Some + (hintPrefix + (match t with + | Const_int _ -> "int" + | Const_char _ -> "char" + | Const_string _ -> "string" + | Const_float _ -> "float" + | Const_int32 _ -> "int32" + | Const_int64 _ -> "int64" + | Const_nativeint _ -> "int")) + | Typed (_, t, locKind) -> + (* let fromType ~docstring typ = *) + (* let typeString = Hover.codeBlock (typ |> Shared.typeToString) in *) + (* let extraTypeInfo = *) + (* let env = QueryEnv.fromFile file in *) + (* match typ |> Shared.digConstructor with *) + (* | None -> None *) + (* | Some path -> ( *) + (* match References.digConstructor ~env ~package path with *) + (* | None -> None *) + (* | Some (_env, {docstring; name = {txt}; item = {decl}}) -> *) + (* if Utils.isUncurriedInternal path then None *) + (* else Some (decl |> Shared.declToString txt, docstring)) *) + (* in *) + (* let typeString, docstring = *) + (* match extraTypeInfo with *) + (* | None -> (typeString, docstring) *) + (* | Some (extra, extraDocstring) -> *) + (* (typeString ^ "\n\n" ^ Hover.codeBlock extra, extraDocstring) *) + (* in *) + (* (typeString, docstring) *) + (* in *) + let parts = + match References.definedForLoc ~file ~package locKind with + | None -> + let typeString = Shared.typeToString t in + typeString + | Some (docstring, res) -> ( + match res with + | `Declared -> + let typeString = Shared.typeToString t in + typeString + | `Constructor {cname = {txt}; args} -> + let typeString = Shared.typeToString t in + typeString + (* let typeString, docstring = t |> fromType ~docstring in *) + (* let argsString = *) + (* match args with *) + (* | [] -> "" *) + (* | _ -> *) + (* args *) + (* |> List.map (fun (t, _) -> (Shared.typeToString t) ^ "hre") *) + (* |> String.concat ", " |> Printf.sprintf "(%s)" *) + (* in *) + (* typeString *) + | `Field -> + let typeString = Shared.typeToString t in + typeString + (* let typeString, docstring = t |> fromType ~docstring in *) + (* typeString) *) + ) + in + Some parts + +let inlay ~path ~debug = + let symbols = ref [] in + let rec exprKind (exp : Parsetree.expression) = + match exp.pexp_desc with + | Pexp_fun _ -> Function + | Pexp_function _ -> Function + | Pexp_constraint (e, _) -> exprKind e + | Pexp_constant (Pconst_string _) -> String + | Pexp_constant (Pconst_float _ | Pconst_integer _) -> Number + | Pexp_constant _ -> Constant + | _ -> Variable + in + (* let processTypeKind (tk : Parsetree.type_kind) = *) + (* match tk with *) + (* | Ptype_variant constrDecls -> *) + (* constrDecls *) + (* |> List.iter (fun (cd : Parsetree.constructor_declaration) -> *) + (* symbols := (cd.pcd_name.txt, cd.pcd_loc, EnumMember) :: !symbols) *) + (* | Ptype_record labelDecls -> *) + (* labelDecls *) + (* |> List.iter (fun (ld : Parsetree.label_declaration) -> *) + (* symbols := (ld.pld_name.txt, ld.pld_loc, Property) :: !symbols) *) + (* | _ -> () *) + (* in *) + (* let processTypeDeclaration (td : Parsetree.type_declaration) = *) + (* symbols := (td.ptype_name.txt, td.ptype_loc, TypeParameter) :: !symbols; *) + (* processTypeKind td.ptype_kind *) + (* in *) + let processValueDescription (vd : Parsetree.value_description) = + symbols := (vd.pval_name.txt, vd.pval_loc, Variable) :: !symbols + in + (* let processModuleBinding (mb : Parsetree.module_binding) = *) + (* symbols := (mb.pmb_name.txt, mb.pmb_loc, Module) :: !symbols *) + (* in *) + (* let processModuleDeclaration (md : Parsetree.module_declaration) = *) + (* symbols := (md.pmd_name.txt, md.pmd_loc, Module) :: !symbols *) + (* in *) + (* let processExtensionConstructor (et : Parsetree.extension_constructor) = *) + (* symbols := (et.pext_name.txt, et.pext_loc, Constructor) :: !symbols *) + (* in *) + let value_binding (iterator : Ast_iterator.iterator) + (vb : Parsetree.value_binding) = + (match vb.pvb_pat.ppat_desc with + | Ppat_var {txt} | Ppat_constraint ({ppat_desc = Ppat_var {txt}}, _) -> + symbols := (txt, vb.pvb_loc, exprKind vb.pvb_expr) :: !symbols + | _ -> ()); + Ast_iterator.default_iterator.value_binding iterator vb + in + (* let expr (iterator : Ast_iterator.iterator) (e : Parsetree.expression) = *) + (* (match e.pexp_desc with *) + (* | Pexp_letmodule ({txt}, modExpr, _) -> *) + (* symbols := *) + (* (txt, {e.pexp_loc with loc_end = modExpr.pmod_loc.loc_end}, Module) *) + (* :: !symbols *) + (* (* | Pexp_letexception (ec, _) -> processExtensionConstructor ec *) *) + (* | _ -> ()); *) + (* Ast_iterator.default_iterator.expr iterator e *) + (* in *) + let structure_item (iterator : Ast_iterator.iterator) + (item : Parsetree.structure_item) = + (match item.pstr_desc with + | Pstr_value _ -> () + | Pstr_primitive vd -> processValueDescription vd + (* | Pstr_type (_, typDecls) -> typDecls |> List.iter processTypeDeclaration *) + (* | Pstr_module mb -> processModuleBinding mb *) + (* | Pstr_recmodule mbs -> mbs |> List.iter processModuleBinding *) + (* | Pstr_exception ec -> processExtensionConstructor ec *) + | _ -> ()); + Ast_iterator.default_iterator.structure_item iterator item + in + let signature_item (iterator : Ast_iterator.iterator) + (item : Parsetree.signature_item) = + (match item.psig_desc with + | Psig_value vd -> processValueDescription vd + (* | Psig_type (_, typDecls) -> typDecls |> List.iter processTypeDeclaration *) + (* | Psig_module md -> processModuleDeclaration md *) + (* | Psig_recmodule mds -> mds |> List.iter processModuleDeclaration *) + (* | Psig_exception ec -> processExtensionConstructor ec *) + | _ -> ()); + Ast_iterator.default_iterator.signature_item iterator item + in + (* let module_expr (iterator : Ast_iterator.iterator) *) + (* (me : Parsetree.module_expr) = *) + (* match me.pmod_desc with *) + (* | Pmod_constraint (modExpr, _modTyp) -> *) + (* (* Don't double-list items in implementation and interface *) *) + (* Ast_iterator.default_iterator.module_expr iterator modExpr *) + (* | _ -> Ast_iterator.default_iterator.module_expr iterator me *) + (* in *) + let iterator = + { + Ast_iterator.default_iterator with + (* expr; *) + (* module_expr; *) + (* signature_item; *) + (* structure_item; *) + value_binding; + } + in + + (if Filename.check_suffix path ".res" then + let parser = + Res_driver.parsingEngine.parseImplementation ~forPrinter:false + in + let {Res_driver.parsetree = structure} = parser ~filename:path in + iterator.structure iterator structure |> ignore + else + let parser = Res_driver.parsingEngine.parseInterface ~forPrinter:false in + let {Res_driver.parsetree = signature} = parser ~filename:path in + iterator.signature iterator signature |> ignore); + !symbols + |> List.rev_map (fun (name, loc, kind) -> + let range = Utils.cmtLocToRange loc in + let character_end_pos = + 4 + range.start.character + String.length name + in + let label = + match Cmt.fullFromPath ~path with + | None -> Protocol.null + | Some full -> ( + match + References.getLocItem ~full + ~pos:(range.start.line, character_end_pos) + ~debug:true + with + | None -> "refereces not found" + | Some s -> ( + match locItemToTypeHint ~full s with + | Some hint -> hint + | None -> "TypeHint not found")) + in + Protocol.stringifyHint + { + kind = hintkindNumber kind; + (* label is type *) + (* label = name; *) + tooltip = { + kind = "markdown"; + value = Hover.codeBlock label; + }; + paddingLeft = false; + paddingRight = false; + label = ": " ^ label; + + position = + { + line = range.start.line; + (* From col 0 to last character + let name = "lol" + ^ + *) + character = + character_end_pos + (* character = pos.start.character; *) + (* line = 0; *) + (* character = 0; *); + }; + }) diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index 652f68f30..1ba335790 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -1,6 +1,7 @@ type position = {line : int; character : int} type range = {start : position; end_ : position} type markupContent = {kind : string; value : string} +type inlayHint = {position : position; label : string; kind : int; tooltip: markupContent; paddingLeft: bool; paddingRight: bool} type completionItem = { label : string; @@ -123,3 +124,16 @@ let stringifyCodeAction ca = Printf.sprintf {|{"title": "%s", "kind": "%s", "edit": %s}|} ca.title (codeActionKindToString ca.codeActionKind) (ca.edit |> stringifyCodeActionEdit) + +let stringifyHint hint = + Printf.sprintf + {|{ + "position": %s, + "label": "%s", + "tooltip": %s, + "kind": %i, + "paddingLeft": %b, + "paddingRight": %b +}|} + (stringifyPosition hint.position) + hint.label (stringifyMarkupContent hint.tooltip) hint.kind hint.paddingLeft hint.paddingRight \ No newline at end of file diff --git a/analysis/tests/src/InlayHint.res b/analysis/tests/src/InlayHint.res new file mode 100644 index 000000000..6aefd5724 --- /dev/null +++ b/analysis/tests/src/InlayHint.res @@ -0,0 +1,40 @@ +let string = "ReScript" +let number = 1 +let float = 1.1 +let char = 'c' + +let add = (x, y) => x + y + +let my_sum = 3 + -> add(1) + -> add(1) + -> add(1) + -> add(8) + +let withAs = (~xx as yyy) => yyy + 1 + +let arity0a = (. ()) => { + //^hov + let f = () => 3 + f +} + +let arity0b = (. (), . ()) => 3 + +type t = (int, float) + +@ocaml.doc("This module is commented") +module Dep: { + @ocaml.doc("Some doc comment") + let customDouble: int => int +} = { + let customDouble = foo => foo * 2 +} + +module D = Dep + +let functionWithTypeAnnotation: unit => int = () => 1 + +@react.component +let make = (~name) => React.string(name) + diff --git a/client/package-lock.json b/client/package-lock.json index c42fac774..d51356d07 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "vscode-languageclient": "^7.0.0" + "vscode-languageclient": "^8.0.1" } }, "node_modules/balanced-match": { @@ -68,39 +68,39 @@ } }, "node_modules/vscode-jsonrpc": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", - "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz", + "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==", "engines": { - "node": ">=8.0.0 || >=10.0.0" + "node": ">=14.0.0" } }, "node_modules/vscode-languageclient": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", - "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.1.tgz", + "integrity": "sha512-9XoE+HJfaWvu7Y75H3VmLo5WLCtsbxEgEhrLPqwt7eyoR49lUIyyrjb98Yfa50JCMqF2cePJAEVI6oe2o1sIhw==", "dependencies": { "minimatch": "^3.0.4", - "semver": "^7.3.4", - "vscode-languageserver-protocol": "3.16.0" + "semver": "^7.3.5", + "vscode-languageserver-protocol": "3.17.1" }, "engines": { - "vscode": "^1.52.0" + "vscode": "^1.67.0" } }, "node_modules/vscode-languageserver-protocol": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", - "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz", + "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==", "dependencies": { - "vscode-jsonrpc": "6.0.0", - "vscode-languageserver-types": "3.16.0" + "vscode-jsonrpc": "8.0.1", + "vscode-languageserver-types": "3.17.1" } }, "node_modules/vscode-languageserver-types": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", - "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz", + "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==" }, "node_modules/yallist": { "version": "4.0.0", @@ -153,33 +153,33 @@ } }, "vscode-jsonrpc": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", - "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz", + "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==" }, "vscode-languageclient": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", - "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.1.tgz", + "integrity": "sha512-9XoE+HJfaWvu7Y75H3VmLo5WLCtsbxEgEhrLPqwt7eyoR49lUIyyrjb98Yfa50JCMqF2cePJAEVI6oe2o1sIhw==", "requires": { "minimatch": "^3.0.4", - "semver": "^7.3.4", - "vscode-languageserver-protocol": "3.16.0" + "semver": "^7.3.5", + "vscode-languageserver-protocol": "3.17.1" } }, "vscode-languageserver-protocol": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", - "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz", + "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==", "requires": { - "vscode-jsonrpc": "6.0.0", - "vscode-languageserver-types": "3.16.0" + "vscode-jsonrpc": "8.0.1", + "vscode-languageserver-types": "3.17.1" } }, "vscode-languageserver-types": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", - "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz", + "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==" }, "yallist": { "version": "4.0.0", diff --git a/client/package.json b/client/package.json index cb7f5d1f8..d4fd1cc9a 100644 --- a/client/package.json +++ b/client/package.json @@ -7,6 +7,6 @@ "author": "chenglou", "license": "MIT", "dependencies": { - "vscode-languageclient": "^7.0.0" + "vscode-languageclient": "^8.0.1" } } diff --git a/client/src/client.ts b/client/src/client.ts new file mode 100644 index 000000000..e358c10b8 --- /dev/null +++ b/client/src/client.ts @@ -0,0 +1,45 @@ +import * as lc from "vscode-languageclient/node"; +import * as vscode from "vscode"; +import * as path from "path"; + +export async function createClient(context: vscode.ExtensionContext) { + const serverModule = context.asAbsolutePath( + path.join("server", "out", "server.js") + ); + // The debug options for the server + // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging + let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] }; + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + const serverOptions: lc.ServerOptions = { + run: { module: serverModule, transport: lc.TransportKind.ipc }, + debug: { + module: serverModule, + transport: lc.TransportKind.ipc, + options: debugOptions, + }, + }; + + // Options to control the language client + const clientOptions: lc.LanguageClientOptions = { + documentSelector: [{ scheme: "file", language: "rescript" }], + // We'll send the initial configuration in here, but this might be + // problematic because every consumer of the LS will need to mimic this. + // We'll leave it like this for now, but might be worth revisiting later on. + initializationOptions: { + extensionConfiguration: vscode.workspace.getConfiguration("rescript.settings"), + }, + }; + + const client = new lc.LanguageClient( + "ReScriptLSP", + "ReScript Language Server", + serverOptions, + clientOptions + ); + + client.registerProposedFeatures() + + return client; +} \ No newline at end of file diff --git a/client/src/extension.ts b/client/src/extension.ts index 89e0c75ee..0fc0d82b4 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -1,189 +1,81 @@ import * as path from "path"; -import { - workspace, - ExtensionContext, - commands, - languages, - window, - StatusBarAlignment, -} from "vscode"; - -import { - LanguageClient, - LanguageClientOptions, - ServerOptions, - TransportKind, -} from "vscode-languageclient/node"; +import * as lc from "vscode-languageclient/node"; +import * as vscode from "vscode"; import * as customCommands from "./commands"; import { DiagnosticsResultCodeActionsMap } from "./commands/code_analysis"; +import { createClient } from "./client"; +import { lstat } from 'fs'; -let client: LanguageClient; - -// let taskProvider = tasks.registerTaskProvider('Run ReScript build', { -// provideTasks: () => { -// // if (!rakePromise) { -// // rakePromise = getRakeTasks(); -// // } -// // return rakePromise; - -// // taskDefinition: TaskDefinition, -// // scope: WorkspaceFolder | TaskScope.Global | TaskScope.Workspace, -// // name: string, -// // source: string, -// // execution ?: ProcessExecution | ShellExecution | CustomExecution, -// // problemMatchers ?: string | string[] -// return [ -// new Task( -// { -// type: 'bsb', -// }, -// TaskScope.Workspace, -// // definition.task, -// 'build and watch', -// 'bsb', -// new ShellExecution( -// // `./node_modules/.bin/bsb -make-world -w` -// `pwd` -// ), -// "Hello" -// ) -// ] -// }, -// resolveTask(_task: Task): Task | undefined { -// // const task = _task.definition.task; -// // // A Rake task consists of a task and an optional file as specified in RakeTaskDefinition -// // // Make sure that this looks like a Rake task by checking that there is a task. -// // if (task) { -// // // resolveTask requires that the same definition object be used. -// // const definition: RakeTaskDefinition = _task.definition; -// // return new Task( -// // definition, -// // definition.task, -// // 'rake', -// // new vscode.ShellExecution(`rake ${definition.task}`) -// // ); -// // } -// return undefined; -// } -// }); - -export function activate(context: ExtensionContext) { - function createLanguageClient() { - // The server is implemented in node - let serverModule = context.asAbsolutePath( - path.join("server", "out", "server.js") - ); - // The debug options for the server - // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging - let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] }; - - // If the extension is launched in debug mode then the debug server options are used - // Otherwise the run options are used - let serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { - module: serverModule, - transport: TransportKind.ipc, - options: debugOptions, - }, - }; - - // Options to control the language client - let clientOptions: LanguageClientOptions = { - documentSelector: [{ scheme: "file", language: "rescript" }], - // We'll send the initial configuration in here, but this might be - // problematic because every consumer of the LS will need to mimic this. - // We'll leave it like this for now, but might be worth revisiting later on. - initializationOptions: { - extensionConfiguration: workspace.getConfiguration("rescript.settings"), - }, - }; - - const client = new LanguageClient( - "ReScriptLSP", - "ReScript Language Server", - serverOptions, - clientOptions - ); +let client: lc.LanguageClient | undefined; - // This sets up a listener that, if we're in code analysis mode, triggers - // code analysis as the LS server reports that ReScript compilation has - // finished. This is needed because code analysis must wait until - // compilation has finished, and the most reliable source for that is the LS - // server, that already keeps track of when the compiler finishes in order to - // other provide fresh diagnostics. - client.onReady().then(() => { - context.subscriptions.push( - client.onNotification("rescript/compilationFinished", () => { - if (inCodeAnalysisState.active === true) { - customCommands.codeAnalysisWithReanalyze( - inCodeAnalysisState.activatedFromDirectory, - diagnosticsCollection, - diagnosticsResultCodeActions - ); - } - }) - ); - }); - - return client; - } +export async function activate(context: vscode.ExtensionContext) { + client = await createClient(context); + + await client.start() - // Create the language client and start the client. - client = createLanguageClient(); - - // Create a custom diagnostics collection, for cases where we want to report - // diagnostics programatically from inside of the extension. The reason this - // is separate from the diagnostics provided by the LS server itself is that - // this should be possible to clear independently of the other diagnostics - // coming from the ReScript compiler. - let diagnosticsCollection = languages.createDiagnosticCollection("rescript"); - - // This map will hold code actions produced by the code analysis, in a - // format that's cheap to look up. - let diagnosticsResultCodeActions: DiagnosticsResultCodeActionsMap = new Map(); - let codeAnalysisRunningStatusBarItem = window.createStatusBarItem( - StatusBarAlignment.Right - ); + await initCommonContext(context, client) - let inCodeAnalysisState: { - active: boolean; - activatedFromDirectory: string | null; - } = { active: false, activatedFromDirectory: null }; + return client +} - // This code actions provider yields the code actions potentially extracted - // from the code analysis to the editor. - languages.registerCodeActionsProvider("rescript", { - async provideCodeActions(document, rangeOrSelection) { - let availableActions = - diagnosticsResultCodeActions.get(document.uri.fsPath) ?? []; +async function registerCommand(ctx: vscode.ExtensionContext, name:string, cmd: (...args: any[]) => unknown) { + const fullName = `rescript-vscode.${name}`; + const register = vscode.commands.registerCommand(fullName, cmd) + ctx.subscriptions.push(register) +} - return availableActions - .filter( - ({ range }) => - range.contains(rangeOrSelection) || range.isEqual(rangeOrSelection) - ) - .map(({ codeAction }) => codeAction); - }, - }); +async function initCommonContext(ctx: vscode.ExtensionContext, client: lc.LanguageClient) { // Register custom commands - commands.registerCommand("rescript-vscode.create_interface", () => { - customCommands.createInterface(client); - }); - - commands.registerCommand("rescript-vscode.open_compiled", () => { - customCommands.openCompiled(client); - }); + // @see https://github.com/microsoft/vscode/issues/45774#issuecomment-373423895 + registerCommand(ctx, "restart_language_server", async () => { + await deactivate(); + while (ctx.subscriptions.length > 0) { + try { + ctx.subscriptions.pop()!.dispose(); + } catch (err) { + console.error("Dispose error:", err); + } + } + await activate(ctx); + void vscode.window.showInformationMessage("rescript-vscode reloaded"); + }) + + ctx.subscriptions.push( + client.onNotification("rescript/compilationFinished", () => { + if (inCodeAnalysisState.active) { + customCommands.codeAnalysisWithReanalyze( + inCodeAnalysisState.activatedFromDirectory, + diagnosticsCollection, + diagnosticsResultCodeActions + ); + } + }) + ) + + registerCommand(ctx, "create_interface", async () => customCommands.createInterface(client)); + registerCommand(ctx, "open_compiled", async () => customCommands.openCompiled(client)); + registerCommand(ctx, "switch-impl-intf",async () => customCommands.switchImplIntf(client)); + + + const diagnosticsCollection = vscode.languages.createDiagnosticCollection("rescript"); + const diagnosticsResultCodeActions: DiagnosticsResultCodeActionsMap = new Map(); + const codeAnalysisRunningStatusBarItem = vscode.window.createStatusBarItem( + vscode.StatusBarAlignment.Right + ); + let inCodeAnalysisState: { + active: boolean; + activatedFromDirectory: string | null; + } = { active: false, activatedFromDirectory: null }; // Starts the code analysis mode. - commands.registerCommand("rescript-vscode.start_code_analysis", () => { + registerCommand(ctx, "start_code_analysis", async () => { // Save the directory this first ran from, and re-use that when continuously // running the analysis. This is so that the target of the analysis does not // change on subsequent runs, if there are multiple ReScript projects open // in the editor. - let currentDocument = window.activeTextEditor.document; + let currentDocument = vscode.window.activeTextEditor.document; inCodeAnalysisState.active = true; @@ -205,8 +97,8 @@ export function activate(context: ExtensionContext) { diagnosticsResultCodeActions ); }); - - commands.registerCommand("rescript-vscode.stop_code_analysis", () => { + + registerCommand(ctx, "stop_code_analysis", async () => { inCodeAnalysisState.active = false; inCodeAnalysisState.activatedFromDirectory = null; @@ -216,33 +108,29 @@ export function activate(context: ExtensionContext) { codeAnalysisRunningStatusBarItem.hide(); }); - commands.registerCommand("rescript-vscode.switch-impl-intf", () => { - customCommands.switchImplIntf(client); - }); + // Code Actions + vscode.languages.registerCodeActionsProvider("rescript", { + async provideCodeActions(document, rangeOrSelection) { + const availableActions = + diagnosticsResultCodeActions.get(document.uri.fsPath) ?? []; - commands.registerCommand("rescript-vscode.restart_language_server", () => { - client.stop().then(() => { - client = createLanguageClient(); - context.subscriptions.push(client.start()); - }); - }); + return availableActions + .filter( + ({ range }) => + range.contains(rangeOrSelection) || range.isEqual(rangeOrSelection) + ) + .map(({ codeAction }) => codeAction); + }, + }) - // Start the client. This will also launch the server - context.subscriptions.push(client.start()); - // Autostart code analysis if wanted - if ( - workspace - .getConfiguration("rescript.settings") - .get("autoRunCodeAnalysis") - ) { - commands.executeCommand("rescript-vscode.start_code_analysis"); - } -} -export function deactivate(): Thenable | undefined { - if (!client) { - return undefined; + if (vscode.workspace.getConfiguration("rescript.settings").get("autoRunCodeAnalysis")) { + vscode.commands.executeCommand("rescript-vscode.start_code_analysis") } - return client.stop(); } + +export async function deactivate() { + await client?.stop(); + client = undefined; +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index dd85dc945..093d8c31c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,8 @@ "license": "MIT", "devDependencies": { "@types/node": "^14.14.41", - "@types/vscode": "1.55.0", - "typescript": "^4.2.4" + "@types/vscode": "^1.68.0", + "typescript": "^4.7.3" }, "engines": { "vscode": "^1.55.0" @@ -25,15 +25,15 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.55.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.55.0.tgz", - "integrity": "sha512-49hysH7jneTQoSC8TWbAi7nKK9Lc5osQNjmDHVosrcU8o3jecD9GrK0Qyul8q4aGPSXRfNGqIp9CBdb13akETg==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.68.0.tgz", + "integrity": "sha512-duBwEK5ta/eBBMJMQ7ECMEsMvlE3XJdRGh3xoS1uOO4jl2Z4LPBl5vx8WvBP10ERAgDRmIt/FaSD4RHyBGbChw==", "dev": true }, "node_modules/typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", + "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -52,15 +52,15 @@ "dev": true }, "@types/vscode": { - "version": "1.55.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.55.0.tgz", - "integrity": "sha512-49hysH7jneTQoSC8TWbAi7nKK9Lc5osQNjmDHVosrcU8o3jecD9GrK0Qyul8q4aGPSXRfNGqIp9CBdb13akETg==", + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.68.0.tgz", + "integrity": "sha512-duBwEK5ta/eBBMJMQ7ECMEsMvlE3XJdRGh3xoS1uOO4jl2Z4LPBl5vx8WvBP10ERAgDRmIt/FaSD4RHyBGbChw==", "dev": true }, "typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", + "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", "dev": true } } diff --git a/package.json b/package.json index 7ed204e86..385aa7f06 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "language-server" ], "engines": { - "vscode": "^1.55.0" + "vscode": "^1.64.0" }, "activationEvents": [ "onLanguage:rescript" @@ -31,9 +31,15 @@ "semanticTokenScopes": [ { "scopes": { - "jsx-lowercase": ["entity.name.tag"], - "jsx-tag": ["punctuation.definition.tag"], - "support-type-primitive": ["support.type.primitive"] + "jsx-lowercase": [ + "entity.name.tag" + ], + "jsx-tag": [ + "punctuation.definition.tag" + ], + "support-type-primitive": [ + "support.type.primitive" + ] } } ], @@ -131,6 +137,11 @@ "type": "boolean", "default": false, "description": "Automatically start ReScript's code analysis." + }, + "rescript.settings.inlayHints.enable": { + "type": "boolean", + "default": false, + "description": "Enable type hint" } } }, @@ -164,7 +175,7 @@ }, "devDependencies": { "@types/node": "^14.14.41", - "@types/vscode": "1.55.0", - "typescript": "^4.2.4" + "@types/vscode": "^1.68.0", + "typescript": "^4.7.3" } } diff --git a/server/package-lock.json b/server/package-lock.json index 68d935771..1c1163a02 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,375 +1,360 @@ { - "name": "rescript-language-server", - "version": "1.3.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "rescript-language-server", - "version": "1.3.0", - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.1", - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver": "^7.0.0", - "vscode-languageserver-protocol": "^3.16.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.1" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/picomatch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", - "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageserver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", - "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", - "dependencies": { - "vscode-languageserver-protocol": "3.16.0" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", - "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", - "dependencies": { - "vscode-jsonrpc": "6.0.0", - "vscode-languageserver-types": "3.16.0" - } - }, - "node_modules/vscode-languageserver-protocol/node_modules/vscode-jsonrpc": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", - "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageserver-types": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", - "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" - } - }, - "dependencies": { - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "picomatch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", - "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==" - }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "requires": { - "picomatch": "^2.2.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" - }, - "vscode-languageserver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", - "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", - "requires": { - "vscode-languageserver-protocol": "3.16.0" - } - }, - "vscode-languageserver-protocol": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", - "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", - "requires": { - "vscode-jsonrpc": "6.0.0", - "vscode-languageserver-types": "3.16.0" - }, - "dependencies": { - "vscode-jsonrpc": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", - "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==" - } - } - }, - "vscode-languageserver-types": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", - "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" - } - } + "name": "rescript-language-server", + "version": "1.3.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "rescript-language-server", + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.1", + "vscode-jsonrpc": "^8.0.1", + "vscode-languageserver": "^8.0.1", + "vscode-languageserver-protocol": "^3.17.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz", + "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.0.1.tgz", + "integrity": "sha512-sn7SjBwWm3OlmLtgg7jbM0wBULppyL60rj8K5HF0ny/MzN+GzPBX1kCvYdybhl7UW63V5V5tRVnyB8iwC73lSQ==", + "dependencies": { + "vscode-languageserver-protocol": "3.17.1" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz", + "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==", + "dependencies": { + "vscode-jsonrpc": "8.0.1", + "vscode-languageserver-types": "3.17.1" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz", + "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==" + } + }, + "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==" + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "vscode-jsonrpc": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz", + "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==" + }, + "vscode-languageserver": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.0.1.tgz", + "integrity": "sha512-sn7SjBwWm3OlmLtgg7jbM0wBULppyL60rj8K5HF0ny/MzN+GzPBX1kCvYdybhl7UW63V5V5tRVnyB8iwC73lSQ==", + "requires": { + "vscode-languageserver-protocol": "3.17.1" + } + }, + "vscode-languageserver-protocol": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz", + "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==", + "requires": { + "vscode-jsonrpc": "8.0.1", + "vscode-languageserver-types": "3.17.1" + } + }, + "vscode-languageserver-types": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz", + "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==" + } + } } diff --git a/server/package.json b/server/package.json index fffb2f044..8f99893ab 100644 --- a/server/package.json +++ b/server/package.json @@ -1,21 +1,21 @@ { - "name": "rescript-language-server", - "description": "ReScript's language-server", - "version": "1.3.0", - "author": "chenglou", - "license": "MIT", - "engines": { - "node": "*" - }, - "repository": { - "type": "git", - "url": "https://github.com/rescript-lang/rescript-vscode" - }, - "dependencies": { - "chokidar": "^3.5.1", - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver": "^7.0.0", - "vscode-languageserver-protocol": "^3.16.0" - }, - "scripts": {} + "name": "rescript-language-server", + "description": "ReScript's language-server", + "version": "1.3.0", + "author": "chenglou", + "license": "MIT", + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/rescript-lang/rescript-vscode" + }, + "dependencies": { + "chokidar": "^3.5.1", + "vscode-jsonrpc": "^8.0.1", + "vscode-languageserver": "^8.0.1", + "vscode-languageserver-protocol": "^3.17.1" + }, + "scripts": {} } diff --git a/server/src/server.ts b/server/src/server.ts index a4c6a9958..3c64e2bdf 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,8 +1,8 @@ import process from "process"; import * as p from "vscode-languageserver-protocol"; -import * as m from "vscode-jsonrpc/lib/messages"; +// import * as m from "vscode-jsonrpc/node"; import * as v from "vscode-languageserver"; -import * as rpc from "vscode-jsonrpc"; +import * as rpc from "vscode-jsonrpc/node"; import * as path from "path"; import fs from "fs"; // TODO: check DidChangeWatchedFilesNotification. @@ -51,7 +51,7 @@ let projectsFiles: Map< let codeActionsFromDiagnostics: codeActions.filesCodeActions = {}; // will be properly defined later depending on the mode (stdio/node-rpc) -let send: (msg: m.Message) => void = (_) => {}; +let send: (msg: p.Message) => void = (_) => { }; interface CreateInterfaceRequestParams { uri: string; @@ -93,7 +93,7 @@ let sendUpdatedDiagnostics = () => { uri: file, diagnostics: filesAndErrors[file], }; - let notification: m.NotificationMessage = { + let notification: v.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "textDocument/publishDiagnostics", params: params, @@ -111,7 +111,7 @@ let sendUpdatedDiagnostics = () => { uri: file, diagnostics: [], }; - let notification: m.NotificationMessage = { + let notification: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "textDocument/publishDiagnostics", params: params, @@ -131,7 +131,7 @@ let deleteProjectDiagnostics = (projectRootPath: string) => { uri: file, diagnostics: [], }; - let notification: m.NotificationMessage = { + let notification: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "textDocument/publishDiagnostics", params: params, @@ -143,7 +143,7 @@ let deleteProjectDiagnostics = (projectRootPath: string) => { } }; let sendCompilationFinishedMessage = () => { - let notification: m.NotificationMessage = { + let notification: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "rescript/compilationFinished", }; @@ -211,7 +211,7 @@ let openedFile = (fileUri: string, fileContent: string) => { message: `Start a build for this project to get the freshest data?`, actions: [payload], }; - let request: m.RequestMessage = { + let request: p.RequestMessage = { jsonrpc: c.jsonrpcVersion, id: serverSentRequestIdCounter++, method: "window/showMessageRequest", @@ -274,11 +274,11 @@ if (process.argv.includes("--stdio")) { let writer = new rpc.StreamMessageWriter(process.stdout); let reader = new rpc.StreamMessageReader(process.stdin); // proper `this` scope for writer - send = (msg: m.Message) => writer.write(msg); + send = (msg: p.Message) => writer.write(msg); reader.listen(onMessage); } else { // proper `this` scope for process - send = (msg: m.Message) => process.send!(msg); + send = (msg: p.Message) => process.send!(msg); process.on("message", onMessage); } @@ -303,6 +303,33 @@ function hover(msg: p.RequestMessage) { return response; } +function inlayHint(msg: p.RequestMessage) { + const params = msg.params as p.InlayHintParams; + const filePath = fileURLToPath(params.textDocument.uri); + + console.log(params); + + const response = utils.runAnalysisCommand( + filePath, + [ + "inlayHint", + filePath, + params.range.start.line, + params.range.end.line + ], + msg + ); + return response; +} + +function inlayHintResolve(msg: p.RequestMessage) { + return { + jsonrpc: c.jsonrpcVersion, + id: msg.id, + result: msg.params + } as p.ResponseMessage +} + function definition(msg: p.RequestMessage) { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition let params = msg.params as p.DefinitionParams; @@ -340,7 +367,7 @@ function references(msg: p.RequestMessage) { filePath, params.position ); - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result, @@ -349,7 +376,7 @@ function references(msg: p.RequestMessage) { return response; } -function prepareRename(msg: p.RequestMessage): m.ResponseMessage { +function prepareRename(msg: p.RequestMessage): p.ResponseMessage { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareRename let params = msg.params as p.PrepareRenameParams; let filePath = fileURLToPath(params.textDocument.uri); @@ -400,7 +427,7 @@ function rename(msg: p.RequestMessage) { if (documentChanges !== null) { result = { documentChanges }; } - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result, @@ -531,7 +558,7 @@ function codeAction(msg: p.RequestMessage): p.ResponseMessage { return res; } -function format(msg: p.RequestMessage): Array { +function format(msg: p.RequestMessage): Array { // technically, a formatting failure should reply with the error. Sadly // the LSP alert box for these error replies sucks (e.g. doesn't actually // display the message). In order to signal the client to display a proper @@ -539,7 +566,7 @@ function format(msg: p.RequestMessage): Array { // back a fake success message (because each request mandates a // response), then right away send a server notification to display a // nicer alert. Ugh. - let fakeSuccessResponse: m.ResponseMessage = { + let fakeSuccessResponse: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: [], @@ -552,7 +579,7 @@ function format(msg: p.RequestMessage): Array { type: p.MessageType.Error, message: `Not a ${c.resExt} or ${c.resiExt} file. Cannot format it.`, }; - let response: m.NotificationMessage = { + let response: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params: params, @@ -573,7 +600,7 @@ function format(msg: p.RequestMessage): Array { newText: formattedResult.result, }, ]; - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: result, @@ -589,7 +616,7 @@ function format(msg: p.RequestMessage): Array { } } -function createInterface(msg: p.RequestMessage): m.Message { +function createInterface(msg: p.RequestMessage): p.Message { let params = msg.params as CreateInterfaceRequestParams; let extension = path.extname(params.uri); let filePath = fileURLToPath(params.uri); @@ -601,7 +628,7 @@ function createInterface(msg: p.RequestMessage): m.Message { message: `Cannot locate project directory to generate the interface file.`, }; - let response: m.NotificationMessage = { + let response: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params: params, @@ -616,7 +643,7 @@ function createInterface(msg: p.RequestMessage): m.Message { message: `Not a ${c.resExt} file. Cannot create an interface for it.`, }; - let response: m.NotificationMessage = { + let response: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params: params, @@ -636,7 +663,7 @@ function createInterface(msg: p.RequestMessage): m.Message { message: `Error reading bsconfig file.`, }; - let response: m.NotificationMessage = { + let response: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params, @@ -662,7 +689,7 @@ function createInterface(msg: p.RequestMessage): m.Message { message: `No compiled interface file found. Please compile your project first.`, }; - let response: m.NotificationMessage = { + let response: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params, @@ -681,18 +708,18 @@ function createInterface(msg: p.RequestMessage): m.Message { try { let resiPath = utils.replaceFileExtension(filePath, c.resiExt); fs.writeFileSync(resiPath, result, { encoding: "utf-8" }); - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: "Interface successfully created.", }; return response; } catch (e) { - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, error: { - code: m.ErrorCodes.InternalError, + code: p.ErrorCodes.InternalError, message: "Unable to create interface file.", }, }; @@ -700,7 +727,7 @@ function createInterface(msg: p.RequestMessage): m.Message { } } -function openCompiledFile(msg: p.RequestMessage): m.Message { +function openCompiledFile(msg: p.RequestMessage): p.Message { let params = msg.params as OpenCompiledFileParams; let filePath = fileURLToPath(params.uri); let projDir = utils.findProjectRootOfFile(filePath); @@ -711,7 +738,7 @@ function openCompiledFile(msg: p.RequestMessage): m.Message { message: `Cannot locate project directory.`, }; - let response: m.NotificationMessage = { + let response: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params: params, @@ -736,7 +763,7 @@ function openCompiledFile(msg: p.RequestMessage): m.Message { message, }; - let response: m.NotificationMessage = { + let response: p.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params, @@ -749,7 +776,7 @@ function openCompiledFile(msg: p.RequestMessage): m.Message { uri: compiledFilePath.result, }; - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result, @@ -758,8 +785,8 @@ function openCompiledFile(msg: p.RequestMessage): m.Message { return response; } -function onMessage(msg: m.Message) { - if (m.isNotificationMessage(msg)) { +function onMessage(msg: p.Message) { + if (p.Message.isNotification(msg)) { // notification message, aka the client ends it and doesn't want a reply if (!initialized && msg.method !== "exit") { // From spec: "Notifications should be dropped, except for the exit notification. This will allow the exit of a server without an initialize request" @@ -797,14 +824,14 @@ function onMessage(msg: m.Message) { // Can't seem to get this notification to trigger, but if it does this will be here and ensure we're synced up at the server. askForAllCurrentConfiguration(); } - } else if (m.isRequestMessage(msg)) { + } else if (p.Message.isRequest(msg)) { // request message, aka client sent request and waits for our mandatory reply if (!initialized && msg.method !== "initialize") { - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, error: { - code: m.ErrorCodes.ServerNotInitialized, + code: p.ErrorCodes.ServerNotInitialized, message: "Server not initialized.", }, }; @@ -845,9 +872,12 @@ function onMessage(msg: m.Message) { // TODO: Support range for full, and add delta support full: true, }, + inlayHintProvider: { + resolveProvider: true, + }, }, }; - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: result, @@ -871,7 +901,7 @@ function onMessage(msg: m.Message) { send(response); } else if (msg.method === "initialized") { // sent from client after initialize. Nothing to do for now - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: null, @@ -880,11 +910,11 @@ function onMessage(msg: m.Message) { } else if (msg.method === "shutdown") { // https://microsoft.github.io/language-server-protocol/specification#shutdown if (shutdownRequestAlreadyReceived) { - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, error: { - code: m.ErrorCodes.InvalidRequest, + code: p.ErrorCodes.InvalidRequest, message: `Language server already received the shutdown request`, }, }; @@ -899,7 +929,7 @@ function onMessage(msg: m.Message) { clearInterval(pullConfigurationPeriodically); } - let response: m.ResponseMessage = { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: null, @@ -933,18 +963,23 @@ function onMessage(msg: m.Message) { send(createInterface(msg)); } else if (msg.method === openCompiledFileRequest.method) { send(openCompiledFile(msg)); - } else { - let response: m.ResponseMessage = { + } else if (msg.method == p.InlayHintRequest.method) { + send(inlayHint((msg))); + } else if (msg.method == p.InlayHintResolveRequest.method) { + send(inlayHintResolve(msg)) + } + else { + let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, error: { - code: m.ErrorCodes.InvalidRequest, + code: p.ErrorCodes.InvalidRequest, message: "Unrecognized editor request.", }, }; send(response); } - } else if (m.isResponseMessage(msg)) { + } else if (p.Message.isResponse(msg)) { if (msg.id === c.configurationRequestId) { if (msg.result != null) { // This is a response from a request to get updated configuration. Note From 19d6585322784ef4c051fb7e159c9d2231a0221a Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 10 Jun 2022 21:11:39 -0300 Subject: [PATCH 02/42] feat(inlayHint): remove log --- server/src/server.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/src/server.ts b/server/src/server.ts index 3c64e2bdf..3fd84396b 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -306,8 +306,6 @@ function hover(msg: p.RequestMessage) { function inlayHint(msg: p.RequestMessage) { const params = msg.params as p.InlayHintParams; const filePath = fileURLToPath(params.textDocument.uri); - - console.log(params); const response = utils.runAnalysisCommand( filePath, From a4fae36a1adaa118ec2d209dae97599dbd080ed3 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 11 Jun 2022 03:40:48 -0300 Subject: [PATCH 03/42] feat(inlayHint): add pos argument --- analysis/src/Commands.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index db6e7b669..15d6b672d 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -29,7 +29,7 @@ let completion ~debug ~path ~pos ~currentFile = |> Protocol.array) let inlayhint ~path ~pos ~debug = - let result = match Hint.inlay ~path ~debug with + let result = match Hint.inlay ~path ~pos ~debug with | [] -> Protocol.null | hints -> "[\n" ^ String.concat ",\n" hints ^ "\n]" in print_endline result From 5e0648c6c4ef28ebfabda67fb5be608e5e099b3f Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 11 Jun 2022 03:41:35 -0300 Subject: [PATCH 04/42] feat(inlayHint): simplify hint --- analysis/src/Hint.ml | 282 ++++++++----------------------------------- 1 file changed, 53 insertions(+), 229 deletions(-) diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 8cfe1f405..3e973ca14 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -12,125 +12,40 @@ type kind = | EnumMember | TypeParameter -let hintPrefix label = Printf.sprintf ": %s" label -let hintkindNumber = function TypeParameter | EnumMember -> 2 | _ -> 1 +let typeHintKindToNumber = function Variable -> 1 | _ -> 2 +let getPaddingFromKind = function Variable -> 4 | _ -> 0 + +let parseTypeReturn (t : Types.type_expr) = + let typeString = Shared.typeToString t in + match Str.split (Str.regexp "=>") typeString with + | x :: xs -> List.fold_left (fun _ y -> y) x xs |> String.trim + | _ -> typeString let locItemToTypeHint ~full:{file; package} locItem = match locItem.locType with - (* | TypeDefinition (name, decl, _stamp) -> *) - (* let typeDef = Shared.declToString name decl in *) - (* Some (hintPrefix typeDef) *) - (* | LModule (Definition (stamp, _tip)) | LModule (LocalReference (stamp, _tip)) *) - (* -> ( *) - (* match Stamps.findModule file.stamps stamp with *) - (* | None -> None *) - (* | Some md -> ( *) - (* match References.resolveModuleReference ~file ~package md with *) - (* | None -> None *) - (* | Some (file, declared) -> *) - (* let name, docstring = *) - (* match declared with *) - (* | Some d -> (d.name.txt, d.docstring) *) - (* | None -> (file.moduleName, file.structure.docstring) *) - (* in *) - (* Hover.showModule ~docstring ~name ~file declared)) *) - (* | LModule (GlobalReference (moduleName, path, tip)) -> ( *) - (* match ProcessCmt.fileForModule ~package moduleName with *) - (* | None -> None *) - (* | Some file -> ( *) - (* let env = QueryEnv.fromFile file in *) - (* match ResolvePath.resolvePath ~env ~path ~package with *) - (* | None -> None *) - (* | Some (env, name) -> ( *) - (* match References.exportedForTip ~env name tip with *) - (* | None -> None *) - (* | Some stamp -> ( *) - (* match Stamps.findModule file.stamps stamp with *) - (* | None -> None *) - (* | Some md -> ( *) - (* match References.resolveModuleReference ~file ~package md with *) - (* | None -> None *) - (* | Some (file, declared) -> *) - (* let name, docstring = *) - (* match declared with *) - (* | Some d -> (d.name.txt, d.docstring) *) - (* | None -> (file.moduleName, file.structure.docstring) *) - (* in *) - (* Hover.showModule ~docstring ~name ~file declared))))) *) - | LModule NotFound -> None - (* | TopLevelModule name -> ( *) - (* match ProcessCmt.fileForModule ~package name with *) - (* | None -> None *) - (* | Some file -> *) - (* Hover.showModule ~docstring:file.structure.docstring ~name:file.moduleName *) - (* ~file None) *) - | Typed (_, _, Definition (_, (Field _ | Constructor _))) -> None | Constant t -> Some - (hintPrefix - (match t with - | Const_int _ -> "int" - | Const_char _ -> "char" - | Const_string _ -> "string" - | Const_float _ -> "float" - | Const_int32 _ -> "int32" - | Const_int64 _ -> "int64" - | Const_nativeint _ -> "int")) + (match t with + | Const_int _ -> "int" + | Const_char _ -> "char" + | Const_string _ -> "string" + | Const_float _ -> "float" + | Const_int32 _ -> "int32" + | Const_int64 _ -> "int64" + | Const_nativeint _ -> "int") | Typed (_, t, locKind) -> - (* let fromType ~docstring typ = *) - (* let typeString = Hover.codeBlock (typ |> Shared.typeToString) in *) - (* let extraTypeInfo = *) - (* let env = QueryEnv.fromFile file in *) - (* match typ |> Shared.digConstructor with *) - (* | None -> None *) - (* | Some path -> ( *) - (* match References.digConstructor ~env ~package path with *) - (* | None -> None *) - (* | Some (_env, {docstring; name = {txt}; item = {decl}}) -> *) - (* if Utils.isUncurriedInternal path then None *) - (* else Some (decl |> Shared.declToString txt, docstring)) *) - (* in *) - (* let typeString, docstring = *) - (* match extraTypeInfo with *) - (* | None -> (typeString, docstring) *) - (* | Some (extra, extraDocstring) -> *) - (* (typeString ^ "\n\n" ^ Hover.codeBlock extra, extraDocstring) *) - (* in *) - (* (typeString, docstring) *) - (* in *) - let parts = - match References.definedForLoc ~file ~package locKind with - | None -> - let typeString = Shared.typeToString t in - typeString - | Some (docstring, res) -> ( + Some + (match References.definedForLoc ~file ~package locKind with + | None -> parseTypeReturn t + | Some (_, res) -> ( match res with - | `Declared -> - let typeString = Shared.typeToString t in - typeString - | `Constructor {cname = {txt}; args} -> - let typeString = Shared.typeToString t in - typeString - (* let typeString, docstring = t |> fromType ~docstring in *) - (* let argsString = *) - (* match args with *) - (* | [] -> "" *) - (* | _ -> *) - (* args *) - (* |> List.map (fun (t, _) -> (Shared.typeToString t) ^ "hre") *) - (* |> String.concat ", " |> Printf.sprintf "(%s)" *) - (* in *) - (* typeString *) - | `Field -> - let typeString = Shared.typeToString t in - typeString - (* let typeString, docstring = t |> fromType ~docstring in *) - (* typeString) *) - ) - in - Some parts + | `Declared -> parseTypeReturn t + | `Constructor _ -> parseTypeReturn t + | `Field -> parseTypeReturn t)) + | _ -> None -let inlay ~path ~debug = +(* TODO: filter for range of lines*) +let inlay ~path ~pos ~debug = let symbols = ref [] in let rec exprKind (exp : Parsetree.expression) = match exp.pexp_desc with @@ -142,34 +57,7 @@ let inlay ~path ~debug = | Pexp_constant _ -> Constant | _ -> Variable in - (* let processTypeKind (tk : Parsetree.type_kind) = *) - (* match tk with *) - (* | Ptype_variant constrDecls -> *) - (* constrDecls *) - (* |> List.iter (fun (cd : Parsetree.constructor_declaration) -> *) - (* symbols := (cd.pcd_name.txt, cd.pcd_loc, EnumMember) :: !symbols) *) - (* | Ptype_record labelDecls -> *) - (* labelDecls *) - (* |> List.iter (fun (ld : Parsetree.label_declaration) -> *) - (* symbols := (ld.pld_name.txt, ld.pld_loc, Property) :: !symbols) *) - (* | _ -> () *) - (* in *) - (* let processTypeDeclaration (td : Parsetree.type_declaration) = *) - (* symbols := (td.ptype_name.txt, td.ptype_loc, TypeParameter) :: !symbols; *) - (* processTypeKind td.ptype_kind *) - (* in *) - let processValueDescription (vd : Parsetree.value_description) = - symbols := (vd.pval_name.txt, vd.pval_loc, Variable) :: !symbols - in - (* let processModuleBinding (mb : Parsetree.module_binding) = *) - (* symbols := (mb.pmb_name.txt, mb.pmb_loc, Module) :: !symbols *) - (* in *) - (* let processModuleDeclaration (md : Parsetree.module_declaration) = *) - (* symbols := (md.pmd_name.txt, md.pmd_loc, Module) :: !symbols *) - (* in *) - (* let processExtensionConstructor (et : Parsetree.extension_constructor) = *) - (* symbols := (et.pext_name.txt, et.pext_loc, Constructor) :: !symbols *) - (* in *) + (* TODO: Handle with tuples let-bindings *) let value_binding (iterator : Ast_iterator.iterator) (vb : Parsetree.value_binding) = (match vb.pvb_pat.ppat_desc with @@ -178,58 +66,7 @@ let inlay ~path ~debug = | _ -> ()); Ast_iterator.default_iterator.value_binding iterator vb in - (* let expr (iterator : Ast_iterator.iterator) (e : Parsetree.expression) = *) - (* (match e.pexp_desc with *) - (* | Pexp_letmodule ({txt}, modExpr, _) -> *) - (* symbols := *) - (* (txt, {e.pexp_loc with loc_end = modExpr.pmod_loc.loc_end}, Module) *) - (* :: !symbols *) - (* (* | Pexp_letexception (ec, _) -> processExtensionConstructor ec *) *) - (* | _ -> ()); *) - (* Ast_iterator.default_iterator.expr iterator e *) - (* in *) - let structure_item (iterator : Ast_iterator.iterator) - (item : Parsetree.structure_item) = - (match item.pstr_desc with - | Pstr_value _ -> () - | Pstr_primitive vd -> processValueDescription vd - (* | Pstr_type (_, typDecls) -> typDecls |> List.iter processTypeDeclaration *) - (* | Pstr_module mb -> processModuleBinding mb *) - (* | Pstr_recmodule mbs -> mbs |> List.iter processModuleBinding *) - (* | Pstr_exception ec -> processExtensionConstructor ec *) - | _ -> ()); - Ast_iterator.default_iterator.structure_item iterator item - in - let signature_item (iterator : Ast_iterator.iterator) - (item : Parsetree.signature_item) = - (match item.psig_desc with - | Psig_value vd -> processValueDescription vd - (* | Psig_type (_, typDecls) -> typDecls |> List.iter processTypeDeclaration *) - (* | Psig_module md -> processModuleDeclaration md *) - (* | Psig_recmodule mds -> mds |> List.iter processModuleDeclaration *) - (* | Psig_exception ec -> processExtensionConstructor ec *) - | _ -> ()); - Ast_iterator.default_iterator.signature_item iterator item - in - (* let module_expr (iterator : Ast_iterator.iterator) *) - (* (me : Parsetree.module_expr) = *) - (* match me.pmod_desc with *) - (* | Pmod_constraint (modExpr, _modTyp) -> *) - (* (* Don't double-list items in implementation and interface *) *) - (* Ast_iterator.default_iterator.module_expr iterator modExpr *) - (* | _ -> Ast_iterator.default_iterator.module_expr iterator me *) - (* in *) - let iterator = - { - Ast_iterator.default_iterator with - (* expr; *) - (* module_expr; *) - (* signature_item; *) - (* structure_item; *) - value_binding; - } - in - + let iterator = {Ast_iterator.default_iterator with value_binding} in (if Filename.check_suffix path ".res" then let parser = Res_driver.parsingEngine.parseImplementation ~forPrinter:false @@ -243,48 +80,35 @@ let inlay ~path ~debug = !symbols |> List.rev_map (fun (name, loc, kind) -> let range = Utils.cmtLocToRange loc in - let character_end_pos = - 4 + range.start.character + String.length name + (* TODO: find the ending or starting position of a let bindings *) + let rangeEndCharacter = + getPaddingFromKind kind + range.start.character + String.length name in - let label = - match Cmt.fullFromPath ~path with - | None -> Protocol.null - | Some full -> ( - match - References.getLocItem ~full - ~pos:(range.start.line, character_end_pos) - ~debug:true - with - | None -> "refereces not found" - | Some s -> ( - match locItemToTypeHint ~full s with - | Some hint -> hint - | None -> "TypeHint not found")) + let hintKind = typeHintKindToNumber kind in + let position : Protocol.position = + {line = range.start.line; character = rangeEndCharacter} in + match Cmt.fullFromPath ~path with + | None -> None + | Some full -> ( + match + References.getLocItem ~full + ~pos:(position.line, position.character) + ~debug + with + | None -> None + | Some s -> ( + match locItemToTypeHint ~full s with + | Some typeHint -> Some (typeHint, hintKind, position) + | None -> None))) + |> List.filter_map (fun x -> x) + |> List.map (fun (typeHint, kind, position) -> Protocol.stringifyHint { - kind = hintkindNumber kind; - (* label is type *) - (* label = name; *) - tooltip = { - kind = "markdown"; - value = Hover.codeBlock label; - }; + kind; + position; + tooltip = {kind = "markdown"; value = Hover.codeBlock typeHint}; paddingLeft = false; paddingRight = false; - label = ": " ^ label; - - position = - { - line = range.start.line; - (* From col 0 to last character - let name = "lol" - ^ - *) - character = - character_end_pos - (* character = pos.start.character; *) - (* line = 0; *) - (* character = 0; *); - }; + label = ": " ^ typeHint; }) From a75a2b826d69359685514b5e9e42047ae446bd29 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 11 Jun 2022 03:42:06 -0300 Subject: [PATCH 05/42] feat(inlayHint): remove import extension --- client/src/extension.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/src/extension.ts b/client/src/extension.ts index 0fc0d82b4..7cfe00efa 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -5,7 +5,6 @@ import * as vscode from "vscode"; import * as customCommands from "./commands"; import { DiagnosticsResultCodeActionsMap } from "./commands/code_analysis"; import { createClient } from "./client"; -import { lstat } from 'fs'; let client: lc.LanguageClient | undefined; @@ -123,8 +122,6 @@ async function initCommonContext(ctx: vscode.ExtensionContext, client: lc.Langua }, }) - - if (vscode.workspace.getConfiguration("rescript.settings").get("autoRunCodeAnalysis")) { vscode.commands.executeCommand("rescript-vscode.start_code_analysis") } From b4172dc1c763970a7c51809dc651aa05681d4a4f Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 11 Jun 2022 03:42:31 -0300 Subject: [PATCH 06/42] feat(inlayHint): add rescript test file --- analysis/tests/src/InlayHint.res | 3 +++ 1 file changed, 3 insertions(+) diff --git a/analysis/tests/src/InlayHint.res b/analysis/tests/src/InlayHint.res index 6aefd5724..1a34851fc 100644 --- a/analysis/tests/src/InlayHint.res +++ b/analysis/tests/src/InlayHint.res @@ -38,3 +38,6 @@ let functionWithTypeAnnotation: unit => int = () => 1 @react.component let make = (~name) => React.string(name) +let tuple = ("ReScript", "lol") + +let (lang, _) = tuple \ No newline at end of file From 310522756e988d1f70cf027aa2b6c2de530e382f Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 11 Jun 2022 17:52:31 -0300 Subject: [PATCH 07/42] cleanup --- client/package-lock.json | 70 ++-- client/package.json | 2 +- client/src/extension.ts | 275 ++++++++++----- package-lock.json | 28 +- package.json | 23 +- server/package-lock.json | 731 ++++++++++++++++++++------------------- server/package.json | 38 +- server/src/server.ts | 119 +++---- 8 files changed, 686 insertions(+), 600 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index d51356d07..c42fac774 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "vscode-languageclient": "^8.0.1" + "vscode-languageclient": "^7.0.0" } }, "node_modules/balanced-match": { @@ -68,39 +68,39 @@ } }, "node_modules/vscode-jsonrpc": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz", - "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", "engines": { - "node": ">=14.0.0" + "node": ">=8.0.0 || >=10.0.0" } }, "node_modules/vscode-languageclient": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.1.tgz", - "integrity": "sha512-9XoE+HJfaWvu7Y75H3VmLo5WLCtsbxEgEhrLPqwt7eyoR49lUIyyrjb98Yfa50JCMqF2cePJAEVI6oe2o1sIhw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", + "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", "dependencies": { "minimatch": "^3.0.4", - "semver": "^7.3.5", - "vscode-languageserver-protocol": "3.17.1" + "semver": "^7.3.4", + "vscode-languageserver-protocol": "3.16.0" }, "engines": { - "vscode": "^1.67.0" + "vscode": "^1.52.0" } }, "node_modules/vscode-languageserver-protocol": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz", - "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", "dependencies": { - "vscode-jsonrpc": "8.0.1", - "vscode-languageserver-types": "3.17.1" + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" } }, "node_modules/vscode-languageserver-types": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz", - "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==" + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" }, "node_modules/yallist": { "version": "4.0.0", @@ -153,33 +153,33 @@ } }, "vscode-jsonrpc": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz", - "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==" + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==" }, "vscode-languageclient": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-8.0.1.tgz", - "integrity": "sha512-9XoE+HJfaWvu7Y75H3VmLo5WLCtsbxEgEhrLPqwt7eyoR49lUIyyrjb98Yfa50JCMqF2cePJAEVI6oe2o1sIhw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", + "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", "requires": { "minimatch": "^3.0.4", - "semver": "^7.3.5", - "vscode-languageserver-protocol": "3.17.1" + "semver": "^7.3.4", + "vscode-languageserver-protocol": "3.16.0" } }, "vscode-languageserver-protocol": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz", - "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", "requires": { - "vscode-jsonrpc": "8.0.1", - "vscode-languageserver-types": "3.17.1" + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" } }, "vscode-languageserver-types": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz", - "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==" + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" }, "yallist": { "version": "4.0.0", diff --git a/client/package.json b/client/package.json index d4fd1cc9a..cb7f5d1f8 100644 --- a/client/package.json +++ b/client/package.json @@ -7,6 +7,6 @@ "author": "chenglou", "license": "MIT", "dependencies": { - "vscode-languageclient": "^8.0.1" + "vscode-languageclient": "^7.0.0" } } diff --git a/client/src/extension.ts b/client/src/extension.ts index 7cfe00efa..89e0c75ee 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -1,80 +1,189 @@ import * as path from "path"; -import * as lc from "vscode-languageclient/node"; -import * as vscode from "vscode"; +import { + workspace, + ExtensionContext, + commands, + languages, + window, + StatusBarAlignment, +} from "vscode"; + +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind, +} from "vscode-languageclient/node"; import * as customCommands from "./commands"; import { DiagnosticsResultCodeActionsMap } from "./commands/code_analysis"; -import { createClient } from "./client"; -let client: lc.LanguageClient | undefined; - -export async function activate(context: vscode.ExtensionContext) { - client = await createClient(context); - - await client.start() - - await initCommonContext(context, client) - - return client -} - -async function registerCommand(ctx: vscode.ExtensionContext, name:string, cmd: (...args: any[]) => unknown) { - const fullName = `rescript-vscode.${name}`; - const register = vscode.commands.registerCommand(fullName, cmd) - ctx.subscriptions.push(register) -} +let client: LanguageClient; + +// let taskProvider = tasks.registerTaskProvider('Run ReScript build', { +// provideTasks: () => { +// // if (!rakePromise) { +// // rakePromise = getRakeTasks(); +// // } +// // return rakePromise; + +// // taskDefinition: TaskDefinition, +// // scope: WorkspaceFolder | TaskScope.Global | TaskScope.Workspace, +// // name: string, +// // source: string, +// // execution ?: ProcessExecution | ShellExecution | CustomExecution, +// // problemMatchers ?: string | string[] +// return [ +// new Task( +// { +// type: 'bsb', +// }, +// TaskScope.Workspace, +// // definition.task, +// 'build and watch', +// 'bsb', +// new ShellExecution( +// // `./node_modules/.bin/bsb -make-world -w` +// `pwd` +// ), +// "Hello" +// ) +// ] +// }, +// resolveTask(_task: Task): Task | undefined { +// // const task = _task.definition.task; +// // // A Rake task consists of a task and an optional file as specified in RakeTaskDefinition +// // // Make sure that this looks like a Rake task by checking that there is a task. +// // if (task) { +// // // resolveTask requires that the same definition object be used. +// // const definition: RakeTaskDefinition = _task.definition; +// // return new Task( +// // definition, +// // definition.task, +// // 'rake', +// // new vscode.ShellExecution(`rake ${definition.task}`) +// // ); +// // } +// return undefined; +// } +// }); + +export function activate(context: ExtensionContext) { + function createLanguageClient() { + // The server is implemented in node + let serverModule = context.asAbsolutePath( + path.join("server", "out", "server.js") + ); + // The debug options for the server + // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging + let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] }; + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + let serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { + module: serverModule, + transport: TransportKind.ipc, + options: debugOptions, + }, + }; + + // Options to control the language client + let clientOptions: LanguageClientOptions = { + documentSelector: [{ scheme: "file", language: "rescript" }], + // We'll send the initial configuration in here, but this might be + // problematic because every consumer of the LS will need to mimic this. + // We'll leave it like this for now, but might be worth revisiting later on. + initializationOptions: { + extensionConfiguration: workspace.getConfiguration("rescript.settings"), + }, + }; + + const client = new LanguageClient( + "ReScriptLSP", + "ReScript Language Server", + serverOptions, + clientOptions + ); -async function initCommonContext(ctx: vscode.ExtensionContext, client: lc.LanguageClient) { + // This sets up a listener that, if we're in code analysis mode, triggers + // code analysis as the LS server reports that ReScript compilation has + // finished. This is needed because code analysis must wait until + // compilation has finished, and the most reliable source for that is the LS + // server, that already keeps track of when the compiler finishes in order to + // other provide fresh diagnostics. + client.onReady().then(() => { + context.subscriptions.push( + client.onNotification("rescript/compilationFinished", () => { + if (inCodeAnalysisState.active === true) { + customCommands.codeAnalysisWithReanalyze( + inCodeAnalysisState.activatedFromDirectory, + diagnosticsCollection, + diagnosticsResultCodeActions + ); + } + }) + ); + }); + + return client; + } - // Register custom commands - // @see https://github.com/microsoft/vscode/issues/45774#issuecomment-373423895 - registerCommand(ctx, "restart_language_server", async () => { - await deactivate(); - while (ctx.subscriptions.length > 0) { - try { - ctx.subscriptions.pop()!.dispose(); - } catch (err) { - console.error("Dispose error:", err); - } - } - await activate(ctx); - void vscode.window.showInformationMessage("rescript-vscode reloaded"); - }) - - ctx.subscriptions.push( - client.onNotification("rescript/compilationFinished", () => { - if (inCodeAnalysisState.active) { - customCommands.codeAnalysisWithReanalyze( - inCodeAnalysisState.activatedFromDirectory, - diagnosticsCollection, - diagnosticsResultCodeActions - ); - } - }) - ) - - registerCommand(ctx, "create_interface", async () => customCommands.createInterface(client)); - registerCommand(ctx, "open_compiled", async () => customCommands.openCompiled(client)); - registerCommand(ctx, "switch-impl-intf",async () => customCommands.switchImplIntf(client)); - - - const diagnosticsCollection = vscode.languages.createDiagnosticCollection("rescript"); - const diagnosticsResultCodeActions: DiagnosticsResultCodeActionsMap = new Map(); - const codeAnalysisRunningStatusBarItem = vscode.window.createStatusBarItem( - vscode.StatusBarAlignment.Right + // Create the language client and start the client. + client = createLanguageClient(); + + // Create a custom diagnostics collection, for cases where we want to report + // diagnostics programatically from inside of the extension. The reason this + // is separate from the diagnostics provided by the LS server itself is that + // this should be possible to clear independently of the other diagnostics + // coming from the ReScript compiler. + let diagnosticsCollection = languages.createDiagnosticCollection("rescript"); + + // This map will hold code actions produced by the code analysis, in a + // format that's cheap to look up. + let diagnosticsResultCodeActions: DiagnosticsResultCodeActionsMap = new Map(); + let codeAnalysisRunningStatusBarItem = window.createStatusBarItem( + StatusBarAlignment.Right ); + let inCodeAnalysisState: { active: boolean; activatedFromDirectory: string | null; } = { active: false, activatedFromDirectory: null }; + // This code actions provider yields the code actions potentially extracted + // from the code analysis to the editor. + languages.registerCodeActionsProvider("rescript", { + async provideCodeActions(document, rangeOrSelection) { + let availableActions = + diagnosticsResultCodeActions.get(document.uri.fsPath) ?? []; + + return availableActions + .filter( + ({ range }) => + range.contains(rangeOrSelection) || range.isEqual(rangeOrSelection) + ) + .map(({ codeAction }) => codeAction); + }, + }); + + // Register custom commands + commands.registerCommand("rescript-vscode.create_interface", () => { + customCommands.createInterface(client); + }); + + commands.registerCommand("rescript-vscode.open_compiled", () => { + customCommands.openCompiled(client); + }); + // Starts the code analysis mode. - registerCommand(ctx, "start_code_analysis", async () => { + commands.registerCommand("rescript-vscode.start_code_analysis", () => { // Save the directory this first ran from, and re-use that when continuously // running the analysis. This is so that the target of the analysis does not // change on subsequent runs, if there are multiple ReScript projects open // in the editor. - let currentDocument = vscode.window.activeTextEditor.document; + let currentDocument = window.activeTextEditor.document; inCodeAnalysisState.active = true; @@ -96,8 +205,8 @@ async function initCommonContext(ctx: vscode.ExtensionContext, client: lc.Langua diagnosticsResultCodeActions ); }); - - registerCommand(ctx, "stop_code_analysis", async () => { + + commands.registerCommand("rescript-vscode.stop_code_analysis", () => { inCodeAnalysisState.active = false; inCodeAnalysisState.activatedFromDirectory = null; @@ -107,27 +216,33 @@ async function initCommonContext(ctx: vscode.ExtensionContext, client: lc.Langua codeAnalysisRunningStatusBarItem.hide(); }); - // Code Actions - vscode.languages.registerCodeActionsProvider("rescript", { - async provideCodeActions(document, rangeOrSelection) { - const availableActions = - diagnosticsResultCodeActions.get(document.uri.fsPath) ?? []; + commands.registerCommand("rescript-vscode.switch-impl-intf", () => { + customCommands.switchImplIntf(client); + }); - return availableActions - .filter( - ({ range }) => - range.contains(rangeOrSelection) || range.isEqual(rangeOrSelection) - ) - .map(({ codeAction }) => codeAction); - }, - }) + commands.registerCommand("rescript-vscode.restart_language_server", () => { + client.stop().then(() => { + client = createLanguageClient(); + context.subscriptions.push(client.start()); + }); + }); + + // Start the client. This will also launch the server + context.subscriptions.push(client.start()); - if (vscode.workspace.getConfiguration("rescript.settings").get("autoRunCodeAnalysis")) { - vscode.commands.executeCommand("rescript-vscode.start_code_analysis") + // Autostart code analysis if wanted + if ( + workspace + .getConfiguration("rescript.settings") + .get("autoRunCodeAnalysis") + ) { + commands.executeCommand("rescript-vscode.start_code_analysis"); } } -export async function deactivate() { - await client?.stop(); - client = undefined; -} \ No newline at end of file +export function deactivate(): Thenable | undefined { + if (!client) { + return undefined; + } + return client.stop(); +} diff --git a/package-lock.json b/package-lock.json index 093d8c31c..dd85dc945 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,8 @@ "license": "MIT", "devDependencies": { "@types/node": "^14.14.41", - "@types/vscode": "^1.68.0", - "typescript": "^4.7.3" + "@types/vscode": "1.55.0", + "typescript": "^4.2.4" }, "engines": { "vscode": "^1.55.0" @@ -25,15 +25,15 @@ "dev": true }, "node_modules/@types/vscode": { - "version": "1.68.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.68.0.tgz", - "integrity": "sha512-duBwEK5ta/eBBMJMQ7ECMEsMvlE3XJdRGh3xoS1uOO4jl2Z4LPBl5vx8WvBP10ERAgDRmIt/FaSD4RHyBGbChw==", + "version": "1.55.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.55.0.tgz", + "integrity": "sha512-49hysH7jneTQoSC8TWbAi7nKK9Lc5osQNjmDHVosrcU8o3jecD9GrK0Qyul8q4aGPSXRfNGqIp9CBdb13akETg==", "dev": true }, "node_modules/typescript": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", - "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -52,15 +52,15 @@ "dev": true }, "@types/vscode": { - "version": "1.68.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.68.0.tgz", - "integrity": "sha512-duBwEK5ta/eBBMJMQ7ECMEsMvlE3XJdRGh3xoS1uOO4jl2Z4LPBl5vx8WvBP10ERAgDRmIt/FaSD4RHyBGbChw==", + "version": "1.55.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.55.0.tgz", + "integrity": "sha512-49hysH7jneTQoSC8TWbAi7nKK9Lc5osQNjmDHVosrcU8o3jecD9GrK0Qyul8q4aGPSXRfNGqIp9CBdb13akETg==", "dev": true }, "typescript": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", - "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", "dev": true } } diff --git a/package.json b/package.json index 385aa7f06..7ed204e86 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "language-server" ], "engines": { - "vscode": "^1.64.0" + "vscode": "^1.55.0" }, "activationEvents": [ "onLanguage:rescript" @@ -31,15 +31,9 @@ "semanticTokenScopes": [ { "scopes": { - "jsx-lowercase": [ - "entity.name.tag" - ], - "jsx-tag": [ - "punctuation.definition.tag" - ], - "support-type-primitive": [ - "support.type.primitive" - ] + "jsx-lowercase": ["entity.name.tag"], + "jsx-tag": ["punctuation.definition.tag"], + "support-type-primitive": ["support.type.primitive"] } } ], @@ -137,11 +131,6 @@ "type": "boolean", "default": false, "description": "Automatically start ReScript's code analysis." - }, - "rescript.settings.inlayHints.enable": { - "type": "boolean", - "default": false, - "description": "Enable type hint" } } }, @@ -175,7 +164,7 @@ }, "devDependencies": { "@types/node": "^14.14.41", - "@types/vscode": "^1.68.0", - "typescript": "^4.7.3" + "@types/vscode": "1.55.0", + "typescript": "^4.2.4" } } diff --git a/server/package-lock.json b/server/package-lock.json index 1c1163a02..68d935771 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,360 +1,375 @@ { - "name": "rescript-language-server", - "version": "1.3.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "rescript-language-server", - "version": "1.3.0", - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.1", - "vscode-jsonrpc": "^8.0.1", - "vscode-languageserver": "^8.0.1", - "vscode-languageserver-protocol": "^3.17.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.1" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/picomatch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", - "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/vscode-jsonrpc": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz", - "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/vscode-languageserver": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.0.1.tgz", - "integrity": "sha512-sn7SjBwWm3OlmLtgg7jbM0wBULppyL60rj8K5HF0ny/MzN+GzPBX1kCvYdybhl7UW63V5V5tRVnyB8iwC73lSQ==", - "dependencies": { - "vscode-languageserver-protocol": "3.17.1" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz", - "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==", - "dependencies": { - "vscode-jsonrpc": "8.0.1", - "vscode-languageserver-types": "3.17.1" - } - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz", - "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==" - } - }, - "dependencies": { - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "picomatch": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", - "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==" - }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "requires": { - "picomatch": "^2.2.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "vscode-jsonrpc": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz", - "integrity": "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==" - }, - "vscode-languageserver": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-8.0.1.tgz", - "integrity": "sha512-sn7SjBwWm3OlmLtgg7jbM0wBULppyL60rj8K5HF0ny/MzN+GzPBX1kCvYdybhl7UW63V5V5tRVnyB8iwC73lSQ==", - "requires": { - "vscode-languageserver-protocol": "3.17.1" - } - }, - "vscode-languageserver-protocol": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.1.tgz", - "integrity": "sha512-BNlAYgQoYwlSgDLJhSG+DeA8G1JyECqRzM2YO6tMmMji3Ad9Mw6AW7vnZMti90qlAKb0LqAlJfSVGEdqMMNzKg==", - "requires": { - "vscode-jsonrpc": "8.0.1", - "vscode-languageserver-types": "3.17.1" - } - }, - "vscode-languageserver-types": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz", - "integrity": "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==" - } - } + "name": "rescript-language-server", + "version": "1.3.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "rescript-language-server", + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.1", + "vscode-jsonrpc": "^5.0.1", + "vscode-languageserver": "^7.0.0", + "vscode-languageserver-protocol": "^3.16.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", + "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", + "engines": { + "node": ">=8.0.0 || >=10.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", + "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", + "dependencies": { + "vscode-languageserver-protocol": "3.16.0" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "dependencies": { + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" + } + }, + "node_modules/vscode-languageserver-protocol/node_modules/vscode-jsonrpc": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", + "engines": { + "node": ">=8.0.0 || >=10.0.0" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + } + }, + "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==" + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "vscode-jsonrpc": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", + "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" + }, + "vscode-languageserver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", + "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", + "requires": { + "vscode-languageserver-protocol": "3.16.0" + } + }, + "vscode-languageserver-protocol": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", + "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", + "requires": { + "vscode-jsonrpc": "6.0.0", + "vscode-languageserver-types": "3.16.0" + }, + "dependencies": { + "vscode-jsonrpc": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", + "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==" + } + } + }, + "vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" + } + } } diff --git a/server/package.json b/server/package.json index 8f99893ab..fffb2f044 100644 --- a/server/package.json +++ b/server/package.json @@ -1,21 +1,21 @@ { - "name": "rescript-language-server", - "description": "ReScript's language-server", - "version": "1.3.0", - "author": "chenglou", - "license": "MIT", - "engines": { - "node": "*" - }, - "repository": { - "type": "git", - "url": "https://github.com/rescript-lang/rescript-vscode" - }, - "dependencies": { - "chokidar": "^3.5.1", - "vscode-jsonrpc": "^8.0.1", - "vscode-languageserver": "^8.0.1", - "vscode-languageserver-protocol": "^3.17.1" - }, - "scripts": {} + "name": "rescript-language-server", + "description": "ReScript's language-server", + "version": "1.3.0", + "author": "chenglou", + "license": "MIT", + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/rescript-lang/rescript-vscode" + }, + "dependencies": { + "chokidar": "^3.5.1", + "vscode-jsonrpc": "^5.0.1", + "vscode-languageserver": "^7.0.0", + "vscode-languageserver-protocol": "^3.16.0" + }, + "scripts": {} } diff --git a/server/src/server.ts b/server/src/server.ts index 3fd84396b..a4c6a9958 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,8 +1,8 @@ import process from "process"; import * as p from "vscode-languageserver-protocol"; -// import * as m from "vscode-jsonrpc/node"; +import * as m from "vscode-jsonrpc/lib/messages"; import * as v from "vscode-languageserver"; -import * as rpc from "vscode-jsonrpc/node"; +import * as rpc from "vscode-jsonrpc"; import * as path from "path"; import fs from "fs"; // TODO: check DidChangeWatchedFilesNotification. @@ -51,7 +51,7 @@ let projectsFiles: Map< let codeActionsFromDiagnostics: codeActions.filesCodeActions = {}; // will be properly defined later depending on the mode (stdio/node-rpc) -let send: (msg: p.Message) => void = (_) => { }; +let send: (msg: m.Message) => void = (_) => {}; interface CreateInterfaceRequestParams { uri: string; @@ -93,7 +93,7 @@ let sendUpdatedDiagnostics = () => { uri: file, diagnostics: filesAndErrors[file], }; - let notification: v.NotificationMessage = { + let notification: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "textDocument/publishDiagnostics", params: params, @@ -111,7 +111,7 @@ let sendUpdatedDiagnostics = () => { uri: file, diagnostics: [], }; - let notification: p.NotificationMessage = { + let notification: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "textDocument/publishDiagnostics", params: params, @@ -131,7 +131,7 @@ let deleteProjectDiagnostics = (projectRootPath: string) => { uri: file, diagnostics: [], }; - let notification: p.NotificationMessage = { + let notification: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "textDocument/publishDiagnostics", params: params, @@ -143,7 +143,7 @@ let deleteProjectDiagnostics = (projectRootPath: string) => { } }; let sendCompilationFinishedMessage = () => { - let notification: p.NotificationMessage = { + let notification: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "rescript/compilationFinished", }; @@ -211,7 +211,7 @@ let openedFile = (fileUri: string, fileContent: string) => { message: `Start a build for this project to get the freshest data?`, actions: [payload], }; - let request: p.RequestMessage = { + let request: m.RequestMessage = { jsonrpc: c.jsonrpcVersion, id: serverSentRequestIdCounter++, method: "window/showMessageRequest", @@ -274,11 +274,11 @@ if (process.argv.includes("--stdio")) { let writer = new rpc.StreamMessageWriter(process.stdout); let reader = new rpc.StreamMessageReader(process.stdin); // proper `this` scope for writer - send = (msg: p.Message) => writer.write(msg); + send = (msg: m.Message) => writer.write(msg); reader.listen(onMessage); } else { // proper `this` scope for process - send = (msg: p.Message) => process.send!(msg); + send = (msg: m.Message) => process.send!(msg); process.on("message", onMessage); } @@ -303,31 +303,6 @@ function hover(msg: p.RequestMessage) { return response; } -function inlayHint(msg: p.RequestMessage) { - const params = msg.params as p.InlayHintParams; - const filePath = fileURLToPath(params.textDocument.uri); - - const response = utils.runAnalysisCommand( - filePath, - [ - "inlayHint", - filePath, - params.range.start.line, - params.range.end.line - ], - msg - ); - return response; -} - -function inlayHintResolve(msg: p.RequestMessage) { - return { - jsonrpc: c.jsonrpcVersion, - id: msg.id, - result: msg.params - } as p.ResponseMessage -} - function definition(msg: p.RequestMessage) { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition let params = msg.params as p.DefinitionParams; @@ -365,7 +340,7 @@ function references(msg: p.RequestMessage) { filePath, params.position ); - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result, @@ -374,7 +349,7 @@ function references(msg: p.RequestMessage) { return response; } -function prepareRename(msg: p.RequestMessage): p.ResponseMessage { +function prepareRename(msg: p.RequestMessage): m.ResponseMessage { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareRename let params = msg.params as p.PrepareRenameParams; let filePath = fileURLToPath(params.textDocument.uri); @@ -425,7 +400,7 @@ function rename(msg: p.RequestMessage) { if (documentChanges !== null) { result = { documentChanges }; } - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result, @@ -556,7 +531,7 @@ function codeAction(msg: p.RequestMessage): p.ResponseMessage { return res; } -function format(msg: p.RequestMessage): Array { +function format(msg: p.RequestMessage): Array { // technically, a formatting failure should reply with the error. Sadly // the LSP alert box for these error replies sucks (e.g. doesn't actually // display the message). In order to signal the client to display a proper @@ -564,7 +539,7 @@ function format(msg: p.RequestMessage): Array { // back a fake success message (because each request mandates a // response), then right away send a server notification to display a // nicer alert. Ugh. - let fakeSuccessResponse: p.ResponseMessage = { + let fakeSuccessResponse: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: [], @@ -577,7 +552,7 @@ function format(msg: p.RequestMessage): Array { type: p.MessageType.Error, message: `Not a ${c.resExt} or ${c.resiExt} file. Cannot format it.`, }; - let response: p.NotificationMessage = { + let response: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params: params, @@ -598,7 +573,7 @@ function format(msg: p.RequestMessage): Array { newText: formattedResult.result, }, ]; - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: result, @@ -614,7 +589,7 @@ function format(msg: p.RequestMessage): Array { } } -function createInterface(msg: p.RequestMessage): p.Message { +function createInterface(msg: p.RequestMessage): m.Message { let params = msg.params as CreateInterfaceRequestParams; let extension = path.extname(params.uri); let filePath = fileURLToPath(params.uri); @@ -626,7 +601,7 @@ function createInterface(msg: p.RequestMessage): p.Message { message: `Cannot locate project directory to generate the interface file.`, }; - let response: p.NotificationMessage = { + let response: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params: params, @@ -641,7 +616,7 @@ function createInterface(msg: p.RequestMessage): p.Message { message: `Not a ${c.resExt} file. Cannot create an interface for it.`, }; - let response: p.NotificationMessage = { + let response: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params: params, @@ -661,7 +636,7 @@ function createInterface(msg: p.RequestMessage): p.Message { message: `Error reading bsconfig file.`, }; - let response: p.NotificationMessage = { + let response: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params, @@ -687,7 +662,7 @@ function createInterface(msg: p.RequestMessage): p.Message { message: `No compiled interface file found. Please compile your project first.`, }; - let response: p.NotificationMessage = { + let response: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params, @@ -706,18 +681,18 @@ function createInterface(msg: p.RequestMessage): p.Message { try { let resiPath = utils.replaceFileExtension(filePath, c.resiExt); fs.writeFileSync(resiPath, result, { encoding: "utf-8" }); - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: "Interface successfully created.", }; return response; } catch (e) { - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, error: { - code: p.ErrorCodes.InternalError, + code: m.ErrorCodes.InternalError, message: "Unable to create interface file.", }, }; @@ -725,7 +700,7 @@ function createInterface(msg: p.RequestMessage): p.Message { } } -function openCompiledFile(msg: p.RequestMessage): p.Message { +function openCompiledFile(msg: p.RequestMessage): m.Message { let params = msg.params as OpenCompiledFileParams; let filePath = fileURLToPath(params.uri); let projDir = utils.findProjectRootOfFile(filePath); @@ -736,7 +711,7 @@ function openCompiledFile(msg: p.RequestMessage): p.Message { message: `Cannot locate project directory.`, }; - let response: p.NotificationMessage = { + let response: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params: params, @@ -761,7 +736,7 @@ function openCompiledFile(msg: p.RequestMessage): p.Message { message, }; - let response: p.NotificationMessage = { + let response: m.NotificationMessage = { jsonrpc: c.jsonrpcVersion, method: "window/showMessage", params, @@ -774,7 +749,7 @@ function openCompiledFile(msg: p.RequestMessage): p.Message { uri: compiledFilePath.result, }; - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result, @@ -783,8 +758,8 @@ function openCompiledFile(msg: p.RequestMessage): p.Message { return response; } -function onMessage(msg: p.Message) { - if (p.Message.isNotification(msg)) { +function onMessage(msg: m.Message) { + if (m.isNotificationMessage(msg)) { // notification message, aka the client ends it and doesn't want a reply if (!initialized && msg.method !== "exit") { // From spec: "Notifications should be dropped, except for the exit notification. This will allow the exit of a server without an initialize request" @@ -822,14 +797,14 @@ function onMessage(msg: p.Message) { // Can't seem to get this notification to trigger, but if it does this will be here and ensure we're synced up at the server. askForAllCurrentConfiguration(); } - } else if (p.Message.isRequest(msg)) { + } else if (m.isRequestMessage(msg)) { // request message, aka client sent request and waits for our mandatory reply if (!initialized && msg.method !== "initialize") { - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, error: { - code: p.ErrorCodes.ServerNotInitialized, + code: m.ErrorCodes.ServerNotInitialized, message: "Server not initialized.", }, }; @@ -870,12 +845,9 @@ function onMessage(msg: p.Message) { // TODO: Support range for full, and add delta support full: true, }, - inlayHintProvider: { - resolveProvider: true, - }, }, }; - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: result, @@ -899,7 +871,7 @@ function onMessage(msg: p.Message) { send(response); } else if (msg.method === "initialized") { // sent from client after initialize. Nothing to do for now - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: null, @@ -908,11 +880,11 @@ function onMessage(msg: p.Message) { } else if (msg.method === "shutdown") { // https://microsoft.github.io/language-server-protocol/specification#shutdown if (shutdownRequestAlreadyReceived) { - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, error: { - code: p.ErrorCodes.InvalidRequest, + code: m.ErrorCodes.InvalidRequest, message: `Language server already received the shutdown request`, }, }; @@ -927,7 +899,7 @@ function onMessage(msg: p.Message) { clearInterval(pullConfigurationPeriodically); } - let response: p.ResponseMessage = { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, result: null, @@ -961,23 +933,18 @@ function onMessage(msg: p.Message) { send(createInterface(msg)); } else if (msg.method === openCompiledFileRequest.method) { send(openCompiledFile(msg)); - } else if (msg.method == p.InlayHintRequest.method) { - send(inlayHint((msg))); - } else if (msg.method == p.InlayHintResolveRequest.method) { - send(inlayHintResolve(msg)) - } - else { - let response: p.ResponseMessage = { + } else { + let response: m.ResponseMessage = { jsonrpc: c.jsonrpcVersion, id: msg.id, error: { - code: p.ErrorCodes.InvalidRequest, + code: m.ErrorCodes.InvalidRequest, message: "Unrecognized editor request.", }, }; send(response); } - } else if (p.Message.isResponse(msg)) { + } else if (m.isResponseMessage(msg)) { if (msg.id === c.configurationRequestId) { if (msg.result != null) { // This is a response from a request to get updated configuration. Note From c73fa084de671da59da9121ced986e66a7cb0959 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 11 Jun 2022 17:54:06 -0300 Subject: [PATCH 08/42] cleanup rm client.ts --- client/src/client.ts | 45 -------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 client/src/client.ts diff --git a/client/src/client.ts b/client/src/client.ts deleted file mode 100644 index e358c10b8..000000000 --- a/client/src/client.ts +++ /dev/null @@ -1,45 +0,0 @@ -import * as lc from "vscode-languageclient/node"; -import * as vscode from "vscode"; -import * as path from "path"; - -export async function createClient(context: vscode.ExtensionContext) { - const serverModule = context.asAbsolutePath( - path.join("server", "out", "server.js") - ); - // The debug options for the server - // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging - let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] }; - - // If the extension is launched in debug mode then the debug server options are used - // Otherwise the run options are used - const serverOptions: lc.ServerOptions = { - run: { module: serverModule, transport: lc.TransportKind.ipc }, - debug: { - module: serverModule, - transport: lc.TransportKind.ipc, - options: debugOptions, - }, - }; - - // Options to control the language client - const clientOptions: lc.LanguageClientOptions = { - documentSelector: [{ scheme: "file", language: "rescript" }], - // We'll send the initial configuration in here, but this might be - // problematic because every consumer of the LS will need to mimic this. - // We'll leave it like this for now, but might be worth revisiting later on. - initializationOptions: { - extensionConfiguration: vscode.workspace.getConfiguration("rescript.settings"), - }, - }; - - const client = new lc.LanguageClient( - "ReScriptLSP", - "ReScript Language Server", - serverOptions, - clientOptions - ); - - client.registerProposedFeatures() - - return client; -} \ No newline at end of file From 935a8dfaa8b1562e91374783373a4be57ffb6f09 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 16 Jun 2022 08:22:31 +0200 Subject: [PATCH 09/42] add config option for inlay hints --- package.json | 5 +++++ server/src/server.ts | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/package.json b/package.json index 950827877..13d9d9401 100644 --- a/package.json +++ b/package.json @@ -131,6 +131,11 @@ "type": "boolean", "default": false, "description": "Automatically start ReScript's code analysis." + }, + "rescript.settings.inlayHints": { + "type": "boolean", + "default": false, + "description": "Enable (experimental) inlay hints." } } }, diff --git a/server/src/server.ts b/server/src/server.ts index eb6b36afd..4bf78c03e 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -23,9 +23,13 @@ import { WorkspaceEdit } from "vscode-languageserver"; interface extensionConfiguration { askToStartBuild: boolean; + autoRunCodeAnalysis: boolean; + inlayHints: boolean; } let extensionConfiguration: extensionConfiguration = { askToStartBuild: true, + autoRunCodeAnalysis: false, + inlayHints: false, }; let pullConfigurationPeriodically: NodeJS.Timeout | null = null; From 8b41f2184b5aebc87ba25539194f66f77feb0e8d Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 16 Jun 2022 10:04:11 +0200 Subject: [PATCH 10/42] wire up inline hints again --- server/src/server.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/server/src/server.ts b/server/src/server.ts index 4bf78c03e..829f556be 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -163,6 +163,7 @@ let compilerLogsWatcher = chokidar .on("all", (_e, changedPath) => { sendUpdatedDiagnostics(); sendCompilationFinishedMessage(); + sendInlayHintsRefresh(); }); let stopWatchingCompilerLog = () => { // TODO: cleanup of compilerLogs? @@ -306,6 +307,27 @@ function hover(msg: p.RequestMessage) { return response; } +function inlayHint(msg: p.RequestMessage) { + const params = msg.params as p.InlayHintParams; + const filePath = fileURLToPath(params.textDocument.uri); + + const response = utils.runAnalysisCommand( + filePath, + ["inlayHint", filePath, params.range.start.line, params.range.end.line], + msg + ); + return response; +} + +function sendInlayHintsRefresh() { + let request: p.RequestMessage = { + jsonrpc: c.jsonrpcVersion, + method: p.InlayHintRefreshRequest.method, + id: serverSentRequestIdCounter++, + }; + send(request); +} + function definition(msg: p.RequestMessage) { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition let params = msg.params as p.DefinitionParams; @@ -848,6 +870,7 @@ function onMessage(msg: p.Message) { // TODO: Support range for full, and add delta support full: true, }, + inlayHintProvider: true, }, }; let response: p.ResponseMessage = { @@ -936,6 +959,8 @@ function onMessage(msg: p.Message) { send(createInterface(msg)); } else if (msg.method === openCompiledFileRequest.method) { send(openCompiledFile(msg)); + } else if (msg.method === p.InlayHintRequest.method) { + send(inlayHint(msg)); } else { let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, From f46998e82b7823dec8ce2445f69a4c04278dd7c6 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Thu, 16 Jun 2022 10:19:07 +0200 Subject: [PATCH 11/42] honor inline hints configuration --- client/src/extension.ts | 11 +++++++++++ server/src/server.ts | 24 +++++++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/client/src/extension.ts b/client/src/extension.ts index 4b57f6ddf..2a0abef5d 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -235,6 +235,17 @@ export function activate(context: ExtensionContext) { // Start the client. This will also launch the server client.start(); + // Restart the language client automatically certain configuration changes. + // These are typically settings that affect the capabilities of the language + // client, and because of that requires a full restart. + context.subscriptions.push( + workspace.onDidChangeConfiguration(({ affectsConfiguration }) => { + if (affectsConfiguration("rescript.settings.inlayHints")) { + commands.executeCommand("rescript-vscode.restart_language_server"); + } + }) + ); + // Autostart code analysis if wanted if ( workspace diff --git a/server/src/server.ts b/server/src/server.ts index 829f556be..7c03c7e84 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -163,7 +163,9 @@ let compilerLogsWatcher = chokidar .on("all", (_e, changedPath) => { sendUpdatedDiagnostics(); sendCompilationFinishedMessage(); - sendInlayHintsRefresh(); + if (extensionConfiguration.inlayHints === true) { + sendInlayHintsRefresh(); + } }); let stopWatchingCompilerLog = () => { // TODO: cleanup of compilerLogs? @@ -835,6 +837,15 @@ function onMessage(msg: p.Message) { }; send(response); } else if (msg.method === "initialize") { + // Save initial configuration, if present + let initParams = msg.params as InitializeParams; + let initialConfiguration = initParams.initializationOptions + ?.extensionConfiguration as extensionConfiguration | undefined; + + if (initialConfiguration != null) { + extensionConfiguration = initialConfiguration; + } + // send the list of features we support let result: p.InitializeResult = { // This tells the client: "hey, we support the following operations". @@ -870,7 +881,7 @@ function onMessage(msg: p.Message) { // TODO: Support range for full, and add delta support full: true, }, - inlayHintProvider: true, + inlayHintProvider: extensionConfiguration.inlayHints, }, }; let response: p.ResponseMessage = { @@ -885,15 +896,6 @@ function onMessage(msg: p.Message) { askForAllCurrentConfiguration(); }, c.pullConfigurationInterval); - // Save initial configuration, if present - let initParams = msg.params as InitializeParams; - let initialConfiguration = initParams.initializationOptions - ?.extensionConfiguration as extensionConfiguration | undefined; - - if (initialConfiguration != null) { - extensionConfiguration = initialConfiguration; - } - send(response); } else if (msg.method === "initialized") { // sent from client after initialize. Nothing to do for now From a2562c62885a2d6ac6ceda912505d9aa38907bb8 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 18 Jun 2022 19:43:38 -0300 Subject: [PATCH 12/42] refactor hint analysis --- analysis/src/Hint.ml | 81 +++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 53 deletions(-) diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 3e973ca14..787c21f73 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -1,20 +1,5 @@ open SharedTypes -type kind = - | Module - | Property - | Constructor - | Function - | Variable - | Constant - | String - | Number - | EnumMember - | TypeParameter - -let typeHintKindToNumber = function Variable -> 1 | _ -> 2 -let getPaddingFromKind = function Variable -> 4 | _ -> 0 - let parseTypeReturn (t : Types.type_expr) = let typeString = Shared.typeToString t in match Str.split (Str.regexp "=>") typeString with @@ -47,22 +32,12 @@ let locItemToTypeHint ~full:{file; package} locItem = (* TODO: filter for range of lines*) let inlay ~path ~pos ~debug = let symbols = ref [] in - let rec exprKind (exp : Parsetree.expression) = - match exp.pexp_desc with - | Pexp_fun _ -> Function - | Pexp_function _ -> Function - | Pexp_constraint (e, _) -> exprKind e - | Pexp_constant (Pconst_string _) -> String - | Pexp_constant (Pconst_float _ | Pconst_integer _) -> Number - | Pexp_constant _ -> Constant - | _ -> Variable - in (* TODO: Handle with tuples let-bindings *) let value_binding (iterator : Ast_iterator.iterator) (vb : Parsetree.value_binding) = (match vb.pvb_pat.ppat_desc with | Ppat_var {txt} | Ppat_constraint ({ppat_desc = Ppat_var {txt}}, _) -> - symbols := (txt, vb.pvb_loc, exprKind vb.pvb_expr) :: !symbols + symbols := vb.pvb_pat.ppat_loc :: !symbols | _ -> ()); Ast_iterator.default_iterator.value_binding iterator vb in @@ -78,37 +53,37 @@ let inlay ~path ~pos ~debug = let {Res_driver.parsetree = signature} = parser ~filename:path in iterator.signature iterator signature |> ignore); !symbols - |> List.rev_map (fun (name, loc, kind) -> - let range = Utils.cmtLocToRange loc in - (* TODO: find the ending or starting position of a let bindings *) - let rangeEndCharacter = - getPaddingFromKind kind + range.start.character + String.length name - in - let hintKind = typeHintKindToNumber kind in - let position : Protocol.position = - {line = range.start.line; character = rangeEndCharacter} - in + |> List.rev_map (fun locOfName -> + let range = Utils.cmtLocToRange locOfName in match Cmt.fullFromPath ~path with - | None -> None | Some full -> ( match References.getLocItem ~full - ~pos:(position.line, position.character) + ~pos:(range.start.line, range.start.character + 1) ~debug with - | None -> None - | Some s -> ( - match locItemToTypeHint ~full s with - | Some typeHint -> Some (typeHint, hintKind, position) - | None -> None))) + | Some locItem -> + let position : Protocol.position = + {line = range.start.line; character = range.end_.character} + in + let typeHint = + match locItemToTypeHint locItem ~full with + | Some hint -> hint + | None -> "Unknown type" + in + let result = + Protocol.stringifyHint + { + kind = 1; + position; + tooltip = + {kind = "markdown"; value = Hover.codeBlock typeHint}; + paddingLeft = false; + paddingRight = false; + label = ": " ^ typeHint; + } + in + Some result + | None -> None) + | None -> None) |> List.filter_map (fun x -> x) - |> List.map (fun (typeHint, kind, position) -> - Protocol.stringifyHint - { - kind; - position; - tooltip = {kind = "markdown"; value = Hover.codeBlock typeHint}; - paddingLeft = false; - paddingRight = false; - label = ": " ^ typeHint; - }) From 4c2bad3f60160745293637e192c3b8b98e3da191 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 18 Jun 2022 23:23:34 -0300 Subject: [PATCH 13/42] add docstring to tooltip --- analysis/src/Hint.ml | 110 +++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 40 deletions(-) diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 787c21f73..1e1652e41 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -1,32 +1,64 @@ open SharedTypes -let parseTypeReturn (t : Types.type_expr) = - let typeString = Shared.typeToString t in - match Str.split (Str.regexp "=>") typeString with - | x :: xs -> List.fold_left (fun _ y -> y) x xs |> String.trim - | _ -> typeString - let locItemToTypeHint ~full:{file; package} locItem = match locItem.locType with | Constant t -> - Some - (match t with - | Const_int _ -> "int" - | Const_char _ -> "char" - | Const_string _ -> "string" - | Const_float _ -> "float" - | Const_int32 _ -> "int32" - | Const_int64 _ -> "int64" - | Const_nativeint _ -> "int") + let typehint = (match t with + | Const_int _ -> "int" + | Const_char _ -> "char" + | Const_string _ -> "string" + | Const_float _ -> "float" + | Const_int32 _ -> "int32" + | Const_int64 _ -> "int64" + | Const_nativeint _ -> "int") in + Some(typehint, typehint) | Typed (_, t, locKind) -> + let fromType ~docstring typ = + (* TODO: get only type return *) + let typeString = typ + |> Shared.typeToString + |> Str.split (Str.regexp "\n") + |> List.filter(fun c -> c <> "\n") + |> String.concat "" in + + let extraTypeInfo = + let env = QueryEnv.fromFile file in + match typ |> Shared.digConstructor with + | None -> None + | Some path -> ( + match References.digConstructor ~env ~package path with + | None -> None + | Some (_env, {docstring; name = {txt}; item = {decl}}) -> + if Utils.isUncurriedInternal path then None + else Some (decl |> Shared.declToString txt, docstring)) + in + let typeString, docstring = + match extraTypeInfo with + | None -> (typeString, [typeString]) + | Some (extra, extraDocstring) -> + (typeString, extra :: extraDocstring) + in + (typeString, String.concat "" docstring) + in Some (match References.definedForLoc ~file ~package locKind with - | None -> parseTypeReturn t - | Some (_, res) -> ( + | None -> t |> fromType ~docstring:[] + | Some (docstring, res) -> ( match res with - | `Declared -> parseTypeReturn t - | `Constructor _ -> parseTypeReturn t - | `Field -> parseTypeReturn t)) + | `Declared -> t |> fromType ~docstring:[] + | `Constructor {cname = {txt}; args} -> + let typeString, docstring = t |> fromType ~docstring in + let argsString = + match args with + | [] -> "" + | _ -> + args + |> List.map (fun (t, _) -> Shared.typeToString t) + |> String.concat ", " |> Printf.sprintf "(%s)" + in + (typeString, Hover.codeBlock (txt ^ argsString ^ docstring)) + | `Field -> t |> fromType ~docstring) + ) | _ -> None (* TODO: filter for range of lines*) @@ -56,34 +88,32 @@ let inlay ~path ~pos ~debug = |> List.rev_map (fun locOfName -> let range = Utils.cmtLocToRange locOfName in match Cmt.fullFromPath ~path with + | None -> None | Some full -> ( match References.getLocItem ~full ~pos:(range.start.line, range.start.character + 1) ~debug with + | None -> None | Some locItem -> let position : Protocol.position = {line = range.start.line; character = range.end_.character} in - let typeHint = - match locItemToTypeHint locItem ~full with - | Some hint -> hint - | None -> "Unknown type" - in - let result = - Protocol.stringifyHint - { - kind = 1; - position; - tooltip = - {kind = "markdown"; value = Hover.codeBlock typeHint}; - paddingLeft = false; - paddingRight = false; - label = ": " ^ typeHint; - } - in - Some result - | None -> None) - | None -> None) + match locItemToTypeHint locItem ~full with + | Some (label, tooltip) -> + let result = + Protocol.stringifyHint + { + kind = 1; + position; + tooltip = + {kind = "markdown"; value = Hover.codeBlock tooltip}; + paddingLeft = false; + paddingRight = false; + label = ": " ^ label; + } + in + Some(result) + | None -> None)) |> List.filter_map (fun x -> x) From f43ef11d90ece28ffc82c5ab16abb8f0441973c9 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 8 Jul 2022 00:46:33 -0300 Subject: [PATCH 14/42] rewrite inlay hints --- analysis/src/Hint.ml | 145 ++++++++++++++++++++++++--------------- analysis/src/Protocol.ml | 13 ++++ 2 files changed, 104 insertions(+), 54 deletions(-) diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 1e1652e41..8b61d7e90 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -1,25 +1,33 @@ open SharedTypes +type inlayHintKind = Type | Parameter +let inlayKindToNumber = function + | Type -> 1 + | Parameter -> 2 + let locItemToTypeHint ~full:{file; package} locItem = match locItem.locType with | Constant t -> - let typehint = (match t with - | Const_int _ -> "int" - | Const_char _ -> "char" - | Const_string _ -> "string" - | Const_float _ -> "float" - | Const_int32 _ -> "int32" - | Const_int64 _ -> "int64" - | Const_nativeint _ -> "int") in - Some(typehint, typehint) + let typehint = + match t with + | Const_int _ -> "int" + | Const_char _ -> "char" + | Const_string _ -> "string" + | Const_float _ -> "float" + | Const_int32 _ -> "int32" + | Const_int64 _ -> "int64" + | Const_nativeint _ -> "int" + in + Some (typehint, typehint) | Typed (_, t, locKind) -> let fromType ~docstring typ = (* TODO: get only type return *) - let typeString = typ - |> Shared.typeToString - |> Str.split (Str.regexp "\n") - |> List.filter(fun c -> c <> "\n") - |> String.concat "" in + let typeString = + typ |> Shared.typeToString + |> Str.split (Str.regexp "\n") + |> List.filter (fun c -> c <> "\n") + |> String.concat "" + in let extraTypeInfo = let env = QueryEnv.fromFile file in @@ -35,8 +43,7 @@ let locItemToTypeHint ~full:{file; package} locItem = let typeString, docstring = match extraTypeInfo with | None -> (typeString, [typeString]) - | Some (extra, extraDocstring) -> - (typeString, extra :: extraDocstring) + | Some (extra, extraDocstring) -> (typeString, extra :: extraDocstring) in (typeString, String.concat "" docstring) in @@ -46,30 +53,61 @@ let locItemToTypeHint ~full:{file; package} locItem = | Some (docstring, res) -> ( match res with | `Declared -> t |> fromType ~docstring:[] - | `Constructor {cname = {txt}; args} -> - let typeString, docstring = t |> fromType ~docstring in - let argsString = - match args with - | [] -> "" - | _ -> - args - |> List.map (fun (t, _) -> Shared.typeToString t) - |> String.concat ", " |> Printf.sprintf "(%s)" - in - (typeString, Hover.codeBlock (txt ^ argsString ^ docstring)) - | `Field -> t |> fromType ~docstring) - ) + | `Constructor {cname = {txt}; args} -> + let typeString, docstring = t |> fromType ~docstring in + let argsString = + match args with + | [] -> "" + | _ -> + args + |> List.map (fun (t, _) -> Shared.typeToString t) + |> String.concat ", " |> Printf.sprintf "(%s)" + in + (typeString, Hover.codeBlock (txt ^ argsString ^ docstring)) + | `Field -> t |> fromType ~docstring)) | _ -> None (* TODO: filter for range of lines*) let inlay ~path ~pos ~debug = - let symbols = ref [] in - (* TODO: Handle with tuples let-bindings *) + let hints = ref [] in + let rec funArgs (exp : Parsetree.expression) = + match exp.pexp_desc with + | Pexp_fun (_, _, pat_exp, bodyExpr) -> ( + match pat_exp with + | {ppat_desc = Ppat_var _} -> + hints := (pat_exp.ppat_loc, Parameter) :: !hints; + funArgs bodyExpr + | _ -> funArgs bodyExpr) + | _ -> () + in let value_binding (iterator : Ast_iterator.iterator) (vb : Parsetree.value_binding) = - (match vb.pvb_pat.ppat_desc with - | Ppat_var {txt} | Ppat_constraint ({ppat_desc = Ppat_var {txt}}, _) -> - symbols := vb.pvb_pat.ppat_loc :: !symbols + (match vb with + | { + pvb_pat = {ppat_desc = Ppat_var _}; + pvb_expr = + { + pexp_desc = + ( Pexp_constant _ | Pexp_tuple _ | Pexp_record _ | Pexp_apply _ + | Pexp_match _ | Pexp_construct _ | Pexp_ifthenelse _ | Pexp_array _ + | Pexp_ident _ ); + }; + } -> + hints := (vb.pvb_pat.ppat_loc, Type) :: !hints + | {pvb_pat = {ppat_desc = Ppat_tuple tuples}} -> + List.iter + (fun (tuple : Parsetree.pattern) -> + hints := (tuple.ppat_loc, Type) :: !hints) + tuples + | { + pvb_pat = {ppat_desc = Ppat_var _}; + pvb_expr = {pexp_desc = Pexp_fun (_, _, pat, bodyExpr)}; + } -> + hints := (vb.pvb_pat.ppat_loc, Type) :: !hints; + (match pat with + | {ppat_desc = Ppat_var _} -> hints := (pat.ppat_loc, Parameter) :: !hints + | _ -> ()); + funArgs bodyExpr | _ -> ()); Ast_iterator.default_iterator.value_binding iterator vb in @@ -84,8 +122,8 @@ let inlay ~path ~pos ~debug = let parser = Res_driver.parsingEngine.parseInterface ~forPrinter:false in let {Res_driver.parsetree = signature} = parser ~filename:path in iterator.signature iterator signature |> ignore); - !symbols - |> List.rev_map (fun locOfName -> + !hints + |> List.filter_map (fun (locOfName, inlayKind) -> let range = Utils.cmtLocToRange locOfName in match Cmt.fullFromPath ~path with | None -> None @@ -96,24 +134,23 @@ let inlay ~path ~pos ~debug = ~debug with | None -> None - | Some locItem -> + | Some locItem -> ( let position : Protocol.position = {line = range.start.line; character = range.end_.character} in - match locItemToTypeHint locItem ~full with - | Some (label, tooltip) -> - let result = - Protocol.stringifyHint - { - kind = 1; - position; - tooltip = - {kind = "markdown"; value = Hover.codeBlock tooltip}; - paddingLeft = false; - paddingRight = false; - label = ": " ^ label; - } - in - Some(result) - | None -> None)) - |> List.filter_map (fun x -> x) + match locItemToTypeHint locItem ~full with + | Some (label, tooltip) -> + let result = + Protocol.stringifyHint + { + kind = inlayKindToNumber inlayKind; + position; + tooltip = + {kind = "markdown"; value = Hover.codeBlock tooltip}; + paddingLeft = false; + paddingRight = false; + label = ": " ^ label; + } + in + Some result + | None -> None))) \ No newline at end of file diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index 5a2cca80e..4ac8d63e0 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -133,6 +133,19 @@ let stringifyCodeAction ca = (codeActionKindToString ca.codeActionKind) (ca.edit |> stringifyCodeActionEdit) +let stringifyHint hint = + Printf.sprintf + {|{ + "position": %s, + "label": "%s", + "tooltip": %s, + "kind": %i, + "paddingLeft": %b, + "paddingRight": %b +}|} + (stringifyPosition hint.position) + (Json.escape hint.label) (stringifyMarkupContent hint.tooltip) hint.kind hint.paddingLeft hint.paddingRight + (* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnostic *) let stringifyDiagnostic d = Printf.sprintf {|{ From f4e9f1d5e8960f3d2febb4b91475e25912bcdc25 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 8 Jul 2022 02:46:32 -0300 Subject: [PATCH 15/42] add more exp --- analysis/src/Hint.ml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 8b61d7e90..36b0c8228 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -88,9 +88,10 @@ let inlay ~path ~pos ~debug = pvb_expr = { pexp_desc = - ( Pexp_constant _ | Pexp_tuple _ | Pexp_record _ | Pexp_apply _ - | Pexp_match _ | Pexp_construct _ | Pexp_ifthenelse _ | Pexp_array _ - | Pexp_ident _ ); + ( Pexp_constant _ | Pexp_tuple _ | Pexp_record _ | Pexp_variant _ + | Pexp_apply _ | Pexp_match _ | Pexp_construct _ | Pexp_ifthenelse _ + | Pexp_array _ | Pexp_ident _ | Pexp_try _ | Pexp_lazy _ + | Pexp_send _ | Pexp_field _ ); }; } -> hints := (vb.pvb_pat.ppat_loc, Type) :: !hints From 29b77d16b6952c1e96c863a74727c3ad996c49e1 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Tue, 19 Jul 2022 22:55:06 -0300 Subject: [PATCH 16/42] refactor --- analysis/src/Cli.ml | 6 ++-- analysis/src/Commands.ml | 6 ++-- analysis/src/Hint.ml | 75 ++++++++++++---------------------------- analysis/src/Protocol.ml | 5 ++- server/src/server.ts | 2 +- 5 files changed, 30 insertions(+), 64 deletions(-) diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index 31a490ccd..f9e86ddd3 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -89,10 +89,8 @@ let main () = Commands.hover ~path ~pos:(int_of_string line, int_of_string col) ~currentFile ~debug:false - | [_; "inlayHint"; path; line_start; line_end] -> - Commands.inlayhint ~path - ~pos:(int_of_string line_start, int_of_string line_end) - ~debug:false + | [_; "inlayHint"; path;] -> + Commands.inlayhint ~path ~debug:false | [_; "codeAction"; path; line; col; currentFile] -> Commands.codeAction ~path ~pos:(int_of_string line, int_of_string col) diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 6e6b3dbb7..fb8e70aab 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -28,10 +28,10 @@ let completion ~debug ~path ~pos ~currentFile = |> List.map Protocol.stringifyCompletionItem |> Protocol.array) -let inlayhint ~path ~pos ~debug = - let result = match Hint.inlay ~path ~pos ~debug with +let inlayhint ~path ~debug = + let result = match Hint.inlay ~path ~debug with | [] -> Protocol.null - | hints -> "[\n" ^ String.concat ",\n" hints ^ "\n]" in + | hints -> hints |> Protocol.array in print_endline result let hover ~path ~pos ~currentFile ~debug = diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 36b0c8228..faec92d2a 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -18,66 +18,38 @@ let locItemToTypeHint ~full:{file; package} locItem = | Const_int64 _ -> "int64" | Const_nativeint _ -> "int" in - Some (typehint, typehint) + Some typehint | Typed (_, t, locKind) -> - let fromType ~docstring typ = - (* TODO: get only type return *) - let typeString = + let fromType typ kind = + let result = typ |> Shared.typeToString - |> Str.split (Str.regexp "\n") - |> List.filter (fun c -> c <> "\n") - |> String.concat "" + |> Str.global_replace (Str.regexp "[\r\n\t ]") "" + |> Str.global_replace (Str.regexp "=>") " => " in - - let extraTypeInfo = - let env = QueryEnv.fromFile file in - match typ |> Shared.digConstructor with - | None -> None - | Some path -> ( - match References.digConstructor ~env ~package path with - | None -> None - | Some (_env, {docstring; name = {txt}; item = {decl}}) -> - if Utils.isUncurriedInternal path then None - else Some (decl |> Shared.declToString txt, docstring)) - in - let typeString, docstring = - match extraTypeInfo with - | None -> (typeString, [typeString]) - | Some (extra, extraDocstring) -> (typeString, extra :: extraDocstring) - in - (typeString, String.concat "" docstring) + match kind with + | Parameter -> result + | _ -> result in Some (match References.definedForLoc ~file ~package locKind with - | None -> t |> fromType ~docstring:[] - | Some (docstring, res) -> ( + | None -> t |> fromType + | Some (_, res) -> ( match res with - | `Declared -> t |> fromType ~docstring:[] - | `Constructor {cname = {txt}; args} -> - let typeString, docstring = t |> fromType ~docstring in - let argsString = - match args with - | [] -> "" - | _ -> - args - |> List.map (fun (t, _) -> Shared.typeToString t) - |> String.concat ", " |> Printf.sprintf "(%s)" - in - (typeString, Hover.codeBlock (txt ^ argsString ^ docstring)) - | `Field -> t |> fromType ~docstring)) + | `Declared -> t |> fromType + | `Constructor _ -> t |> fromType + | `Field -> t |> fromType)) | _ -> None -(* TODO: filter for range of lines*) -let inlay ~path ~pos ~debug = +let inlay ~path ~debug = let hints = ref [] in - let rec funArgs (exp : Parsetree.expression) = + let rec processFunction (exp : Parsetree.expression) = match exp.pexp_desc with - | Pexp_fun (_, _, pat_exp, bodyExpr) -> ( + | Pexp_fun (_, _, pat_exp, e) -> ( match pat_exp with | {ppat_desc = Ppat_var _} -> hints := (pat_exp.ppat_loc, Parameter) :: !hints; - funArgs bodyExpr - | _ -> funArgs bodyExpr) + processFunction e + | _ -> processFunction e) | _ -> () in let value_binding (iterator : Ast_iterator.iterator) @@ -102,13 +74,12 @@ let inlay ~path ~pos ~debug = tuples | { pvb_pat = {ppat_desc = Ppat_var _}; - pvb_expr = {pexp_desc = Pexp_fun (_, _, pat, bodyExpr)}; + pvb_expr = {pexp_desc = Pexp_fun (_, _, pat, e)}; } -> - hints := (vb.pvb_pat.ppat_loc, Type) :: !hints; (match pat with | {ppat_desc = Ppat_var _} -> hints := (pat.ppat_loc, Parameter) :: !hints | _ -> ()); - funArgs bodyExpr + processFunction e | _ -> ()); Ast_iterator.default_iterator.value_binding iterator vb in @@ -140,15 +111,13 @@ let inlay ~path ~pos ~debug = {line = range.start.line; character = range.end_.character} in match locItemToTypeHint locItem ~full with - | Some (label, tooltip) -> + | Some label -> let result = Protocol.stringifyHint { kind = inlayKindToNumber inlayKind; position; - tooltip = - {kind = "markdown"; value = Hover.codeBlock tooltip}; - paddingLeft = false; + paddingLeft = true; paddingRight = false; label = ": " ^ label; } diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index ae7be63a6..f623dd60b 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -1,7 +1,7 @@ type position = {line : int; character : int} type range = {start : position; end_ : position} type markupContent = {kind : string; value : string} -type inlayHint = {position : position; label : string; kind : int; tooltip: markupContent; paddingLeft: bool; paddingRight: bool} +type inlayHint = {position : position; label : string; kind : int; paddingLeft: bool; paddingRight: bool} type completionItem = { label: string; @@ -134,13 +134,12 @@ let stringifyHint hint = {|{ "position": %s, "label": "%s", - "tooltip": %s, "kind": %i, "paddingLeft": %b, "paddingRight": %b }|} (stringifyPosition hint.position) - (Json.escape hint.label) (stringifyMarkupContent hint.tooltip) hint.kind hint.paddingLeft hint.paddingRight + (Json.escape hint.label) hint.kind hint.paddingLeft hint.paddingRight (* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnostic *) let stringifyDiagnostic d = diff --git a/server/src/server.ts b/server/src/server.ts index 0d99fce45..2d2be7a92 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -372,7 +372,7 @@ function inlayHint(msg: p.RequestMessage) { const response = utils.runAnalysisCommand( filePath, - ["inlayHint", filePath, params.range.start.line, params.range.end.line], + ["inlayHint", filePath], msg ); return response; From fefee5183f925ea96fe63165491d73ee8bad8203 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 15:05:38 -0300 Subject: [PATCH 17/42] add tests --- analysis/src/Commands.ml | 1 + analysis/tests/src/expected/InlayHint.res.txt | 1 + 2 files changed, 2 insertions(+) create mode 100644 analysis/tests/src/expected/InlayHint.res.txt diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index fb8e70aab..8d7d04793 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -388,6 +388,7 @@ let test ~path = (Protocol.stringifyRange range) indent indent newText))) | "dia" -> diagnosticSyntax ~path + | "hint" -> inlayhint ~path ~debug:true | _ -> ()); print_newline ()) in diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -0,0 +1 @@ + From b995ac2db9dfe80721be2a77af81d300be739abf Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 15:06:01 -0300 Subject: [PATCH 18/42] simplify typehint --- analysis/src/Hint.ml | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index faec92d2a..7d9dfa6b5 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -8,36 +8,28 @@ let inlayKindToNumber = function let locItemToTypeHint ~full:{file; package} locItem = match locItem.locType with | Constant t -> - let typehint = - match t with + Some + (match t with | Const_int _ -> "int" | Const_char _ -> "char" | Const_string _ -> "string" | Const_float _ -> "float" | Const_int32 _ -> "int32" | Const_int64 _ -> "int64" - | Const_nativeint _ -> "int" - in - Some typehint + | Const_nativeint _ -> "int") | Typed (_, t, locKind) -> - let fromType typ kind = - let result = - typ |> Shared.typeToString - |> Str.global_replace (Str.regexp "[\r\n\t ]") "" - |> Str.global_replace (Str.regexp "=>") " => " - in - match kind with - | Parameter -> result - | _ -> result + let fromType typ = + typ |> Shared.typeToString + |> Str.global_replace (Str.regexp "[\r\n\t]") "" in Some (match References.definedForLoc ~file ~package locKind with - | None -> t |> fromType + | None -> fromType t | Some (_, res) -> ( match res with - | `Declared -> t |> fromType - | `Constructor _ -> t |> fromType - | `Field -> t |> fromType)) + | `Declared -> fromType t + | `Constructor _ -> fromType t + | `Field -> fromType t)) | _ -> None let inlay ~path ~debug = @@ -47,7 +39,7 @@ let inlay ~path ~debug = | Pexp_fun (_, _, pat_exp, e) -> ( match pat_exp with | {ppat_desc = Ppat_var _} -> - hints := (pat_exp.ppat_loc, Parameter) :: !hints; + hints := (pat_exp.ppat_loc, Type) :: !hints; processFunction e | _ -> processFunction e) | _ -> () @@ -63,7 +55,7 @@ let inlay ~path ~debug = ( Pexp_constant _ | Pexp_tuple _ | Pexp_record _ | Pexp_variant _ | Pexp_apply _ | Pexp_match _ | Pexp_construct _ | Pexp_ifthenelse _ | Pexp_array _ | Pexp_ident _ | Pexp_try _ | Pexp_lazy _ - | Pexp_send _ | Pexp_field _ ); + | Pexp_send _ | Pexp_field _ | Pexp_open _ ); }; } -> hints := (vb.pvb_pat.ppat_loc, Type) :: !hints @@ -77,7 +69,7 @@ let inlay ~path ~debug = pvb_expr = {pexp_desc = Pexp_fun (_, _, pat, e)}; } -> (match pat with - | {ppat_desc = Ppat_var _} -> hints := (pat.ppat_loc, Parameter) :: !hints + | {ppat_desc = Ppat_var _} -> hints := (pat.ppat_loc, Type) :: !hints | _ -> ()); processFunction e | _ -> ()); @@ -95,7 +87,7 @@ let inlay ~path ~debug = let {Res_driver.parsetree = signature} = parser ~filename:path in iterator.signature iterator signature |> ignore); !hints - |> List.filter_map (fun (locOfName, inlayKind) -> + |> List.filter_map (fun (locOfName, hintKind) -> let range = Utils.cmtLocToRange locOfName in match Cmt.fullFromPath ~path with | None -> None @@ -115,7 +107,7 @@ let inlay ~path ~debug = let result = Protocol.stringifyHint { - kind = inlayKindToNumber inlayKind; + kind = inlayKindToNumber hintKind; position; paddingLeft = true; paddingRight = false; From 516f701fbec42c664c44c9eeba7fa3016d9dcd63 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 15:09:14 -0300 Subject: [PATCH 19/42] fix test --- analysis/tests/src/expected/InlayHint.res.txt | 75 ++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt index 8b1378917..237e0810d 100644 --- a/analysis/tests/src/expected/InlayHint.res.txt +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -1 +1,74 @@ - +inlayHint src/InlayHint.res +[{ + "position": {"line": 42, "character": 9}, + "label": ": string", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 40, "character": 9}, + "label": ": (string, string)", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 38, "character": 17}, + "label": ": string", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 30, "character": 24}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 13, "character": 24}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 7, "character": 10}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 5, "character": 15}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 5, "character": 12}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 3, "character": 8}, + "label": ": char", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 2, "character": 9}, + "label": ": float", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 1, "character": 10}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 0, "character": 10}, + "label": ": string", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}] \ No newline at end of file From 5ee6f66c679cdf9abe84924e8ad1d5e42690a97c Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 15:12:35 -0300 Subject: [PATCH 20/42] add cli help --- analysis/src/Cli.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index f9e86ddd3..9c092b567 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -65,6 +65,10 @@ Options: ./rescript-editor-analysis.exe diagnosticSyntax src/MyFile.res + inlayHint: get all inlay Hint declared in MyFile.res + + ./rescript-editor-analysis.exe inlayHint src/MyFile.res + test: run tests specified by special comments in file src/MyFile.res ./rescript-editor-analysis.exe test src/src/MyFile.res From 13be958b22a050e97680b6284ed2cf2c745ba74e Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 15:22:32 -0300 Subject: [PATCH 21/42] fix test --- analysis/tests/src/InlayHint.res | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/analysis/tests/src/InlayHint.res b/analysis/tests/src/InlayHint.res index 1a34851fc..f15418634 100644 --- a/analysis/tests/src/InlayHint.res +++ b/analysis/tests/src/InlayHint.res @@ -5,39 +5,16 @@ let char = 'c' let add = (x, y) => x + y -let my_sum = 3 - -> add(1) - -> add(1) - -> add(1) - -> add(8) +let my_sum = 3->add(1)->add(1)->add(1)->add(8) let withAs = (~xx as yyy) => yyy + 1 -let arity0a = (. ()) => { - //^hov - let f = () => 3 - f -} - -let arity0b = (. (), . ()) => 3 - -type t = (int, float) - -@ocaml.doc("This module is commented") -module Dep: { - @ocaml.doc("Some doc comment") - let customDouble: int => int -} = { - let customDouble = foo => foo * 2 -} - -module D = Dep - -let functionWithTypeAnnotation: unit => int = () => 1 @react.component let make = (~name) => React.string(name) let tuple = ("ReScript", "lol") -let (lang, _) = tuple \ No newline at end of file +let (lang, _) = tuple + +//^hint \ No newline at end of file From 7bd68f20d35864f186ac8f297b6d55595b9b0f1a Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 15:29:04 -0300 Subject: [PATCH 22/42] fix test --- analysis/tests/src/expected/InlayHint.res.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt index 237e0810d..9f2dcbd22 100644 --- a/analysis/tests/src/expected/InlayHint.res.txt +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -1,4 +1,3 @@ -inlayHint src/InlayHint.res [{ "position": {"line": 42, "character": 9}, "label": ": string", From 02f080a2bd149fc8632d017eebb9acbef426b037 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 15:32:07 -0300 Subject: [PATCH 23/42] update expected test --- analysis/tests/src/expected/InlayHint.res.txt | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt index 9f2dcbd22..46bed1773 100644 --- a/analysis/tests/src/expected/InlayHint.res.txt +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -1,29 +1,23 @@ [{ - "position": {"line": 42, "character": 9}, + "position": {"line": 17, "character": 9}, "label": ": string", "kind": 1, "paddingLeft": true, "paddingRight": false }, { - "position": {"line": 40, "character": 9}, + "position": {"line": 15, "character": 9}, "label": ": (string, string)", "kind": 1, "paddingLeft": true, "paddingRight": false }, { - "position": {"line": 38, "character": 17}, + "position": {"line": 13, "character": 17}, "label": ": string", "kind": 1, "paddingLeft": true, "paddingRight": false }, { - "position": {"line": 30, "character": 24}, - "label": ": int", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 13, "character": 24}, + "position": {"line": 9, "character": 24}, "label": ": int", "kind": 1, "paddingLeft": true, From a4353efd190c4a2ef48273611b38816bfc6206fd Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 16:38:15 -0300 Subject: [PATCH 24/42] trim whitespace --- analysis/src/Hint.ml | 2 +- analysis/tests/src/expected/InlayHint.res.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 7d9dfa6b5..d2d278c5e 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -20,7 +20,7 @@ let locItemToTypeHint ~full:{file; package} locItem = | Typed (_, t, locKind) -> let fromType typ = typ |> Shared.typeToString - |> Str.global_replace (Str.regexp "[\r\n\t]") "" + |> Str.global_replace (Str.regexp "[\r\n\t ]") "" in Some (match References.definedForLoc ~file ~package locKind with diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt index 46bed1773..608b084bb 100644 --- a/analysis/tests/src/expected/InlayHint.res.txt +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -6,7 +6,7 @@ "paddingRight": false }, { "position": {"line": 15, "character": 9}, - "label": ": (string, string)", + "label": ": (string,string)", "kind": 1, "paddingLeft": true, "paddingRight": false From 674e8be77db6505c33fc32e412d54b2f02a15cd6 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 16:38:47 -0300 Subject: [PATCH 25/42] format --- analysis/src/Protocol.ml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index f623dd60b..6838a29ca 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -1,7 +1,13 @@ -type position = {line : int; character : int} -type range = {start : position; end_ : position} -type markupContent = {kind : string; value : string} -type inlayHint = {position : position; label : string; kind : int; paddingLeft: bool; paddingRight: bool} +type position = {line: int; character: int} +type range = {start: position; end_: position} +type markupContent = {kind: string; value: string} +type inlayHint = { + position: position; + label: string; + kind: int; + paddingLeft: bool; + paddingRight: bool; +} type completionItem = { label: string; @@ -150,5 +156,4 @@ let stringifyDiagnostic d = "severity": %d, "source": "ReScript" }|} - (stringifyRange d.range) (Json.escape d.message) - d.severity + (stringifyRange d.range) (Json.escape d.message) d.severity From 9a30439490b44fc9eb9e0e8fec370c03862338b4 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Wed, 20 Jul 2022 16:41:44 -0300 Subject: [PATCH 26/42] remove autoRunCodeAnalysis --- server/src/server.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/src/server.ts b/server/src/server.ts index 6db9785e3..d16466558 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -25,13 +25,11 @@ import { filesDiagnostics } from "./utils"; interface extensionConfiguration { askToStartBuild: boolean; - autoRunCodeAnalysis: boolean; inlayHints: boolean; binaryPath: string | null; } let extensionConfiguration: extensionConfiguration = { askToStartBuild: true, - autoRunCodeAnalysis: false, inlayHints: false, binaryPath: null, }; From b8d1ece20839119463eb69e349865514e080ae82 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Thu, 21 Jul 2022 18:30:54 -0300 Subject: [PATCH 27/42] add maxLength option --- analysis/src/Cli.ml | 9 +++++---- analysis/src/Commands.ml | 6 +++--- analysis/src/Hint.ml | 9 ++++++--- package.json | 11 ++++++++++- server/src/server.ts | 16 +++++++++++----- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index 9c092b567..6258ab590 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -11,6 +11,7 @@ API examples: ./rescript-editor-analysis.exe references src/MyFile.res 10 2 ./rescript-editor-analysis.exe rename src/MyFile.res 10 2 foo ./rescript-editor-analysis.exe diagnosticSyntax src/MyFile.res + /rescript-editor-analysis.exe inlayHint src/MyFile.res 25 Dev-time examples: ./rescript-editor-analysis.exe dump src/MyFile.res src/MyFile2.res @@ -65,9 +66,9 @@ Options: ./rescript-editor-analysis.exe diagnosticSyntax src/MyFile.res - inlayHint: get all inlay Hint declared in MyFile.res + inlayHint: get all inlay Hint with max length equal a 25 declared in MyFile.res - ./rescript-editor-analysis.exe inlayHint src/MyFile.res + ./rescript-editor-analysis.exe inlayHint 25 src/MyFile.res test: run tests specified by special comments in file src/MyFile.res @@ -93,8 +94,8 @@ let main () = Commands.hover ~path ~pos:(int_of_string line, int_of_string col) ~currentFile ~debug:false - | [_; "inlayHint"; path;] -> - Commands.inlayhint ~path ~debug:false + | [_; "inlayHint"; path; maxLength] -> + Commands.inlayhint ~path ~maxLength ~debug:false | [_; "codeAction"; path; line; col; currentFile] -> Commands.codeAction ~path ~pos:(int_of_string line, int_of_string col) diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 8d7d04793..5c40feaf0 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -28,8 +28,8 @@ let completion ~debug ~path ~pos ~currentFile = |> List.map Protocol.stringifyCompletionItem |> Protocol.array) -let inlayhint ~path ~debug = - let result = match Hint.inlay ~path ~debug with +let inlayhint ~path ~maxLength ~debug = + let result = match Hint.inlay ~path ~maxLength ~debug with | [] -> Protocol.null | hints -> hints |> Protocol.array in print_endline result @@ -388,7 +388,7 @@ let test ~path = (Protocol.stringifyRange range) indent indent newText))) | "dia" -> diagnosticSyntax ~path - | "hint" -> inlayhint ~path ~debug:true + | "hint" -> inlayhint ~path ~maxLength:"25" ~debug:true | _ -> ()); print_newline ()) in diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index d2d278c5e..9df606cc1 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -32,7 +32,8 @@ let locItemToTypeHint ~full:{file; package} locItem = | `Field -> fromType t)) | _ -> None -let inlay ~path ~debug = +let inlay ~path ~maxLength ~debug = + let maxlen = try Some(int_of_string maxLength) with Failure _ -> None in let hints = ref [] in let rec processFunction (exp : Parsetree.expression) = match exp.pexp_desc with @@ -103,7 +104,7 @@ let inlay ~path ~debug = {line = range.start.line; character = range.end_.character} in match locItemToTypeHint locItem ~full with - | Some label -> + | Some label -> ( let result = Protocol.stringifyHint { @@ -114,5 +115,7 @@ let inlay ~path ~debug = label = ": " ^ label; } in - Some result + match maxlen with + | Some value -> if (String.length label) > value then None else Some(result) + | None -> Some(result)) | None -> None))) \ No newline at end of file diff --git a/package.json b/package.json index c1f61409e..cfc99facf 100644 --- a/package.json +++ b/package.json @@ -132,11 +132,20 @@ "default": false, "description": "Automatically start ReScript's code analysis." }, - "rescript.settings.inlayHints": { + "rescript.settings.inlayHints.enable": { "type": "boolean", "default": false, "description": "Enable (experimental) inlay hints." }, + "rescript.settings.inlayHints.maxLength": { + "markdownDescription": "Maximum length for inlay hints. Set to null to have an unlimited length.", + "default": 25, + "type": [ + "null", + "integer" + ], + "minimum": 0 + }, "rescript.settings.binaryPath": { "type": ["string", "null"], "default": null, diff --git a/server/src/server.ts b/server/src/server.ts index d16466558..34a19290b 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -25,12 +25,18 @@ import { filesDiagnostics } from "./utils"; interface extensionConfiguration { askToStartBuild: boolean; - inlayHints: boolean; + inlayHints: { + enable: boolean; + maxLength: number | null; + }; binaryPath: string | null; } let extensionConfiguration: extensionConfiguration = { askToStartBuild: true, - inlayHints: false, + inlayHints: { + enable: false, + maxLength: 25 + }, binaryPath: null, }; let pullConfigurationPeriodically: NodeJS.Timeout | null = null; @@ -219,7 +225,7 @@ let compilerLogsWatcher = chokidar .on("all", (_e, changedPath) => { sendUpdatedDiagnostics(); sendCompilationFinishedMessage(); - if (extensionConfiguration.inlayHints === true) { + if (extensionConfiguration.inlayHints.enable === true) { sendInlayHintsRefresh(); } }); @@ -389,7 +395,7 @@ function inlayHint(msg: p.RequestMessage) { const response = utils.runAnalysisCommand( filePath, - ["inlayHint", filePath], + ["inlayHint", filePath, extensionConfiguration.inlayHints.maxLength], msg ); return response; @@ -993,7 +999,7 @@ function onMessage(msg: p.Message) { // TODO: Support range for full, and add delta support full: true, }, - inlayHintProvider: extensionConfiguration.inlayHints, + inlayHintProvider: extensionConfiguration.inlayHints.enable, }, }; let response: p.ResponseMessage = { From bd4cfdd19d329e6179f8365114a9f7985af0a8e3 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Thu, 21 Jul 2022 18:36:37 -0300 Subject: [PATCH 28/42] keep whitespace --- analysis/src/Hint.ml | 2 +- analysis/tests/src/expected/InlayHint.res.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 9df606cc1..7dadf9308 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -20,7 +20,7 @@ let locItemToTypeHint ~full:{file; package} locItem = | Typed (_, t, locKind) -> let fromType typ = typ |> Shared.typeToString - |> Str.global_replace (Str.regexp "[\r\n\t ]") "" + |> Str.global_replace (Str.regexp "[\r\n\t]") "" in Some (match References.definedForLoc ~file ~package locKind with diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt index 608b084bb..9ed0d1213 100644 --- a/analysis/tests/src/expected/InlayHint.res.txt +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -1,4 +1,4 @@ -[{ +{ "position": {"line": 17, "character": 9}, "label": ": string", "kind": 1, @@ -6,7 +6,7 @@ "paddingRight": false }, { "position": {"line": 15, "character": 9}, - "label": ": (string,string)", + "label": ": (string, string)", "kind": 1, "paddingLeft": true, "paddingRight": false From bc5494c96ba6a07aa0b01f645002d16df9f62a3e Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Thu, 21 Jul 2022 18:48:07 -0300 Subject: [PATCH 29/42] fix cli arg --- analysis/src/Cli.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index 6258ab590..83af18337 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -68,7 +68,7 @@ Options: inlayHint: get all inlay Hint with max length equal a 25 declared in MyFile.res - ./rescript-editor-analysis.exe inlayHint 25 src/MyFile.res + ./rescript-editor-analysis.exe inlayHint src/MyFile.res 25 test: run tests specified by special comments in file src/MyFile.res From 6921165127ef147d8723d5a0607f1ebb00671697 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 22 Jul 2022 02:01:13 +0200 Subject: [PATCH 30/42] Update tests. --- analysis/tests/src/expected/Dce.res.txt | 2 +- analysis/tests/src/expected/Debug.res.txt | 3 +- analysis/tests/src/expected/InlayHint.res.txt | 68 +------------------ 3 files changed, 4 insertions(+), 69 deletions(-) diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 308ef678c..441bb5807 100644 --- a/analysis/tests/src/expected/Dce.res.txt +++ b/analysis/tests/src/expected/Dce.res.txt @@ -1,3 +1,3 @@ DCE src/Dce.res -issues:235 +issues:243 diff --git a/analysis/tests/src/expected/Debug.res.txt b/analysis/tests/src/expected/Debug.res.txt index ff23fed2d..ff23fe834 100644 --- a/analysis/tests/src/expected/Debug.res.txt +++ b/analysis/tests/src/expected/Debug.res.txt @@ -4,7 +4,7 @@ Dependencies: @rescript/react Source directories: ./node_modules/@rescript/react/src ./node_modules/@rescript/react/src/legacy Source files: ./node_modules/@rescript/react/src/React.res ./node_modules/@rescript/react/src/ReactDOM.res ./node_modules/@rescript/react/src/ReactDOMServer.res ./node_modules/@rescript/react/src/ReactDOMStyle.res ./node_modules/@rescript/react/src/ReactEvent.res ./node_modules/@rescript/react/src/ReactEvent.resi ./node_modules/@rescript/react/src/ReactTestUtils.res ./node_modules/@rescript/react/src/ReactTestUtils.resi ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.res ./node_modules/@rescript/react/src/RescriptReactErrorBoundary.resi ./node_modules/@rescript/react/src/RescriptReactRouter.res ./node_modules/@rescript/react/src/RescriptReactRouter.resi ./node_modules/@rescript/react/src/legacy/ReactDOMRe.res ./node_modules/@rescript/react/src/legacy/ReasonReact.res Source directories: ./src ./src/expected -Source files: ./src/Auto.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeDefinition.res ./src/Xform.res +Source files: ./src/Auto.res ./src/CompletePrioritize1.res ./src/CompletePrioritize2.res ./src/Completion.res ./src/Component.res ./src/Component.resi ./src/CreateInterface.res ./src/Cross.res ./src/Dce.res ./src/Debug.res ./src/Definition.res ./src/DefinitionWithInterface.res ./src/DefinitionWithInterface.resi ./src/Div.res ./src/DocumentSymbol.res ./src/Fragment.res ./src/Highlight.res ./src/Hover.res ./src/InlayHint.res ./src/Jsx.res ./src/Jsx.resi ./src/LongIdentTest.res ./src/Object.res ./src/Patterns.res ./src/RecModules.res ./src/RecordCompletion.res ./src/RecoveryOnProp.res ./src/References.res ./src/ReferencesWithInterface.res ./src/ReferencesWithInterface.resi ./src/Rename.res ./src/RenameWithInterface.res ./src/RenameWithInterface.resi ./src/TableclothMap.ml ./src/TableclothMap.mli ./src/TypeDefinition.res ./src/Xform.res Impl cmt:./lib/bs/src/Auto.cmt res:./src/Auto.res Impl cmt:./lib/bs/src/CompletePrioritize1.cmt res:./src/CompletePrioritize1.res Impl cmt:./lib/bs/src/CompletePrioritize2.cmt res:./src/CompletePrioritize2.res @@ -21,6 +21,7 @@ Impl cmt:./lib/bs/src/DocumentSymbol.cmt res:./src/DocumentSymbol.res Impl cmt:./lib/bs/src/Fragment.cmt res:./src/Fragment.res Impl cmt:./lib/bs/src/Highlight.cmt res:./src/Highlight.res Impl cmt:./lib/bs/src/Hover.cmt res:./src/Hover.res +Impl cmt:./lib/bs/src/InlayHint.cmt res:./src/InlayHint.res IntfAndImpl cmti:./lib/bs/src/Jsx.cmti resi:./src/Jsx.resi cmt:./lib/bs/src/Jsx.cmt res:./src/Jsx.res Impl cmt:./lib/bs/src/LongIdentTest.cmt res:./src/LongIdentTest.res Impl cmt:./lib/bs/src/Object.cmt res:./src/Object.res diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt index 9ed0d1213..8b1378917 100644 --- a/analysis/tests/src/expected/InlayHint.res.txt +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -1,67 +1 @@ -{ - "position": {"line": 17, "character": 9}, - "label": ": string", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 15, "character": 9}, - "label": ": (string, string)", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 13, "character": 17}, - "label": ": string", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 9, "character": 24}, - "label": ": int", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 7, "character": 10}, - "label": ": int", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 5, "character": 15}, - "label": ": int", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 5, "character": 12}, - "label": ": int", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 3, "character": 8}, - "label": ": char", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 2, "character": 9}, - "label": ": float", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 1, "character": 10}, - "label": ": int", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 0, "character": 10}, - "label": ": string", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}] \ No newline at end of file + From 13b804a3b5f44f6d131ad48ff7b00e3d304a5ca3 Mon Sep 17 00:00:00 2001 From: Cristiano Calcagno Date: Fri, 22 Jul 2022 02:04:31 +0200 Subject: [PATCH 31/42] Simple cleanup. --- analysis/src/Commands.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 5c40feaf0..048a4efcd 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -29,9 +29,7 @@ let completion ~debug ~path ~pos ~currentFile = |> Protocol.array) let inlayhint ~path ~maxLength ~debug = - let result = match Hint.inlay ~path ~maxLength ~debug with - | [] -> Protocol.null - | hints -> hints |> Protocol.array in + let result = Hint.inlay ~path ~maxLength ~debug |> Protocol.array in print_endline result let hover ~path ~pos ~currentFile ~debug = From 58d3d67eb8d72dd8d7777cd469680a15a6a0b536 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 22 Jul 2022 10:50:42 -0300 Subject: [PATCH 32/42] fix server.ts --- server/src/server.ts | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/server/src/server.ts b/server/src/server.ts index 6f9e80988..cc01f5e6f 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1014,26 +1014,6 @@ function onMessage(msg: p.Message) { askForAllCurrentConfiguration(); }, c.pullConfigurationInterval); - // Save initial configuration, if present - let initParams = msg.params as InitializeParams; - let initialConfiguration = initParams.initializationOptions - ?.extensionConfiguration as extensionConfiguration | undefined; - - if (initialConfiguration != null) { - extensionConfiguration = initialConfiguration; - if ( - extensionConfiguration.binaryPath != null && - extensionConfiguration.binaryPath[0] === "~" - ) { - // What should happen if the path contains the home directory symbol? - // This situation is handled below, but maybe it isn't the best option. - extensionConfiguration.binaryPath = path.join( - os.homedir(), - extensionConfiguration.binaryPath.slice(1) - ); - } - } - send(response); } else if (msg.method === "initialized") { // sent from client after initialize. Nothing to do for now From 83a7d7439e37dd18d934fc9b89279bb5b4c5a94b Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 22 Jul 2022 12:01:46 -0300 Subject: [PATCH 33/42] add range params --- analysis/examples/larger-project/.merlin | 14 +++++----- analysis/src/Cli.ml | 6 +++-- analysis/src/Commands.ml | 6 ++--- analysis/src/Hint.ml | 33 ++++++++++++------------ server/src/server.ts | 11 +++++--- 5 files changed, 39 insertions(+), 31 deletions(-) diff --git a/analysis/examples/larger-project/.merlin b/analysis/examples/larger-project/.merlin index c5130bee7..05434917e 100644 --- a/analysis/examples/larger-project/.merlin +++ b/analysis/examples/larger-project/.merlin @@ -1,12 +1,12 @@ ####{BSB GENERATED: NO EDIT -FLG -ppx '/Users/cristianocalcagno/GitHub/rescript-vscode/analysis/examples/larger-project/node_modules/rescript/darwin/bsc.exe -as-ppx -bs-jsx 3' -S /Users/cristianocalcagno/GitHub/rescript-vscode/analysis/examples/larger-project/node_modules/rescript/lib/ocaml -B /Users/cristianocalcagno/GitHub/rescript-vscode/analysis/examples/larger-project/node_modules/rescript/lib/ocaml +FLG -ppx '/home/pedro/Desktop/Projects/rescript-vscode/analysis/examples/larger-project/node_modules/rescript/linux/bsc.exe -as-ppx -bs-jsx 3' +S /home/pedro/Desktop/Projects/rescript-vscode/analysis/examples/larger-project/node_modules/rescript/lib/ocaml +B /home/pedro/Desktop/Projects/rescript-vscode/analysis/examples/larger-project/node_modules/rescript/lib/ocaml FLG -w +a-4-9-20-40-41-42-50-61-102 -S /Users/cristianocalcagno/GitHub/rescript-vscode/analysis/examples/larger-project/node_modules/@rescript/react/lib/ocaml -B /Users/cristianocalcagno/GitHub/rescript-vscode/analysis/examples/larger-project/node_modules/@rescript/react/lib/ocaml -S /Users/cristianocalcagno/GitHub/rescript-vscode/analysis/examples/larger-project/node_modules/@glennsl/bs-json/lib/ocaml -B /Users/cristianocalcagno/GitHub/rescript-vscode/analysis/examples/larger-project/node_modules/@glennsl/bs-json/lib/ocaml +S /home/pedro/Desktop/Projects/rescript-vscode/analysis/examples/larger-project/node_modules/@rescript/react/lib/ocaml +B /home/pedro/Desktop/Projects/rescript-vscode/analysis/examples/larger-project/node_modules/@rescript/react/lib/ocaml +S /home/pedro/Desktop/Projects/rescript-vscode/analysis/examples/larger-project/node_modules/@glennsl/bs-json/lib/ocaml +B /home/pedro/Desktop/Projects/rescript-vscode/analysis/examples/larger-project/node_modules/@glennsl/bs-json/lib/ocaml S src B lib/bs/src S src/exception diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index 83af18337..ef7401f2f 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -94,8 +94,10 @@ let main () = Commands.hover ~path ~pos:(int_of_string line, int_of_string col) ~currentFile ~debug:false - | [_; "inlayHint"; path; maxLength] -> - Commands.inlayhint ~path ~maxLength ~debug:false + | [_; "inlayHint"; path; line_start; line_end; maxLength] -> + Commands.inlayhint ~path + ~pos:(int_of_string line_start, int_of_string line_end) + ~maxLength ~debug:false | [_; "codeAction"; path; line; col; currentFile] -> Commands.codeAction ~path ~pos:(int_of_string line, int_of_string col) diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 048a4efcd..65256c7d0 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -28,8 +28,8 @@ let completion ~debug ~path ~pos ~currentFile = |> List.map Protocol.stringifyCompletionItem |> Protocol.array) -let inlayhint ~path ~maxLength ~debug = - let result = Hint.inlay ~path ~maxLength ~debug |> Protocol.array in +let inlayhint ~path ~pos ~maxLength ~debug = + let result = Hint.inlay ~path ~pos ~maxLength ~debug |> Protocol.array in print_endline result let hover ~path ~pos ~currentFile ~debug = @@ -386,7 +386,7 @@ let test ~path = (Protocol.stringifyRange range) indent indent newText))) | "dia" -> diagnosticSyntax ~path - | "hint" -> inlayhint ~path ~maxLength:"25" ~debug:true + | "hint" -> inlayhint ~path ~pos:(0, 20) ~maxLength:"25" ~debug:true | _ -> ()); print_newline ()) in diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 7dadf9308..c3d8a9682 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -32,15 +32,21 @@ let locItemToTypeHint ~full:{file; package} locItem = | `Field -> fromType t)) | _ -> None -let inlay ~path ~maxLength ~debug = - let maxlen = try Some(int_of_string maxLength) with Failure _ -> None in +let inlay ~path ~pos ~maxLength ~debug = + let maxlen = try Some (int_of_string maxLength) with Failure _ -> None in let hints = ref [] in + let start_line, end_line = pos in + let push loc kind = + let range = Utils.cmtLocToRange loc in + if start_line <= range.end_.line && end_line >= range.start.line then + hints := (range, kind) :: !hints + in let rec processFunction (exp : Parsetree.expression) = match exp.pexp_desc with | Pexp_fun (_, _, pat_exp, e) -> ( match pat_exp with | {ppat_desc = Ppat_var _} -> - hints := (pat_exp.ppat_loc, Type) :: !hints; + push pat_exp.ppat_loc Type; processFunction e | _ -> processFunction e) | _ -> () @@ -59,18 +65,17 @@ let inlay ~path ~maxLength ~debug = | Pexp_send _ | Pexp_field _ | Pexp_open _ ); }; } -> - hints := (vb.pvb_pat.ppat_loc, Type) :: !hints + push vb.pvb_pat.ppat_loc Type | {pvb_pat = {ppat_desc = Ppat_tuple tuples}} -> List.iter - (fun (tuple : Parsetree.pattern) -> - hints := (tuple.ppat_loc, Type) :: !hints) + (fun (tuple : Parsetree.pattern) -> push tuple.ppat_loc Type) tuples | { pvb_pat = {ppat_desc = Ppat_var _}; pvb_expr = {pexp_desc = Pexp_fun (_, _, pat, e)}; } -> (match pat with - | {ppat_desc = Ppat_var _} -> hints := (pat.ppat_loc, Type) :: !hints + | {ppat_desc = Ppat_var _} -> push pat.ppat_loc Type | _ -> ()); processFunction e | _ -> ()); @@ -82,14 +87,9 @@ let inlay ~path ~maxLength ~debug = Res_driver.parsingEngine.parseImplementation ~forPrinter:false in let {Res_driver.parsetree = structure} = parser ~filename:path in - iterator.structure iterator structure |> ignore - else - let parser = Res_driver.parsingEngine.parseInterface ~forPrinter:false in - let {Res_driver.parsetree = signature} = parser ~filename:path in - iterator.signature iterator signature |> ignore); + iterator.structure iterator structure |> ignore); !hints - |> List.filter_map (fun (locOfName, hintKind) -> - let range = Utils.cmtLocToRange locOfName in + |> List.filter_map (fun ((range : Protocol.range), hintKind) -> match Cmt.fullFromPath ~path with | None -> None | Some full -> ( @@ -116,6 +116,7 @@ let inlay ~path ~maxLength ~debug = } in match maxlen with - | Some value -> if (String.length label) > value then None else Some(result) - | None -> Some(result)) + | Some value -> + if String.length label > value then None else Some result + | None -> Some result) | None -> None))) \ No newline at end of file diff --git a/server/src/server.ts b/server/src/server.ts index cc01f5e6f..542d1010b 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -12,6 +12,7 @@ import { DidCloseTextDocumentNotification, DidChangeConfigurationNotification, InitializeParams, + InlayHintParams, } from "vscode-languageserver-protocol"; import * as utils from "./utils"; import * as codeActions from "./codeActions"; @@ -71,7 +72,7 @@ let projectsFiles: Map< let codeActionsFromDiagnostics: codeActions.filesCodeActions = {}; // will be properly defined later depending on the mode (stdio/node-rpc) -let send: (msg: p.Message) => void = (_) => {}; +let send: (msg: p.Message) => void = (_) => { }; let findBinaryDirPathFromProjectRoot = ( directory: p.DocumentUri // This must be a directory and not a file! @@ -395,7 +396,7 @@ function inlayHint(msg: p.RequestMessage) { const response = utils.runAnalysisCommand( filePath, - ["inlayHint", filePath, extensionConfiguration.inlayHints.maxLength], + ["inlayHint", filePath, params.range.start.line, params.range.end.line, extensionConfiguration.inlayHints.maxLength], msg ); return response; @@ -1080,7 +1081,11 @@ function onMessage(msg: p.Message) { } else if (msg.method === openCompiledFileRequest.method) { send(openCompiledFile(msg)); } else if (msg.method === p.InlayHintRequest.method) { - send(inlayHint(msg)); + let params = msg.params as InlayHintParams; + let extName = path.extname(params.textDocument.uri); + if (extName === c.resExt) { + send(inlayHint(msg)); + } } else { let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, From c185c0a25353b17699fdb55a4accdc2b5b990429 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 22 Jul 2022 12:07:10 -0300 Subject: [PATCH 34/42] update Cli --- analysis/src/Cli.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index ef7401f2f..f07e534a9 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -11,7 +11,7 @@ API examples: ./rescript-editor-analysis.exe references src/MyFile.res 10 2 ./rescript-editor-analysis.exe rename src/MyFile.res 10 2 foo ./rescript-editor-analysis.exe diagnosticSyntax src/MyFile.res - /rescript-editor-analysis.exe inlayHint src/MyFile.res 25 + /rescript-editor-analysis.exe inlayHint src/MyFile.res 0 3 25 Dev-time examples: ./rescript-editor-analysis.exe dump src/MyFile.res src/MyFile2.res @@ -66,9 +66,9 @@ Options: ./rescript-editor-analysis.exe diagnosticSyntax src/MyFile.res - inlayHint: get all inlay Hint with max length equal a 25 declared in MyFile.res + inlayHint: get all inlay Hint between line 0 and 3 declared in MyFile.res. Last argument is maximum length for inlay hints - ./rescript-editor-analysis.exe inlayHint src/MyFile.res 25 + ./rescript-editor-analysis.exe inlayHint src/MyFile.res 0 3 25 test: run tests specified by special comments in file src/MyFile.res From 9b4bac90649c342d7b721e38b9b567ee7f4e209d Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 22 Jul 2022 12:23:46 -0300 Subject: [PATCH 35/42] update readme --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 92ca8b97f..009011390 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,18 @@ The extension will look for the existence of a `/node_modules/.bin/rescript` fil To override this lookup process, the path can be configured explicitly using the setting `rescript.settings.binaryPath`. +### Inlay Hints (experimental) + +This allows an editor to place annotations inline with text to display type hints. + +```jsonc +// Enable (experimental) inlay hints. +rescript.settings.inlayHints.enable: true + +// Maximum length for inlay hints. Set to null to have an unlimited length. +rescript.settings.inlayHints.maxLength: 25 +``` + ### Hide generated files You can configure VSCode to collapse the JavaScript files ReScript generates under its source ReScript file. This will "hide" the generated files in the VSCode file explorer, but still leaving them accessible by expanding the source ReScript file they belong to. From fc3e3f941e8e6ea643e8393d2f156e5c5e2de49f Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 22 Jul 2022 21:09:31 -0300 Subject: [PATCH 36/42] add test --- analysis/tests/src/expected/InlayHint.res.txt | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt index 8b1378917..4952a3e83 100644 --- a/analysis/tests/src/expected/InlayHint.res.txt +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -1 +1,68 @@ +[{ + "position": {"line": 17, "character": 9}, + "label": ": string", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 15, "character": 9}, + "label": ": (string, string)", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 13, "character": 17}, + "label": ": string", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 9, "character": 24}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 7, "character": 10}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 5, "character": 15}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 5, "character": 12}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 3, "character": 8}, + "label": ": char", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 2, "character": 9}, + "label": ": float", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 1, "character": 10}, + "label": ": int", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}, { + "position": {"line": 0, "character": 10}, + "label": ": string", + "kind": 1, + "paddingLeft": true, + "paddingRight": false +}] \ No newline at end of file From 99bd0731564f968f2947343dcce91f6ab63db8fd Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 22 Jul 2022 21:24:30 -0300 Subject: [PATCH 37/42] fix test --- analysis/src/Commands.ml | 6 +++- analysis/tests/src/InlayHint.res | 2 +- analysis/tests/src/expected/InlayHint.res.txt | 34 ++----------------- 3 files changed, 8 insertions(+), 34 deletions(-) diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 65256c7d0..3dd16c468 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -386,7 +386,11 @@ let test ~path = (Protocol.stringifyRange range) indent indent newText))) | "dia" -> diagnosticSyntax ~path - | "hint" -> inlayhint ~path ~pos:(0, 20) ~maxLength:"25" ~debug:true + | "hin" -> ( + let line_start = 0 in + let line_end = 6 in + print_endline ("Inlay Hint " ^ path ^ " " ^ string_of_int line_start ^ ":" ^ string_of_int line_end); + inlayhint ~path ~pos:(line_start, line_end) ~maxLength:"25" ~debug:false) | _ -> ()); print_newline ()) in diff --git a/analysis/tests/src/InlayHint.res b/analysis/tests/src/InlayHint.res index f15418634..ef49412e9 100644 --- a/analysis/tests/src/InlayHint.res +++ b/analysis/tests/src/InlayHint.res @@ -17,4 +17,4 @@ let tuple = ("ReScript", "lol") let (lang, _) = tuple -//^hint \ No newline at end of file +//^hin \ No newline at end of file diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt index 4952a3e83..b7c20e8a5 100644 --- a/analysis/tests/src/expected/InlayHint.res.txt +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -1,35 +1,5 @@ - -[{ - "position": {"line": 17, "character": 9}, - "label": ": string", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 15, "character": 9}, - "label": ": (string, string)", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 13, "character": 17}, - "label": ": string", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 9, "character": 24}, - "label": ": int", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { - "position": {"line": 7, "character": 10}, - "label": ": int", - "kind": 1, - "paddingLeft": true, - "paddingRight": false -}, { +Inlay Hint tests/src/InlayHint.res 0:6 +[{ "position": {"line": 5, "character": 15}, "label": ": int", "kind": 1, From 65fe0ecdd538d1e9061cd156bf3c4e3ab80dca85 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 22 Jul 2022 21:25:22 -0300 Subject: [PATCH 38/42] fix test --- analysis/tests/src/expected/InlayHint.res.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/analysis/tests/src/expected/InlayHint.res.txt b/analysis/tests/src/expected/InlayHint.res.txt index b7c20e8a5..a129f9331 100644 --- a/analysis/tests/src/expected/InlayHint.res.txt +++ b/analysis/tests/src/expected/InlayHint.res.txt @@ -1,4 +1,4 @@ -Inlay Hint tests/src/InlayHint.res 0:6 +Inlay Hint src/InlayHint.res 0:6 [{ "position": {"line": 5, "character": 15}, "label": ": int", @@ -35,4 +35,5 @@ Inlay Hint tests/src/InlayHint.res 0:6 "kind": 1, "paddingLeft": true, "paddingRight": false -}] \ No newline at end of file +}] + From 21338b0825d7a2df3ae19d61f57334c0d37272b4 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 22 Jul 2022 23:06:08 -0300 Subject: [PATCH 39/42] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 356942d0a..cdf9f6f95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ ## master +#### :rocket: New Feature + +- Inlay Hint (experimetal). `rescript.settings.inlayHints.enable: true` ## v1.4.2 #### :bug: Bug Fix From de032db7ff2431524a690cefc95db58fd5298643 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Fri, 22 Jul 2022 23:09:20 -0300 Subject: [PATCH 40/42] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdf9f6f95..5bb7cd495 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ #### :rocket: New Feature -- Inlay Hint (experimetal). `rescript.settings.inlayHints.enable: true` +- Inlay Hints (experimetal). `rescript.settings.inlayHints.enable: true` ## v1.4.2 #### :bug: Bug Fix From dfe05f1ace725acc746e527edabdf7c07a94eb69 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sat, 23 Jul 2022 09:40:57 +0200 Subject: [PATCH 41/42] fix comment --- client/src/extension.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/extension.ts b/client/src/extension.ts index 2a0abef5d..95d3387de 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -235,9 +235,9 @@ export function activate(context: ExtensionContext) { // Start the client. This will also launch the server client.start(); - // Restart the language client automatically certain configuration changes. - // These are typically settings that affect the capabilities of the language - // client, and because of that requires a full restart. + // Restart the language client automatically when certain configuration + // changes. These are typically settings that affect the capabilities of the + // language client, and because of that requires a full restart. context.subscriptions.push( workspace.onDidChangeConfiguration(({ affectsConfiguration }) => { if (affectsConfiguration("rescript.settings.inlayHints")) { From 4df48ae9a1df6ab5f132ae7c67d813cbbaa190a8 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 23 Jul 2022 14:27:22 -0300 Subject: [PATCH 42/42] clarify maxLegth config --- README.md | 2 +- analysis/src/Cli.ml | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 009011390..ed047c0d0 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ This allows an editor to place annotations inline with text to display type hint // Enable (experimental) inlay hints. rescript.settings.inlayHints.enable: true -// Maximum length for inlay hints. Set to null to have an unlimited length. +// Maximum length of character for inlay hints. Set to null to have an unlimited length. Inlay hints that exceed the maximum length will not be shown rescript.settings.inlayHints.maxLength: 25 ``` diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index f07e534a9..9acc01417 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -66,7 +66,7 @@ Options: ./rescript-editor-analysis.exe diagnosticSyntax src/MyFile.res - inlayHint: get all inlay Hint between line 0 and 3 declared in MyFile.res. Last argument is maximum length for inlay hints + inlayHint: get all inlay Hint between line 0 and 3 declared in MyFile.res. Last argument is maximum of character length for inlay hints ./rescript-editor-analysis.exe inlayHint src/MyFile.res 0 3 25 diff --git a/package.json b/package.json index cfc99facf..f24f89a35 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "description": "Enable (experimental) inlay hints." }, "rescript.settings.inlayHints.maxLength": { - "markdownDescription": "Maximum length for inlay hints. Set to null to have an unlimited length.", + "markdownDescription": "Maximum length of character for inlay hints. Set to null to have an unlimited length. Inlay hints that exceed the maximum length will not be shown.", "default": 25, "type": [ "null",