monaco-languageclient 10.0.0-next.0 → 10.0.0-next.2
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.
- package/CHANGELOG.md +20 -3
- package/README.md +98 -34
- package/lib/common/utils.d.ts +1 -1
- package/lib/common/utils.d.ts.map +1 -1
- package/lib/common/utils.js +1 -1
- package/lib/common/utils.js.map +1 -1
- package/lib/editorApp/config.d.ts +0 -2
- package/lib/editorApp/config.d.ts.map +1 -1
- package/lib/editorApp/config.js +1 -2
- package/lib/editorApp/config.js.map +1 -1
- package/lib/editorApp/editorApp.d.ts +4 -11
- package/lib/editorApp/editorApp.d.ts.map +1 -1
- package/lib/editorApp/editorApp.js +73 -88
- package/lib/editorApp/editorApp.js.map +1 -1
- package/lib/fs/definitions.d.ts +2 -2
- package/lib/fs/definitions.d.ts.map +1 -1
- package/lib/vscode/apiWrapper.d.ts +21 -6
- package/lib/vscode/apiWrapper.d.ts.map +1 -1
- package/lib/vscode/apiWrapper.js +67 -39
- package/lib/vscode/apiWrapper.js.map +1 -1
- package/lib/vscode/config.d.ts +8 -6
- package/lib/vscode/config.d.ts.map +1 -1
- package/lib/vscode/config.js +1 -1
- package/lib/vscode/utils.d.ts.map +1 -1
- package/lib/vscode/utils.js +4 -5
- package/lib/vscode/utils.js.map +1 -1
- package/lib/worker/index.js +1 -1
- package/lib/wrapper/lcconfig.d.ts +3 -3
- package/lib/wrapper/lcconfig.d.ts.map +1 -1
- package/lib/wrapper/lcconfig.js +1 -1
- package/lib/wrapper/lcmanager.d.ts +2 -1
- package/lib/wrapper/lcmanager.d.ts.map +1 -1
- package/lib/wrapper/lcmanager.js +21 -17
- package/lib/wrapper/lcmanager.js.map +1 -1
- package/lib/wrapper/lcwrapper.d.ts +1 -1
- package/lib/wrapper/lcwrapper.d.ts.map +1 -1
- package/lib/wrapper/lcwrapper.js +10 -9
- package/lib/wrapper/lcwrapper.js.map +1 -1
- package/package.json +41 -40
- package/src/common/utils.ts +1 -1
- package/src/editorApp/config.ts +1 -3
- package/src/editorApp/editorApp.ts +81 -96
- package/src/fs/definitions.ts +2 -2
- package/src/vscode/apiWrapper.ts +84 -44
- package/src/vscode/config.ts +13 -8
- package/src/vscode/utils.ts +4 -5
- package/src/worker/index.ts +1 -1
- package/src/wrapper/lcconfig.ts +5 -5
- package/src/wrapper/lcmanager.ts +23 -18
- package/src/wrapper/lcwrapper.ts +10 -9
|
@@ -8,12 +8,13 @@ import { createModelReference, type ITextFileEditorModel } from '@codingame/mona
|
|
|
8
8
|
import * as monaco from '@codingame/monaco-vscode-editor-api';
|
|
9
9
|
import type { IReference } from '@codingame/monaco-vscode-editor-service-override';
|
|
10
10
|
import { ConsoleLogger, type Logger } from 'monaco-languageclient/common';
|
|
11
|
-
import { getEnhancedMonacoEnvironment
|
|
11
|
+
import { getEnhancedMonacoEnvironment } from 'monaco-languageclient/vscodeApiWrapper';
|
|
12
12
|
import * as vscode from 'vscode';
|
|
13
|
-
import {
|
|
13
|
+
import type { CallbackDisposeable, CodeContent, CodeResources, DisposableModelRefs, EditorAppConfig, TextContents, TextModels } from './config.js';
|
|
14
|
+
import { ModelRefs } from './config.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
|
-
* This is the base class for both Monaco
|
|
17
|
+
* This is the base class for both Monaco Editor Apps:
|
|
17
18
|
* - EditorAppClassic
|
|
18
19
|
* - EditorAppExtended
|
|
19
20
|
*
|
|
@@ -21,7 +22,6 @@ import { ModelRefs, type CallbackDisposeable, type CodeContent, type CodeResourc
|
|
|
21
22
|
*/
|
|
22
23
|
export class EditorApp {
|
|
23
24
|
|
|
24
|
-
private $type: OverallConfigType;
|
|
25
25
|
private id: string;
|
|
26
26
|
private config: EditorAppConfig;
|
|
27
27
|
|
|
@@ -33,19 +33,16 @@ export class EditorApp {
|
|
|
33
33
|
private modelRefs: ModelRefs = new ModelRefs();
|
|
34
34
|
|
|
35
35
|
private onTextChanged?: (textChanges: TextContents) => void;
|
|
36
|
-
private
|
|
36
|
+
private textChangedDisposables: CallbackDisposeable = {};
|
|
37
37
|
private modelDisposables: DisposableModelRefs = {};
|
|
38
38
|
|
|
39
39
|
private modelRefDisposeTimeout = -1;
|
|
40
40
|
|
|
41
41
|
private startingAwait?: Promise<void>;
|
|
42
|
-
private startingResolve: (value: void | PromiseLike<void>) => void;
|
|
43
42
|
|
|
44
43
|
private disposingAwait?: Promise<void>;
|
|
45
|
-
private disposingResolve: (value: void | PromiseLike<void>) => void;
|
|
46
44
|
|
|
47
45
|
constructor(userAppConfig?: EditorAppConfig) {
|
|
48
|
-
this.$type = userAppConfig?.$type ?? 'extended';
|
|
49
46
|
this.id = userAppConfig?.id ?? Math.floor(Math.random() * 1000001).toString();
|
|
50
47
|
if ((userAppConfig?.useDiffEditor ?? false) && !userAppConfig?.codeResources?.original) {
|
|
51
48
|
throw new Error(`Use diff editor was used without a valid config. code: ${userAppConfig?.codeResources?.modified} codeOriginal: ${userAppConfig?.codeResources?.original}`);
|
|
@@ -105,17 +102,6 @@ export class EditorApp {
|
|
|
105
102
|
this.modelRefDisposeTimeout = modelRefDisposeTimeout;
|
|
106
103
|
}
|
|
107
104
|
|
|
108
|
-
private markStarting() {
|
|
109
|
-
this.startingAwait = new Promise<void>((resolve) => {
|
|
110
|
-
this.startingResolve = resolve;
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private markStarted() {
|
|
115
|
-
this.startingResolve();
|
|
116
|
-
this.startingAwait = undefined;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
105
|
isStarting() {
|
|
120
106
|
return this.startingAwait !== undefined;
|
|
121
107
|
}
|
|
@@ -135,44 +121,71 @@ export class EditorApp {
|
|
|
135
121
|
if (this.isStarting()) {
|
|
136
122
|
await this.getStartingAwait();
|
|
137
123
|
}
|
|
138
|
-
this.markStarting();
|
|
139
124
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
125
|
+
let startingResolve: (value: void | PromiseLike<void>) => void = () => { };
|
|
126
|
+
this.startingAwait = new Promise<void>((resolve) => {
|
|
127
|
+
startingResolve = resolve;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const envEnhanced = getEnhancedMonacoEnvironment();
|
|
132
|
+
const viewServiceType = envEnhanced.viewServiceType;
|
|
143
133
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
throw new Error('Language definition is not supported for extended editor apps where textmate is used.');
|
|
134
|
+
// check general error case first
|
|
135
|
+
if (!(envEnhanced.vscodeApiInitialised ?? false)) {
|
|
136
|
+
return Promise.reject('monaco-vscode-api was not initialized. Aborting.');
|
|
148
137
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// this is only meaningful for languages supported by monaco out of the box
|
|
155
|
-
monaco.languages.register({
|
|
156
|
-
id: languageDef.languageExtensionConfig.id
|
|
157
|
-
});
|
|
138
|
+
if (viewServiceType !== 'EditorService' && viewServiceType !== undefined) {
|
|
139
|
+
return Promise.reject('No EditorService configured. monaco-editor will not be started.');
|
|
140
|
+
}
|
|
141
|
+
if (!this.isDisposed()) {
|
|
142
|
+
return Promise.reject('Start was called without properly disposing the EditorApp first.');
|
|
158
143
|
}
|
|
159
144
|
|
|
160
|
-
|
|
161
|
-
if (languageDef
|
|
162
|
-
|
|
145
|
+
const languageDef = this.config.languageDef;
|
|
146
|
+
if (languageDef) {
|
|
147
|
+
// register own language first
|
|
148
|
+
monaco.languages.register(languageDef.languageExtensionConfig);
|
|
149
|
+
|
|
150
|
+
const languageRegistered = monaco.languages.getLanguages().filter(x => x.id === languageDef.languageExtensionConfig.id);
|
|
151
|
+
if (languageRegistered.length === 0) {
|
|
152
|
+
// this is only meaningful for languages supported by monaco out of the box
|
|
153
|
+
monaco.languages.register({
|
|
154
|
+
id: languageDef.languageExtensionConfig.id
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// apply monarch definitions
|
|
159
|
+
if (languageDef.monarchLanguage) {
|
|
160
|
+
monaco.languages.setMonarchTokensProvider(languageDef.languageExtensionConfig.id, languageDef.monarchLanguage);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (languageDef.theme) {
|
|
164
|
+
monaco.editor.defineTheme(languageDef.theme.name, languageDef.theme.data);
|
|
165
|
+
monaco.editor.setTheme(languageDef.theme.name);
|
|
166
|
+
}
|
|
163
167
|
}
|
|
164
168
|
|
|
165
|
-
if (
|
|
166
|
-
|
|
167
|
-
|
|
169
|
+
if (this.config.editorOptions?.['semanticHighlighting.enabled'] !== undefined) {
|
|
170
|
+
StandaloneServices.get(IConfigurationService).updateValue('editor.semanticHighlighting.enabled',
|
|
171
|
+
this.config.editorOptions['semanticHighlighting.enabled'], ConfigurationTarget.USER);
|
|
168
172
|
}
|
|
169
|
-
}
|
|
170
173
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
await this.createEditors(htmlContainer);
|
|
175
|
+
|
|
176
|
+
// everything is fine at this point
|
|
177
|
+
startingResolve();
|
|
178
|
+
this.logger.info('EditorApp start completed successfully.');
|
|
179
|
+
} catch (e) {
|
|
180
|
+
// in case of further errors (after general ones above)
|
|
181
|
+
// take the error and build a new rejection to complete the promise
|
|
182
|
+
return Promise.reject(e);
|
|
183
|
+
} finally {
|
|
184
|
+
this.startingAwait = undefined;
|
|
174
185
|
}
|
|
186
|
+
}
|
|
175
187
|
|
|
188
|
+
async createEditors(htmlContainer: HTMLElement): Promise<void> {
|
|
176
189
|
// ensure proper default resources are initialized, uris have to be unique
|
|
177
190
|
const modified = {
|
|
178
191
|
text: this.config.codeResources?.modified?.text ?? '',
|
|
@@ -190,30 +203,10 @@ export class EditorApp {
|
|
|
190
203
|
this.modelRefs.original = await this.buildModelReference(original, this.logger);
|
|
191
204
|
}
|
|
192
205
|
|
|
193
|
-
|
|
194
|
-
const envEnhanced = getEnhancedMonacoEnvironment();
|
|
195
|
-
const viewServiceType = envEnhanced.viewServiceType;
|
|
196
|
-
if (viewServiceType === 'EditorService' || viewServiceType === undefined) {
|
|
197
|
-
this.logger.info(`Starting monaco-editor (${this.id})`);
|
|
198
|
-
await this.createEditors(htmlContainer!);
|
|
199
|
-
} else {
|
|
200
|
-
this.logger.info('No EditorService configured. monaco-editor will not be started.');
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
this.logger.info('EditorApp start completed successfully.');
|
|
204
|
-
// eslint-disable-next-line no-useless-catch
|
|
205
|
-
} catch (e) {
|
|
206
|
-
throw e;
|
|
207
|
-
} finally {
|
|
208
|
-
// in case of rejection, mark as started, otherwise the promise will never resolve
|
|
209
|
-
this.markStarted();
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
async createEditors(htmlContainer: HTMLElement): Promise<void> {
|
|
206
|
+
this.logger.info(`Starting monaco-editor (${this.id})`);
|
|
214
207
|
if (this.isDiffEditor()) {
|
|
215
208
|
this.diffEditor = monaco.editor.createDiffEditor(htmlContainer, this.config.diffEditorOptions);
|
|
216
|
-
const modified = this.modelRefs.modified
|
|
209
|
+
const modified = this.modelRefs.modified.object.textEditorModel ?? undefined;
|
|
217
210
|
const original = this.modelRefs.original?.object.textEditorModel ?? undefined;
|
|
218
211
|
if (modified !== undefined && original !== undefined) {
|
|
219
212
|
const model = {
|
|
@@ -225,7 +218,7 @@ export class EditorApp {
|
|
|
225
218
|
}
|
|
226
219
|
} else {
|
|
227
220
|
const model = {
|
|
228
|
-
modified: this.modelRefs.modified
|
|
221
|
+
modified: this.modelRefs.modified.object.textEditorModel
|
|
229
222
|
};
|
|
230
223
|
this.editor = monaco.editor.create(htmlContainer, {
|
|
231
224
|
...this.config.editorOptions,
|
|
@@ -318,8 +311,8 @@ export class EditorApp {
|
|
|
318
311
|
if (this.onTextChanged !== undefined) {
|
|
319
312
|
let changed = false;
|
|
320
313
|
if (textModels.modified !== undefined && textModels.modified !== null) {
|
|
321
|
-
const old = this.
|
|
322
|
-
this.
|
|
314
|
+
const old = this.textChangedDisposables.modified;
|
|
315
|
+
this.textChangedDisposables.modified = textModels.modified.onDidChangeContent(() => {
|
|
323
316
|
didModelContentChange(textModels, this.onTextChanged);
|
|
324
317
|
});
|
|
325
318
|
old?.dispose();
|
|
@@ -327,8 +320,8 @@ export class EditorApp {
|
|
|
327
320
|
}
|
|
328
321
|
|
|
329
322
|
if (textModels.original !== undefined && textModels.original !== null) {
|
|
330
|
-
const old = this.
|
|
331
|
-
this.
|
|
323
|
+
const old = this.textChangedDisposables.original;
|
|
324
|
+
this.textChangedDisposables.original = textModels.original.onDidChangeContent(() => {
|
|
332
325
|
didModelContentChange(textModels, this.onTextChanged);
|
|
333
326
|
});
|
|
334
327
|
old?.dispose();
|
|
@@ -346,7 +339,10 @@ export class EditorApp {
|
|
|
346
339
|
if (this.isDisposing()) {
|
|
347
340
|
await this.getDisposingAwait();
|
|
348
341
|
}
|
|
349
|
-
|
|
342
|
+
let disposingResolve: (value: void | PromiseLike<void>) => void = () => { };
|
|
343
|
+
this.disposingAwait = new Promise<void>((resolve) => {
|
|
344
|
+
disposingResolve = resolve;
|
|
345
|
+
});
|
|
350
346
|
|
|
351
347
|
if (this.editor) {
|
|
352
348
|
this.editor.dispose();
|
|
@@ -357,33 +353,22 @@ export class EditorApp {
|
|
|
357
353
|
this.diffEditor = undefined;
|
|
358
354
|
}
|
|
359
355
|
|
|
360
|
-
this.
|
|
361
|
-
this.
|
|
362
|
-
this.
|
|
363
|
-
this.
|
|
356
|
+
this.textChangedDisposables.modified?.dispose();
|
|
357
|
+
this.textChangedDisposables.original?.dispose();
|
|
358
|
+
this.textChangedDisposables.modified = undefined;
|
|
359
|
+
this.textChangedDisposables.original = undefined;
|
|
364
360
|
|
|
365
361
|
await this.disposeModelRefs();
|
|
366
362
|
|
|
367
|
-
|
|
363
|
+
disposingResolve();
|
|
364
|
+
this.disposingAwait = undefined;
|
|
368
365
|
}
|
|
369
366
|
|
|
370
367
|
isDisposed(): boolean {
|
|
371
368
|
return this.editor === undefined && this.diffEditor === undefined &&
|
|
372
|
-
// this.textChangedDiposeables.modified === undefined && this.textChangedDiposeables.original === undefined &&
|
|
373
369
|
this.modelDisposables.original === undefined && this.modelDisposables.modified === undefined;
|
|
374
370
|
}
|
|
375
371
|
|
|
376
|
-
private markDisposing() {
|
|
377
|
-
this.disposingAwait = new Promise<void>((resolve) => {
|
|
378
|
-
this.disposingResolve = resolve;
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
private markDisposed() {
|
|
383
|
-
this.disposingResolve();
|
|
384
|
-
this.disposingAwait = undefined;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
372
|
isDisposing() {
|
|
388
373
|
return this.disposingAwait !== undefined;
|
|
389
374
|
}
|
|
@@ -393,7 +378,7 @@ export class EditorApp {
|
|
|
393
378
|
}
|
|
394
379
|
|
|
395
380
|
async disposeModelRefs() {
|
|
396
|
-
const
|
|
381
|
+
const disposeRefs = () => {
|
|
397
382
|
if (this.logger.getLevel() === LogLevel.Debug) {
|
|
398
383
|
const models = monaco.editor.getModels();
|
|
399
384
|
this.logger.debug('Current model URIs:');
|
|
@@ -402,11 +387,11 @@ export class EditorApp {
|
|
|
402
387
|
});
|
|
403
388
|
}
|
|
404
389
|
|
|
405
|
-
if (this.modelDisposables.modified !== undefined && !
|
|
390
|
+
if (this.modelDisposables.modified !== undefined && !this.modelDisposables.modified.object.isDisposed()) {
|
|
406
391
|
this.modelDisposables.modified.dispose();
|
|
407
392
|
this.modelDisposables.modified = undefined;
|
|
408
393
|
}
|
|
409
|
-
if (this.modelDisposables.original !== undefined && !
|
|
394
|
+
if (this.modelDisposables.original !== undefined && !this.modelDisposables.original.object.isDisposed()) {
|
|
410
395
|
this.modelDisposables.original.dispose();
|
|
411
396
|
this.modelDisposables.original = undefined;
|
|
412
397
|
}
|
|
@@ -423,11 +408,11 @@ export class EditorApp {
|
|
|
423
408
|
if (this.modelRefDisposeTimeout > 0) {
|
|
424
409
|
this.logger.debug('Using async dispose of model references');
|
|
425
410
|
await new Promise<void>(resolve => setTimeout(() => {
|
|
426
|
-
|
|
411
|
+
disposeRefs();
|
|
427
412
|
resolve();
|
|
428
413
|
}, this.modelRefDisposeTimeout));
|
|
429
414
|
} else {
|
|
430
|
-
|
|
415
|
+
disposeRefs();
|
|
431
416
|
}
|
|
432
417
|
}
|
|
433
418
|
|
package/src/fs/definitions.ts
CHANGED
|
@@ -13,12 +13,12 @@ export type FileReadResultStatus = 'success' | 'denied';
|
|
|
13
13
|
|
|
14
14
|
export interface FileReadRequestResult {
|
|
15
15
|
status: FileReadResultStatus
|
|
16
|
-
content: string | ArrayBuffer
|
|
16
|
+
content: string | ArrayBuffer | ArrayBufferLike | BlobPart
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface FileUpdate {
|
|
20
20
|
resourceUri: string
|
|
21
|
-
content: string | ArrayBuffer
|
|
21
|
+
content: string | ArrayBuffer | ArrayBufferLike | BlobPart
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export type FileUpdateResultStatus = 'equal' | 'updated' | 'created' | 'denied';
|
package/src/vscode/apiWrapper.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* --------------------------------------------------------------------------------------------
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) 2025 TypeFox and others.
|
|
3
3
|
* Licensed under the MIT License. See LICENSE in the package root for license information.
|
|
4
4
|
* ------------------------------------------------------------------------------------------ */
|
|
5
5
|
|
|
@@ -7,20 +7,29 @@ import { initialize, LogLevel } from '@codingame/monaco-vscode-api';
|
|
|
7
7
|
import { ExtensionHostKind, getExtensionManifests, registerExtension, type IExtensionManifest, type RegisterExtensionResult } from '@codingame/monaco-vscode-api/extensions';
|
|
8
8
|
import { DisposableStore, setUnexpectedErrorHandler } from '@codingame/monaco-vscode-api/monaco';
|
|
9
9
|
import getConfigurationServiceOverride, { initUserConfiguration } from '@codingame/monaco-vscode-configuration-service-override';
|
|
10
|
-
import
|
|
10
|
+
import * as monaco from '@codingame/monaco-vscode-editor-api';
|
|
11
11
|
import getLogServiceOverride from '@codingame/monaco-vscode-log-service-override';
|
|
12
12
|
import getModelServiceOverride from '@codingame/monaco-vscode-model-service-override';
|
|
13
|
-
import { ConsoleLogger,
|
|
13
|
+
import { ConsoleLogger, encodeStringOrUrlToDataUrl, type Logger } from 'monaco-languageclient/common';
|
|
14
14
|
import { useWorkerFactory } from 'monaco-languageclient/workerFactory';
|
|
15
15
|
import * as vscode from 'vscode';
|
|
16
16
|
import 'vscode/localExtensionHost';
|
|
17
|
-
import type { MonacoVscodeApiConfig } from './config.js';
|
|
17
|
+
import type { ExtensionConfig, MonacoVscodeApiConfig, ViewsConfig } from './config.js';
|
|
18
18
|
import { configureExtHostWorker, getEnhancedMonacoEnvironment, mergeServices, reportServiceLoading, useOpenEditorStub } from './utils.js';
|
|
19
19
|
|
|
20
|
-
export interface
|
|
20
|
+
export interface ViewsConfigRuntime extends ViewsConfig {
|
|
21
|
+
htmlContainer: HTMLElement;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface MonacoVscodeApiConfigRuntime extends MonacoVscodeApiConfig {
|
|
25
|
+
serviceOverrides: monaco.editor.IEditorOverrideServices;
|
|
26
|
+
logLevel: LogLevel | number;
|
|
27
|
+
viewsConfig: ViewsConfigRuntime;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface StartInstructions {
|
|
21
31
|
caller?: string;
|
|
22
32
|
performServiceConsistencyChecks?: boolean;
|
|
23
|
-
htmlContainer?: HTMLElement | null;
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
export class MonacoVscodeApiWrapper {
|
|
@@ -28,11 +37,20 @@ export class MonacoVscodeApiWrapper {
|
|
|
28
37
|
private logger: Logger = new ConsoleLogger();
|
|
29
38
|
private extensionRegisterResults: Map<string, | RegisterExtensionResult> = new Map();
|
|
30
39
|
private disposableStore: DisposableStore = new DisposableStore();
|
|
31
|
-
private apiConfig:
|
|
40
|
+
private apiConfig: MonacoVscodeApiConfigRuntime;
|
|
32
41
|
|
|
33
42
|
constructor(apiConfig: MonacoVscodeApiConfig) {
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
const intermediate = {
|
|
44
|
+
...apiConfig,
|
|
45
|
+
serviceOverrides: apiConfig.serviceOverrides ?? {},
|
|
46
|
+
logLevel: apiConfig.logLevel ?? LogLevel.Off,
|
|
47
|
+
};
|
|
48
|
+
if (intermediate.viewsConfig.htmlContainer === 'ReactPlaceholder') {
|
|
49
|
+
// this is temporary and must be overriden at start by react component with
|
|
50
|
+
// correct react dom element
|
|
51
|
+
intermediate.viewsConfig.htmlContainer = document.body;
|
|
52
|
+
}
|
|
53
|
+
this.apiConfig = intermediate as MonacoVscodeApiConfigRuntime;
|
|
36
54
|
this.logger.setLevel(this.apiConfig.logLevel);
|
|
37
55
|
}
|
|
38
56
|
|
|
@@ -48,6 +66,10 @@ export class MonacoVscodeApiWrapper {
|
|
|
48
66
|
return this.apiConfig;
|
|
49
67
|
}
|
|
50
68
|
|
|
69
|
+
getHtmlContainer() {
|
|
70
|
+
return this.apiConfig.viewsConfig.htmlContainer;
|
|
71
|
+
}
|
|
72
|
+
|
|
51
73
|
protected configureMonacoWorkers() {
|
|
52
74
|
if (typeof this.apiConfig.monacoWorkerFactory === 'function') {
|
|
53
75
|
this.apiConfig.monacoWorkerFactory(this.logger);
|
|
@@ -62,7 +84,9 @@ export class MonacoVscodeApiWrapper {
|
|
|
62
84
|
if (this.apiConfig.$type === 'extended') {
|
|
63
85
|
const getTextmateServiceOverride = (await import('@codingame/monaco-vscode-textmate-service-override')).default;
|
|
64
86
|
const getThemeServiceOverride = (await import('@codingame/monaco-vscode-theme-service-override')).default;
|
|
87
|
+
const getLanguagesServiceOverride = (await import('@codingame/monaco-vscode-languages-service-override')).default;
|
|
65
88
|
mergeServices(this.apiConfig.serviceOverrides, {
|
|
89
|
+
...getLanguagesServiceOverride(),
|
|
66
90
|
...getTextmateServiceOverride(),
|
|
67
91
|
...getThemeServiceOverride()
|
|
68
92
|
});
|
|
@@ -75,19 +99,19 @@ export class MonacoVscodeApiWrapper {
|
|
|
75
99
|
}
|
|
76
100
|
|
|
77
101
|
protected async configureViewsServices() {
|
|
78
|
-
const
|
|
79
|
-
if (this.apiConfig.$type === 'classic' && (
|
|
80
|
-
throw new Error(`View Service Type "${
|
|
102
|
+
const viewsConfigType = this.apiConfig.viewsConfig.$type;
|
|
103
|
+
if (this.apiConfig.$type === 'classic' && (viewsConfigType === 'ViewsService' || viewsConfigType === 'WorkspaceService')) {
|
|
104
|
+
throw new Error(`View Service Type "${viewsConfigType}" cannot be used with classic configuration.`);
|
|
81
105
|
}
|
|
82
106
|
|
|
83
107
|
const envEnhanced = getEnhancedMonacoEnvironment();
|
|
84
|
-
if (
|
|
108
|
+
if (viewsConfigType === 'ViewsService') {
|
|
85
109
|
const getViewsServiceOverride = (await import('@codingame/monaco-vscode-views-service-override')).default;
|
|
86
110
|
mergeServices(this.apiConfig.serviceOverrides, {
|
|
87
111
|
...getViewsServiceOverride(this.apiConfig.viewsConfig.openEditorFunc ?? useOpenEditorStub)
|
|
88
112
|
});
|
|
89
113
|
envEnhanced.viewServiceType = 'ViewsService';
|
|
90
|
-
} else if (
|
|
114
|
+
} else if (viewsConfigType === 'WorkspaceService') {
|
|
91
115
|
const getWorkbenchServiceOverride = (await import('@codingame/monaco-vscode-workbench-service-override')).default;
|
|
92
116
|
mergeServices(this.apiConfig.serviceOverrides, {
|
|
93
117
|
...getWorkbenchServiceOverride()
|
|
@@ -96,15 +120,15 @@ export class MonacoVscodeApiWrapper {
|
|
|
96
120
|
} else {
|
|
97
121
|
const getEditorServiceOverride = (await import('@codingame/monaco-vscode-editor-service-override')).default;
|
|
98
122
|
mergeServices(this.apiConfig.serviceOverrides, {
|
|
99
|
-
...getEditorServiceOverride(this.apiConfig.viewsConfig
|
|
123
|
+
...getEditorServiceOverride(this.apiConfig.viewsConfig.openEditorFunc ?? useOpenEditorStub)
|
|
100
124
|
});
|
|
101
125
|
envEnhanced.viewServiceType = 'EditorService';
|
|
102
126
|
}
|
|
103
127
|
}
|
|
104
128
|
|
|
105
129
|
protected async applyViewsPostConfig() {
|
|
106
|
-
this.apiConfig.viewsConfig
|
|
107
|
-
await this.apiConfig.viewsConfig
|
|
130
|
+
this.apiConfig.viewsConfig.htmlAugmentationInstructions?.(this.apiConfig.viewsConfig.htmlContainer);
|
|
131
|
+
await this.apiConfig.viewsConfig.viewsInitFunc?.();
|
|
108
132
|
}
|
|
109
133
|
|
|
110
134
|
/**
|
|
@@ -128,13 +152,13 @@ export class MonacoVscodeApiWrapper {
|
|
|
128
152
|
}
|
|
129
153
|
|
|
130
154
|
/**
|
|
131
|
-
*
|
|
155
|
+
* Set the log-level via the development settings.
|
|
156
|
+
* VSCode developmentOptions are read-only. There are no functions exposed to set options directly.
|
|
157
|
+
* Therefore the Object properties need to be manipulated directly via Object.assign.
|
|
132
158
|
*/
|
|
133
159
|
protected configureDevLogLevel() {
|
|
134
160
|
const devLogLevel = this.apiConfig.workspaceConfig?.developmentOptions?.logLevel;
|
|
135
161
|
if (devLogLevel === undefined) {
|
|
136
|
-
|
|
137
|
-
// this needs to be done so complicated, because developmentOptions is read-only
|
|
138
162
|
const devOptions: Record<string, unknown> = {
|
|
139
163
|
...this.apiConfig.workspaceConfig!.developmentOptions
|
|
140
164
|
};
|
|
@@ -169,7 +193,6 @@ export class MonacoVscodeApiWrapper {
|
|
|
169
193
|
protected async supplyRequiredServices() {
|
|
170
194
|
return {
|
|
171
195
|
...getConfigurationServiceOverride(),
|
|
172
|
-
...getLanguagesServiceOverride(),
|
|
173
196
|
...getLogServiceOverride(),
|
|
174
197
|
...getModelServiceOverride()
|
|
175
198
|
};
|
|
@@ -204,8 +227,9 @@ export class MonacoVscodeApiWrapper {
|
|
|
204
227
|
* - languages
|
|
205
228
|
* - log
|
|
206
229
|
* - model
|
|
230
|
+
* - configuration services
|
|
207
231
|
*/
|
|
208
|
-
protected async
|
|
232
|
+
protected async initAllServices(performServiceConsistencyChecks?: boolean) {
|
|
209
233
|
const services = await this.supplyRequiredServices();
|
|
210
234
|
|
|
211
235
|
mergeServices(services, this.apiConfig.serviceOverrides);
|
|
@@ -213,12 +237,12 @@ export class MonacoVscodeApiWrapper {
|
|
|
213
237
|
|
|
214
238
|
reportServiceLoading(services, this.logger);
|
|
215
239
|
|
|
216
|
-
if (
|
|
240
|
+
if (performServiceConsistencyChecks ?? true) {
|
|
217
241
|
this.checkServiceConsistency();
|
|
218
242
|
}
|
|
219
243
|
|
|
220
|
-
if (this.apiConfig.viewsConfig
|
|
221
|
-
await initialize(services, this.apiConfig.htmlContainer, this.apiConfig.workspaceConfig, this.apiConfig.envOptions);
|
|
244
|
+
if (this.apiConfig.viewsConfig.$type === 'ViewsService' || this.apiConfig.viewsConfig.$type === 'WorkspaceService') {
|
|
245
|
+
await initialize(services, this.apiConfig.viewsConfig.htmlContainer, this.apiConfig.workspaceConfig, this.apiConfig.envOptions);
|
|
222
246
|
} else {
|
|
223
247
|
await initialize(services, undefined, this.apiConfig.workspaceConfig, this.apiConfig.envOptions);
|
|
224
248
|
}
|
|
@@ -242,21 +266,29 @@ export class MonacoVscodeApiWrapper {
|
|
|
242
266
|
});
|
|
243
267
|
for (const extensionConfig of extensions ?? []) {
|
|
244
268
|
if (!extensionIds.includes(`${extensionConfig.config.publisher}.${extensionConfig.config.name}`)) {
|
|
245
|
-
|
|
246
|
-
const extRegResult = registerExtension(manifest, ExtensionHostKind.LocalProcess);
|
|
247
|
-
this.extensionRegisterResults.set(manifest.name, extRegResult);
|
|
248
|
-
if (extensionConfig.filesOrContents && Object.hasOwn(extRegResult, 'registerFileUrl')) {
|
|
249
|
-
for (const entry of extensionConfig.filesOrContents) {
|
|
250
|
-
this.disposableStore.add(extRegResult.registerFileUrl(entry[0], verifyUrlOrCreateDataUrl(entry[1])));
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
allPromises.push(extRegResult.whenReady());
|
|
269
|
+
allPromises.push(this.initExtension(extensionConfig, extensionIds));
|
|
254
270
|
}
|
|
255
271
|
}
|
|
256
272
|
await Promise.all(allPromises);
|
|
257
273
|
}
|
|
258
274
|
}
|
|
259
275
|
|
|
276
|
+
protected initExtension(extensionConfig: ExtensionConfig, extensionIds: string[]): Promise<void> {
|
|
277
|
+
if (!extensionIds.includes(`${extensionConfig.config.publisher}.${extensionConfig.config.name}`)) {
|
|
278
|
+
const manifest = extensionConfig.config as IExtensionManifest;
|
|
279
|
+
const extRegResult = registerExtension(manifest, ExtensionHostKind.LocalProcess);
|
|
280
|
+
this.extensionRegisterResults.set(manifest.name, extRegResult);
|
|
281
|
+
if (extensionConfig.filesOrContents && Object.hasOwn(extRegResult, 'registerFileUrl')) {
|
|
282
|
+
for (const entry of extensionConfig.filesOrContents) {
|
|
283
|
+
this.disposableStore.add(extRegResult.registerFileUrl(entry[0], encodeStringOrUrlToDataUrl(entry[1])));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return extRegResult.whenReady();
|
|
287
|
+
} else {
|
|
288
|
+
return Promise.resolve();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
260
292
|
protected markGlobalInit() {
|
|
261
293
|
this.logger.debug('markGlobalInit');
|
|
262
294
|
|
|
@@ -268,33 +300,41 @@ export class MonacoVscodeApiWrapper {
|
|
|
268
300
|
|
|
269
301
|
protected markGlobalInitDone() {
|
|
270
302
|
const envEnhanced = getEnhancedMonacoEnvironment();
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
303
|
+
envEnhanced.vscodeApiGlobalInitResolve?.();
|
|
304
|
+
|
|
274
305
|
envEnhanced.vscodeApiInitialised = true;
|
|
275
306
|
envEnhanced.vscodeApiGlobalInitAwait = undefined;
|
|
276
307
|
envEnhanced.vscodeApiGlobalInitResolve = undefined;
|
|
277
308
|
this.logger.debug('markGlobalInitDone');
|
|
278
309
|
}
|
|
279
310
|
|
|
280
|
-
|
|
311
|
+
overrideViewsConfig(viewsConfigOverride: ViewsConfigRuntime) {
|
|
312
|
+
const orgViewsConfig = this.apiConfig.viewsConfig;
|
|
313
|
+
this.apiConfig.viewsConfig = {
|
|
314
|
+
$type: viewsConfigOverride.$type,
|
|
315
|
+
htmlContainer: viewsConfigOverride.htmlContainer,
|
|
316
|
+
htmlAugmentationInstructions: viewsConfigOverride.htmlAugmentationInstructions ?? orgViewsConfig.htmlAugmentationInstructions,
|
|
317
|
+
openEditorFunc: viewsConfigOverride.openEditorFunc ?? orgViewsConfig.openEditorFunc,
|
|
318
|
+
viewsInitFunc: viewsConfigOverride.viewsInitFunc ?? orgViewsConfig.viewsInitFunc
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async start(startInstructions?: StartInstructions): Promise<void> {
|
|
281
323
|
const envEnhanced = getEnhancedMonacoEnvironment();
|
|
282
324
|
if (envEnhanced.vscodeApiInitialised === true) {
|
|
283
325
|
this.logger.warn('Initialization of monaco-vscode api can only performed once!');
|
|
284
326
|
} else {
|
|
285
327
|
if (!(envEnhanced.vscodeApiInitialising === true)) {
|
|
328
|
+
|
|
286
329
|
envEnhanced.vscodeApiInitialising = true;
|
|
287
330
|
this.markGlobalInit();
|
|
288
|
-
if (instructions?.htmlContainer !== undefined && instructions.htmlContainer !== null) {
|
|
289
|
-
this.apiConfig.htmlContainer = instructions.htmlContainer;
|
|
290
|
-
}
|
|
291
331
|
|
|
292
332
|
// ensures "vscodeApiConfig.workspaceConfig" is available
|
|
293
333
|
this.configureWorkspaceConfig();
|
|
294
334
|
|
|
295
335
|
// ensure logging and development logging options are in-line
|
|
296
336
|
this.configureDevLogLevel();
|
|
297
|
-
this.logger.info(`Initializing monaco-vscode api. Caller: ${
|
|
337
|
+
this.logger.info(`Initializing monaco-vscode api. Caller: ${startInstructions?.caller ?? 'unknown'}`);
|
|
298
338
|
|
|
299
339
|
await this.configureMonacoWorkers();
|
|
300
340
|
|
|
@@ -304,12 +344,12 @@ export class MonacoVscodeApiWrapper {
|
|
|
304
344
|
// ensure one of the three potential view services are configured
|
|
305
345
|
await this.configureViewsServices();
|
|
306
346
|
|
|
307
|
-
//
|
|
347
|
+
// enforce semantic highlighting if configured
|
|
308
348
|
this.configureSemanticHighlighting();
|
|
309
349
|
|
|
310
350
|
await this.initUserConfiguration();
|
|
311
351
|
|
|
312
|
-
await this.
|
|
352
|
+
await this.initAllServices(startInstructions?.performServiceConsistencyChecks);
|
|
313
353
|
|
|
314
354
|
await this.applyViewsPostConfig();
|
|
315
355
|
|
package/src/vscode/config.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* --------------------------------------------------------------------------------------------
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) 2025 TypeFox and others.
|
|
3
3
|
* Licensed under the MIT License. See LICENSE in the package root for license information.
|
|
4
4
|
* ------------------------------------------------------------------------------------------ */
|
|
5
5
|
|
|
@@ -11,21 +11,27 @@ import type { EnvironmentOverride } from '@codingame/monaco-vscode-api/workbench
|
|
|
11
11
|
import type { OpenEditor } from '@codingame/monaco-vscode-editor-service-override';
|
|
12
12
|
import type { Logger } from 'monaco-languageclient/common';
|
|
13
13
|
|
|
14
|
+
export type OverallConfigType = 'extended' | 'classic';
|
|
15
|
+
|
|
16
|
+
export type ViewsConfigTypes = 'EditorService' | 'ViewsService' | 'WorkspaceService';
|
|
17
|
+
|
|
18
|
+
export type HtmlContainerConfig = HTMLElement | 'ReactPlaceholder';
|
|
19
|
+
|
|
14
20
|
export interface MonacoEnvironmentEnhanced extends monaco.Environment {
|
|
15
21
|
vscodeApiInitialising?: boolean;
|
|
16
22
|
vscodeApiInitialised?: boolean;
|
|
17
23
|
vscodeApiGlobalInitAwait?: Promise<void>;
|
|
18
24
|
vscodeApiGlobalInitResolve?: ((value: void | PromiseLike<void>) => void);
|
|
19
|
-
viewServiceType?:
|
|
25
|
+
viewServiceType?: ViewsConfigTypes;
|
|
20
26
|
}
|
|
21
27
|
|
|
22
|
-
export type OverallConfigType = 'extended' | 'classic';
|
|
23
|
-
|
|
24
28
|
export interface UserConfiguration {
|
|
25
29
|
json?: string;
|
|
26
30
|
}
|
|
31
|
+
|
|
27
32
|
export interface ViewsConfig {
|
|
28
|
-
|
|
33
|
+
$type: ViewsConfigTypes;
|
|
34
|
+
htmlContainer: HtmlContainerConfig;
|
|
29
35
|
openEditorFunc?: OpenEditor;
|
|
30
36
|
htmlAugmentationInstructions?: (htmlContainer: HTMLElement | null | undefined) => void;
|
|
31
37
|
viewsInitFunc?: () => Promise<void>;
|
|
@@ -38,12 +44,11 @@ export interface ExtensionConfig {
|
|
|
38
44
|
|
|
39
45
|
export interface MonacoVscodeApiConfig {
|
|
40
46
|
$type: OverallConfigType;
|
|
41
|
-
|
|
42
|
-
serviceOverrides
|
|
47
|
+
viewsConfig: ViewsConfig,
|
|
48
|
+
serviceOverrides?: monaco.editor.IEditorOverrideServices;
|
|
43
49
|
logLevel?: LogLevel | number;
|
|
44
50
|
workspaceConfig?: IWorkbenchConstructionOptions;
|
|
45
51
|
userConfiguration?: UserConfiguration;
|
|
46
|
-
viewsConfig?: ViewsConfig,
|
|
47
52
|
envOptions?: EnvironmentOverride;
|
|
48
53
|
extensions?: ExtensionConfig[];
|
|
49
54
|
monacoWorkerFactory?: (logger?: Logger) => void;
|