44from abc import ABC , abstractmethod
55from collections .abc import AsyncGenerator
66from contextlib import asynccontextmanager , suppress
7+ from functools import cached_property
78from pathlib import Path
89from typing import Any , Literal , Self , override
910
@@ -58,10 +59,13 @@ class Client(
5859 initialization_options : dict = field (factory = dict )
5960
6061 _server : Server = field (init = False )
61- _workspace : Workspace = field (init = False )
6262 _buffer : LSPFileBuffer = field (factory = LSPFileBuffer , init = False )
6363 _config : ConfigurationMap = Factory (ConfigurationMap )
6464
65+ @cached_property
66+ def _workspace (self ) -> Workspace :
67+ return format_workspace (self ._workspace_arg )
68+
6569 async def _iter_candidate_servers (self ) -> AsyncGenerator [Server ]:
6670 """
6771 Server candidates in order of priority:
@@ -96,7 +100,7 @@ async def run_server(
96100 errors : list [ServerRuntimeError ] = []
97101 async for candidate in self ._iter_candidate_servers ():
98102 try :
99- async with candidate .run (self ._workspace , sender = sender ) as server : # ty: ignore[invalid-argument-type]
103+ async with candidate .run (self ._workspace , sender = sender ) as server :
100104 yield server , receiver
101105 return
102106 except ServerRuntimeError as e :
@@ -118,8 +122,9 @@ def get_config_map(self) -> ConfigurationMap:
118122 def get_server (self ) -> Server :
119123 return self ._server
120124
125+ @classmethod
121126 @abstractmethod
122- def create_default_servers (self ) -> DefaultServers :
127+ def create_default_servers (cls ) -> DefaultServers :
123128 """Create default servers for this client."""
124129
125130 def create_default_config (self ) -> dict [str , Any ] | None :
@@ -244,20 +249,15 @@ async def _exit(self) -> None:
244249 @asynccontextmanager
245250 @logger .catch (reraise = True )
246251 async def __asynccontextmanager__ (self ) -> AsyncGenerator [Self ]:
247- self ._workspace = format_workspace (self ._workspace_arg )
248-
249- if init_config := self .create_default_config ():
250- await self ._config .update_global (init_config )
251-
252252 async with (
253253 asyncer .create_task_group () as tg ,
254- self .run_server () as (server , receiver ), # ty: ignore[invalid-argument-type]
254+ self .run_server () as (server , receiver ),
255255 ):
256256 self ._server = server
257257
258258 # start to receive server requests here,
259259 # since server notification can be sent before `initialize`
260- tg .soonify (self ._dispatch_server_requests )(receiver ) # ty: ignore[invalid-argument-type]
260+ tg .soonify (self ._dispatch_server_requests )(receiver )
261261
262262 client_capabilities = build_client_capabilities (self .__class__ )
263263 root_workspace = self .get_workspace ().get (DEFAULT_WORKSPACE_DIR )
@@ -283,6 +283,9 @@ async def __asynccontextmanager__(self) -> AsyncGenerator[Self]:
283283 )
284284 )
285285
286+ if init_config := self .create_default_config ():
287+ await self ._config .update_global (init_config )
288+
286289 try :
287290 yield self
288291 finally :
0 commit comments