Cannot extend `info.languageService` asynchronously with `createAsyncLanguageServicePlugin`
Opened this issue · 0 comments
Summary
I am developing TypeScript Language Service Plugin with createAsyncLanguageServicePlugin
. I want to extend info.languageService
to add language features. For example, I want to always return the keyword "Hello"
from getCompletionsAtPosition
.
However, when I do that, tsserver doesn't seem to load the extended functionality.
Reproduction
repository: https://github.com/mizdra/repro-volar-setup-with-async-language-service
- Execute
npm i
in the terminal. - Open this repository in VS Code.
- Open
example/index.ts
in the editor. - When "Would you like to use the workspace TypeScript version for TypeScript and JavaScript language features?" prompt appears, select "Allow".
- Press Ctrl+Space on
example/index.ts
and check the completion items
src/index.cjs
:
const { proxyLanguageService } = require('./language-service.cjs');
const { createAsyncLanguageServicePlugin } = require('@volar/typescript/lib/quickstart/createAsyncLanguageServicePlugin.js');
const ts = require('typescript');
module.exports = createAsyncLanguageServicePlugin([], ts.ScriptKind.TS, async (ts, info) => {
if (info.project.projectKind !== ts.server.ProjectKind.Configured) {
return { languagePlugins: [] };
}
return {
languagePlugins: [],
setup: (language) => {
info.languageService = proxyLanguageService(info.languageService);
},
};
});
src/language-service.cjs
:
const ts = require('typescript');
/**
* @param {import('typescript/lib/tsserverlibrary').LanguageService} languageService
* @returns {import('typescript/lib/tsserverlibrary').LanguageService}
*/
exports.proxyLanguageService = function proxyLanguageService(
languageService,
) {
/** @type {import('typescript/lib/tsserverlibrary').LanguageService} */
const proxy = Object.create(null);
for (const k of Object.keys(languageService)) {
// @ts-ignore
const x = (languageService)[k];
// @ts-ignore
proxy[k] = (...args) => x.apply(languageService, args);
}
proxy.getCompletionsAtPosition = (fileName, position, options) => {
const prior = languageService.getCompletionsAtPosition(fileName, position, options) ?? {
isGlobalCompletion: false,
isMemberCompletion: false,
isNewIdentifierLocation: false,
entries: [],
};
prior.entries.push({
name: 'Hello',
kind: ts.ScriptElementKind.keyword,
sortText: '0',
});
return prior;
};
return proxy;
}
Expected behavior
The completion items contain "Hello"
.
Actual behavior
The completion items do not contain "Hello"
.
Additional context
Apparently, extending info.languageService
asynchronously reproduces the problem. If I extend it synchronously as follows, the problem does not reproduce.
--- a/src/index.cjs
+++ b/src/index.cjs
@@ -6,11 +6,11 @@ module.exports = createAsyncLanguageServicePlugin([], ts.ScriptKind.TS, async (t
if (info.project.projectKind !== ts.server.ProjectKind.Configured) {
return { languagePlugins: [] };
}
+ info.languageService = proxyLanguageService(info.languageService);
return {
languagePlugins: [],
setup: (language) => {
- info.languageService = proxyLanguageService(info.languageService);
},
};
});
However, if I insert asynchronous operations as follows, the problem reproduces.
--- a/src/index.cjs
+++ b/src/index.cjs
@@ -1,3 +1,4 @@
+const { setTimeout } = require('node:timers/promises');
const { proxyLanguageService } = require('./language-service.cjs');
const { createAsyncLanguageServicePlugin } = require('@volar/typescript/lib/quickstart/createAsyncLanguageServicePlugin.js');
const ts = require('typescript');
@@ -6,11 +7,12 @@ module.exports = createAsyncLanguageServicePlugin([], ts.ScriptKind.TS, async (t
if (info.project.projectKind !== ts.server.ProjectKind.Configured) {
return { languagePlugins: [] };
}
+ await setTimeout(0);
+ info.languageService = proxyLanguageService(info.languageService);
return {
languagePlugins: [],
setup: (language) => {
- info.languageService = proxyLanguageService(info.languageService);
},
Environment
- VSCode: 1.96.2
- OS: Darwin arm64 24.1.0
- @volar/typescript: 2.4.11
- @volar/language-core: 2.4.11