()
| 371 | }, |
| 372 | |
| 373 | async stop(): Promise<void> { |
| 374 | let shutdownError: Error | undefined |
| 375 | |
| 376 | // Mark as stopping to prevent error handlers from logging spurious errors |
| 377 | isStopping = true |
| 378 | |
| 379 | try { |
| 380 | if (connection) { |
| 381 | // Try to send shutdown request and exit notification |
| 382 | await connection.sendRequest('shutdown', {}) |
| 383 | await connection.sendNotification('exit', {}) |
| 384 | } |
| 385 | } catch (error) { |
| 386 | const err = error as Error |
| 387 | logError( |
| 388 | new Error(`LSP server ${serverName} stop failed: ${err.message}`), |
| 389 | ) |
| 390 | shutdownError = err |
| 391 | // Continue to cleanup despite shutdown failure |
| 392 | } finally { |
| 393 | // Always cleanup resources, even if shutdown/exit failed |
| 394 | if (connection) { |
| 395 | try { |
| 396 | connection.dispose() |
| 397 | } catch (error) { |
| 398 | // Log but don't throw - disposal errors are less critical |
| 399 | logForDebugging( |
| 400 | `Connection disposal failed for ${serverName}: ${errorMessage(error)}`, |
| 401 | ) |
| 402 | } |
| 403 | connection = undefined |
| 404 | } |
| 405 | |
| 406 | if (process) { |
| 407 | // Remove event listeners to prevent memory leaks |
| 408 | process.removeAllListeners('error') |
| 409 | process.removeAllListeners('exit') |
| 410 | if (process.stdin) { |
| 411 | process.stdin.removeAllListeners('error') |
| 412 | } |
| 413 | if (process.stderr) { |
| 414 | process.stderr.removeAllListeners('data') |
| 415 | } |
| 416 | |
| 417 | try { |
| 418 | process.kill() |
| 419 | } catch (error) { |
| 420 | // Process might already be dead, which is fine |
| 421 | logForDebugging( |
| 422 | `Process kill failed for ${serverName} (may already be dead): ${errorMessage(error)}`, |
| 423 | ) |
| 424 | } |
| 425 | process = undefined |
| 426 | } |
| 427 | |
| 428 | isInitialized = false |
| 429 | capabilities = undefined |
| 430 | isStopping = false // Reset for potential restart |
nothing calls this directly
no test coverage detected