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/incrementalCompilation.ts b/server/src/incrementalCompilation.ts index 576e87cec..0edd8d503 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,9 +469,10 @@ 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); + }, 0); if (entry.compilation != null) { entry.compilation.timeout = timeout; @@ -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..4524f8f69 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -673,13 +673,22 @@ 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" }); + + if (config.extensionConfiguration.newCompletion) { + await new Promise((resolve) => { + ic.triggerIncrementalCompilationOfFile(filePath, code, send, () => { + resolve(); + }); + }); + } + let response = utils.runAnalysisCommand( filePath, [ @@ -1235,7 +1244,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) { 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, }, };