Skip to content

Commit 9cd6b93

Browse files
committed
LanguageClientWrapper improvements: Allow to directly pass a web socket
1 parent 737c347 commit 9cd6b93

25 files changed

+278
-198
lines changed

packages/client/src/client.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* --------------------------------------------------------------------------------------------
2+
* Copyright (c) 2024 TypeFox and others.
3+
* Licensed under the MIT License. See LICENSE in the package root for license information.
4+
* ------------------------------------------------------------------------------------------ */
5+
6+
import { BaseLanguageClient, MessageTransports, LanguageClientOptions } from 'vscode-languageclient/browser.js';
7+
8+
export interface IConnectionProvider {
9+
get(encoding: string): Promise<MessageTransports>;
10+
}
11+
12+
export type MonacoLanguageClientOptions = {
13+
name: string;
14+
id?: string;
15+
clientOptions: LanguageClientOptions;
16+
connectionProvider: IConnectionProvider;
17+
}
18+
19+
export class MonacoLanguageClient extends BaseLanguageClient {
20+
protected readonly connectionProvider: IConnectionProvider;
21+
22+
constructor({ id, name, clientOptions, connectionProvider }: MonacoLanguageClientOptions) {
23+
super(id ?? name.toLowerCase(), name, clientOptions);
24+
this.connectionProvider = connectionProvider;
25+
}
26+
27+
protected override createMessageTransports(encoding: string): Promise<MessageTransports> {
28+
return this.connectionProvider.get(encoding);
29+
}
30+
}

packages/wrapper/src/commonTypes.ts renamed to packages/client/src/commonTypes.ts

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See LICENSE in the package root for license information.
44
* ------------------------------------------------------------------------------------------ */
55

6-
import { MonacoLanguageClient } from 'monaco-languageclient';
6+
import { MonacoLanguageClient } from './client.js';
77

88
export type WebSocketCallOptions = {
99
/** Adds handle on languageClient */
@@ -12,29 +12,45 @@ export type WebSocketCallOptions = {
1212
reportStatus?: boolean;
1313
}
1414

15-
export type LanguageClientConfigType = 'WebSocket' | 'WebSocketUrl' | 'WorkerConfig' | 'Worker';
15+
export type LanguageClientRestartOptions = {
16+
retries: number;
17+
timeout: number;
18+
keepWorker?: boolean;
19+
}
1620

17-
export type WebSocketUrl = {
18-
secured: boolean;
19-
host: string;
20-
port?: number;
21-
path?: string;
21+
export type LanguageClientConfigType = 'WebSocket' | 'WebSocketUrl' | 'WebSocketDirect' | 'WorkerConfig' | 'Worker';
22+
23+
export type LanguageClientConfigOptions = (WebSocketConfigOptionsDirect | WebSocketConfigOptionsParams | WebSocketConfigOptionsUrl | WorkerConfigOptions | WorkerConfigDirect) & {
24+
restartOptions?: LanguageClientRestartOptions;
2225
}
2326

24-
export type WebSocketConfigOptions = {
25-
$type: 'WebSocket'
27+
export type WebSocketUrlParams = {
2628
secured: boolean;
2729
host: string;
2830
port?: number;
2931
path?: string;
3032
extraParams?: Record<string, string | number | Array<string | number>>;
33+
}
34+
35+
export type WebSocketUrlString = {
36+
url: string;
37+
}
38+
39+
export type WebSocketConfigOptionsDirect = {
40+
$type: 'WebSocketDirect'
41+
webSocket: WebSocket
42+
startOptions?: WebSocketCallOptions;
43+
stopOptions?: WebSocketCallOptions;
44+
}
45+
46+
export type WebSocketConfigOptionsParams = WebSocketUrlParams & {
47+
$type: 'WebSocketParams'
3148
startOptions?: WebSocketCallOptions;
3249
stopOptions?: WebSocketCallOptions;
3350
}
3451

35-
export type WebSocketConfigOptionsUrl = {
52+
export type WebSocketConfigOptionsUrl = WebSocketUrlString & {
3653
$type: 'WebSocketUrl'
37-
url: string;
3854
startOptions?: WebSocketCallOptions;
3955
stopOptions?: WebSocketCallOptions;
4056
}

packages/client/src/index.ts

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,7 @@
33
* Licensed under the MIT License. See LICENSE in the package root for license information.
44
* ------------------------------------------------------------------------------------------ */
55

6-
import { BaseLanguageClient, MessageTransports, LanguageClientOptions } from 'vscode-languageclient/lib/common/client.js';
7-
8-
export interface IConnectionProvider {
9-
get(encoding: string): Promise<MessageTransports>;
10-
}
11-
12-
export type MonacoLanguageClientOptions = {
13-
name: string;
14-
id?: string;
15-
clientOptions: LanguageClientOptions;
16-
connectionProvider: IConnectionProvider;
17-
}
18-
19-
export class MonacoLanguageClient extends BaseLanguageClient {
20-
protected readonly connectionProvider: IConnectionProvider;
21-
22-
constructor({ id, name, clientOptions, connectionProvider }: MonacoLanguageClientOptions) {
23-
super(id ?? name.toLowerCase(), name, clientOptions);
24-
this.connectionProvider = connectionProvider;
25-
}
26-
27-
protected override createMessageTransports(encoding: string): Promise<MessageTransports> {
28-
return this.connectionProvider.get(encoding);
29-
}
30-
}
6+
export type * from './client.js';
7+
export * from './client.js';
8+
export type * from './commonTypes.js';
9+
export * from './commonTypes.js';

packages/client/tsconfig.src.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
"rootDir": "src",
55
"outDir": "lib",
66
"declarationDir": "lib",
7-
"types": [
8-
"vscode"
9-
]
7+
// because vscode-jsonrpc requires DedicatedWorkerGlobalScope
8+
// we are required to include both DOM and WebWorker libs
9+
// the only way out currently is to disable lib checking
10+
"skipLibCheck": true
1011
},
1112
"include": [
1213
"src/**/*.ts",

packages/examples/src/bare/client.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import '@codingame/monaco-vscode-theme-defaults-default-extension';
1313
import '@codingame/monaco-vscode-json-default-extension';
1414
import { MonacoLanguageClient } from 'monaco-languageclient';
1515
import { WebSocketMessageReader, WebSocketMessageWriter, toSocket } from 'vscode-ws-jsonrpc';
16-
import { CloseAction, ErrorAction, MessageTransports } from 'vscode-languageclient';
16+
import { CloseAction, ErrorAction, MessageTransports } from 'vscode-languageclient/browser.js';
1717
import { useWorkerFactory } from 'monaco-editor-wrapper/workerFactory';
1818

1919
export const configureMonacoWorkers = () => {
@@ -87,9 +87,7 @@ export const createLanguageClient = (transports: MessageTransports): MonacoLangu
8787
},
8888
// create a language client connection from the JSON RPC connection on demand
8989
connectionProvider: {
90-
get: () => {
91-
return Promise.resolve(transports);
92-
}
90+
get: async () => (transports)
9391
}
9492
});
9593
};

packages/examples/src/common/node/server-commons.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { dirname } from 'node:path';
1010
import { fileURLToPath } from 'node:url';
1111
import { IWebSocket, WebSocketMessageReader, WebSocketMessageWriter } from 'vscode-ws-jsonrpc';
1212
import { createConnection, createServerProcess, forward } from 'vscode-ws-jsonrpc/server';
13-
import { Message, InitializeRequest, InitializeParams } from 'vscode-languageserver';
13+
import { Message, InitializeRequest, InitializeParams, RequestMessage, ResponseMessage } from 'vscode-languageserver-protocol';
1414
import * as cp from 'child_process';
1515

1616
export enum LanguageName {
@@ -28,6 +28,9 @@ export interface LanguageServerRunConfig {
2828
runCommandArgs: string[];
2929
wsServerOptions: ServerOptions,
3030
spawnOptions?: cp.SpawnOptions;
31+
logMessages?: boolean;
32+
requestMessageHandler?: (message: RequestMessage) => RequestMessage;
33+
responseMessageHandler?: (message: ResponseMessage) => ResponseMessage;
3134
}
3235

3336
/**
@@ -43,16 +46,27 @@ export const launchLanguageServer = (runconfig: LanguageServerRunConfig, socket:
4346
if (serverConnection) {
4447
forward(socketConnection, serverConnection, message => {
4548
if (Message.isRequest(message)) {
46-
console.log(`${serverName} Server received:`);
47-
console.log(message);
4849
if (message.method === InitializeRequest.type.method) {
4950
const initializeParams = message.params as InitializeParams;
5051
initializeParams.processId = process.pid;
5152
}
53+
54+
if (runconfig.logMessages ?? false) {
55+
console.log(`${serverName} Server received: ${message.method}`);
56+
console.log(message);
57+
}
58+
if (runconfig.requestMessageHandler !== undefined) {
59+
return runconfig.requestMessageHandler(message);
60+
}
5261
}
5362
if (Message.isResponse(message)) {
54-
console.log(`${serverName} Server sent:`);
55-
console.log(message);
63+
if (runconfig.logMessages ?? false) {
64+
console.log(`${serverName} Server sent:`);
65+
console.log(message);
66+
}
67+
if (runconfig.responseMessageHandler !== undefined) {
68+
return runconfig.responseMessageHandler(message);
69+
}
5670
}
5771
return message;
5872
});
@@ -76,7 +90,6 @@ export const upgradeWsServer = (runconfig: LanguageServerRunConfig,
7690
}
7791
}),
7892
onMessage: cb => webSocket.on('message', (data) => {
79-
console.log(data.toString());
8093
cb(data);
8194
}),
8295
onError: cb => webSocket.on('error', cb),

packages/examples/src/eclipse.jdt.ls/client/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import '@codingame/monaco-vscode-java-default-extension';
1010
import { MonacoEditorLanguageClientWrapper, UserConfig } from 'monaco-editor-wrapper';
1111
import { useWorkerFactory } from 'monaco-editor-wrapper/workerFactory';
1212
import { RegisteredFileSystemProvider, RegisteredMemoryFile, registerFileSystemOverlay } from '@codingame/monaco-vscode-files-service-override';
13-
import { eclipseJdtLsConfig } from '../config';
13+
import { eclipseJdtLsConfig } from '../config.js';
1414
import helloJavaCode from '../../../resources/eclipse.jdt.ls/workspace/hello.java?raw';
1515

1616
export const configureMonacoWorkers = () => {

packages/examples/src/langium/langium-dsl/config/extendedConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export const setupLangiumClientExtended = async (): Promise<UserConfig> => {
8383
worker: langiumWorker
8484
},
8585
connectionProvider: {
86-
get: async () => ({ reader, writer }),
86+
get: async () => ({ reader, writer })
8787
}
8888
}
8989
};

packages/examples/src/python/client/config.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,33 @@ import * as vscode from 'vscode';
77
import getEditorServiceOverride from '@codingame/monaco-vscode-editor-service-override';
88
import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-service-override';
99
import '@codingame/monaco-vscode-python-default-extension';
10-
import { UserConfig } from 'monaco-editor-wrapper';
10+
import { createUrl, UserConfig } from 'monaco-editor-wrapper';
1111
import { useOpenEditorStub } from 'monaco-editor-wrapper/vscode/services';
1212
import { MonacoLanguageClient } from 'monaco-languageclient';
13+
import { toSocket, WebSocketMessageReader, WebSocketMessageWriter } from 'vscode-ws-jsonrpc';
1314

1415
export const createUserConfig = (workspaceRoot: string, code: string, codeUri: string): UserConfig => {
16+
const url = createUrl({
17+
secured: false,
18+
host: 'localhost',
19+
port: 30001,
20+
path: 'pyright',
21+
extraParams: {
22+
authorization: 'UserAuth'
23+
}
24+
});
25+
const webSocket = new WebSocket(url);
26+
const iWebSocket = toSocket(webSocket);
27+
const reader = new WebSocketMessageReader(iWebSocket);
28+
const writer = new WebSocketMessageWriter(iWebSocket);
29+
1530
return {
1631
languageClientConfig: {
1732
languageId: 'python',
1833
name: 'Python Language Server Example',
1934
options: {
20-
$type: 'WebSocket',
21-
host: 'localhost',
22-
port: 30001,
23-
path: 'pyright',
24-
extraParams: {
25-
authorization: 'UserAuth'
26-
},
27-
secured: false,
35+
$type: 'WebSocketDirect',
36+
webSocket: webSocket,
2837
startOptions: {
2938
onCall: (languageClient?: MonacoLanguageClient) => {
3039
setTimeout(() => {
@@ -46,6 +55,9 @@ export const createUserConfig = (workspaceRoot: string, code: string, codeUri: s
4655
uri: vscode.Uri.parse(workspaceRoot)
4756
},
4857
},
58+
connectionProvider: {
59+
get: async () => ({ reader, writer })
60+
}
4961
},
5062
wrapperConfig: {
5163
serviceConfig: {

packages/examples/src/python/server/main.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export const runPythonServer = (baseDir: string, relativeDir: string) => {
3535
callback(false);
3636
}
3737
}
38-
}
38+
},
39+
logMessages: true
3940
});
4041
};

packages/examples/src/ts/wrapperAdvanced.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Same again.`,
5757
languageId: 'json',
5858
name: 'wrapper42 language client',
5959
options: {
60-
$type: 'WebSocket',
60+
$type: 'WebSocketParams',
6161
host: 'localhost',
6262
port: 30000,
6363
path: 'sampleServer',

packages/examples/tsconfig.build.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@
22
"extends": "../../tsconfig.json",
33
"compilerOptions": {
44
"rootDir": "./build",
5-
"noEmit": true,
6-
// all other types are not needed here
7-
"types": [
8-
"node"
9-
]
5+
"noEmit": true
106
},
117
"include": [
128
"build/**/*.ts",

packages/vscode-ws-jsonrpc/tsconfig.src.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
"compilerOptions": {
44
"rootDir": "src",
55
"outDir": "lib",
6-
"declarationDir": "lib",
7-
// no types definitions are required to undertand dependent code
8-
"types": []
6+
"declarationDir": "lib"
97
},
108
"include": [
119
"src/**/*.ts",

packages/wrapper-react/test/index.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { render } from '@testing-library/react';
88
import React from 'react';
99
import { MonacoEditorReactComp } from '@typefox/monaco-editor-react';
1010
import { UserConfig } from 'monaco-editor-wrapper';
11-
import { updateExtendedAppPrototyp } from './helper';
11+
import { updateExtendedAppPrototyp } from './helper.js';
1212

1313
describe('Test MonacoEditorReactComp', () => {
1414
test('rerender', async () => {

packages/wrapper-react/tsconfig.src.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
"rootDir": "src",
55
"outDir": "dist",
66
"declarationDir": "dist",
7-
"types": [
8-
"vscode"
9-
]
7+
// because vscode-jsonrpc requires DedicatedWorkerGlobalScope
8+
// we are required to include both DOM and WebWorker libs
9+
// the only way out currently is to disable lib checking
10+
"skipLibCheck": true
1011
},
1112
"references": [{
1213
"path": "../wrapper/tsconfig.src.json"

packages/wrapper-react/tsconfig.test.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
"extends": "./tsconfig.src.json",
33
"compilerOptions": {
44
"noEmit": true,
5-
"rootDir": "test"
5+
"rootDir": "test",
6+
// because vscode-jsonrpc requires DedicatedWorkerGlobalScope
7+
// we are required to include both DOM and WebWorker libs
8+
// the only way out currently is to disable lib checking
9+
"skipLibCheck": true
610
},
711
"references": [{
812
"path": "./tsconfig.src.json"

packages/wrapper/src/index.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,6 @@ import {
3737
EditorAppExtended
3838
} from './editorAppExtended.js';
3939

40-
import type {
41-
WebSocketCallOptions,
42-
LanguageClientConfigType,
43-
WebSocketConfigOptions,
44-
WebSocketConfigOptionsUrl,
45-
WorkerConfigOptions,
46-
WorkerConfigDirect
47-
} from './commonTypes.js';
48-
4940
import type {
5041
LanguageClientConfig,
5142
LanguageClientError
@@ -74,12 +65,6 @@ export type {
7465
RegisterExtensionResult,
7566
RegisterLocalProcessExtensionResult,
7667
UserConfiguration,
77-
WebSocketCallOptions,
78-
LanguageClientConfigType,
79-
WebSocketConfigOptions,
80-
WebSocketConfigOptionsUrl,
81-
WorkerConfigOptions,
82-
WorkerConfigDirect,
8368
LanguageClientConfig,
8469
LanguageClientError,
8570
UserConfig,

0 commit comments

Comments
 (0)