Я пытаюсь создать собственный LSP. Моя цель - создать один языковой сервер для редактора monaco (в Интернете) и расширения vscode.
В настоящее время я использую Node / IPC для подключения расширения vscode к серверу. и ws-jsonrpc для подключения редактора monaco к серверу.
цитата из этой статьи Расширение клиента с помощью протокола языкового сервера:
Есть несколько способов использования JSON-RPC, но в большинстве реализаций вы видите эти два:
- Связь осуществляется через стандартный ввод / вывод, т. Е. Через интерфейс командной строки.
- Связь осуществляется через TCP / IP, т. Е. Сетевые сообщения, аналогичные HTTP.
Я должен иметь возможность использовать JSON-RPC как для связи (внутренняя связь между процессами, которая является расширением vscode в моем случае, так и внешняя связь, которая в моем случае является редактором monaco)
Вот как я сейчас запускаю сервер:
Для связи IPC:
const languageServer = new LanguageServer(createConnection(ProposedFeatures.all));
languageServer.start();
Для WebSocket RPC:
import * as express from "express";
import * as ws from "ws";
import * as rpc from "vscode-ws-jsonrpc";
import * as url from "url";
import * as http from "http";
import * as net from "net";
const app = express();
const server = app.listen(3000);
const wss = new ws.Server({
noServer: true,
perMessageDeflate: false
});
function launch(socket : rpc.IWebSocket ){
const reader = new rpc.WebSocketMessageReader(socket);
const writer = new rpc.WebSocketMessageWriter(socket);
const languageServer = new LanguageServer(createConnection(reader, writer));
languageServer.start();
}
server.on('upgrade', (request: http.IncomingMessage, socket: net.Socket, head: Buffer) => {
const pathname = request.url ? url.parse(request.url).pathname : undefined;
console.log("server on upgrade ", pathname);
if (pathname === '/sampleServer') {
wss.handleUpgrade(request, socket, head, (webSocket: any) => {
const socket: rpc.IWebSocket = {
send: (content: any) => webSocket.send(content, (error: any) => {
if (error) {
throw error;
}
}),
onMessage: (cb: any) => webSocket.on('message', cb),
onError: (cb: any) => webSocket.on('error', cb),
onClose: (cb: any) => webSocket.on('close', cb),
dispose: () => webSocket.close()
};
// launch the server when the web socket is opened
if (webSocket.readyState === webSocket.OPEN) {
launch(socket);
} else {
webSocket.on('open', () => {
launch(socket);
});
}
});
}
})