Skip to content

Commit 9bc4412

Browse files
committed
update
1 parent ab2772f commit 9bc4412

File tree

7 files changed

+94
-12
lines changed

7 files changed

+94
-12
lines changed

python/src/lsap/definition.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@
1717
from lsprotocol.types import Location
1818

1919
from .abc import Capability, ClientProtocol
20+
from .exception import UnsupportedCapabilityError
2021
from .locate import LocateCapability
2122
from .symbol import SymbolCapability
2223

2324

2425
@runtime_checkable
2526
class DefinitionClient(
2627
WithRequestDefinition,
27-
WithRequestDeclaration,
28-
WithRequestTypeDefinition,
2928
WithRequestDocumentSymbol,
3029
WithRequestHover,
3130
ClientProtocol,
@@ -59,10 +58,24 @@ async def __call__(self, req: DefinitionRequest) -> DefinitionResponse | None:
5958
file_path, lsp_pos
6059
)
6160
case "declaration":
61+
if not isinstance(self.client, WithRequestDeclaration):
62+
raise UnsupportedCapabilityError(
63+
"Client does not support 'textDocument/declaration'. "
64+
"To find declarations, you can: "
65+
"1) Use 'definition' mode (most language servers treat them similarly); "
66+
"2) For C/C++, check corresponding header files manually."
67+
)
6268
locations = await self.client.request_declaration_locations(
6369
file_path, lsp_pos
6470
)
6571
case "type_definition":
72+
if not isinstance(self.client, WithRequestTypeDefinition):
73+
raise UnsupportedCapabilityError(
74+
"Client does not support 'textDocument/typeDefinition'. "
75+
"To find type definitions, you can: "
76+
"1) Use 'definition' on the type name itself if visible; "
77+
"2) Use 'hover' to see the type name and then search for it."
78+
)
6679
locations = await self.client.request_type_definition_locations(
6780
file_path, lsp_pos
6881
)

python/src/lsap/exception.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ class AmbiguousError(LSAPError):
1111

1212
class NotFoundError(LSAPError):
1313
"""Raised when something is not found."""
14+
15+
16+
class UnsupportedCapabilityError(LSAPError):
17+
"""Raised when a capability is not supported by the client."""

python/src/lsap/reference.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
from lsap.utils.symbol import symbol_at
2323

2424
from .abc import Capability
25+
from .exception import UnsupportedCapabilityError
2526
from .locate import LocateCapability
2627
from .utils.cache import PaginationCache
2728

2829

2930
@runtime_checkable
3031
class ReferenceClient(
3132
WithRequestReferences,
32-
WithRequestImplementation,
3333
WithRequestDocumentSymbol,
3434
WithRequestHover,
3535
CapabilityClientProtocol,
@@ -61,6 +61,14 @@ async def fetcher() -> list[ReferenceItem] | None:
6161
):
6262
locations.extend(refs)
6363
elif req.mode == "implementations":
64+
if not isinstance(self.client, WithRequestImplementation):
65+
raise UnsupportedCapabilityError(
66+
"Client does not support 'textDocument/implementation'. "
67+
"To find implementations, you can: "
68+
"1) Use 'references' mode to find all usages (often including implementations); "
69+
"2) Find the symbol definition and then search for its references; "
70+
"3) Use 'search' or 'symbol' capability to find name-matched definitions."
71+
)
6472
if impls := await self.client.request_implementation_locations(
6573
file_path, lsp_pos
6674
):

python/tests/test_definition.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from lsprotocol.types import Range as LSPRange
1010

1111
from lsap.definition import DefinitionCapability
12+
from lsap.exception import UnsupportedCapabilityError
1213

1314

1415
class MockDefinitionClient:
@@ -87,3 +88,20 @@ async def test_definition():
8788
assert resp.items[0].path == ["foo"]
8889
assert resp.items[0].code is not None
8990
assert "def foo():" in resp.items[0].code
91+
92+
93+
@pytest.mark.asyncio
94+
async def test_unsupported_declaration():
95+
client = MockDefinitionClient()
96+
capability = DefinitionCapability(client=client) # type: ignore
97+
98+
req = DefinitionRequest(
99+
locate=Locate(file_path=Path("main.py"), scope=LineScope(line=2), find="foo"),
100+
mode="declaration",
101+
)
102+
103+
with pytest.raises(UnsupportedCapabilityError) as excinfo:
104+
await capability(req)
105+
106+
assert "textDocument/declaration" in str(excinfo.value)
107+
assert "definition" in str(excinfo.value)

python/tests/test_outline.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
from pathlib import Path
22

33
import pytest
4-
from lsprotocol.types import (
5-
DocumentSymbol,
6-
Position as LSPPosition,
7-
Range as LSPRange,
8-
SymbolKind,
9-
)
4+
from lsap_schema.outline import OutlineRequest
5+
from lsprotocol.types import DocumentSymbol, SymbolKind
6+
from lsprotocol.types import Position as LSPPosition
7+
from lsprotocol.types import Range as LSPRange
108

119
from lsap.outline import OutlineCapability
12-
from lsap_schema.outline import OutlineRequest
1310

1411

1512
class MockOutlineClient:

python/tests/test_reference.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
Position as LSPPosition,
88
Location,
99
)
10+
from lsap.exception import UnsupportedCapabilityError
1011
from lsap.reference import ReferenceCapability
1112
from lsap_schema.reference import ReferenceRequest
1213
from lsap_schema.locate import LineScope, Locate
@@ -122,3 +123,20 @@ async def test_reference_pagination():
122123
assert len(resp2.items) == 1
123124
assert resp2.has_more is False
124125
assert resp2.pagination_id is None
126+
127+
128+
@pytest.mark.asyncio
129+
async def test_unsupported_implementation():
130+
client = MockReferenceClient()
131+
capability = ReferenceCapability(client=client) # type: ignore
132+
133+
req = ReferenceRequest(
134+
locate=Locate(file_path=Path("test.py"), scope=LineScope(line=2), find="foo"),
135+
mode="implementations",
136+
)
137+
138+
with pytest.raises(UnsupportedCapabilityError) as excinfo:
139+
await capability(req)
140+
141+
assert "textDocument/implementation" in str(excinfo.value)
142+
assert "references" in str(excinfo.value)

python/uv.lock

Lines changed: 26 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)