@@ -434,11 +434,14 @@ export class LanguageClientManager {
434434 this . languageClient = undefined ;
435435 return ;
436436 }
437- const client = this . createLSPClient ( folder ) ;
438- return this . startClient ( client ) ;
437+ const { client, errorHandler } = this . createLSPClient ( folder ) ;
438+ return this . startClient ( client , errorHandler ) ;
439439 }
440440
441- private createLSPClient ( folder ?: vscode . Uri ) : langclient . LanguageClient {
441+ private createLSPClient ( folder ?: vscode . Uri ) : {
442+ client : langclient . LanguageClient ;
443+ errorHandler : SourceKitLSPErrorHandler ;
444+ } {
442445 const toolchainSourceKitLSP =
443446 this . workspaceContext . toolchain . getToolchainExecutable ( "sourcekit-lsp" ) ;
444447 const lspConfig = configuration . lsp ;
@@ -488,6 +491,7 @@ export class LanguageClientManager {
488491 workspaceFolder = { uri : folder , name : FolderContext . uriName ( folder ) , index : 0 } ;
489492 }
490493
494+ const errorHandler = new SourceKitLSPErrorHandler ( 5 ) ;
491495 const clientOptions : langclient . LanguageClientOptions = {
492496 documentSelector : LanguageClientManager . documentSelector ,
493497 revealOutputChannelOn : langclient . RevealOutputChannelOn . Never ,
@@ -563,7 +567,10 @@ export class LanguageClientManager {
563567 } ;
564568 } ) ( ) ,
565569 } ,
566- errorHandler : new SourceKitLSPErrorHandler ( 5 ) ,
570+ errorHandler,
571+ // Avoid attempting to reinitialize multiple times. If we fail to initialize
572+ // we aren't doing anything different the second time and so will fail again.
573+ initializationFailedHandler : ( ) => false ,
567574 initializationOptions : {
568575 "workspace/peekDocuments" : true , // workaround for client capability to handle `PeekDocumentsRequest`
569576 "textDocument/codeLens" : {
@@ -575,15 +582,21 @@ export class LanguageClientManager {
575582 } ,
576583 } ;
577584
578- return new langclient . LanguageClient (
579- "swift.sourcekit-lsp" ,
580- "SourceKit Language Server" ,
581- serverOptions ,
582- clientOptions
583- ) ;
585+ return {
586+ client : new langclient . LanguageClient (
587+ "swift.sourcekit-lsp" ,
588+ "SourceKit Language Server" ,
589+ serverOptions ,
590+ clientOptions
591+ ) ,
592+ errorHandler,
593+ } ;
584594 }
585595
586- private async startClient ( client : langclient . LanguageClient ) {
596+ private async startClient (
597+ client : langclient . LanguageClient ,
598+ errorHandler : SourceKitLSPErrorHandler
599+ ) {
587600 client . onDidChangeState ( e => {
588601 // if state is now running add in any sub-folder workspaces that
589602 // we have cached. If this is the first time we are starting then
@@ -595,7 +608,6 @@ export class LanguageClientManager {
595608 ) {
596609 this . addSubFolderWorkspaces ( client ) ;
597610 }
598- //console.log(e);
599611 } ) ;
600612 if ( client . clientOptions . workspaceFolder ) {
601613 this . workspaceContext . outputChannel . log (
@@ -615,6 +627,10 @@ export class LanguageClientManager {
615627 this . clientReadyPromise = client
616628 . start ( )
617629 . then ( ( ) => {
630+ // Now that we've started up correctly, start the error handler to auto-restart
631+ // if sourcekit-lsp crashes during normal operation.
632+ errorHandler . enable ( ) ;
633+
618634 if ( this . workspaceContext . swiftVersion . isLessThan ( new Version ( 5 , 7 , 0 ) ) ) {
619635 this . legacyInlayHints = activateLegacyInlayHints ( client ) ;
620636 }
@@ -623,7 +639,6 @@ export class LanguageClientManager {
623639 } )
624640 . catch ( reason => {
625641 this . workspaceContext . outputChannel . log ( `${ reason } ` ) ;
626- // if language client failed to initialise then shutdown and set to undefined
627642 this . languageClient ?. stop ( ) ;
628643 this . languageClient = undefined ;
629644 throw reason ;
@@ -671,10 +686,17 @@ export class LanguageClientManager {
671686 */
672687class SourceKitLSPErrorHandler implements langclient . ErrorHandler {
673688 private restarts : number [ ] ;
689+ private enabled : boolean = false ;
674690
675691 constructor ( private maxRestartCount : number ) {
676692 this . restarts = [ ] ;
677693 }
694+ /**
695+ * Start listening for errors and requesting to restart the LSP server when appropriate.
696+ */
697+ enable ( ) {
698+ this . enabled = true ;
699+ }
678700 /**
679701 * An error has occurred while writing or reading from the connection.
680702 *
@@ -697,6 +719,13 @@ class SourceKitLSPErrorHandler implements langclient.ErrorHandler {
697719 * The connection to the server got closed.
698720 */
699721 closed ( ) : langclient . CloseHandlerResult | Promise < langclient . CloseHandlerResult > {
722+ if ( ! this . enabled ) {
723+ return {
724+ action : langclient . CloseAction . DoNotRestart ,
725+ handled : true ,
726+ } ;
727+ }
728+
700729 this . restarts . push ( Date . now ( ) ) ;
701730 if ( this . restarts . length <= this . maxRestartCount ) {
702731 return { action : langclient . CloseAction . Restart } ;
0 commit comments