Warp the websocket connection to a mock stream

This commit is contained in:
geequlim
2019-05-19 18:46:14 +08:00
parent ece1f3118d
commit 41b36e6e95
2 changed files with 71 additions and 23 deletions

View File

@@ -1,8 +1,10 @@
import { workspace } from "vscode";
import * as websocket from "websocket-stream";
import { LanguageClient, LanguageClientOptions, ServerOptions } from "vscode-languageclient";
import { is_debug_mode, get_configuration } from "../utils";
import logger from "../loggger";
import {DuplexMock} from 'stream-mock';
import * as WebSocket from 'ws';
import * as vscode from 'vscode';
function getClientOptions(): LanguageClientOptions {
return {
@@ -18,30 +20,75 @@ function getClientOptions(): LanguageClientOptions {
};
}
const serverOptions: ServerOptions = () => {
return new Promise((resolve, reject) => {
class MessageIO {
stream: DuplexMock = null;
socket: WebSocket = null;
public get server_uri() : string {
let port = get_configuration("gdscript_lsp_server_port", 6008);
const ws = websocket(`ws://localhost:${port}`);
if (is_debug_mode()) {
let text = '';
ws.on('data', (chunk)=>{
let message = chunk.toString();
text += message;
logger.log("[server]", message);
});
const origin_write = ws._write.bind(ws);
ws._write = (function (chunk: any, encoding: string, callback: (error?: Error | null) => void) {
let message = chunk.toString();
text += message;
origin_write(chunk, encoding, callback);
logger.log("[client]", message);
}).bind(ws);
return `ws://localhost:${port}`;
}
constructor() {
this.stream = new DuplexMock();
const origin_write = this.stream._write.bind(this.stream);
this.stream._write = (chunk: any, encoding: string, callback: (error?: Error | null) => void) => {
this.send_message(chunk);
origin_write(chunk, encoding, callback);
};
}
protected send_message(chunk: Buffer) {
let message = chunk.toString();
if (this.socket) {
this.socket.send(message);
this.stream.pause();
}
resolve({reader: ws, writer: ws});
});
logger.log("[client]", message);
}
protected on_recive_message(chunk: WebSocket.Data) {
let message = chunk.toString();
this.stream.emit('data',message);
this.stream.resume();
logger.log("[server]", message);
}
connect_to_language_server():Promise<void> {
return new Promise((resolve, reject) => {
this.socket = null;
const ws = new WebSocket(this.server_uri);
ws.on('open', ()=>{ this.on_connected(ws); resolve(); });
ws.on('message', this.on_recive_message.bind(this));
ws.on('error', this.on_disconnected.bind(this));
ws.on('close', this.on_disconnected.bind(this));
});
}
private on_connected(socket: WebSocket) {
this.socket = socket;
}
private on_disconnected() {
this.socket = null;
vscode.window.showErrorMessage(`Failed connect to GDScript Language Server`, 'Retry', 'Close').then(item=>{
if (item == 'Retry') {
this.connect_to_language_server();
}
});
}
};
export default class GDScriptLanguageClient extends LanguageClient {
const io = new MessageIO();
const serverOptions: ServerOptions = () => {
return new Promise((resolve, reject) => {
io.connect_to_language_server().then(()=>{
resolve({reader: io.stream, writer: io.stream});
});
});
};
export default class GDScriptLanguageClient extends LanguageClient {
constructor() {
super(`GDScriptLanguageClient`, serverOptions, getClientOptions());
}