From f508796e39e4760198e0d8db1e9cc4b7b01c86c6 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 24 Jul 2022 18:43:23 +0200 Subject: [PATCH 01/10] This sets our language server up to handle the codeLens requests coming from the language client. This just ensures that the server tells the client that sending codeLens requests is fine. Next we'll implement the actual functionality that resolves the code leneses. --- server/src/server.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/server/src/server.ts b/server/src/server.ts index 542d1010b..71e4f3fcb 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -13,6 +13,7 @@ import { DidChangeConfigurationNotification, InitializeParams, InlayHintParams, + CodeLensParams, } from "vscode-languageserver-protocol"; import * as utils from "./utils"; import * as codeActions from "./codeActions"; @@ -411,6 +412,18 @@ function sendInlayHintsRefresh() { send(request); } +function codeLens(msg: p.RequestMessage) { + const params = msg.params as p.CodeLensParams; + const filePath = fileURLToPath(params.textDocument.uri); + + const response = utils.runAnalysisCommand( + filePath, + ["codeLens", filePath], + msg + ); + return response; +} + function definition(msg: p.RequestMessage) { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition let params = msg.params as p.DefinitionParams; @@ -1001,6 +1014,9 @@ function onMessage(msg: p.Message) { full: true, }, inlayHintProvider: extensionConfiguration.inlayHints.enable, + codeLensProvider: { + workDoneProgress: false + }, }, }; let response: p.ResponseMessage = { @@ -1086,6 +1102,12 @@ function onMessage(msg: p.Message) { if (extName === c.resExt) { send(inlayHint(msg)); } + } else if (msg.method === p.CodeLensRequest.method) { + let params = msg.params as CodeLensParams; + let extName = path.extname(params.textDocument.uri); + if (extName === c.resExt) { + send(codeLens(msg)); + } } else { let response: p.ResponseMessage = { jsonrpc: c.jsonrpcVersion, From 005388a8a8b1fd0a8010a4fbd57c1580d8612a8b Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 24 Jul 2022 21:39:55 +0200 Subject: [PATCH 02/10] Allow setting line width when printing types. Will use to nudge the printer towards printing function types for code lenses on one line --- analysis/src/PrintType.ml | 4 ++-- analysis/src/Shared.ml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/analysis/src/PrintType.ml b/analysis/src/PrintType.ml index b146430fb..3da8293c0 100644 --- a/analysis/src/PrintType.ml +++ b/analysis/src/PrintType.ml @@ -1,6 +1,6 @@ -let printExpr typ = +let printExpr ?(lineWidth = 60) typ = Printtyp.reset_names (); - Res_doc.toString ~width:60 + Res_doc.toString ~width:lineWidth (Res_outcome_printer.printOutTypeDoc (Printtyp.tree_of_typexp false typ)) let printDecl ~recStatus name decl = diff --git a/analysis/src/Shared.ml b/analysis/src/Shared.ml index 21b84a125..a44ca111b 100644 --- a/analysis/src/Shared.ml +++ b/analysis/src/Shared.ml @@ -49,12 +49,12 @@ let declToString ?(recStatus = Types.Trec_not) name t = let cacheTypeToString = ref false let typeTbl = Hashtbl.create 1 -let typeToString (t : Types.type_expr) = +let typeToString ?(lineWidth = 60) (t : Types.type_expr) = match if !cacheTypeToString then Hashtbl.find_opt typeTbl (t.id, t) else None with | None -> - let s = PrintType.printExpr t in + let s = PrintType.printExpr ~lineWidth t in Hashtbl.replace typeTbl (t.id, t) s; s | Some s -> s From 564f905077a7e236144ae349698fd8e1fe5dec43 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 24 Jul 2022 21:43:33 +0200 Subject: [PATCH 03/10] Add needed LSP protocol types for code lenses. --- analysis/src/Protocol.ml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index 6838a29ca..87dda6b05 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -1,6 +1,8 @@ type position = {line: int; character: int} type range = {start: position; end_: position} type markupContent = {kind: string; value: string} +type command = {title: string; command: string} +type codeLens = {range: range; command: command option} type inlayHint = { position: position; label: string; @@ -147,6 +149,26 @@ let stringifyHint hint = (stringifyPosition hint.position) (Json.escape hint.label) hint.kind hint.paddingLeft hint.paddingRight +let stringifyCommand (command : command) = + Printf.sprintf + {|{ + "title": "%s", + "command": "%s" + }|} + (Json.escape command.title) + (Json.escape command.command) + +let stringifyCodeLens (codeLens : codeLens) = + Printf.sprintf + {|{ + "range": %s, + "command": %s + }|} + (stringifyRange codeLens.range) + (match codeLens.command with + | None -> "" + | Some command -> stringifyCommand command) + (* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnostic *) let stringifyDiagnostic d = Printf.sprintf From d64ed9a3b9aeab65b4faad6e345443afae16783f Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 24 Jul 2022 21:51:16 +0200 Subject: [PATCH 04/10] Implement emitting code lenses for functions. --- analysis/src/Cli.ml | 8 +++++- analysis/src/Commands.ml | 7 +++++ analysis/src/Hint.ml | 56 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/analysis/src/Cli.ml b/analysis/src/Cli.ml index 9acc01417..90b82b1c8 100644 --- a/analysis/src/Cli.ml +++ b/analysis/src/Cli.ml @@ -11,7 +11,8 @@ 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 0 3 25 + ./rescript-editor-analysis.exe inlayHint src/MyFile.res 0 3 25 + ./rescript-editor-analysis.exe codeLens src/MyFile.res Dev-time examples: ./rescript-editor-analysis.exe dump src/MyFile.res src/MyFile2.res @@ -70,6 +71,10 @@ Options: ./rescript-editor-analysis.exe inlayHint src/MyFile.res 0 3 25 + codeLens: get all code lens entries for file src/MyFile.res + + ./rescript-editor-analysis.exe codeLens src/MyFile.res + test: run tests specified by special comments in file src/MyFile.res ./rescript-editor-analysis.exe test src/src/MyFile.res @@ -98,6 +103,7 @@ let main () = Commands.inlayhint ~path ~pos:(int_of_string line_start, int_of_string line_end) ~maxLength ~debug:false + | [_; "codeLens"; path] -> Commands.codeLens ~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 3dd16c468..552cdc996 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -32,6 +32,10 @@ let inlayhint ~path ~pos ~maxLength ~debug = let result = Hint.inlay ~path ~pos ~maxLength ~debug |> Protocol.array in print_endline result +let codeLens ~path ~debug = + let result = Hint.codeLens ~path ~debug |> Protocol.array in + print_endline result + let hover ~path ~pos ~currentFile ~debug = let result = match Cmt.fullFromPath ~path with @@ -391,6 +395,9 @@ let test ~path = 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) + | "clens" -> + print_endline ("Code Lens " ^ path); + codeLens ~path ~debug:false | _ -> ()); print_newline ()) in diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index c3d8a9682..788ad5005 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -119,4 +119,58 @@ let inlay ~path ~pos ~maxLength ~debug = | Some value -> if String.length label > value then None else Some result | None -> Some result) - | None -> None))) \ No newline at end of file + | None -> None))) + +let codeLens ~path ~debug = + let lenses = ref [] in + let push loc = + let range = Utils.cmtLocToRange loc in + lenses := range :: !lenses + in + (* Code lenses are only emitted for functions right now. So look for value bindings that are functions, + and use the loc of the value binding itself so we can look up the full function type for our code lens. *) + let value_binding (iterator : Ast_iterator.iterator) + (vb : Parsetree.value_binding) = + (match vb with + | { + pvb_pat = {ppat_desc = Ppat_var _; ppat_loc}; + pvb_expr = {pexp_desc = Pexp_fun _}; + } -> + push ppat_loc + | _ -> ()); + Ast_iterator.default_iterator.value_binding iterator vb + 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 + in + let {Res_driver.parsetree = structure} = parser ~filename:path in + iterator.structure iterator structure |> ignore); + !lenses + |> List.filter_map (fun (range : Protocol.range) -> + match Cmt.fullFromPath ~path with + | None -> None + | Some full -> ( + match + References.getLocItem ~full + ~pos:(range.start.line, range.start.character + 1) + ~debug + with + | Some {locType = Typed (_, typeExpr, _)} -> + Some + (Protocol.stringifyCodeLens + { + range; + command = + Some + { + (* Code lenses can run commands. An empty command string means we just want the editor + to print the text, not link to running a command. *) + command = ""; + (* Print the type with a huge line width, because the code lens always prints on a + single line in the editor. *) + title = typeExpr |> Shared.typeToString ~lineWidth:400; + }; + }) + | _ -> None)) From c79a8f9506ac84e36f5a93d902db0dcaaca14d59 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 24 Jul 2022 21:59:52 +0200 Subject: [PATCH 05/10] Add tests for code lenses. --- analysis/src/Commands.ml | 2 +- analysis/src/Protocol.ml | 6 +----- analysis/tests/src/CodeLens.res | 11 +++++++++++ analysis/tests/src/expected/CodeLens.res.txt | 15 +++++++++++++++ analysis/tests/src/expected/Dce.res.txt | 2 +- analysis/tests/src/expected/Debug.res.txt | 3 ++- 6 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 analysis/tests/src/CodeLens.res create mode 100644 analysis/tests/src/expected/CodeLens.res.txt diff --git a/analysis/src/Commands.ml b/analysis/src/Commands.ml index 552cdc996..ad9ad4a89 100644 --- a/analysis/src/Commands.ml +++ b/analysis/src/Commands.ml @@ -395,7 +395,7 @@ let test ~path = 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) - | "clens" -> + | "cle" -> print_endline ("Code Lens " ^ path); codeLens ~path ~debug:false | _ -> ()); diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index 87dda6b05..5247a487d 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -150,11 +150,7 @@ let stringifyHint hint = (Json.escape hint.label) hint.kind hint.paddingLeft hint.paddingRight let stringifyCommand (command : command) = - Printf.sprintf - {|{ - "title": "%s", - "command": "%s" - }|} + Printf.sprintf {|{"title": "%s", "command": "%s"}|} (Json.escape command.title) (Json.escape command.command) diff --git a/analysis/tests/src/CodeLens.res b/analysis/tests/src/CodeLens.res new file mode 100644 index 000000000..a63bed6df --- /dev/null +++ b/analysis/tests/src/CodeLens.res @@ -0,0 +1,11 @@ +let add = (x, y) => x + y + +let foo = (~age, ~name) => name ++ string_of_int(age) + +let ff = (~opt1=0, ~a, ~b, (), ~opt2=0, (), ~c) => a + b + c + opt1 + opt2 + +let compFF = Completion.ff + +@react.component +let make = (~name) => React.string(name) +//^cle diff --git a/analysis/tests/src/expected/CodeLens.res.txt b/analysis/tests/src/expected/CodeLens.res.txt new file mode 100644 index 000000000..06472d5e4 --- /dev/null +++ b/analysis/tests/src/expected/CodeLens.res.txt @@ -0,0 +1,15 @@ +Code Lens src/CodeLens.res +[{ + "range": {"start": {"line": 9, "character": 4}, "end": {"line": 9, "character": 8}}, + "command": {"title": "{\"name\": string} => React.element", "command": ""} + }, { + "range": {"start": {"line": 4, "character": 4}, "end": {"line": 4, "character": 6}}, + "command": {"title": "(~opt1: int=?, ~a: int, ~b: int, unit, ~opt2: int=?, unit, ~c: int) => int", "command": ""} + }, { + "range": {"start": {"line": 2, "character": 4}, "end": {"line": 2, "character": 7}}, + "command": {"title": "(~age: int, ~name: string) => string", "command": ""} + }, { + "range": {"start": {"line": 0, "character": 4}, "end": {"line": 0, "character": 7}}, + "command": {"title": "(int, int) => int", "command": ""} + }] + diff --git a/analysis/tests/src/expected/Dce.res.txt b/analysis/tests/src/expected/Dce.res.txt index 441bb5807..9e47ef48c 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:243 +issues:249 diff --git a/analysis/tests/src/expected/Debug.res.txt b/analysis/tests/src/expected/Debug.res.txt index ff23fe834..a95597eae 100644 --- a/analysis/tests/src/expected/Debug.res.txt +++ b/analysis/tests/src/expected/Debug.res.txt @@ -4,8 +4,9 @@ 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/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 +Source files: ./src/Auto.res ./src/CodeLens.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/CodeLens.cmt res:./src/CodeLens.res Impl cmt:./lib/bs/src/CompletePrioritize1.cmt res:./src/CompletePrioritize1.res Impl cmt:./lib/bs/src/CompletePrioritize2.cmt res:./src/CompletePrioritize2.res Impl cmt:./lib/bs/src/Completion.cmt res:./src/Completion.res From 47cf51beb503300e210b4d7ea9e7b01a16f50b00 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 24 Jul 2022 22:06:25 +0200 Subject: [PATCH 06/10] Hide code lens functionality behind a setting. --- client/src/extension.ts | 5 ++++- package.json | 5 +++++ server/src/server.ts | 22 +++++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/client/src/extension.ts b/client/src/extension.ts index 95d3387de..9e9cf89fd 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -240,7 +240,10 @@ export function activate(context: ExtensionContext) { // language client, and because of that requires a full restart. context.subscriptions.push( workspace.onDidChangeConfiguration(({ affectsConfiguration }) => { - if (affectsConfiguration("rescript.settings.inlayHints")) { + if ( + affectsConfiguration("rescript.settings.inlayHints") || + affectsConfiguration("rescript.settings.codeLens") + ) { commands.executeCommand("rescript-vscode.restart_language_server"); } }) diff --git a/package.json b/package.json index f24f89a35..181499112 100644 --- a/package.json +++ b/package.json @@ -146,6 +146,11 @@ ], "minimum": 0 }, + "rescript.settings.codeLens.enable": { + "type": "boolean", + "default": false, + "description": "Enable (experimental) code lens for function definitions." + }, "rescript.settings.binaryPath": { "type": ["string", "null"], "default": null, diff --git a/server/src/server.ts b/server/src/server.ts index 71e4f3fcb..316996807 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -31,6 +31,7 @@ interface extensionConfiguration { enable: boolean; maxLength: number | null; }; + codeLens: boolean; binaryPath: string | null; } let extensionConfiguration: extensionConfiguration = { @@ -39,6 +40,7 @@ let extensionConfiguration: extensionConfiguration = { enable: false, maxLength: 25 }, + codeLens: false, binaryPath: null, }; let pullConfigurationPeriodically: NodeJS.Timeout | null = null; @@ -230,6 +232,9 @@ let compilerLogsWatcher = chokidar if (extensionConfiguration.inlayHints.enable === true) { sendInlayHintsRefresh(); } + if (extensionConfiguration.codeLens === true) { + sendCodeLensRefresh(); + } }); let stopWatchingCompilerLog = () => { // TODO: cleanup of compilerLogs? @@ -424,6 +429,15 @@ function codeLens(msg: p.RequestMessage) { return response; } +function sendCodeLensRefresh() { + let request: p.RequestMessage = { + jsonrpc: c.jsonrpcVersion, + method: p.CodeLensRefreshRequest.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; @@ -1014,9 +1028,11 @@ function onMessage(msg: p.Message) { full: true, }, inlayHintProvider: extensionConfiguration.inlayHints.enable, - codeLensProvider: { - workDoneProgress: false - }, + codeLensProvider: extensionConfiguration.codeLens + ? { + workDoneProgress: false, + } + : undefined, }, }; let response: p.ResponseMessage = { From 124643453c252766febd954fcad26fb94b99b808 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Sun, 24 Jul 2022 22:07:16 +0200 Subject: [PATCH 07/10] Readme + changelog for code lenses. --- CHANGELOG.md | 2 ++ README.md | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bb7cd495..33c350334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ #### :rocket: New Feature - Inlay Hints (experimetal). `rescript.settings.inlayHints.enable: true` +- Code Lenses for functions (experimetal). `rescript.settings.codeLens: true` + ## v1.4.2 #### :bug: Bug Fix diff --git a/README.md b/README.md index ed047c0d0..c432d7d2f 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,15 @@ rescript.settings.inlayHints.enable: true rescript.settings.inlayHints.maxLength: 25 ``` +### Code Lens (experimental) + +This tells the editor to add code lenses to function definitions, showing its full type as an annotation above the definition. + +```jsonc +// Enable (experimental) code lens. +rescript.settings.codeLens: true +``` + ### 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 e81288bd12393e2284795368be940b7d38b5254e Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 25 Jul 2022 09:22:05 +0200 Subject: [PATCH 08/10] Clarify readme and changelog. --- CHANGELOG.md | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33c350334..f227d4717 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,8 +14,8 @@ #### :rocket: New Feature -- Inlay Hints (experimetal). `rescript.settings.inlayHints.enable: true` -- Code Lenses for functions (experimetal). `rescript.settings.codeLens: true` +- Inlay Hints (experimetal). `rescript.settings.inlayHints.enable: true`. Turned off by default. +- Code Lenses for functions (experimetal). `rescript.settings.codeLens: true`. Turned off by default. ## v1.4.2 diff --git a/README.md b/README.md index c432d7d2f..d51428d8a 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ rescript.settings.inlayHints.maxLength: 25 ### Code Lens (experimental) -This tells the editor to add code lenses to function definitions, showing its full type as an annotation above the definition. +This tells the editor to add code lenses to function definitions, showing its full type above the definition. ```jsonc // Enable (experimental) code lens. From 8d76d6fb4bf5308abdb019ca58819ec428d04318 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 25 Jul 2022 09:22:36 +0200 Subject: [PATCH 09/10] Remove redundant default value. --- analysis/src/Shared.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/analysis/src/Shared.ml b/analysis/src/Shared.ml index a44ca111b..467238629 100644 --- a/analysis/src/Shared.ml +++ b/analysis/src/Shared.ml @@ -49,12 +49,12 @@ let declToString ?(recStatus = Types.Trec_not) name t = let cacheTypeToString = ref false let typeTbl = Hashtbl.create 1 -let typeToString ?(lineWidth = 60) (t : Types.type_expr) = +let typeToString ?lineWidth (t : Types.type_expr) = match if !cacheTypeToString then Hashtbl.find_opt typeTbl (t.id, t) else None with | None -> - let s = PrintType.printExpr ~lineWidth t in + let s = PrintType.printExpr ?lineWidth t in Hashtbl.replace typeTbl (t.id, t) s; s | Some s -> s From 980beeb85f7b10975e055b75d2aca08415719e4c Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 25 Jul 2022 09:22:57 +0200 Subject: [PATCH 10/10] Add clarifying comments. --- analysis/src/Hint.ml | 2 ++ analysis/src/Protocol.ml | 5 +++++ client/src/extension.ts | 5 +++++ server/src/server.ts | 3 +++ 4 files changed, 15 insertions(+) diff --git a/analysis/src/Hint.ml b/analysis/src/Hint.ml index 788ad5005..0f90ff8ea 100644 --- a/analysis/src/Hint.ml +++ b/analysis/src/Hint.ml @@ -141,6 +141,8 @@ let codeLens ~path ~debug = Ast_iterator.default_iterator.value_binding iterator vb in let iterator = {Ast_iterator.default_iterator with value_binding} in + (* We only print code lenses in implementation files. This is because they'd be redundant in interface files, + where the definition itself will be the same thing as what would've been printed in the code lens. *) (if Filename.check_suffix path ".res" then let parser = Res_driver.parsingEngine.parseImplementation ~forPrinter:false diff --git a/analysis/src/Protocol.ml b/analysis/src/Protocol.ml index 5247a487d..a1440aa85 100644 --- a/analysis/src/Protocol.ml +++ b/analysis/src/Protocol.ml @@ -1,8 +1,13 @@ type position = {line: int; character: int} type range = {start: position; end_: position} type markupContent = {kind: string; value: string} + +(* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#command *) type command = {title: string; command: string} + +(* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#codeLens *) type codeLens = {range: range; command: command option} + type inlayHint = { position: position; label: string; diff --git a/client/src/extension.ts b/client/src/extension.ts index 9e9cf89fd..7bd85b918 100644 --- a/client/src/extension.ts +++ b/client/src/extension.ts @@ -240,6 +240,11 @@ export function activate(context: ExtensionContext) { // language client, and because of that requires a full restart. context.subscriptions.push( workspace.onDidChangeConfiguration(({ affectsConfiguration }) => { + // Put any configuration that, when changed, requires a full restart of + // the server here. That will typically be any configuration that affects + // the capabilities declared by the server, since those cannot be updated + // on the fly, and require a full restart with new capabilities set when + // initializing. if ( affectsConfiguration("rescript.settings.inlayHints") || affectsConfiguration("rescript.settings.codeLens") diff --git a/server/src/server.ts b/server/src/server.ts index 316996807..072195bf4 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -34,6 +34,9 @@ interface extensionConfiguration { codeLens: boolean; binaryPath: string | null; } + +// All values here are temporary, and will be overridden as the server is +// initialized, and the current config is received from the client. let extensionConfiguration: extensionConfiguration = { askToStartBuild: true, inlayHints: {