Skip to content

Commit 01301e1

Browse files
Copilotobserverw
andcommitted
Add support for typescript-language-server
Co-authored-by: observerw <[email protected]>
1 parent 8e32402 commit 01301e1

File tree

4 files changed

+165
-6
lines changed

4 files changed

+165
-6
lines changed

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,13 @@ if __name__ == "__main__":
8888

8989
The library includes pre-configured clients for popular language servers:
9090

91-
| Language Server | Module Path | Language |
92-
| --------------- | ---------------------------------- | --------------------- |
93-
| Pyright | `lsp_client.clients.pyright` | Python |
94-
| Pyrefly | `lsp_client.clients.pyrefly` | Python |
95-
| Rust Analyzer | `lsp_client.clients.rust_analyzer` | Rust |
96-
| Deno | `lsp_client.clients.deno` | TypeScript/JavaScript |
91+
| Language Server | Module Path | Language |
92+
| ---------------------------- | ---------------------------------- | --------------------- |
93+
| Pyright | `lsp_client.clients.pyright` | Python |
94+
| Pyrefly | `lsp_client.clients.pyrefly` | Python |
95+
| Rust Analyzer | `lsp_client.clients.rust_analyzer` | Rust |
96+
| Deno | `lsp_client.clients.deno` | TypeScript/JavaScript |
97+
| TypeScript Language Server | `lsp_client.clients.tsserver` | TypeScript/JavaScript |
9798

9899
## Contributing
99100

examples/tsserver.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Example: Using TypeScript Language Server for TypeScript code analysis
2+
#
3+
# This example demonstrates how to use the TypeScript Language Server
4+
# to find definition locations in TypeScript code. The typescript-language-server
5+
# provides powerful static analysis for TypeScript and JavaScript projects.
6+
7+
from __future__ import annotations
8+
9+
from pathlib import Path
10+
11+
import anyio
12+
13+
from lsp_client.clients.tsserver import TsserverClient, TsserverLocalServer
14+
15+
16+
async def main():
17+
# Set up workspace directory
18+
workspace = Path.cwd()
19+
async with TsserverClient(
20+
server=TsserverLocalServer(),
21+
workspace=workspace,
22+
) as client:
23+
# Example: Find definition of TsserverClient at line 13, column 28
24+
# This demonstrates the definition lookup capability
25+
print(f"Using language server for: {client.get_language_id()}")
26+
27+
# In a real scenario, you would provide a TypeScript file path
28+
# refs = await client.request_definition_locations(
29+
# file_path="src/index.ts",
30+
# position=Position(10, 15),
31+
# )
32+
#
33+
# if not refs:
34+
# print("No definition locations found.")
35+
# return
36+
#
37+
# # Display all definition locations found
38+
# for ref in refs:
39+
# print(f"Definition location found at {ref.uri} - Range: {ref.range}")
40+
41+
42+
if __name__ == "__main__":
43+
anyio.run(main) # Run the async example

src/lsp_client/clients/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
from .pyrefly import PyreflyClient
77
from .pyright import PyrightClient
88
from .rust_analyzer import RustAnalyzerClient
9+
from .tsserver import TsserverClient
910

1011
clients: Final = (
1112
DenoClient,
1213
PyreflyClient,
1314
PyrightClient,
1415
RustAnalyzerClient,
16+
TsserverClient,
1517
)
1618

1719
PythonClient = PyrightClient

src/lsp_client/clients/tsserver.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
from __future__ import annotations
2+
3+
import shutil
4+
from functools import partial
5+
from subprocess import CalledProcessError
6+
from typing import Any, override
7+
8+
import anyio
9+
from attrs import define
10+
from loguru import logger
11+
12+
from lsp_client.capability.request import (
13+
WithRequestCallHierarchy,
14+
WithRequestDefinition,
15+
WithRequestDocumentSymbol,
16+
WithRequestHover,
17+
WithRequestImplementation,
18+
WithRequestReferences,
19+
WithRequestTypeDefinition,
20+
WithRequestWorkspaceSymbol,
21+
)
22+
from lsp_client.capability.server_notification import (
23+
WithReceivePublishDiagnostics,
24+
)
25+
from lsp_client.capability.server_notification.log_message import WithReceiveLogMessage
26+
from lsp_client.client.abc import LSPClient
27+
from lsp_client.server.docker import DockerServer
28+
from lsp_client.server.local import LocalServer
29+
from lsp_client.utils.types import lsp_type
30+
31+
TsserverLocalServer = partial(
32+
LocalServer, command=["typescript-language-server", "--stdio"]
33+
)
34+
TsserverDockerServer = partial(DockerServer, image="docker.io/lspcontainers/tsserver")
35+
36+
37+
@define
38+
class TsserverClient(
39+
LSPClient,
40+
WithRequestHover,
41+
WithRequestDefinition,
42+
WithRequestReferences,
43+
WithRequestImplementation,
44+
WithRequestTypeDefinition,
45+
WithRequestCallHierarchy,
46+
WithRequestDocumentSymbol,
47+
WithRequestWorkspaceSymbol,
48+
WithReceiveLogMessage,
49+
WithReceivePublishDiagnostics,
50+
):
51+
"""
52+
- Language: TypeScript, JavaScript
53+
- Homepage: https://github.com/typescript-language-server/typescript-language-server
54+
- Doc: https://github.com/typescript-language-server/typescript-language-server#readme
55+
- Github: https://github.com/typescript-language-server/typescript-language-server
56+
- VSCode Extension: Built-in TypeScript support in VS Code
57+
"""
58+
59+
# Preferences for TypeScript/JavaScript language features
60+
suggest_complete_function_calls: bool = True
61+
include_automatic_optional_chain_completions: bool = True
62+
include_completions_for_module_exports: bool = True
63+
include_completions_with_insert_text: bool = True
64+
65+
# Auto-import and path suggestions
66+
auto_import_suggestions: bool = True
67+
path_suggestions: bool = True
68+
69+
# Code actions and refactorings
70+
enable_call_hierarchy: bool = True
71+
enable_semantic_highlighting: bool = True
72+
73+
@override
74+
def get_language_id(self) -> lsp_type.LanguageKind:
75+
return lsp_type.LanguageKind.TypeScript
76+
77+
@override
78+
def create_initialization_options(self) -> dict[str, Any]:
79+
return {
80+
"preferences": {
81+
"includeCompletionsForModuleExports": self.include_completions_for_module_exports,
82+
"includeAutomaticOptionalChainCompletions": self.include_automatic_optional_chain_completions,
83+
"includeCompletionsWithInsertText": self.include_completions_with_insert_text,
84+
},
85+
"suggest": {
86+
"completeFunctionCalls": self.suggest_complete_function_calls,
87+
},
88+
}
89+
90+
@override
91+
def check_server_compatibility(self, info: lsp_type.ServerInfo | None) -> None:
92+
return
93+
94+
@override
95+
async def ensure_installed(self) -> None:
96+
if shutil.which("typescript-language-server"):
97+
return
98+
99+
logger.warning(
100+
"typescript-language-server not found, attempting to install via npm..."
101+
)
102+
103+
try:
104+
await anyio.run_process(
105+
["npm", "install", "-g", "typescript-language-server", "typescript"]
106+
)
107+
logger.info("Successfully installed typescript-language-server via npm")
108+
return
109+
except CalledProcessError as e:
110+
raise RuntimeError(
111+
"Could not install typescript-language-server. Please install it manually with 'npm install -g typescript-language-server typescript'. "
112+
"See https://github.com/typescript-language-server/typescript-language-server for more information."
113+
) from e

0 commit comments

Comments
 (0)