* Starts the LSP server and initializes it with workspace information. * * If the server is already running or starting, this method returns immediately. * On failure, sets state to 'error', logs for monitoring, and throws. * * @throws {Error} If server fails to start or initialize
()
| 133 | * @throws {Error} If server fails to start or initialize |
| 134 | */ |
| 135 | async function start(): Promise<void> { |
| 136 | if (state === 'running' || state === 'starting') { |
| 137 | return |
| 138 | } |
| 139 | |
| 140 | // Cap crash-recovery attempts so a persistently crashing server doesn't |
| 141 | // spawn unbounded child processes on every incoming request. |
| 142 | const maxRestarts = config.maxRestarts ?? 3 |
| 143 | if (state === 'error' && crashRecoveryCount > maxRestarts) { |
| 144 | const error = new Error( |
| 145 | `LSP server '${name}' exceeded max crash recovery attempts (${maxRestarts})`, |
| 146 | ) |
| 147 | lastError = error |
| 148 | logError(error) |
| 149 | throw error |
| 150 | } |
| 151 | |
| 152 | let initPromise: Promise<unknown> | undefined |
| 153 | try { |
| 154 | state = 'starting' |
| 155 | logForDebugging(`Starting LSP server instance: ${name}`) |
| 156 | |
| 157 | // Start the client |
| 158 | await client.start(config.command, config.args || [], { |
| 159 | env: config.env, |
| 160 | cwd: config.workspaceFolder, |
| 161 | }) |
| 162 | |
| 163 | // Initialize with workspace info |
| 164 | const workspaceFolder = config.workspaceFolder || getCwd() |
| 165 | const workspaceUri = pathToFileURL(workspaceFolder).href |
| 166 | |
| 167 | const initParams: InitializeParams = { |
| 168 | processId: process.pid, |
| 169 | |
| 170 | // Pass server-specific initialization options from plugin config |
| 171 | // Required by vue-language-server, optional for others |
| 172 | // Provide empty object as default to avoid undefined errors in servers |
| 173 | // that expect this field to exist |
| 174 | initializationOptions: config.initializationOptions ?? {}, |
| 175 | |
| 176 | // Modern approach (LSP 3.16+) - required for Pyright, gopls |
| 177 | workspaceFolders: [ |
| 178 | { |
| 179 | uri: workspaceUri, |
| 180 | name: path.basename(workspaceFolder), |
| 181 | }, |
| 182 | ], |
| 183 | |
| 184 | // Deprecated fields - some servers still need these for proper URI resolution |
| 185 | rootPath: workspaceFolder, // Deprecated in LSP 3.8 but needed by some servers |
| 186 | rootUri: workspaceUri, // Deprecated in LSP 3.16 but needed by typescript-language-server for goToDefinition |
| 187 | |
| 188 | // Client capabilities - declare what features we support |
| 189 | capabilities: { |
| 190 | workspace: { |
| 191 | // Don't claim to support workspace/configuration since we don't implement it |
| 192 | // This prevents servers from requesting config we can't provide |
no test coverage detected