From 0210fd274c09c236816f2e2a5b5ad4e4f3bb6848 Mon Sep 17 00:00:00 2001 From: nojaf Date: Mon, 6 Jan 2025 21:21:00 +0100 Subject: [PATCH 1/4] Initial SendLogNotification --- package.json | 6 ++++ server/src/config.ts | 2 ++ server/src/server.ts | 65 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 3c81516cd..515cc5a02 100644 --- a/package.json +++ b/package.json @@ -212,6 +212,12 @@ ], "default": null, "description": "Path to the directory where platform-specific ReScript binaries are. You can use it if you haven't or don't want to use the installed ReScript from node_modules in your project." + }, + "rescript.settings.logLevel": { + "type": "string", + "enum": ["error", "warning", "info", "log"], + "default": "info", + "description": "Controls the log level of the language server. Logs below this level will be filtered out." } } }, diff --git a/server/src/config.ts b/server/src/config.ts index ef8e4c773..bb59e38c6 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -26,6 +26,7 @@ export interface extensionConfiguration { enable?: boolean; }; }; + logLevel: "error" | "warning" | "info" | "log" } // All values here are temporary, and will be overridden as the server is @@ -55,6 +56,7 @@ let config: { extensionConfiguration: extensionConfiguration } = { enable: true, }, }, + logLevel: "info" }, }; diff --git a/server/src/server.ts b/server/src/server.ts index f41c13219..860a8a3b3 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -28,6 +28,38 @@ import * as ic from "./incrementalCompilation"; import config, { extensionConfiguration } from "./config"; import { projectsFiles } from "./projectFiles"; +const notificationLevelMap = new Map([ + ["error", p.MessageType.Error], + ["warning", p.MessageType.Warning], + ["info", p.MessageType.Info], + ["log", p.MessageType.Log] +]) + +/** + * Sends an LSP log notification that will appear in the ReScript Language Server Output window in VSCode. + * Other LSP clients will also receive this notification, + * as we utilize LanguageClient in the VSCode extension, providing this functionality at no extra cost. + */ +function sendLogNotification(level: p.MessageType, message: string) { + const currentLogLevel = notificationLevelMap.get(config.extensionConfiguration.logLevel) || p.MessageType.Info; + + if (currentLogLevel >= level) { + const logMessageParams: p.LogMessageParams = { + type: level, + message + } + const notificationMessage: p.NotificationMessage = { + method: "window/logMessage", + jsonrpc: c.jsonrpcVersion, + params: logMessageParams + } + + if (send) { + send(notificationMessage); + } + } +} + // This holds client capabilities specific to our extension, and not necessarily // related to the LS protocol. It's for enabling/disabling features that might // work in one client, like VSCode, but perhaps not in others, like vim. @@ -55,18 +87,18 @@ let stupidFileContentCache: Map = new 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 findRescriptBinary = (projectRootPath: p.DocumentUri | null) => config.extensionConfiguration.binaryPath == null ? lookup.findFilePathFromProjectRoot( - projectRootPath, - path.join(c.nodeModulesBinDir, c.rescriptBinName) - ) + projectRootPath, + path.join(c.nodeModulesBinDir, c.rescriptBinName) + ) : utils.findBinary( - config.extensionConfiguration.binaryPath, - c.rescriptBinName - ); + config.extensionConfiguration.binaryPath, + c.rescriptBinName + ); let createInterfaceRequest = new v.RequestType< p.TextDocumentIdentifier, @@ -333,9 +365,9 @@ let openedFile = (fileUri: string, fileContent: string) => { message: config.extensionConfiguration.binaryPath == null ? `Can't find ReScript binary in ${path.join( - projectRootPath, - c.nodeModulesBinDir - )} or parent directories. Did you install it? It's required to use "rescript" > 9.1` + projectRootPath, + c.nodeModulesBinDir + )} or parent directories. Did you install it? It's required to use "rescript" > 9.1` : `Can't find ReScript binary in the directory ${config.extensionConfiguration.binaryPath}`, }, }; @@ -419,6 +451,7 @@ export default function listen(useStdio = false) { send = (msg: p.Message) => process.send!(msg); process.on("message", onMessage); } + utils.setSendLogNotification(sendLogNotification); } function hover(msg: p.RequestMessage) { @@ -1183,15 +1216,15 @@ function onMessage(msg: p.Message) { inlayHintProvider: config.extensionConfiguration.inlayHints?.enable, codeLensProvider: config.extensionConfiguration.codeLens ? { - workDoneProgress: false, - } + workDoneProgress: false, + } : undefined, signatureHelpProvider: config.extensionConfiguration.signatureHelp ?.enabled ? { - triggerCharacters: ["("], - retriggerCharacters: ["=", ","], - } + triggerCharacters: ["("], + retriggerCharacters: ["=", ","], + } : undefined, }, }; @@ -1202,6 +1235,8 @@ function onMessage(msg: p.Message) { }; initialized = true; + sendLogNotification(p.MessageType.Info, `LSP Server started!`) + // Periodically pull configuration from the client. pullConfigurationPeriodically = setInterval(() => { askForAllCurrentConfiguration(); From 190243ec9be2b100db102202e3206331cfdbd396 Mon Sep 17 00:00:00 2001 From: nojaf Date: Mon, 6 Jan 2025 21:22:09 +0100 Subject: [PATCH 2/4] Log completion analysis invocations --- server/src/utils.ts | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/server/src/utils.ts b/server/src/utils.ts index 6f386cc83..1ba73bab4 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -16,6 +16,13 @@ import { reportError } from "./errorReporter"; import config from "./config"; import { filesDiagnostics, projectsFiles } from "./projectFiles"; +// This is a bit dirty but avoids passing down this function each time. +export type SendLogNotification = (level: p.MessageType, message: string) => void +let sendLogNotification: SendLogNotification = () => { }; +export function setSendLogNotification(send: SendLogNotification) { + sendLogNotification = send; +} + let tempFilePrefix = "rescript_format_file_" + process.pid + "_"; let tempFileId = 0; @@ -92,19 +99,19 @@ export let findBinary = ( type execResult = | { - kind: "success"; - result: string; - } + kind: "success"; + result: string; + } | { - kind: "error"; - error: string; - }; + kind: "error"; + error: string; + }; type formatCodeResult = | execResult | { - kind: "blocked-using-built-in-formatter"; - }; + kind: "blocked-using-built-in-formatter"; + }; export let formatCode = ( bscPath: p.DocumentUri | null, @@ -265,6 +272,9 @@ export let runAnalysisAfterSanityCheck = ( let stdout = ""; try { + if(args.includes("completion")){ + sendLogNotification(p.MessageType.Log, `Running completion: ${binaryPath} ${args.join(" ")}`); + } stdout = childProcess.execFileSync(binaryPath, args, options).toString(); return JSON.parse(stdout); } catch (e) { @@ -693,7 +703,7 @@ export let parseCompilerLogOutput = ( diagnostic, diagnosticMessage, file, - range, + range }); result[file].push(diagnostic); From 61c08f859fe3ddb1a2b093bcf5d4605ce404cd1e Mon Sep 17 00:00:00 2001 From: nojaf Date: Mon, 6 Jan 2025 21:30:29 +0100 Subject: [PATCH 3/4] Include ReScript version --- server/src/server.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/src/server.ts b/server/src/server.ts index 860a8a3b3..3e418ef8e 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1235,7 +1235,11 @@ function onMessage(msg: p.Message) { }; initialized = true; - sendLogNotification(p.MessageType.Info, `LSP Server started!`) + let rescriptVersion = undefined; + if (initParams.workspaceFolders && initParams.workspaceFolders.length > 0) { + rescriptVersion = utils.findReScriptVersion(initParams.workspaceFolders[0].uri); + } + sendLogNotification(p.MessageType.Info, `LSP Server started! Rescript Version ${rescriptVersion}`); // Periodically pull configuration from the client. pullConfigurationPeriodically = setInterval(() => { From 177b028f2ac8b1f817f8d1a240c5cf6c8fe955f0 Mon Sep 17 00:00:00 2001 From: nojaf Date: Mon, 6 Jan 2025 21:36:29 +0100 Subject: [PATCH 4/4] Add setting to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index a46aa1cc5..cf243eab9 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,7 @@ You'll find all ReScript specific settings under the scope `rescript.settings`. | Inlay Hints (experimental) | This allows an editor to place annotations inline with text to display type hints. Enable using `rescript.settings.inlayHints.enable: true` | | Code Lens (experimental) | This tells the editor to add code lenses to function definitions, showing its full type above the definition. Enable using `rescript.settings.codeLens: true` | | Signature Help | This tells the editor to show signature help when you're writing function calls. Enable using `rescript.settings.signatureHelp.enabled: true` | +| Log level | This tells the editor which log messages to show in the Output window. The options are `"error"`, `"warning"`, `"info"`, `"log"` with default `"info"`. Set via `"rescript.settings.logLevel"`. | **Default settings:** @@ -126,6 +127,9 @@ You'll find all ReScript specific settings under the scope `rescript.settings`. // Enable (experimental) code lens for function definitions. "rescript.settings.codeLens": true + +// Set log level ("error", "warning", "info", "log"). +"rescript.settings.logLevel": "info" ``` ## 🚀 Code Analyzer