Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

monaco-languageclient config improvement, wrapper+languageclientwrapper improvements #741

Merged
merged 7 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions packages/client/src/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) 2024 TypeFox and others.
* Licensed under the MIT License. See LICENSE in the package root for license information.
* ------------------------------------------------------------------------------------------ */

import { BaseLanguageClient, MessageTransports, LanguageClientOptions } from 'vscode-languageclient/browser.js';

export interface IConnectionProvider {
get(encoding: string): Promise<MessageTransports>;
}

export type MonacoLanguageClientOptions = {
name: string;
id?: string;
clientOptions: LanguageClientOptions;
connectionProvider: IConnectionProvider;
}

export class MonacoLanguageClient extends BaseLanguageClient {
protected readonly connectionProvider: IConnectionProvider;

constructor({ id, name, clientOptions, connectionProvider }: MonacoLanguageClientOptions) {
super(id ?? name.toLowerCase(), name, clientOptions);
this.connectionProvider = connectionProvider;
}

protected override createMessageTransports(encoding: string): Promise<MessageTransports> {
return this.connectionProvider.get(encoding);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See LICENSE in the package root for license information.
* ------------------------------------------------------------------------------------------ */

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

export type WebSocketCallOptions = {
/** Adds handle on languageClient */
Expand All @@ -12,29 +12,45 @@ export type WebSocketCallOptions = {
reportStatus?: boolean;
}

export type LanguageClientConfigType = 'WebSocket' | 'WebSocketUrl' | 'WorkerConfig' | 'Worker';
export type LanguageClientRestartOptions = {
retries: number;
timeout: number;
keepWorker?: boolean;
}

export type WebSocketUrl = {
secured: boolean;
host: string;
port?: number;
path?: string;
export type LanguageClientConfigType = 'WebSocket' | 'WebSocketUrl' | 'WebSocketDirect' | 'WorkerConfig' | 'Worker';

export type LanguageClientConfigOptions = (WebSocketConfigOptionsDirect | WebSocketConfigOptionsParams | WebSocketConfigOptionsUrl | WorkerConfigOptions | WorkerConfigDirect) & {
restartOptions?: LanguageClientRestartOptions;
}

export type WebSocketConfigOptions = {
$type: 'WebSocket'
export type WebSocketUrlParams = {
secured: boolean;
host: string;
port?: number;
path?: string;
extraParams?: Record<string, string | number | Array<string | number>>;
}

export type WebSocketUrlString = {
url: string;
}

export type WebSocketConfigOptionsDirect = {
$type: 'WebSocketDirect'
webSocket: WebSocket
startOptions?: WebSocketCallOptions;
stopOptions?: WebSocketCallOptions;
}
kaisalmen marked this conversation as resolved.
Show resolved Hide resolved

export type WebSocketConfigOptionsParams = WebSocketUrlParams & {
$type: 'WebSocketParams'
kaisalmen marked this conversation as resolved.
Show resolved Hide resolved
startOptions?: WebSocketCallOptions;
stopOptions?: WebSocketCallOptions;
}

export type WebSocketConfigOptionsUrl = {
export type WebSocketConfigOptionsUrl = WebSocketUrlString & {
$type: 'WebSocketUrl'
url: string;
startOptions?: WebSocketCallOptions;
stopOptions?: WebSocketCallOptions;
}
Expand Down
29 changes: 4 additions & 25 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,7 @@
* Licensed under the MIT License. See LICENSE in the package root for license information.
* ------------------------------------------------------------------------------------------ */

import { BaseLanguageClient, MessageTransports, LanguageClientOptions } from 'vscode-languageclient/lib/common/client.js';

export interface IConnectionProvider {
get(encoding: string): Promise<MessageTransports>;
}

export type MonacoLanguageClientOptions = {
name: string;
id?: string;
clientOptions: LanguageClientOptions;
connectionProvider: IConnectionProvider;
}

export class MonacoLanguageClient extends BaseLanguageClient {
protected readonly connectionProvider: IConnectionProvider;

constructor({ id, name, clientOptions, connectionProvider }: MonacoLanguageClientOptions) {
super(id ?? name.toLowerCase(), name, clientOptions);
this.connectionProvider = connectionProvider;
}

protected override createMessageTransports(encoding: string): Promise<MessageTransports> {
return this.connectionProvider.get(encoding);
}
}
export type * from './client.js';
export * from './client.js';
export type * from './commonTypes.js';
export * from './commonTypes.js';
7 changes: 4 additions & 3 deletions packages/client/tsconfig.src.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
"rootDir": "src",
"outDir": "lib",
"declarationDir": "lib",
"types": [
"vscode"
]
// because vscode-jsonrpc requires DedicatedWorkerGlobalScope
// we are required to include both DOM and WebWorker libs
// the only way out currently is to disable lib checking
"skipLibCheck": true
},
"include": [
"src/**/*.ts",
Expand Down
6 changes: 2 additions & 4 deletions packages/examples/src/bare/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import '@codingame/monaco-vscode-theme-defaults-default-extension';
import '@codingame/monaco-vscode-json-default-extension';
import { MonacoLanguageClient } from 'monaco-languageclient';
import { WebSocketMessageReader, WebSocketMessageWriter, toSocket } from 'vscode-ws-jsonrpc';
import { CloseAction, ErrorAction, MessageTransports } from 'vscode-languageclient';
import { CloseAction, ErrorAction, MessageTransports } from 'vscode-languageclient/browser.js';
import { useWorkerFactory } from 'monaco-editor-wrapper/workerFactory';

export const configureMonacoWorkers = () => {
Expand Down Expand Up @@ -87,9 +87,7 @@ export const createLanguageClient = (transports: MessageTransports): MonacoLangu
},
// create a language client connection from the JSON RPC connection on demand
connectionProvider: {
get: () => {
return Promise.resolve(transports);
}
get: async () => (transports)
}
});
};
25 changes: 19 additions & 6 deletions packages/examples/src/common/node/server-commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { IWebSocket, WebSocketMessageReader, WebSocketMessageWriter } from 'vscode-ws-jsonrpc';
import { createConnection, createServerProcess, forward } from 'vscode-ws-jsonrpc/server';
import { Message, InitializeRequest, InitializeParams } from 'vscode-languageserver';
import { Message, InitializeRequest, InitializeParams, RequestMessage, ResponseMessage } from 'vscode-languageserver-protocol';
import * as cp from 'child_process';

export enum LanguageName {
Expand All @@ -28,6 +28,9 @@ export interface LanguageServerRunConfig {
runCommandArgs: string[];
wsServerOptions: ServerOptions,
spawnOptions?: cp.SpawnOptions;
logMessages?: boolean;
requestMessageHandler?: (message: RequestMessage) => RequestMessage;
responseMessageHandler?: (message: ResponseMessage) => ResponseMessage;
}

/**
Expand All @@ -43,16 +46,27 @@ export const launchLanguageServer = (runconfig: LanguageServerRunConfig, socket:
if (serverConnection) {
forward(socketConnection, serverConnection, message => {
if (Message.isRequest(message)) {
console.log(`${serverName} Server received:`);
console.log(message);
if (message.method === InitializeRequest.type.method) {
const initializeParams = message.params as InitializeParams;
initializeParams.processId = process.pid;
}

if (runconfig.logMessages ?? false) {
console.log(`${serverName} Server received: ${message.method}`);
console.log(message);
}
if (runconfig.requestMessageHandler !== undefined) {
return runconfig.requestMessageHandler(message);
}
}
if (Message.isResponse(message)) {
console.log(`${serverName} Server sent:`);
console.log(message);
if (runconfig.logMessages ?? false) {
console.log(`${serverName} Server sent:`);
console.log(message);
}
if (runconfig.responseMessageHandler !== undefined) {
return runconfig.responseMessageHandler(message);
}
}
return message;
});
Expand All @@ -76,7 +90,6 @@ export const upgradeWsServer = (runconfig: LanguageServerRunConfig,
}
}),
onMessage: cb => webSocket.on('message', (data) => {
console.log(data.toString());
cb(data);
}),
onError: cb => webSocket.on('error', cb),
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/src/eclipse.jdt.ls/client/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import '@codingame/monaco-vscode-java-default-extension';
import { MonacoEditorLanguageClientWrapper, UserConfig } from 'monaco-editor-wrapper';
import { useWorkerFactory } from 'monaco-editor-wrapper/workerFactory';
import { RegisteredFileSystemProvider, RegisteredMemoryFile, registerFileSystemOverlay } from '@codingame/monaco-vscode-files-service-override';
import { eclipseJdtLsConfig } from '../config';
import { eclipseJdtLsConfig } from '../config.js';
import helloJavaCode from '../../../resources/eclipse.jdt.ls/workspace/hello.java?raw';

export const configureMonacoWorkers = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export const setupLangiumClientExtended = async (): Promise<UserConfig> => {
worker: langiumWorker
},
connectionProvider: {
get: async () => ({ reader, writer }),
get: async () => ({ reader, writer })
}
}
};
Expand Down
30 changes: 21 additions & 9 deletions packages/examples/src/python/client/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,33 @@ import * as vscode from 'vscode';
import getEditorServiceOverride from '@codingame/monaco-vscode-editor-service-override';
import getKeybindingsServiceOverride from '@codingame/monaco-vscode-keybindings-service-override';
import '@codingame/monaco-vscode-python-default-extension';
import { UserConfig } from 'monaco-editor-wrapper';
import { createUrl, UserConfig } from 'monaco-editor-wrapper';
import { useOpenEditorStub } from 'monaco-editor-wrapper/vscode/services';
import { MonacoLanguageClient } from 'monaco-languageclient';
import { toSocket, WebSocketMessageReader, WebSocketMessageWriter } from 'vscode-ws-jsonrpc';

export const createUserConfig = (workspaceRoot: string, code: string, codeUri: string): UserConfig => {
const url = createUrl({
secured: false,
host: 'localhost',
port: 30001,
path: 'pyright',
extraParams: {
authorization: 'UserAuth'
}
});
const webSocket = new WebSocket(url);
const iWebSocket = toSocket(webSocket);
const reader = new WebSocketMessageReader(iWebSocket);
const writer = new WebSocketMessageWriter(iWebSocket);

return {
languageClientConfig: {
languageId: 'python',
name: 'Python Language Server Example',
options: {
$type: 'WebSocket',
host: 'localhost',
port: 30001,
path: 'pyright',
extraParams: {
authorization: 'UserAuth'
},
secured: false,
$type: 'WebSocketDirect',
webSocket: webSocket,
startOptions: {
onCall: (languageClient?: MonacoLanguageClient) => {
setTimeout(() => {
Expand All @@ -46,6 +55,9 @@ export const createUserConfig = (workspaceRoot: string, code: string, codeUri: s
uri: vscode.Uri.parse(workspaceRoot)
},
},
connectionProvider: {
get: async () => ({ reader, writer })
}
},
wrapperConfig: {
serviceConfig: {
Expand Down
3 changes: 2 additions & 1 deletion packages/examples/src/python/server/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const runPythonServer = (baseDir: string, relativeDir: string) => {
callback(false);
}
}
}
},
logMessages: true
});
};
2 changes: 1 addition & 1 deletion packages/examples/src/ts/wrapperAdvanced.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Same again.`,
languageId: 'json',
name: 'wrapper42 language client',
options: {
$type: 'WebSocket',
$type: 'WebSocketParams',
host: 'localhost',
port: 30000,
path: 'sampleServer',
Expand Down
6 changes: 1 addition & 5 deletions packages/examples/tsconfig.build.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./build",
"noEmit": true,
// all other types are not needed here
"types": [
"node"
]
"noEmit": true
},
"include": [
"build/**/*.ts",
Expand Down
4 changes: 1 addition & 3 deletions packages/vscode-ws-jsonrpc/tsconfig.src.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
"compilerOptions": {
"rootDir": "src",
"outDir": "lib",
"declarationDir": "lib",
// no types definitions are required to undertand dependent code
"types": []
"declarationDir": "lib"
},
"include": [
"src/**/*.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/wrapper-react/test/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { render, RenderResult } from '@testing-library/react';
import React from 'react';
import { MonacoEditorReactComp, TextChanges } from '@typefox/monaco-editor-react';
import { MonacoEditorLanguageClientWrapper, UserConfig } from 'monaco-editor-wrapper';
import { updateExtendedAppPrototyp } from './helper';
import { updateExtendedAppPrototyp } from './helper.js';

describe('Test MonacoEditorReactComp', () => {
test('rerender', async () => {
Expand Down
7 changes: 4 additions & 3 deletions packages/wrapper-react/tsconfig.src.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
"rootDir": "src",
"outDir": "dist",
"declarationDir": "dist",
"types": [
"vscode"
]
// because vscode-jsonrpc requires DedicatedWorkerGlobalScope
// we are required to include both DOM and WebWorker libs
// the only way out currently is to disable lib checking
"skipLibCheck": true
},
"references": [{
"path": "../wrapper/tsconfig.src.json"
Expand Down
6 changes: 5 additions & 1 deletion packages/wrapper-react/tsconfig.test.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
"extends": "./tsconfig.src.json",
"compilerOptions": {
"noEmit": true,
"rootDir": "test"
"rootDir": "test",
// because vscode-jsonrpc requires DedicatedWorkerGlobalScope
// we are required to include both DOM and WebWorker libs
// the only way out currently is to disable lib checking
"skipLibCheck": true
},
"references": [{
"path": "./tsconfig.src.json"
Expand Down
15 changes: 0 additions & 15 deletions packages/wrapper/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,6 @@ import {
EditorAppExtended
} from './editorAppExtended.js';

import type {
WebSocketCallOptions,
LanguageClientConfigType,
WebSocketConfigOptions,
WebSocketConfigOptionsUrl,
WorkerConfigOptions,
WorkerConfigDirect
} from './commonTypes.js';

import type {
LanguageClientConfig,
LanguageClientError
Expand Down Expand Up @@ -76,12 +67,6 @@ export type {
RegisterExtensionResult,
RegisterLocalProcessExtensionResult,
UserConfiguration,
WebSocketCallOptions,
LanguageClientConfigType,
WebSocketConfigOptions,
WebSocketConfigOptionsUrl,
WorkerConfigOptions,
WorkerConfigDirect,
LanguageClientConfig,
LanguageClientError,
UserConfig,
Expand Down
Loading