From e3deea5dcff7579551b921f12fb4e01ed8da2b0a Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Fri, 4 Apr 2025 09:26:33 +0200 Subject: [PATCH 1/3] wait for incremental compilation before doing completions --- server/src/incrementalCompilation.ts | 4 +++- server/src/server.ts | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/server/src/incrementalCompilation.ts b/server/src/incrementalCompilation.ts index 576e87cec..babcc667f 100644 --- a/server/src/incrementalCompilation.ts +++ b/server/src/incrementalCompilation.ts @@ -370,7 +370,7 @@ function removeAnsiCodes(s: string): string { const ansiEscape = /\x1B[@-_][0-?]*[ -/]*[@-~]/g; return s.replace(ansiEscape, ""); } -function triggerIncrementalCompilationOfFile( +export function triggerIncrementalCompilationOfFile( filePath: string, fileContent: string, send: send, @@ -469,6 +469,7 @@ function triggerIncrementalCompilationOfFile( entry.killCompilationListeners = []; } const triggerToken = performance.now(); + // TODO: Can we remove this timeout? Don't remember why it was added... const timeout = setTimeout(() => { compileContents(entry, fileContent, send, onCompilationFinished); }, 20); @@ -727,6 +728,7 @@ async function compileContents( } } +// TODO(compilation-revamp) make sure we don't unecessarily trigger incremental compilations export function handleUpdateOpenedFile( filePath: string, fileContent: string, diff --git a/server/src/server.ts b/server/src/server.ts index 1c74132e7..4f4024705 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -673,13 +673,18 @@ function semanticTokens(msg: p.RequestMessage) { return response; } -function completion(msg: p.RequestMessage) { +async function completion(msg: p.RequestMessage) { // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion let params = msg.params as p.ReferenceParams; let filePath = fileURLToPath(params.textDocument.uri); let code = getOpenedFileContent(params.textDocument.uri); let tmpname = utils.createFileInTempDir(); fs.writeFileSync(tmpname, code, { encoding: "utf-8" }); + await new Promise((resolve) => { + ic.triggerIncrementalCompilationOfFile(filePath, code, send, () => { + resolve(); + }); + }); let response = utils.runAnalysisCommand( filePath, [ @@ -1235,7 +1240,7 @@ function onMessage(msg: p.Message) { } else if (msg.method === p.DocumentSymbolRequest.method) { send(documentSymbol(msg)); } else if (msg.method === p.CompletionRequest.method) { - send(completion(msg)); + completion(msg).then(send); } else if (msg.method === p.CompletionResolveRequest.method) { send(completionResolve(msg)); } else if (msg.method === p.SemanticTokensRequest.method) { From 5c2761d180aa096dc4fd6c51529d1fca69850a0e Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Fri, 4 Apr 2025 09:30:43 +0200 Subject: [PATCH 2/3] set timeout to 0 just for the sake of it --- server/src/incrementalCompilation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/incrementalCompilation.ts b/server/src/incrementalCompilation.ts index babcc667f..0edd8d503 100644 --- a/server/src/incrementalCompilation.ts +++ b/server/src/incrementalCompilation.ts @@ -472,7 +472,7 @@ export function triggerIncrementalCompilationOfFile( // TODO: Can we remove this timeout? Don't remember why it was added... const timeout = setTimeout(() => { compileContents(entry, fileContent, send, onCompilationFinished); - }, 20); + }, 0); if (entry.compilation != null) { entry.compilation.timeout = timeout; From 47d7aaf7d9e45ae459f485e7c544bb96320a2d63 Mon Sep 17 00:00:00 2001 From: Gabriel Nordeborn Date: Mon, 28 Apr 2025 08:37:24 +0200 Subject: [PATCH 3/3] make the new completion mode dependent on a setting --- package.json | 5 +++++ server/src/config.ts | 2 ++ server/src/server.ts | 12 ++++++++---- server/src/utils.ts | 4 ++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 5f9ae3e91..18a0a7233 100644 --- a/package.json +++ b/package.json @@ -206,6 +206,11 @@ ], "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.newCompletion": { + "type": "boolean", + "default": false, + "description": "(experimental) Enable new completion engine" } } }, diff --git a/server/src/config.ts b/server/src/config.ts index e8055e379..3472c8c92 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -11,6 +11,7 @@ export interface extensionConfiguration { codeLens?: boolean; binaryPath?: string | null; platformPath?: string | null; + newCompletion?: boolean; signatureHelp?: { enabled?: boolean; forConstructorPayloads?: boolean; @@ -39,6 +40,7 @@ let config: { extensionConfiguration: extensionConfiguration } = { codeLens: false, binaryPath: null, platformPath: null, + newCompletion: false, signatureHelp: { enabled: true, forConstructorPayloads: true, diff --git a/server/src/server.ts b/server/src/server.ts index 4f4024705..4524f8f69 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -680,11 +680,15 @@ async function completion(msg: p.RequestMessage) { let code = getOpenedFileContent(params.textDocument.uri); let tmpname = utils.createFileInTempDir(); fs.writeFileSync(tmpname, code, { encoding: "utf-8" }); - await new Promise((resolve) => { - ic.triggerIncrementalCompilationOfFile(filePath, code, send, () => { - resolve(); + + if (config.extensionConfiguration.newCompletion) { + await new Promise((resolve) => { + ic.triggerIncrementalCompilationOfFile(filePath, code, send, () => { + resolve(); + }); }); - }); + } + let response = utils.runAnalysisCommand( filePath, [ diff --git a/server/src/utils.ts b/server/src/utils.ts index 5de85abfc..2c7ac3751 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -229,6 +229,10 @@ export let runAnalysisAfterSanityCheck = ( config.extensionConfiguration.cache?.projectConfig?.enable === true ? "true" : undefined, + RESCRIPT_NEW_ANALYSIS_ENGINE: + config.extensionConfiguration.newCompletion === true + ? "true" + : undefined, }, };