monaco-languageclient 10.6.0 → 11.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +19 -4
  2. package/LICENSE +0 -0
  3. package/README.md +63 -63
  4. package/lib/common/commonTypes.d.ts +1 -1
  5. package/lib/common/commonTypes.d.ts.map +1 -1
  6. package/lib/common/utils.d.ts.map +1 -1
  7. package/lib/common/utils.js +2 -2
  8. package/lib/common/utils.js.map +1 -1
  9. package/lib/debugger/index.d.ts +1 -1
  10. package/lib/debugger/index.d.ts.map +1 -1
  11. package/lib/debugger/index.js +2 -4
  12. package/lib/debugger/index.js.map +1 -1
  13. package/lib/editorApp/config.d.ts +11 -11
  14. package/lib/editorApp/config.d.ts.map +1 -1
  15. package/lib/editorApp/config.js +0 -1
  16. package/lib/editorApp/config.js.map +1 -1
  17. package/lib/editorApp/editorApp.d.ts +5 -5
  18. package/lib/editorApp/editorApp.d.ts.map +1 -1
  19. package/lib/editorApp/editorApp.js +21 -23
  20. package/lib/editorApp/editorApp.js.map +1 -1
  21. package/lib/fs/definitions.d.ts.map +1 -1
  22. package/lib/fs/endpoints/defaultEndpoint.d.ts.map +1 -1
  23. package/lib/fs/endpoints/defaultEndpoint.js.map +1 -1
  24. package/lib/index.d.ts +1 -1
  25. package/lib/index.d.ts.map +1 -1
  26. package/lib/index.js +1 -1
  27. package/lib/index.js.map +1 -1
  28. package/lib/vscode/apiWrapper.d.ts +2 -2
  29. package/lib/vscode/apiWrapper.d.ts.map +1 -1
  30. package/lib/vscode/apiWrapper.js +19 -22
  31. package/lib/vscode/apiWrapper.js.map +1 -1
  32. package/lib/vscode/config.d.ts +4 -4
  33. package/lib/vscode/config.d.ts.map +1 -1
  34. package/lib/vscode/config.js +0 -1
  35. package/lib/vscode/config.js.map +1 -1
  36. package/lib/vscode/locales.d.ts +1 -1
  37. package/lib/vscode/locales.d.ts.map +1 -1
  38. package/lib/vscode/locales.js +35 -18
  39. package/lib/vscode/locales.js.map +1 -1
  40. package/lib/vscode/utils.d.ts +3 -3
  41. package/lib/vscode/utils.d.ts.map +1 -1
  42. package/lib/vscode/utils.js +3 -10
  43. package/lib/vscode/utils.js.map +1 -1
  44. package/lib/vscode/viewsService.d.ts.map +1 -1
  45. package/lib/vscode/viewsService.js +13 -7
  46. package/lib/vscode/viewsService.js.map +1 -1
  47. package/lib/worker/index.d.ts +1 -1
  48. package/lib/worker/index.d.ts.map +1 -1
  49. package/lib/worker/index.js.map +1 -1
  50. package/lib/wrapper/lcconfig.d.ts +2 -2
  51. package/lib/wrapper/lcconfig.d.ts.map +1 -1
  52. package/lib/wrapper/lcmanager.d.ts.map +1 -1
  53. package/lib/wrapper/lcmanager.js.map +1 -1
  54. package/lib/wrapper/lcwrapper.d.ts +1 -1
  55. package/lib/wrapper/lcwrapper.d.ts.map +1 -1
  56. package/lib/wrapper/lcwrapper.js +17 -16
  57. package/lib/wrapper/lcwrapper.js.map +1 -1
  58. package/package.json +70 -96
  59. package/src/common/commonTypes.ts +35 -30
  60. package/src/common/index.ts +0 -1
  61. package/src/common/utils.ts +45 -45
  62. package/src/debugger/index.ts +130 -133
  63. package/src/editorApp/config.ts +33 -33
  64. package/src/editorApp/editorApp.ts +382 -370
  65. package/src/editorApp/index.ts +0 -0
  66. package/src/fs/definitions.ts +72 -75
  67. package/src/fs/endpoints/defaultEndpoint.ts +50 -41
  68. package/src/fs/index.ts +0 -0
  69. package/src/index.ts +18 -18
  70. package/src/vscode/apiWrapper.ts +302 -296
  71. package/src/vscode/config.ts +30 -30
  72. package/src/vscode/index.ts +0 -0
  73. package/src/vscode/locales.ts +127 -110
  74. package/src/vscode/utils.ts +20 -26
  75. package/src/vscode/viewsService.ts +44 -37
  76. package/src/worker/index.ts +38 -45
  77. package/src/wrapper/index.ts +0 -0
  78. package/src/wrapper/lcconfig.ts +16 -16
  79. package/src/wrapper/lcmanager.ts +68 -69
  80. package/src/wrapper/lcwrapper.ts +256 -249
@@ -7,281 +7,288 @@ import { LogLevel } from '@codingame/monaco-vscode-api';
7
7
  import { ConsoleLogger, type ILogger } from '@codingame/monaco-vscode-log-service-override';
8
8
  import { MonacoLanguageClient, MonacoLanguageClientWithProposedFeatures } from 'monaco-languageclient';
9
9
  import { createUrl, type WorkerConfigOptionsDirect, type WorkerConfigOptionsParams } from 'monaco-languageclient/common';
10
- import { CloseAction, ErrorAction, MessageTransports, State } from 'vscode-languageclient/browser.js';
11
- import { BrowserMessageReader, BrowserMessageWriter } from 'vscode-languageserver-protocol/browser.js';
10
+ import { CloseAction, ErrorAction, MessageTransports, State } from 'vscode-languageclient/browser';
11
+ import { BrowserMessageReader, BrowserMessageWriter } from 'vscode-languageserver-protocol/browser';
12
12
  import { toSocket, WebSocketMessageReader, WebSocketMessageWriter } from 'vscode-ws-jsonrpc';
13
13
  import type { LanguageClientConfig, LanguageClientRestartOptions } from './lcconfig.js';
14
14
 
15
15
  export interface LanguageClientError {
16
- message: string;
17
- error: Error | string;
16
+ message: string;
17
+ error: Error | string;
18
18
  }
19
19
 
20
20
  export class LanguageClientWrapper {
21
-
22
- private languageClient?: MonacoLanguageClient | MonacoLanguageClientWithProposedFeatures;
23
- private languageClientConfig: LanguageClientConfig;
24
- private worker?: Worker;
25
- private port?: MessagePort;
26
- private languageId: string;
27
- private logger: ILogger | undefined;
28
-
29
- constructor(config: LanguageClientConfig) {
30
- this.languageClientConfig = config;
31
- this.languageId = this.languageClientConfig.languageId;
32
- this.logger = new ConsoleLogger(this.languageClientConfig.logLevel ?? LogLevel.Off);
33
- }
34
-
35
- haveLanguageClient(): boolean {
36
- return this.languageClient !== undefined;
21
+ private languageClient?: MonacoLanguageClient | MonacoLanguageClientWithProposedFeatures;
22
+ private languageClientConfig: LanguageClientConfig;
23
+ private worker?: Worker;
24
+ private port?: MessagePort;
25
+ private languageId: string;
26
+ private logger: ILogger | undefined;
27
+
28
+ constructor(config: LanguageClientConfig) {
29
+ this.languageClientConfig = config;
30
+ this.languageId = this.languageClientConfig.languageId;
31
+ this.logger = new ConsoleLogger(this.languageClientConfig.logLevel ?? LogLevel.Off);
32
+ }
33
+
34
+ haveLanguageClient(): boolean {
35
+ return this.languageClient !== undefined;
36
+ }
37
+
38
+ getLanguageClient(): MonacoLanguageClient | undefined {
39
+ return this.languageClient;
40
+ }
41
+
42
+ getWorker(): Worker | undefined {
43
+ return this.worker;
44
+ }
45
+
46
+ isStarted(): boolean {
47
+ return this.languageClient?.isRunning() ?? false;
48
+ }
49
+
50
+ async start(): Promise<void> {
51
+ if (this.languageClient?.isRunning() ?? false) {
52
+ this.logger?.info('startLanguageClientConnection: monaco-languageclient already running!');
53
+ return Promise.resolve();
37
54
  }
38
55
 
39
- getLanguageClient(): MonacoLanguageClient | undefined {
40
- return this.languageClient;
56
+ return new Promise<void>((resolve, reject) => {
57
+ const conConfig = this.languageClientConfig.connection;
58
+ const conOptions = conConfig.options;
59
+
60
+ if (conOptions.$type === 'WebSocketDirect' || conOptions.$type === 'WebSocketParams' || conOptions.$type === 'WebSocketUrl') {
61
+ const webSocket = conOptions.$type === 'WebSocketDirect' ? conOptions.webSocket : new WebSocket(createUrl(conOptions));
62
+ return this.initMessageTransportWebSocket(webSocket, resolve, reject);
63
+ } else {
64
+ // init of worker and start of languageclient can be handled directly, because worker available already
65
+ return this.initMessageTransportWorker(conOptions, resolve, reject);
66
+ }
67
+ });
68
+ }
69
+
70
+ /**
71
+ * Restart the languageclient with options to control worker handling
72
+ *
73
+ * @param updatedWorker Set a new worker here that should be used. keepWorker has no effect then, as we want to dispose of the prior workers
74
+ * @param disposeWorker Set to false if worker should not be disposed
75
+ */
76
+ async restart(updatedWorker?: Worker, forceWorkerDispose?: boolean): Promise<void> {
77
+ await this.dispose(forceWorkerDispose);
78
+
79
+ this.worker = updatedWorker;
80
+ this.logger?.info('Re-Starting monaco-languageclient');
81
+ return this.start();
82
+ }
83
+
84
+ protected async initMessageTransportWebSocket(webSocket: WebSocket, resolve: () => void, reject: (reason?: unknown) => void) {
85
+ let messageTransports = this.languageClientConfig.connection.messageTransports;
86
+ if (messageTransports === undefined) {
87
+ const iWebSocket = toSocket(webSocket);
88
+ messageTransports = {
89
+ reader: new WebSocketMessageReader(iWebSocket),
90
+ writer: new WebSocketMessageWriter(iWebSocket)
91
+ };
41
92
  }
42
93
 
43
- getWorker(): Worker | undefined {
44
- return this.worker;
94
+ // if websocket is already open, then start the languageclient directly
95
+ if (webSocket.readyState === WebSocket.OPEN) {
96
+ await this.performLanguageClientStart(messageTransports, resolve, reject);
45
97
  }
46
98
 
47
- isStarted(): boolean {
48
- return this.languageClient !== undefined && this.languageClient.isRunning();
49
- }
50
-
51
- async start(): Promise<void> {
52
- if (this.languageClient?.isRunning() ?? false) {
53
- this.logger?.info('startLanguageClientConnection: monaco-languageclient already running!');
54
- return Promise.resolve();
55
- }
56
-
57
- return new Promise<void>((resolve, reject) => {
58
- const conConfig = this.languageClientConfig.connection;
59
- const conOptions = conConfig.options;
60
-
61
- if (conOptions.$type === 'WebSocketDirect' || conOptions.$type === 'WebSocketParams' || conOptions.$type === 'WebSocketUrl') {
62
- const webSocket = conOptions.$type === 'WebSocketDirect' ? conOptions.webSocket : new WebSocket(createUrl(conOptions));
63
- this.initMessageTransportWebSocket(webSocket, resolve, reject);
64
- } else {
65
- // init of worker and start of languageclient can be handled directly, because worker available already
66
- this.initMessageTransportWorker(conOptions, resolve, reject);
67
- }
99
+ // otherwise start on open
100
+ webSocket.onopen = async () => {
101
+ await this.performLanguageClientStart(messageTransports, resolve, reject);
102
+ };
103
+ webSocket.onerror = (ev: Event) => {
104
+ const languageClientError: LanguageClientError = {
105
+ message: `languageClientWrapper (${this.languageId}): Websocket connection failed.`,
106
+ error: (ev as ErrorEvent).error ?? 'No error was provided.'
107
+ };
108
+ reject(languageClientError);
109
+ };
110
+ }
111
+
112
+ protected async initMessageTransportWorker(
113
+ lccOptions: WorkerConfigOptionsDirect | WorkerConfigOptionsParams,
114
+ resolve: () => void,
115
+ reject: (reason?: unknown) => void
116
+ ) {
117
+ if (this.worker === undefined) {
118
+ if (lccOptions.$type === 'WorkerConfig') {
119
+ const workerConfig = lccOptions as WorkerConfigOptionsParams;
120
+ this.worker = new Worker(workerConfig.url.href, {
121
+ type: workerConfig.type,
122
+ name: workerConfig.workerName
68
123
  });
69
- }
70
-
71
- /**
72
- * Restart the languageclient with options to control worker handling
73
- *
74
- * @param updatedWorker Set a new worker here that should be used. keepWorker has no effect then, as we want to dispose of the prior workers
75
- * @param disposeWorker Set to false if worker should not be disposed
76
- */
77
- async restart(updatedWorker?: Worker, forceWorkerDispose?: boolean): Promise<void> {
78
- await this.dispose(forceWorkerDispose);
79
-
80
- this.worker = updatedWorker;
81
- this.logger?.info('Re-Starting monaco-languageclient');
82
- return this.start();
83
- }
84
-
85
- protected async initMessageTransportWebSocket(webSocket: WebSocket, resolve: () => void, reject: (reason?: unknown) => void) {
86
-
87
- let messageTransports = this.languageClientConfig.connection.messageTransports;
88
- if (messageTransports === undefined) {
89
- const iWebSocket = toSocket(webSocket);
90
- messageTransports = {
91
- reader: new WebSocketMessageReader(iWebSocket),
92
- writer: new WebSocketMessageWriter(iWebSocket)
93
- };
94
- }
95
-
96
- // if websocket is already open, then start the languageclient directly
97
- if (webSocket.readyState === WebSocket.OPEN) {
98
- await this.performLanguageClientStart(messageTransports, resolve, reject);
99
- }
100
124
 
101
- // otherwise start on open
102
- webSocket.onopen = async () => {
103
- await this.performLanguageClientStart(messageTransports, resolve, reject);
104
- };
105
- webSocket.onerror = (ev: Event) => {
106
- const languageClientError: LanguageClientError = {
107
- message: `languageClientWrapper (${this.languageId}): Websocket connection failed.`,
108
- error: (ev as ErrorEvent).error ?? 'No error was provided.'
109
- };
110
- reject(languageClientError);
125
+ this.worker.onerror = (ev) => {
126
+ const languageClientError: LanguageClientError = {
127
+ message: `languageClientWrapper (${this.languageId}): Illegal worker configuration detected.`,
128
+ error: ev.error ?? 'No error was provided.'
129
+ };
130
+ reject(languageClientError);
111
131
  };
132
+ } else {
133
+ const workerDirectConfig = lccOptions as WorkerConfigOptionsDirect;
134
+ this.worker = workerDirectConfig.worker;
135
+ }
136
+ if (lccOptions.messagePort !== undefined) {
137
+ this.port = lccOptions.messagePort;
138
+ }
112
139
  }
113
140
 
114
- protected async initMessageTransportWorker(lccOptions: WorkerConfigOptionsDirect | WorkerConfigOptionsParams, resolve: () => void, reject: (reason?: unknown) => void) {
115
- if (!this.worker) {
116
- if (lccOptions.$type === 'WorkerConfig') {
117
- const workerConfig = lccOptions as WorkerConfigOptionsParams;
118
- this.worker = new Worker(workerConfig.url.href, {
119
- type: workerConfig.type,
120
- name: workerConfig.workerName
121
- });
122
-
123
- this.worker.onerror = (ev) => {
124
- const languageClientError: LanguageClientError = {
125
- message: `languageClientWrapper (${this.languageId}): Illegal worker configuration detected.`,
126
- error: ev.error ?? 'No error was provided.'
127
- };
128
- reject(languageClientError);
129
- };
130
- } else {
131
- const workerDirectConfig = lccOptions as WorkerConfigOptionsDirect;
132
- this.worker = workerDirectConfig.worker;
133
- }
134
- if (lccOptions.messagePort !== undefined) {
135
- this.port = lccOptions.messagePort;
136
- }
137
- }
138
-
139
- const portOrWorker = this.port ? this.port : this.worker;
140
- let messageTransports = this.languageClientConfig.connection.messageTransports;
141
- if (messageTransports === undefined) {
142
- messageTransports = {
143
- reader: new BrowserMessageReader(portOrWorker),
144
- writer: new BrowserMessageWriter(portOrWorker)
145
- };
146
- }
147
-
148
- await this.performLanguageClientStart(messageTransports, resolve, reject);
141
+ const portOrWorker = this.port ?? this.worker;
142
+ let messageTransports = this.languageClientConfig.connection.messageTransports;
143
+ messageTransports ??= {
144
+ reader: new BrowserMessageReader(portOrWorker),
145
+ writer: new BrowserMessageWriter(portOrWorker)
146
+ };
147
+ await this.performLanguageClientStart(messageTransports, resolve, reject);
148
+ }
149
+
150
+ protected async performLanguageClientStart(
151
+ messageTransports: MessageTransports,
152
+ resolve: () => void,
153
+ reject: (reason?: unknown) => void
154
+ ) {
155
+ let starting = true;
156
+ // do not perform another start attempt if already running
157
+ if (this.languageClient?.isRunning() ?? false) {
158
+ this.logger?.info('performLanguageClientStart: monaco-languageclient already running!');
159
+ resolve();
149
160
  }
150
161
 
151
- protected async performLanguageClientStart(messageTransports: MessageTransports, resolve: () => void, reject: (reason?: unknown) => void) {
152
- let starting = true;
153
- // do not perform another start attempt if already running
154
- if (this.languageClient?.isRunning() ?? false) {
155
- this.logger?.info('performLanguageClientStart: monaco-languageclient already running!');
156
- resolve();
157
- }
158
-
159
- const mlcConfig = {
160
- id: this.languageClientConfig.languageId,
161
- name: 'Monaco Wrapper Language Client',
162
- clientOptions: {
163
- // disable the default error handler...
164
- errorHandler: {
165
- error: (e: Error) => {
166
- if (starting) {
167
- reject(`Error occurred in language client: ${e}`);
168
- return { action: ErrorAction.Shutdown };
169
- } else {
170
- return { action: ErrorAction.Continue };
171
- }
172
- },
173
- closed: () => ({ action: CloseAction.DoNotRestart })
174
- },
175
- // ...but allowm to override all options
176
- ...this.languageClientConfig.clientOptions,
177
- },
178
- messageTransports
179
- };
180
-
181
- const conOptions = this.languageClientConfig.connection.options;
182
- this.initRestartConfiguration(messageTransports, this.languageClientConfig.restartOptions);
183
-
184
- const isWebSocket = conOptions.$type === 'WebSocketParams' || conOptions.$type === 'WebSocketUrl' || conOptions.$type === 'WebSocketDirect';
185
-
186
- messageTransports.reader.onClose(async () => {
187
- await this.languageClient?.stop();
188
-
189
- if (isWebSocket && conOptions.stopOptions !== undefined) {
190
- const stopOptions = conOptions.stopOptions;
191
- stopOptions.onCall(this.getLanguageClient());
192
- if (stopOptions.reportStatus !== undefined) {
193
- this.logger?.info(this.reportStatus().join('\n'));
194
- }
195
- }
196
- });
197
-
198
- try {
199
- this.languageClient = this.languageClientConfig.useClientWithProposedFeatures === true ? new MonacoLanguageClientWithProposedFeatures(mlcConfig) : new MonacoLanguageClient(mlcConfig);
200
- if (this.languageClientConfig.registerFeatures !== undefined) {
201
- this.languageClient.registerFeatures(this.languageClientConfig.registerFeatures);
202
- }
203
-
204
- await this.languageClient.start();
205
-
206
- if (isWebSocket && conOptions.startOptions !== undefined) {
207
- const startOptions = conOptions.startOptions;
208
- startOptions.onCall(this.getLanguageClient());
209
- if (startOptions.reportStatus !== undefined) {
210
- this.logger?.info(this.reportStatus().join('\n'));
211
- }
162
+ const mlcConfig = {
163
+ id: this.languageClientConfig.languageId,
164
+ name: 'Monaco Wrapper Language Client',
165
+ clientOptions: {
166
+ // disable the default error handler...
167
+ errorHandler: {
168
+ error: (e: Error) => {
169
+ if (starting) {
170
+ reject(`Error occurred in language client: ${e}`);
171
+ return { action: ErrorAction.Shutdown };
172
+ } else {
173
+ return { action: ErrorAction.Continue };
212
174
  }
213
- } catch (e: unknown) {
214
- const languageClientError: LanguageClientError = {
215
- message: `languageClientWrapper (${this.languageId}): Start was unsuccessful.`,
216
- error: Object.hasOwn(e ?? {}, 'cause') ? (e as Error) : 'No error was provided.'
217
- };
218
- reject(languageClientError);
175
+ },
176
+ closed: () => ({ action: CloseAction.DoNotRestart })
177
+ },
178
+ // ...but allowm to override all options
179
+ ...this.languageClientConfig.clientOptions
180
+ },
181
+ messageTransports
182
+ };
183
+
184
+ const conOptions = this.languageClientConfig.connection.options;
185
+ this.initRestartConfiguration(messageTransports, this.languageClientConfig.restartOptions);
186
+
187
+ const isWebSocket =
188
+ conOptions.$type === 'WebSocketParams' || conOptions.$type === 'WebSocketUrl' || conOptions.$type === 'WebSocketDirect';
189
+
190
+ messageTransports.reader.onClose(async () => {
191
+ await this.languageClient?.stop();
192
+
193
+ if (isWebSocket && conOptions.stopOptions !== undefined) {
194
+ const stopOptions = conOptions.stopOptions;
195
+ stopOptions.onCall(this.getLanguageClient());
196
+ if (stopOptions.reportStatus !== undefined) {
197
+ this.logger?.info(this.reportStatus().join('\n'));
219
198
  }
220
- this.logger?.info(`languageClientWrapper (${this.languageId}): Started successfully.`);
221
- resolve();
222
- starting = false;
223
- }
224
-
225
- protected initRestartConfiguration(messageTransports: MessageTransports, restartOptions?: LanguageClientRestartOptions) {
226
- if (restartOptions !== undefined) {
227
- let retry = 0;
228
-
229
- const readerOnError = messageTransports.reader.onError(() => restartLC);
230
- const readerOnClose = messageTransports.reader.onClose(() => restartLC);
231
-
232
- const restartLC = async () => {
233
- if (this.isStarted()) {
234
- try {
235
- readerOnError.dispose();
236
- readerOnClose.dispose();
237
-
238
- await this.restart(this.worker, restartOptions.keepWorker);
239
- } finally {
240
- retry++;
241
- if (retry > (restartOptions.retries) && !this.isStarted()) {
242
- this.logger?.info(`Disabling Language Client. Failed to start clangd after ${restartOptions.retries} retries`);
243
- } else {
244
- setTimeout(async () => {
245
- await this.restart(this.worker, restartOptions.keepWorker);
246
- }, restartOptions.timeout);
247
- }
248
- }
249
- }
250
- };
199
+ }
200
+ });
201
+
202
+ try {
203
+ this.languageClient =
204
+ this.languageClientConfig.useClientWithProposedFeatures === true
205
+ ? new MonacoLanguageClientWithProposedFeatures(mlcConfig)
206
+ : new MonacoLanguageClient(mlcConfig);
207
+ if (this.languageClientConfig.registerFeatures !== undefined) {
208
+ this.languageClient.registerFeatures(this.languageClientConfig.registerFeatures);
209
+ }
210
+
211
+ await this.languageClient.start();
212
+
213
+ if (isWebSocket && conOptions.startOptions !== undefined) {
214
+ const startOptions = conOptions.startOptions;
215
+ startOptions.onCall(this.getLanguageClient());
216
+ if (startOptions.reportStatus !== undefined) {
217
+ this.logger?.info(this.reportStatus().join('\n'));
251
218
  }
219
+ }
220
+ } catch (e: unknown) {
221
+ const languageClientError: LanguageClientError = {
222
+ message: `languageClientWrapper (${this.languageId}): Start was unsuccessful.`,
223
+ error: Object.hasOwn(e ?? {}, 'cause') ? (e as Error) : 'No error was provided.'
224
+ };
225
+ reject(languageClientError);
252
226
  }
253
-
254
- protected disposeWorker() {
255
- this.worker?.terminate();
256
- this.worker = undefined;
257
- }
258
-
259
- async dispose(forceWorkerDispose?: boolean): Promise<void> {
260
- try {
261
- if (this.isStarted()) {
262
- await this.languageClient?.dispose();
263
- this.languageClient = undefined;
264
- this.logger?.info('monaco-languageclient was successfully disposed.');
265
- }
266
- } catch (e) {
267
- const languageClientError: LanguageClientError = {
268
- message: `languageClientWrapper (${this.languageId}): Disposing the monaco-languageclient resulted in error.`,
269
- error: Object.hasOwn(e ?? {}, 'cause') ? (e as Error) : 'No error was provided.'
270
- };
271
- return Promise.reject(languageClientError);
272
- } finally {
273
- // always terminate the worker if desired
274
- if (this.languageClientConfig.disposeWorker === true || forceWorkerDispose === true) {
275
- this.disposeWorker();
227
+ this.logger?.info(`languageClientWrapper (${this.languageId}): Started successfully.`);
228
+ resolve();
229
+ starting = false;
230
+ }
231
+
232
+ protected initRestartConfiguration(messageTransports: MessageTransports, restartOptions?: LanguageClientRestartOptions) {
233
+ if (restartOptions !== undefined) {
234
+ let retry = 0;
235
+
236
+ const readerOnError = messageTransports.reader.onError(() => restartLC);
237
+ const readerOnClose = messageTransports.reader.onClose(() => restartLC);
238
+
239
+ const restartLC = async () => {
240
+ if (this.isStarted()) {
241
+ try {
242
+ readerOnError.dispose();
243
+ readerOnClose.dispose();
244
+
245
+ await this.restart(this.worker, restartOptions.keepWorker);
246
+ } finally {
247
+ retry++;
248
+ if (retry > restartOptions.retries && !this.isStarted()) {
249
+ this.logger?.info(`Disabling Language Client. Failed to start clangd after ${restartOptions.retries} retries`);
250
+ } else {
251
+ setTimeout(async () => {
252
+ await this.restart(this.worker, restartOptions.keepWorker);
253
+ }, restartOptions.timeout);
276
254
  }
255
+ }
277
256
  }
257
+ };
278
258
  }
279
-
280
- reportStatus() {
281
- const status: string[] = [];
282
- const languageClient = this.getLanguageClient();
283
- status.push('LanguageClientWrapper status:');
284
- status.push(`LanguageClient: ${languageClient?.name ?? 'Language Client'} is in a '${State[languageClient?.state ?? 1]}' state`);
285
- return status;
259
+ }
260
+
261
+ protected disposeWorker() {
262
+ this.worker?.terminate();
263
+ this.worker = undefined;
264
+ }
265
+
266
+ async dispose(forceWorkerDispose?: boolean): Promise<void> {
267
+ try {
268
+ if (this.isStarted()) {
269
+ await this.languageClient?.dispose();
270
+ this.languageClient = undefined;
271
+ this.logger?.info('monaco-languageclient was successfully disposed.');
272
+ }
273
+ } catch (e) {
274
+ const languageClientError: LanguageClientError = {
275
+ message: `languageClientWrapper (${this.languageId}): Disposing the monaco-languageclient resulted in error.`,
276
+ error: Object.hasOwn(e ?? {}, 'cause') ? (e as Error) : 'No error was provided.'
277
+ };
278
+ return Promise.reject(languageClientError);
279
+ } finally {
280
+ // always terminate the worker if desired
281
+ if (this.languageClientConfig.disposeWorker === true || forceWorkerDispose === true) {
282
+ this.disposeWorker();
283
+ }
286
284
  }
285
+ }
286
+
287
+ reportStatus() {
288
+ const status: string[] = [];
289
+ const languageClient = this.getLanguageClient();
290
+ status.push('LanguageClientWrapper status:');
291
+ status.push(`LanguageClient: ${languageClient?.name ?? 'Language Client'} is in a '${State[languageClient?.state ?? 1]}' state`);
292
+ return status;
293
+ }
287
294
  }