Add WIP TCP connection type; move to use async methods; send client successful server start message

This commit is contained in:
2026-04-03 01:26:15 -05:00
parent abf404de17
commit 75a0d62655
2 changed files with 47 additions and 12 deletions

View File

@@ -5,6 +5,7 @@ const {servers} = require("./languageServers");
const {spawn} = require('child_process'); const {spawn} = require('child_process');
const url = require('url'); const url = require('url');
const WebSocket = require('ws'); const WebSocket = require('ws');
const net = require('net');
const verbose = argv.verbose || false; const verbose = argv.verbose || false;
const { const {
@@ -27,30 +28,35 @@ console.log("Started websocket server on port: ", _port);
wss.on('connection', (ws, req) => { wss.on('connection', async (ws, req) => {
// ws://localhost:6005/gdscript?workspace=/yolo
const address = url.parse(req.url, true); const address = url.parse(req.url, true);
const pathname = address.pathname.substring(1); const pathname = address.pathname.substring(1);
const qdata = address.query; const qdata = address.query;
const workspace = qdata.workspace; const workspace = qdata.workspace;
handleLanguageConnection(ws, pathname, workspace); await handleLanguageConnection(ws, pathname, workspace);
ws.send(JSON.stringify({
type: 'connected',
lang_id: pathname,
message: 'LSP Server connection established...',
}));
}); });
function handleLanguageConnection(ws, pathname, workspace) { async function handleLanguageConnection(ws, pathname, workspace) {
const server = servers.find(server => server.endpointName === pathname); const server = servers.find(server => server.endpointName === pathname);
setupLanguageServer(ws, server, workspace); await setupLanguageServer(ws, server, workspace);
} }
function setupLanguageServer(ws, server, workspace) { async function setupLanguageServer(ws, server, workspace) {
if (!server) return; if (!server) return;
const { const {
reader, reader,
writer writer
} = startLanguageServer(server, workspace); } = await startLanguageServer(server, workspace);
server.writer = writer; server.writer = writer;
@@ -81,13 +87,13 @@ function setupLanguageServer(ws, server, workspace) {
}); });
} }
function startLanguageServer(languageServer, workspace) { async function startLanguageServer(languageServer, workspace) {
const env = process.env; const env = process.env;
const args = languageServer.args.flat().map(arg => const args = languageServer.args.flat().map(arg =>
typeof arg === 'string' ? arg.replace('{workspace.path}', workspace || '') : arg typeof arg === 'string' ? arg.replace('{workspace.path}', workspace || '') : arg
).filter(arg => arg !== ''); ).filter(arg => arg !== '');
const serverProcess = spawn(args[0], args.slice(1), { env, shell: true }); const serverProcess = spawn(args[0], args.slice(1), { env });
serverProcess.stderr.on('data', data => { serverProcess.stderr.on('data', data => {
console.error(`${serverProcess.spawnfile} error: ${data}`); console.error(`${serverProcess.spawnfile} error: ${data}`);
@@ -122,6 +128,17 @@ function startLanguageServer(languageServer, workspace) {
throw 'The language server process does not have a valid stdin or stdout'; throw 'The language server process does not have a valid stdin or stdout';
} }
break;
case "tcp":
if (!languageServer.port) {
throw `Language Server Config for ${languageServer.endpointName} must have 'port' value...`;
}
const socket = await connectWithRetry(languageServer.port);
reader = new StreamMessageReader(socket);
writer = new StreamMessageWriter(socket);
break; break;
default: default:
throw 'Unknown connection type...'; throw 'Unknown connection type...';
@@ -133,6 +150,25 @@ function startLanguageServer(languageServer, workspace) {
}; };
} }
async function connectWithRetry(port, host = "localhost", retries = 5, delay = 1000) {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const socket = net.connect(port, host);
console.log(`Connected on attempt ${attempt}...`);
return socket;
} catch (err) {
console.warn(`Attempt ${attempt} failed`);
if (attempt === retries) {
throw new Error(`Failed to connect after ${retries} retries...`);
}
const wait = ms => new Promise(r => setTimeout(r, ms));
await wait(delay * attempt);
}
}
}
function processMessage(message, ws, server) { function processMessage(message, ws, server) {
if (message.params) { if (message.params) {
if (message.params.textDocument && message.params.textDocument.uri) { if (message.params.textDocument && message.params.textDocument.uri) {

View File

@@ -16,11 +16,10 @@ exports.servers = [
] ]
], ],
nameEndsWith: ".gd", nameEndsWith: ".gd",
connectionType: "ipc", connectionType: "tcp",
port: 6005,
relativePath: false relativePath: false
}, { }, {
endpointName: "go", endpointName: "go",
args: [ args: [
'gopls', ['-mode=stdio', '-remote=auto'] 'gopls', ['-mode=stdio', '-remote=auto']