Skip to content

Commit 38f7342

Browse files
committed
feat: Implement dynamic port discovery and workspace folder support for LSP servers using axs bridge.
1 parent 3c9b637 commit 38f7342

File tree

6 files changed

+478
-50
lines changed

6 files changed

+478
-50
lines changed

src/cm/lsp/clientManager.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import type {
2626
BuiltinExtensionsConfig,
2727
ClientManagerOptions,
2828
ClientState,
29+
EnsureServerResult,
2930
FileMetadata,
3031
FormattingOptions,
3132
LspServerDefinition,
@@ -45,7 +46,12 @@ function asArray<T>(value: T | T[] | null | undefined): T[] {
4546
function pluginKey(
4647
serverId: string,
4748
rootUri: string | null | undefined,
49+
useWorkspaceFolders?: boolean,
4850
): string {
51+
// For workspace folders mode, use just the server ID (one client per server type)
52+
if (useWorkspaceFolders) {
53+
return serverId;
54+
}
4955
return `${serverId}::${rootUri ?? "__global__"}`;
5056
}
5157

@@ -311,16 +317,27 @@ export class LspClientManager {
311317
server: LspServerDefinition,
312318
context: RootUriContext,
313319
): Promise<ClientState> {
320+
const useWsFolders = server.useWorkspaceFolders === true;
314321
const resolvedRoot = await this.#resolveRootUri(server, context);
315322
const { normalizedRootUri, originalRootUri } = normalizeRootUriForServer(
316323
server,
317324
resolvedRoot,
318325
);
319-
const key = pluginKey(server.id, normalizedRootUri);
326+
327+
// For workspace folders mode, use a shared key based on server ID only
328+
const key = pluginKey(server.id, normalizedRootUri, useWsFolders);
320329

321330
// Return existing client if already initialized
322331
if (this.#clients.has(key)) {
323-
return this.#clients.get(key)!;
332+
const existing = this.#clients.get(key)!;
333+
// For workspace folders mode, add the new folder to the existing server
334+
if (useWsFolders && normalizedRootUri) {
335+
const workspace = existing.client.workspace as AcodeWorkspace | null;
336+
if (workspace && !workspace.hasWorkspaceFolder(normalizedRootUri)) {
337+
workspace.addWorkspaceFolder(normalizedRootUri);
338+
}
339+
}
340+
return existing;
324341
}
325342

326343
// If initialization is already in progress, wait for it
@@ -331,8 +348,8 @@ export class LspClientManager {
331348
// Create and track the pending initialization
332349
const initPromise = this.#initializeClient(server, context, {
333350
key,
334-
normalizedRootUri,
335-
originalRootUri,
351+
normalizedRootUri: useWsFolders ? null : normalizedRootUri,
352+
originalRootUri: useWsFolders ? null : originalRootUri,
336353
});
337354
this.#pendingClients.set(key, initPromise);
338355

@@ -604,11 +621,18 @@ export class LspClientManager {
604621
let client: ExtendedLSPClient | undefined;
605622

606623
try {
607-
await ensureServerRunning(server);
624+
// Get session from server ID for auto-port discovery
625+
const session = server.id;
626+
const serverResult = await ensureServerRunning(server, session);
627+
628+
// Use discovered port if available (for auto-port discovery)
629+
const dynamicPort = serverResult.discoveredPort;
630+
608631
transportHandle = createTransport(server, {
609632
...context,
610633
rootUri: normalizedRootUri ?? null,
611634
originalRootUri: originalRootUri ?? undefined,
635+
dynamicPort,
612636
});
613637
await transportHandle.ready;
614638
client = new LSPClient(clientConfig) as ExtendedLSPClient;

0 commit comments

Comments
 (0)