summaryrefslogtreecommitdiff
path: root/cli/tsc/99_main_compiler.js
diff options
context:
space:
mode:
authorNathan Whitaker <17734409+nathanwhit@users.noreply.github.com>2024-05-09 13:49:10 -0700
committerGitHub <noreply@github.com>2024-05-09 13:49:10 -0700
commit19c0633a947f2ee28cc07b59c32322151779101d (patch)
treeab7983bf954cd109517f80b42bd3199eb27efaa4 /cli/tsc/99_main_compiler.js
parent439b3b8db97106be44bb5fde9573632c20ed4e95 (diff)
refactor(lsp): Have JS drive TSC event loop in LSP (#23565)
Diffstat (limited to 'cli/tsc/99_main_compiler.js')
-rw-r--r--cli/tsc/99_main_compiler.js83
1 files changed, 56 insertions, 27 deletions
diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js
index ddbd77ae0..16e8f1ee9 100644
--- a/cli/tsc/99_main_compiler.js
+++ b/cli/tsc/99_main_compiler.js
@@ -1079,19 +1079,69 @@ delete Object.prototype.__proto__;
/**
* @param {number} _id
* @param {any} data
+ * @param {any | null} error
*/
// TODO(bartlomieju): this feels needlessly generic, both type chcking
// and language server use it with inefficient serialization. Id is not used
// anyway...
- function respond(_id, data = null) {
- ops.op_respond(JSON.stringify(data));
+ function respond(_id, data = null, error = null) {
+ if (error) {
+ ops.op_respond(
+ "error",
+ "stack" in error ? error.stack.toString() : error.toString(),
+ );
+ } else {
+ ops.op_respond(JSON.stringify(data), "");
+ }
+ }
+
+ /** @typedef {[[string, number][], number, boolean] } PendingChange */
+ /**
+ * @template T
+ * @typedef {T | null} Option<T> */
+
+ /** @returns {Promise<[number, string, any[], Option<PendingChange>] | null>} */
+ async function pollRequests() {
+ return await ops.op_poll_requests();
+ }
+
+ let hasStarted = false;
+
+ /** @param {boolean} enableDebugLogging */
+ async function serverMainLoop(enableDebugLogging) {
+ if (hasStarted) {
+ throw new Error("The language server has already been initialized.");
+ }
+ hasStarted = true;
+ languageService = ts.createLanguageService(host, documentRegistry);
+ setLogDebug(enableDebugLogging, "TSLS");
+ debug("serverInit()");
+
+ while (true) {
+ const request = await pollRequests();
+ if (request === null) {
+ break;
+ }
+ try {
+ serverRequest(request[0], request[1], request[2], request[3]);
+ } catch (err) {
+ const reqString = "[" + request.map((v) =>
+ JSON.stringify(v)
+ ).join(", ") + "]";
+ error(
+ `Error occurred processing request ${reqString} : ${
+ "stack" in err ? err.stack : err
+ }`,
+ );
+ }
+ }
}
/**
* @param {number} id
* @param {string} method
* @param {any[]} args
- * @param {[[string, number][], number, boolean] | null} maybeChange
+ * @param {PendingChange | null} maybeChange
*/
function serverRequest(id, method, args, maybeChange) {
if (logDebug) {
@@ -1160,11 +1210,7 @@ delete Object.prototype.__proto__;
if (
!isCancellationError(e)
) {
- if ("stack" in e) {
- error(e.stack);
- } else {
- error(e);
- }
+ respond(id, {}, e);
throw e;
}
return respond(id, {});
@@ -1181,11 +1227,7 @@ delete Object.prototype.__proto__;
return respond(id, languageService[method](...args));
} catch (e) {
if (!isCancellationError(e)) {
- if ("stack" in e) {
- error(e.stack);
- } else {
- error(e);
- }
+ respond(id, null, e);
throw e;
}
return respond(id);
@@ -1198,18 +1240,6 @@ delete Object.prototype.__proto__;
}
}
- let hasStarted = false;
- /** @param {{ debug: boolean; }} init */
- function serverInit({ debug: debugFlag }) {
- if (hasStarted) {
- throw new Error("The language server has already been initialized.");
- }
- hasStarted = true;
- languageService = ts.createLanguageService(host, documentRegistry);
- setLogDebug(debugFlag, "TSLS");
- debug("serverInit()");
- }
-
// A build time only op that provides some setup information that is used to
// ensure the snapshot is setup properly.
/** @type {{ buildSpecifier: string; libs: string[]; nodeBuiltInModuleNames: string[] }} */
@@ -1300,6 +1330,5 @@ delete Object.prototype.__proto__;
// exposes the functions that are called when the compiler is used as a
// language service.
- global.serverInit = serverInit;
- global.serverRequest = serverRequest;
+ global.serverMainLoop = serverMainLoop;
})(this);