@@ -84,34 +84,47 @@ def from_languages(languages: list[Language], factory: LanguageServerFactory) ->
8484 :param factory: the factory for language server creation
8585 :return: the instance
8686 """
87- language_servers : dict [ Language , SolidLanguageServer ] = {}
88- threads = []
89- exceptions = {}
90- lock = threading . Lock ( )
91-
92- def start_language_server ( language : Language ) -> None :
93- try :
94- with LogTime ( f"Language server startup (language= { language . value } )" ):
95- language_server = factory . create_language_server ( language )
96- language_server . start ()
97- if not language_server . is_running ( ):
98- raise RuntimeError ( f"Failed to start the language server for language { language . value } " )
99- with lock :
100- language_servers [ language ] = language_server
101- except Exception as e :
102- log . error ( f"Error starting language server for language { language . value } : { e } " , exc_info = e )
103- with lock :
104- exceptions [ language ] = e
87+
88+ class StartLSThread ( threading . Thread ):
89+ def __init__ ( self , language : Language ):
90+ super (). __init__ ( target = self . _start_language_server , name = "StartLS:" + language . value )
91+ self . language = language
92+ self . language_server : SolidLanguageServer | None = None
93+ self . exception : Exception | None = None
94+
95+ def _start_language_server ( self ) -> None :
96+ try :
97+ with LogTime ( f"Language server startup (language= { self . language . value } )" ):
98+ self . language_server = factory . create_language_server ( self . language )
99+ self . language_server . start ()
100+ if not self . language_server . is_running ():
101+ raise RuntimeError ( f"Failed to start the language server for language { self . language . value } " )
102+ except Exception as e :
103+ log . error ( f"Error starting language server for language { self . language . value } : { e } " , exc_info = e )
104+ self . exception = e
105105
106106 # start language servers in parallel threads
107+ threads = []
107108 for language in languages :
108- thread = threading . Thread ( target = start_language_server , args = ( language ,), name = "StartLS:" + language . value )
109+ thread = StartLSThread ( language )
109110 thread .start ()
110111 threads .append (thread )
112+
113+ # collect language servers and exceptions
114+ language_servers : dict [Language , SolidLanguageServer ] = {}
115+ exceptions : dict [Language , Exception ] = {}
111116 for thread in threads :
112117 thread .join ()
113-
114- # If any server failed to start up, raise an exception and stop all started language servers
118+ if thread .exception is not None :
119+ exceptions [thread .language ] = thread .exception
120+ elif thread .language_server is not None :
121+ language_servers [thread .language ] = thread .language_server
122+
123+ # If any server failed to start up, raise an exception and stop all started language servers.
124+ # We intentionally fail fast here. The user's intention is to work with all the specified languages,
125+ # so if any of them is not available, it is better to fail immediately and bring the failure to the
126+ # user's attention instead of silently continuing with a subset of the language servers and potentially
127+ # causing suboptimal agent behaviour.
115128 if exceptions :
116129 for ls in language_servers .values ():
117130 ls .stop ()
0 commit comments