Skip to content

Commit 838ea46

Browse files
committed
feat: update clients impl
1 parent 2ed03c3 commit 838ea46

File tree

6 files changed

+220
-144
lines changed

6 files changed

+220
-144
lines changed

src/lsp_client/clients/deno/client.py

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
WithReceivePublishDiagnostics,
2424
)
2525
from lsp_client.capability.server_notification.log_message import WithReceiveLogMessage
26-
from lsp_client.client.abc import LSPClient
27-
from lsp_client.server.abc import LSPServer
26+
from lsp_client.client.abc import Client
27+
from lsp_client.server import DefaultServers
2828
from lsp_client.server.container import ContainerServer
2929
from lsp_client.server.local import LocalServer
3030
from lsp_client.utils.types import lsp_type
@@ -48,9 +48,38 @@
4848
)
4949

5050

51+
async def ensure_deno_installed() -> None:
52+
if shutil.which("deno"):
53+
return
54+
55+
logger.warning("deno not found, attempting to install...")
56+
57+
try:
58+
# Use shell to execute the piped command
59+
await anyio.run_process(
60+
["sh", "-c", "curl -fsSL https://deno.land/install.sh | sh"]
61+
)
62+
logger.info("Successfully installed deno via shell script")
63+
return
64+
except CalledProcessError as e:
65+
raise RuntimeError(
66+
"Could not install deno. Please install it manually with:\n"
67+
"curl -fsSL https://deno.land/install.sh | sh\n\n"
68+
"See https://deno.land/ for more information."
69+
) from e
70+
71+
72+
DenoLocalServer = partial(
73+
LocalServer,
74+
program="deno",
75+
args=["lsp"],
76+
ensure_installed=ensure_deno_installed,
77+
)
78+
79+
5180
@define
5281
class DenoClient(
53-
LSPClient,
82+
Client,
5483
WithRequestHover,
5584
WithRequestDefinition,
5685
WithRequestReferences,
@@ -108,8 +137,11 @@ def get_language_id(self) -> lsp_type.LanguageKind:
108137
return lsp_type.LanguageKind.TypeScript
109138

110139
@override
111-
def create_default_server(self) -> LSPServer:
112-
return LocalServer(command=["deno", "lsp"])
140+
def create_default_servers(self) -> DefaultServers:
141+
return DefaultServers(
142+
local=DenoLocalServer(),
143+
container=DenoContainerServer(),
144+
)
113145

114146
@override
115147
def create_initialization_options(self) -> dict[str, Any]:
@@ -152,24 +184,3 @@ def create_initialization_options(self) -> dict[str, Any]:
152184
@override
153185
def check_server_compatibility(self, info: lsp_type.ServerInfo | None) -> None:
154186
return
155-
156-
@override
157-
async def ensure_installed(self) -> None:
158-
if shutil.which("deno"):
159-
return
160-
161-
logger.warning("deno not found, attempting to install...")
162-
163-
try:
164-
# Use shell to execute the piped command
165-
await anyio.run_process(
166-
["sh", "-c", "curl -fsSL https://deno.land/install.sh | sh"]
167-
)
168-
logger.info("Successfully installed deno via shell script")
169-
return
170-
except CalledProcessError as e:
171-
raise RuntimeError(
172-
"Could not install deno. Please install it manually with:\n"
173-
"curl -fsSL https://deno.land/install.sh | sh\n\n"
174-
"See https://deno.land/ for more information."
175-
) from e

src/lsp_client/clients/pyrefly.py

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
WithRespondShowMessageRequest,
3636
WithRespondWorkspaceFoldersRequest,
3737
)
38-
from lsp_client.client.abc import LSPClient
39-
from lsp_client.server.abc import LSPServer
38+
from lsp_client.client.abc import Client
39+
from lsp_client.server import DefaultServers
4040
from lsp_client.server.container import ContainerServer
4141
from lsp_client.server.local import LocalServer
4242
from lsp_client.utils.types import lsp_type
@@ -46,9 +46,37 @@
4646
)
4747

4848

49+
async def ensure_pyrefly_installed() -> None:
50+
"""When using local runtime, check and install the server if necessary."""
51+
if shutil.which("pyrefly"):
52+
return
53+
54+
logger.warning("pyrefly not found, attempting to install...")
55+
56+
try:
57+
if shutil.which("uv"):
58+
await anyio.run_process(["uv", "tool", "install", "pyrefly"])
59+
elif shutil.which("pip"):
60+
await anyio.run_process(["pip", "install", "pyrefly"])
61+
logger.info("Successfully installed pyrefly via uv tool")
62+
except CalledProcessError as e:
63+
raise RuntimeError(
64+
"Could not install pyrefly. Please install it manually with 'pip install pyrefly'. "
65+
"See https://pyrefly.org/ for more information."
66+
) from e
67+
68+
69+
PyreflyLocalServer = partial(
70+
LocalServer,
71+
program="pyrefly",
72+
args=["lsp"],
73+
ensure_installed=ensure_pyrefly_installed,
74+
)
75+
76+
4977
@define
5078
class PyreflyClient(
51-
LSPClient,
79+
Client,
5280
WithNotifyDidChangeConfiguration,
5381
WithRequestCallHierarchy,
5482
WithRequestDeclaration,
@@ -87,8 +115,11 @@ def get_language_id(self) -> lsp_type.LanguageKind:
87115
return lsp_type.LanguageKind.Python
88116

89117
@override
90-
def create_default_server(self) -> LSPServer:
91-
return LocalServer(command=["pyrefly", "lsp"])
118+
def create_default_servers(self) -> DefaultServers:
119+
return DefaultServers(
120+
local=PyreflyLocalServer(),
121+
container=PyreflyContainerServer(),
122+
)
92123

93124
@override
94125
def create_initialization_options(self) -> dict[str, Any]:
@@ -102,23 +133,3 @@ def create_initialization_options(self) -> dict[str, Any]:
102133
@override
103134
def check_server_compatibility(self, info: lsp_type.ServerInfo | None) -> None:
104135
return
105-
106-
@override
107-
async def ensure_installed(self) -> None:
108-
"""When using local runtime, check and install the server if necessary."""
109-
if shutil.which("pyrefly"):
110-
return
111-
112-
logger.warning("pyrefly not found, attempting to install...")
113-
114-
try:
115-
if shutil.which("uv"):
116-
await anyio.run_process(["uv", "tool", "install", "pyrefly"])
117-
elif shutil.which("pip"):
118-
await anyio.run_process(["pip", "install", "pyrefly"])
119-
logger.info("Successfully installed pyrefly via uv tool")
120-
except CalledProcessError as e:
121-
raise RuntimeError(
122-
"Could not install pyrefly. Please install it manually with 'pip install pyrefly'. "
123-
"See https://pyrefly.org/ for more information."
124-
) from e

src/lsp_client/clients/pyright.py

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
WithRespondShowMessageRequest,
3535
WithRespondWorkspaceFoldersRequest,
3636
)
37-
from lsp_client.client.abc import LSPClient
38-
from lsp_client.server.abc import LSPServer
37+
from lsp_client.client.abc import Client
38+
from lsp_client.server import DefaultServers
3939
from lsp_client.server.container import ContainerServer
4040
from lsp_client.server.local import LocalServer
4141
from lsp_client.utils.types import lsp_type
@@ -45,9 +45,34 @@
4545
)
4646

4747

48+
async def ensure_pyright_installed() -> None:
49+
if shutil.which("pyright-langserver"):
50+
return
51+
52+
logger.warning("pyright-langserver not found, attempting to install via npm...")
53+
54+
try:
55+
await anyio.run_process(["npm", "install", "-g", "pyright"])
56+
logger.info("Successfully installed pyright-langserver via npm")
57+
return
58+
except CalledProcessError as e:
59+
raise RuntimeError(
60+
"Could not install pyright-langserver. Please install it manually with 'npm install -g pyright'. "
61+
"See https://microsoft.github.io/pyright/ for more information."
62+
) from e
63+
64+
65+
PyrightLocalServer = partial(
66+
LocalServer,
67+
program="pyright-langserver",
68+
args=["--stdio"],
69+
ensure_installed=ensure_pyright_installed,
70+
)
71+
72+
4873
@define
4974
class PyrightClient(
50-
LSPClient,
75+
Client,
5176
WithNotifyDidChangeConfiguration,
5277
WithRequestCallHierarchy,
5378
WithRequestDeclaration,
@@ -82,8 +107,11 @@ def get_language_id(self) -> lsp_type.LanguageKind:
82107
return lsp_type.LanguageKind.Python
83108

84109
@override
85-
def create_default_server(self) -> LSPServer:
86-
return LocalServer(command=["pyright-langserver", "--stdio"])
110+
def create_default_servers(self) -> DefaultServers:
111+
return DefaultServers(
112+
local=PyrightLocalServer(),
113+
container=PyrightContainerServer(),
114+
)
87115

88116
@override
89117
def create_initialization_options(self) -> dict[str, Any]:
@@ -95,20 +123,3 @@ def create_initialization_options(self) -> dict[str, Any]:
95123
@override
96124
def check_server_compatibility(self, info: lsp_type.ServerInfo | None) -> None:
97125
return
98-
99-
@override
100-
async def ensure_installed(self) -> None:
101-
if shutil.which("pyright-langserver"):
102-
return
103-
104-
logger.warning("pyright-langserver not found, attempting to install via npm...")
105-
106-
try:
107-
await anyio.run_process(["npm", "install", "-g", "pyright"])
108-
logger.info("Successfully installed pyright-langserver via npm")
109-
return
110-
except CalledProcessError as e:
111-
raise RuntimeError(
112-
"Could not install pyright-langserver. Please install it manually with 'npm install -g pyright'. "
113-
"See https://microsoft.github.io/pyright/ for more information."
114-
) from e

src/lsp_client/clients/rust_analyzer.py

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
WithRespondShowMessageRequest,
3636
WithRespondWorkspaceFoldersRequest,
3737
)
38-
from lsp_client.client.abc import LSPClient
39-
from lsp_client.server.abc import LSPServer
38+
from lsp_client.client.abc import Client
39+
from lsp_client.server import DefaultServers
4040
from lsp_client.server.container import ContainerServer
4141
from lsp_client.server.local import LocalServer
4242
from lsp_client.utils.types import lsp_type
@@ -46,9 +46,33 @@
4646
)
4747

4848

49+
async def ensure_rust_analyzer_installed() -> None:
50+
if shutil.which("rust-analyzer"):
51+
return
52+
53+
logger.warning("rust-analyzer not found, attempting to install...")
54+
55+
try:
56+
await anyio.run_process(["rustup", "component", "add", "rust-analyzer"])
57+
logger.info("Successfully installed rust-analyzer via rustup")
58+
except CalledProcessError as e:
59+
raise RuntimeError(
60+
"Could not install rust-analyzer. Please install it manually with 'rustup component add rust-analyzer'. "
61+
"See https://rust-analyzer.github.io/ for more information."
62+
) from e
63+
64+
65+
RustAnalyzerLocalServer = partial(
66+
LocalServer,
67+
program="rust-analyzer",
68+
args=[],
69+
ensure_installed=ensure_rust_analyzer_installed,
70+
)
71+
72+
4973
@define
5074
class RustAnalyzerClient(
51-
LSPClient,
75+
Client,
5276
WithNotifyDidChangeConfiguration,
5377
WithRequestCallHierarchy,
5478
WithRequestDeclaration,
@@ -68,6 +92,14 @@ class RustAnalyzerClient(
6892
WithRespondShowMessageRequest,
6993
WithRespondWorkspaceFoldersRequest,
7094
):
95+
"""
96+
- Language: Rust
97+
- Homepage: https://rust-analyzer.github.io/
98+
- Doc: https://rust-analyzer.github.io/manual.html
99+
- Github: https://github.com/rust-lang/rust-analyzer
100+
- VSCode Extension: https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer
101+
"""
102+
71103
proc_macro_enable: bool = True
72104
cargo_build_scripts_enable: bool = True
73105

@@ -87,8 +119,11 @@ def get_language_id(self) -> lsp_type.LanguageKind:
87119
return lsp_type.LanguageKind.Rust
88120

89121
@override
90-
def create_default_server(self) -> LSPServer:
91-
return LocalServer(command=["rust-analyzer"])
122+
def create_default_servers(self) -> DefaultServers:
123+
return DefaultServers(
124+
local=RustAnalyzerLocalServer(),
125+
container=RustAnalyzerContainerServer(),
126+
)
92127

93128
@override
94129
def create_initialization_options(self) -> dict[str, Any]:
@@ -112,19 +147,3 @@ def create_initialization_options(self) -> dict[str, Any]:
112147
@override
113148
def check_server_compatibility(self, info: lsp_type.ServerInfo | None) -> None:
114149
return
115-
116-
@override
117-
async def ensure_installed(self) -> None:
118-
if shutil.which("rust-analyzer"):
119-
return
120-
121-
logger.warning("rust-analyzer not found, attempting to install...")
122-
123-
try:
124-
await anyio.run_process(["rustup", "component", "add", "rust-analyzer"])
125-
logger.info("Successfully installed rust-analyzer via rustup")
126-
except CalledProcessError as e:
127-
raise RuntimeError(
128-
"Could not install rust-analyzer. Please install it manually with 'rustup component add rust-analyzer'. "
129-
"See https://rust-analyzer.github.io/ for more information."
130-
) from e

0 commit comments

Comments
 (0)