Skip to content

Commit

Permalink
feat: make LanguageClientConfig require languageId
Browse files Browse the repository at this point in the history
  • Loading branch information
kaisalmen committed May 2, 2024
1 parent c8bb5c2 commit 7f97fa4
Show file tree
Hide file tree
Showing 17 changed files with 113 additions and 86 deletions.
1 change: 1 addition & 0 deletions packages/examples/src/groovy/client/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const userConfig: UserConfig = {
}
},
languageClientConfig: {
languageId: 'groovy',
options: {
$type: 'WebSocketUrl',
url: `ws://localhost:${groovyConfig.port}${groovyConfig.path}`
Expand Down
3 changes: 2 additions & 1 deletion packages/examples/src/json/client/wrapperWs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-service-override';
// this is required syntax highlighting
import '@codingame/monaco-vscode-json-default-extension';
import '@codingame/monaco-vscode-json-default-extension';
import { disposeEditor, startEditor, swapEditors } from '../../common/example-apps-common.js';
import { UserConfig } from 'monaco-editor-wrapper';
import { useWorkerFactory } from 'monaco-editor-wrapper/workerFactory';
Expand Down Expand Up @@ -53,6 +53,7 @@ export const jsonClientUserConfig: UserConfig = {
}
},
languageClientConfig: {
languageId: 'json',
options: {
$type: 'WebSocketUrl',
url: 'ws://localhost:30000/sampleServer',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const setupLangiumClientClassic = async (): Promise<UserConfig> => {
}
},
languageClientConfig: {
languageId: 'langium',
options: {
$type: 'WorkerDirect',
worker: langiumWorker
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export const setupLangiumClientExtended = async (): Promise<UserConfig> => {
}
},
languageClientConfig: {
languageId: 'langium',
options: {
$type: 'WorkerDirect',
worker: langiumWorker
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const createLangiumGlobalConfig = async (worker: Worker, messagePort?: Me
}
},
languageClientConfig: {
languageId: 'statemachine',
options: {
$type: 'WorkerDirect',
worker,
Expand Down
3 changes: 2 additions & 1 deletion packages/examples/src/python/client/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import { MonacoLanguageClient } from 'monaco-languageclient';
export const createUserConfig = (workspaceRoot: string, code: string, codeUri: string): UserConfig => {
return {
languageClientConfig: {
languageId: 'python',
name: 'Python Language Server Example',
options: {
name: 'Python Language Server Example',
$type: 'WebSocket',
host: 'localhost',
port: 30001,
Expand Down
3 changes: 2 additions & 1 deletion packages/examples/src/ts/wrapperAdvanced.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ Same again.`
}
},
languageClientConfig: {
languageId: 'json',
name: 'wrapper42 language client',
options: {
$type: 'WebSocket',
name: 'wrapper42 language client',
host: 'localhost',
port: 30000,
path: 'sampleServer',
Expand Down
15 changes: 6 additions & 9 deletions packages/wrapper/src/commonTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,16 @@ export type WebSocketCallOptions = {
reportStatus?: boolean;
}

export type LanguageClientConfigBase = {
name?: string;
}

export type LanguageClientConfigType = 'WebSocket' | 'WebSocketUrl' | 'WorkerConfig' | 'Worker';

export type WebSocketUrl = LanguageClientConfigBase & {
export type WebSocketUrl = {
secured: boolean;
host: string;
port?: number;
path?: string;
}

export type WebSocketConfigOptions = LanguageClientConfigBase & {
export type WebSocketConfigOptions = {
$type: 'WebSocket'
secured: boolean;
host: string;
Expand All @@ -36,21 +32,22 @@ export type WebSocketConfigOptions = LanguageClientConfigBase & {
stopOptions?: WebSocketCallOptions;
}

export type WebSocketConfigOptionsUrl = LanguageClientConfigBase & {
export type WebSocketConfigOptionsUrl = {
$type: 'WebSocketUrl'
url: string;
startOptions?: WebSocketCallOptions;
stopOptions?: WebSocketCallOptions;
}

export type WorkerConfigOptions = LanguageClientConfigBase & {
export type WorkerConfigOptions = {
$type: 'WorkerConfig'
url: URL;
type: 'classic' | 'module';
messagePort?: MessagePort;
workerName?: string;
};

export type WorkerConfigDirect = LanguageClientConfigBase & {
export type WorkerConfigDirect = {
$type: 'WorkerDirect';
worker: Worker;
messagePort?: MessagePort;
Expand Down
2 changes: 1 addition & 1 deletion packages/wrapper/src/editorAppClassic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import * as monaco from 'monaco-editor';
import { Logger } from 'monaco-languageclient/tools';
import { EditorAppBase, EditorAppConfigBase, ModelUpdateType, isEqual, isModelUpdateRequired } from './editorAppBase.js';
import { UserConfig } from './wrapper.js';
import { UserConfig } from './userConfig.js';

export type EditorAppConfigClassic = EditorAppConfigBase & {
$type: 'classic';
Expand Down
2 changes: 1 addition & 1 deletion packages/wrapper/src/editorAppExtended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as monaco from 'monaco-editor';
import { EditorAppBase, EditorAppConfigBase, ModelUpdateType, isEqual, isModelUpdateRequired } from './editorAppBase.js';
import { registerExtension, IExtensionManifest, ExtensionHostKind } from 'vscode/extensions';
import { Logger } from 'monaco-languageclient/tools';
import { UserConfig } from './wrapper.js';
import { UserConfig } from './userConfig.js';
import { verifyUrlorCreateDataUrl } from './utils.js';

export type ExtensionConfig = {
Expand Down
2 changes: 1 addition & 1 deletion packages/wrapper/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import {
import type {
UserConfig,
WrapperConfig
} from './wrapper.js';
} from './userConfig.js';

import {
MonacoEditorLanguageClientWrapper,
Expand Down
25 changes: 12 additions & 13 deletions packages/wrapper/src/languageClientWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import { createUrl } from './utils.js';
import { WebSocketConfigOptions, WebSocketConfigOptionsUrl, WorkerConfigDirect, WorkerConfigOptions } from './commonTypes.js';

export type LanguageClientConfig = {
languageId: string;
options: WebSocketConfigOptions | WebSocketConfigOptionsUrl | WorkerConfigOptions | WorkerConfigDirect;
name?: string;
clientOptions?: LanguageClientOptions;
connectionProvider?: IConnectionProvider;
}
Expand All @@ -28,20 +30,15 @@ export class LanguageClientWrapper {
private languageClientConfig?: LanguageClientConfig;
private worker?: Worker;
private port: MessagePort;
private languageId: string;
private name?: string;
private logger: Logger | undefined;

async init(config: {
languageId: string,
languageClientConfig?: LanguageClientConfig,
languageClientConfig: LanguageClientConfig,
logger?: Logger
}) {
this.languageId = config.languageId;
if (config.languageClientConfig) {
this.languageClientConfig = config.languageClientConfig;
this.name = this.languageClientConfig.options.name ?? 'unnamed';
}
this.languageClientConfig = config.languageClientConfig;
this.name = this.languageClientConfig.name ?? 'unnamed';
this.logger = config.logger;
}

Expand Down Expand Up @@ -135,7 +132,7 @@ export class LanguageClientWrapper {
const workerConfig = lcConfig as WorkerConfigOptions;
this.worker = new Worker(new URL(workerConfig.url, import.meta.url).href, {
type: workerConfig.type,
name: workerConfig.name
name: workerConfig.workerName
});

this.worker.onerror = (ev) => {
Expand Down Expand Up @@ -201,12 +198,13 @@ export class LanguageClientWrapper {
}

private createLanguageClient(transports: MessageTransports): MonacoLanguageClient {
const languageId = this.languageClientConfig?.languageId ?? 'unknown';
const mlcConfig = {
name: this.languageClientConfig?.options.name ?? 'Monaco Wrapper Language Client',
name: this.languageClientConfig?.name ?? 'Monaco Wrapper Language Client',

// allow to fully override the clientOptions
clientOptions: this.languageClientConfig?.clientOptions ?? {
documentSelector: [this.languageId!],
documentSelector: [languageId],
// disable the default error handler
errorHandler: {
error: () => ({ action: ErrorAction.Continue }),
Expand All @@ -220,8 +218,9 @@ export class LanguageClientWrapper {
}
}
};
if (!mlcConfig.clientOptions.documentSelector?.includes(this.languageId)) {
throw new Error(`languageClientWrapper (${this.name}): The language id '${this.languageId}' is not included in the document selector.`);

if (!mlcConfig.clientOptions.documentSelector?.includes(languageId)) {
throw new Error(`languageClientWrapper (${this.name}): The language id '${languageId}' is not included in the document selector.`);
}

return new MonacoLanguageClient(mlcConfig);
Expand Down
22 changes: 22 additions & 0 deletions packages/wrapper/src/userConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) 2024 TypeFox and others.
* Licensed under the MIT License. See LICENSE in the package root for license information.
* ------------------------------------------------------------------------------------------ */

import { InitializeServiceConfig } from 'monaco-languageclient/vscode/services';
import type { LoggerConfig } from 'monaco-languageclient/tools';
import { EditorAppConfigExtended } from './editorAppExtended.js';
import { EditorAppConfigClassic } from './editorAppClassic.js';
import { LanguageClientConfig } from './languageClientWrapper.js';

export type WrapperConfig = {
serviceConfig?: InitializeServiceConfig;
editorAppConfig: EditorAppConfigExtended | EditorAppConfigClassic;
};

export type UserConfig = {
id?: string;
loggerConfig?: LoggerConfig;
wrapperConfig: WrapperConfig;
languageClientConfig?: LanguageClientConfig;
}
39 changes: 16 additions & 23 deletions packages/wrapper/src/wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,15 @@

import * as monaco from 'monaco-editor';
import { MonacoLanguageClient } from 'monaco-languageclient';
import { InitializeServiceConfig, initServices } from 'monaco-languageclient/vscode/services';
import { initServices } from 'monaco-languageclient/vscode/services';
import { Logger } from 'monaco-languageclient/tools';
import type { LoggerConfig } from 'monaco-languageclient/tools';
import { checkServiceConsistency, configureServices } from './vscode/services.js';
import { EditorAppExtended, EditorAppConfigExtended } from './editorAppExtended.js';
import { EditorAppClassic, EditorAppConfigClassic } from './editorAppClassic.js';
import { EditorAppExtended } from './editorAppExtended.js';
import { EditorAppClassic } from './editorAppClassic.js';
import { ModelUpdate } from './editorAppBase.js';
import { LanguageClientConfig, LanguageClientWrapper } from './languageClientWrapper.js';
import { LanguageClientWrapper } from './languageClientWrapper.js';
import { WorkerConfigDirect, WorkerConfigOptions } from './commonTypes.js';

export type WrapperConfig = {
serviceConfig?: InitializeServiceConfig;
editorAppConfig: EditorAppConfigExtended | EditorAppConfigClassic;
};

export type UserConfig = {
id?: string;
loggerConfig?: LoggerConfig;
wrapperConfig: WrapperConfig;
languageClientConfig?: LanguageClientConfig;
}
import { UserConfig } from './userConfig.js';

/**
* This class is responsible for the overall ochestration.
Expand Down Expand Up @@ -78,12 +66,13 @@ export class MonacoEditorLanguageClientWrapper {
logger: this.logger
});

this.languageClientWrapper = new LanguageClientWrapper();
await this.languageClientWrapper.init({
languageId: this.editorApp.getConfig().languageId,
languageClientConfig: userConfig.languageClientConfig,
logger: this.logger
});
if (userConfig.languageClientConfig) {
this.languageClientWrapper = new LanguageClientWrapper();
await this.languageClientWrapper.init({
languageClientConfig: userConfig.languageClientConfig,
logger: this.logger
});
}

this.initDone = true;
}
Expand Down Expand Up @@ -132,6 +121,10 @@ export class MonacoEditorLanguageClientWrapper {
return true;
}

haveLanguageClient(): boolean {
return this.languageClientWrapper !== undefined;
}

getMonacoEditorApp() {
return this.editorApp;
}
Expand Down
11 changes: 10 additions & 1 deletion packages/wrapper/test/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,18 @@ export const updateExtendedAppPrototyp = async () => {
* Error: Unable to load extension-file://vscode.theme-defaults/themes/light_modern.json:
* Unable to read file 'extension-file://vscode.theme-defaults/themes/light_modern.json' (TypeError: Failed to fetch)
*/
export const createWrapper = async (userConfig: UserConfig) => {
export const createAndInitWrapper = async (userConfig: UserConfig) => {
updateExtendedAppPrototyp();
const wrapper = new MonacoEditorLanguageClientWrapper();
await wrapper.init(userConfig);
return wrapper;
};

/**
* Helper to generate a quick worker from a function blob
*/
export const createWorkerFromFunction = (fn: () => void): Worker => {
return new Worker(URL.createObjectURL(
new Blob([`(${fn.toString()})()`], { type: 'application/javascript' })
));
};
Loading

0 comments on commit 7f97fa4

Please sign in to comment.