()
| 57 | * await manager.shutdown() |
| 58 | */ |
| 59 | export function createLSPServerManager(): LSPServerManager { |
| 60 | // Private state managed via closures |
| 61 | const servers: Map<string, LSPServerInstance> = new Map() |
| 62 | const extensionMap: Map<string, string[]> = new Map() |
| 63 | // Track which files have been opened on which servers (URI -> server name) |
| 64 | const openedFiles: Map<string, string> = new Map() |
| 65 | |
| 66 | /** |
| 67 | * Initialize the manager by loading all configured LSP servers. |
| 68 | * |
| 69 | * @throws {Error} If configuration loading fails |
| 70 | */ |
| 71 | async function initialize(): Promise<void> { |
| 72 | let serverConfigs: Record<string, ScopedLspServerConfig> |
| 73 | |
| 74 | try { |
| 75 | const result = await getAllLspServers() |
| 76 | serverConfigs = result.servers |
| 77 | logForDebugging( |
| 78 | `[LSP SERVER MANAGER] getAllLspServers returned ${Object.keys(serverConfigs).length} server(s)`, |
| 79 | ) |
| 80 | } catch (error) { |
| 81 | const err = error as Error |
| 82 | logError( |
| 83 | new Error(`Failed to load LSP server configuration: ${err.message}`), |
| 84 | ) |
| 85 | throw error |
| 86 | } |
| 87 | |
| 88 | // Build extension → server mapping |
| 89 | for (const [serverName, config] of Object.entries(serverConfigs)) { |
| 90 | try { |
| 91 | // Validate config before using it |
| 92 | if (!config.command) { |
| 93 | throw new Error( |
| 94 | `Server ${serverName} missing required 'command' field`, |
| 95 | ) |
| 96 | } |
| 97 | if ( |
| 98 | !config.extensionToLanguage || |
| 99 | Object.keys(config.extensionToLanguage).length === 0 |
| 100 | ) { |
| 101 | throw new Error( |
| 102 | `Server ${serverName} missing required 'extensionToLanguage' field`, |
| 103 | ) |
| 104 | } |
| 105 | |
| 106 | // Map file extensions to this server (derive from extensionToLanguage) |
| 107 | const fileExtensions = Object.keys(config.extensionToLanguage) |
| 108 | for (const ext of fileExtensions) { |
| 109 | const normalized = ext.toLowerCase() |
| 110 | if (!extensionMap.has(normalized)) { |
| 111 | extensionMap.set(normalized, []) |
| 112 | } |
| 113 | const serverList = extensionMap.get(normalized) |
| 114 | if (serverList) { |
| 115 | serverList.push(serverName) |
| 116 | } |
no outgoing calls
no test coverage detected