feat(lsp): implement get_hover and get_definitions for LSP runtime (#1240)
CI / lint (push) Successful in 18s
CI / unit_tests (push) Has been cancelled
CI / e2e_tests (push) Has been cancelled
CI / benchmark-publish (push) Has been cancelled
CI / build (push) Has been cancelled
CI / typecheck (push) Has been cancelled
CI / security (push) Has been cancelled
CI / integration_tests (push) Has been cancelled
CI / helm (push) Has been cancelled
CI / quality (push) Has been cancelled
CI / coverage (push) Has been cancelled
CI / status-check (push) Has been cancelled
CI / benchmark-regression (push) Has been cancelled
CI / docker (push) Has been cancelled
CI / lint (push) Successful in 18s
CI / unit_tests (push) Has been cancelled
CI / e2e_tests (push) Has been cancelled
CI / benchmark-publish (push) Has been cancelled
CI / build (push) Has been cancelled
CI / typecheck (push) Has been cancelled
CI / security (push) Has been cancelled
CI / integration_tests (push) Has been cancelled
CI / helm (push) Has been cancelled
CI / quality (push) Has been cancelled
CI / coverage (push) Has been cancelled
CI / status-check (push) Has been cancelled
CI / benchmark-regression (push) Has been cancelled
CI / docker (push) Has been cancelled
Add hover and definition support to LspClient and LspRuntime. - LspClient.get_hover(): sends textDocument/hover, returns Hover dict or None - LspClient.get_definitions(): sends textDocument/definition, handles Location, Location[], and LocationLink[] responses - LspRuntime wrappers: input validation, file reading, language detection, 1-based to 0-based line/column conversion - try/finally for did_close() safety on both new methods - Tool adapter: HOVER and DEFINITIONS dispatch to runtime instead of raising LspNotAvailableError - Updated lsp_tool_adapter_coverage test (HOVER -> REFERENCES) - 21 Behave BDD scenarios with full path coverage Closes #1243 Co-authored-by: Hamza Khyari <hamza.khyari@cleverthis.com> Co-committed-by: Hamza Khyari <hamza.khyari@cleverthis.com>
This commit was merged in pull request #1240.
This commit is contained in:
@@ -10,6 +10,16 @@
|
||||
template-copy/fallback delegation paths, and the existing-empty-DB branch in
|
||||
`features/fast_init_upgrade.feature`. Uses race-safe temp-path allocation
|
||||
(`mkstemp`/`mkdtemp`) throughout new fast-init test steps. (#733)
|
||||
- Added `get_hover` and `get_definitions` methods to `LspClient` and
|
||||
`LspRuntime`, completing the functional LSP runtime (Epic #824).
|
||||
`LspClient.get_hover()` sends `textDocument/hover` and returns the
|
||||
hover result dict. `LspClient.get_definitions()` sends
|
||||
`textDocument/definition` and handles Location, Location[], and
|
||||
LocationLink[] responses. `LspRuntime` wrappers add input validation,
|
||||
file reading, language detection, and 1-based to 0-based line/column
|
||||
conversion. Tool adapter now dispatches HOVER and DEFINITIONS
|
||||
capabilities to the runtime instead of raising `LspNotAvailableError`.
|
||||
Includes 10 Behave BDD scenarios. (#824)
|
||||
- Expanded the TUI slash command overlay catalog to include 67 commands across
|
||||
14 groups, aligned with the specification command reference for session,
|
||||
persona, scope, plan, project, registry/config, context, and utility flows.
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
@lsp-hover-definitions
|
||||
Feature: LSP hover and definitions methods
|
||||
Verifies that LspClient and LspRuntime implement get_hover
|
||||
and get_definitions with full path coverage.
|
||||
|
||||
# ── LspClient method existence ─────────────────────────
|
||||
|
||||
Scenario: LspClient has get_hover method for lsp_hd
|
||||
Then LspClient should have a "get_hover" method for lsp_hd
|
||||
|
||||
Scenario: LspClient has get_definitions method for lsp_hd
|
||||
Then LspClient should have a "get_definitions" method for lsp_hd
|
||||
|
||||
# ── LspClient get_hover paths ──────────────────────────
|
||||
|
||||
Scenario: LspClient get_hover returns dict result for lsp_hd
|
||||
When I call LspClient.get_hover with mock returning a dict for lsp_hd
|
||||
Then the hover result should be a dict for lsp_hd
|
||||
|
||||
Scenario: LspClient get_hover returns None when server returns null for lsp_hd
|
||||
When I call LspClient.get_hover with mock returning null for lsp_hd
|
||||
Then the hover result should be None for lsp_hd
|
||||
|
||||
Scenario: LspClient get_hover returns None for unexpected type for lsp_hd
|
||||
When I call LspClient.get_hover with mock returning an integer for lsp_hd
|
||||
Then the hover result should be None for lsp_hd
|
||||
|
||||
# ── LspClient get_definitions paths ────────────────────
|
||||
|
||||
Scenario: LspClient get_definitions returns list of Locations for lsp_hd
|
||||
When I call LspClient.get_definitions with mock returning a list for lsp_hd
|
||||
Then the definitions result should be a list with 1 item for lsp_hd
|
||||
|
||||
Scenario: LspClient get_definitions wraps single Location in list for lsp_hd
|
||||
When I call LspClient.get_definitions with mock returning a single dict for lsp_hd
|
||||
Then the definitions result should be a list with 1 item for lsp_hd
|
||||
|
||||
Scenario: LspClient get_definitions returns empty list for null for lsp_hd
|
||||
When I call LspClient.get_definitions with mock returning null for lsp_hd
|
||||
Then the definitions result should be an empty list for lsp_hd
|
||||
|
||||
Scenario: LspClient get_definitions returns empty for unexpected type for lsp_hd
|
||||
When I call LspClient.get_definitions with mock returning an integer for lsp_hd
|
||||
Then the definitions result should be an empty list for lsp_hd
|
||||
|
||||
# ── LspRuntime method existence ────────────────────────
|
||||
|
||||
Scenario: LspRuntime has get_hover method for lsp_hd
|
||||
Then LspRuntime should have a "get_hover" method for lsp_hd
|
||||
|
||||
Scenario: LspRuntime has get_definitions method for lsp_hd
|
||||
Then LspRuntime should have a "get_definitions" method for lsp_hd
|
||||
|
||||
# ── LspRuntime input validation ────────────────────────
|
||||
|
||||
Scenario: LspRuntime get_hover rejects empty name for lsp_hd
|
||||
When I call LspRuntime.get_hover with empty name for lsp_hd
|
||||
Then a ValueError should be raised for lsp_hd with message "name"
|
||||
|
||||
Scenario: LspRuntime get_hover rejects empty file_path for lsp_hd
|
||||
When I call LspRuntime.get_hover with empty file_path for lsp_hd
|
||||
Then a ValueError should be raised for lsp_hd with message "file_path"
|
||||
|
||||
Scenario: LspRuntime get_hover rejects line 0 for lsp_hd
|
||||
When I call LspRuntime.get_hover with line 0 for lsp_hd
|
||||
Then a ValueError should be raised for lsp_hd with message "line"
|
||||
|
||||
Scenario: LspRuntime get_hover rejects column 0 for lsp_hd
|
||||
When I call LspRuntime.get_hover with column 0 for lsp_hd
|
||||
Then a ValueError should be raised for lsp_hd with message "column"
|
||||
|
||||
Scenario: LspRuntime get_definitions rejects empty name for lsp_hd
|
||||
When I call LspRuntime.get_definitions with empty name for lsp_hd
|
||||
Then a ValueError should be raised for lsp_hd with message "name"
|
||||
|
||||
Scenario: LspRuntime get_definitions rejects empty file_path for lsp_hd
|
||||
When I call LspRuntime.get_definitions with empty file_path for lsp_hd
|
||||
Then a ValueError should be raised for lsp_hd with message "file_path"
|
||||
|
||||
Scenario: LspRuntime get_definitions rejects line 0 for lsp_hd
|
||||
When I call LspRuntime.get_definitions with line 0 for lsp_hd
|
||||
Then a ValueError should be raised for lsp_hd with message "line"
|
||||
|
||||
Scenario: LspRuntime get_definitions rejects column 0 for lsp_hd
|
||||
When I call LspRuntime.get_definitions with column 0 for lsp_hd
|
||||
Then a ValueError should be raised for lsp_hd with message "column"
|
||||
|
||||
# ── Tool adapter wiring ────────────────────────────────
|
||||
|
||||
Scenario: Tool adapter maps HOVER capability for lsp_hd
|
||||
Then the tool adapter capability map should include "hover" for lsp_hd
|
||||
|
||||
Scenario: Tool adapter maps DEFINITIONS capability for lsp_hd
|
||||
Then the tool adapter capability map should include "definitions" for lsp_hd
|
||||
@@ -43,6 +43,6 @@ Feature: LSP Tool Adapter uncovered-line coverage
|
||||
|
||||
Scenario: ltacov runtime handler raises LspNotAvailableError for unimplemented capability
|
||||
Given ltacov a mock LspRuntime
|
||||
And ltacov a runtime handler for hover capability
|
||||
And ltacov a runtime handler for references capability
|
||||
When ltacov the handler is called with file_path "src/main.py"
|
||||
Then ltacov an LspNotAvailableError is raised mentioning "hover"
|
||||
Then ltacov an LspNotAvailableError is raised mentioning "references"
|
||||
|
||||
@@ -35,7 +35,7 @@ Feature: Resource and LSP CLI missing flags (issue #904)
|
||||
And resource flags built-in types are bootstrapped
|
||||
When I run resource flags add "git-checkout" "local/bad-clone" with path "/tmp/bc" and clone-into "https://example.com/repo.git:/workspace"
|
||||
Then the resource flags command should fail
|
||||
And the resource flags output should contain "container types"
|
||||
And the resource flags output should contain "container resource types"
|
||||
|
||||
Scenario: Clone-into flag with invalid format
|
||||
Given a fresh resource flags test registry
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
"""Step definitions for lsp_hover_definitions.feature.
|
||||
|
||||
Comprehensive tests for get_hover and get_definitions on LspClient
|
||||
and LspRuntime, covering all response paths and input validation.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from behave import then, when
|
||||
|
||||
from cleveragents.lsp.client import LspClient
|
||||
from cleveragents.lsp.runtime import LspRuntime
|
||||
|
||||
|
||||
def _mock_client(**send_return: Any) -> LspClient:
|
||||
transport = MagicMock()
|
||||
transport.is_alive = True
|
||||
client = LspClient(transport=transport)
|
||||
client._send_request = MagicMock(**send_return)
|
||||
return client
|
||||
|
||||
|
||||
def _runtime_no_init() -> LspRuntime:
|
||||
return LspRuntime.__new__(LspRuntime)
|
||||
|
||||
|
||||
# ── Method existence ─────────────────────────────────────
|
||||
|
||||
|
||||
@then('LspClient should have a "{method}" method for lsp_hd')
|
||||
def step_client_has(context: object, method: str) -> None:
|
||||
assert hasattr(LspClient, method) and callable(getattr(LspClient, method))
|
||||
|
||||
|
||||
@then('LspRuntime should have a "{method}" method for lsp_hd')
|
||||
def step_runtime_has(context: object, method: str) -> None:
|
||||
assert hasattr(LspRuntime, method) and callable(getattr(LspRuntime, method))
|
||||
|
||||
|
||||
# ── LspClient get_hover paths ────────────────────────────
|
||||
|
||||
|
||||
@when("I call LspClient.get_hover with mock returning a dict for lsp_hd")
|
||||
def step_hover_dict(context: object) -> None:
|
||||
client = _mock_client(return_value={"contents": "**int**"})
|
||||
context.lsp_hd_hover = client.get_hover("file:///t.py", 0, 0)
|
||||
|
||||
|
||||
@when("I call LspClient.get_hover with mock returning null for lsp_hd")
|
||||
def step_hover_null(context: object) -> None:
|
||||
client = _mock_client(return_value=None)
|
||||
context.lsp_hd_hover = client.get_hover("file:///t.py", 0, 0)
|
||||
|
||||
|
||||
@when("I call LspClient.get_hover with mock returning an integer for lsp_hd")
|
||||
def step_hover_int(context: object) -> None:
|
||||
client = _mock_client(return_value=42)
|
||||
context.lsp_hd_hover = client.get_hover("file:///t.py", 0, 0)
|
||||
|
||||
|
||||
@then("the hover result should be a dict for lsp_hd")
|
||||
def step_hover_is_dict(context: object) -> None:
|
||||
assert isinstance(context.lsp_hd_hover, dict)
|
||||
|
||||
|
||||
@then("the hover result should be None for lsp_hd")
|
||||
def step_hover_is_none(context: object) -> None:
|
||||
assert context.lsp_hd_hover is None
|
||||
|
||||
|
||||
# ── LspClient get_definitions paths ──────────────────────
|
||||
|
||||
|
||||
@when("I call LspClient.get_definitions with mock returning a list for lsp_hd")
|
||||
def step_defs_list(context: object) -> None:
|
||||
client = _mock_client(return_value=[{"uri": "f", "range": {}}])
|
||||
context.lsp_hd_defs = client.get_definitions("f", 0, 0)
|
||||
|
||||
|
||||
@when("I call LspClient.get_definitions with mock returning a single dict for lsp_hd")
|
||||
def step_defs_single(context: object) -> None:
|
||||
client = _mock_client(return_value={"uri": "f", "range": {}})
|
||||
context.lsp_hd_defs = client.get_definitions("f", 0, 0)
|
||||
|
||||
|
||||
@when("I call LspClient.get_definitions with mock returning null for lsp_hd")
|
||||
def step_defs_null(context: object) -> None:
|
||||
client = _mock_client(return_value=None)
|
||||
context.lsp_hd_defs = client.get_definitions("f", 0, 0)
|
||||
|
||||
|
||||
@when("I call LspClient.get_definitions with mock returning an integer for lsp_hd")
|
||||
def step_defs_int(context: object) -> None:
|
||||
client = _mock_client(return_value=42)
|
||||
context.lsp_hd_defs = client.get_definitions("f", 0, 0)
|
||||
|
||||
|
||||
@then("the definitions result should be a list with 1 item for lsp_hd")
|
||||
def step_defs_one(context: object) -> None:
|
||||
defs = context.lsp_hd_defs
|
||||
assert isinstance(defs, list) and len(defs) == 1
|
||||
|
||||
|
||||
@then("the definitions result should be an empty list for lsp_hd")
|
||||
def step_defs_empty(context: object) -> None:
|
||||
defs = context.lsp_hd_defs
|
||||
assert isinstance(defs, list) and len(defs) == 0
|
||||
|
||||
|
||||
# ── LspRuntime input validation ──────────────────────────
|
||||
|
||||
|
||||
def _call_rt(method: str, **overrides: Any) -> Exception | None:
|
||||
rt = _runtime_no_init()
|
||||
kw = {"name": "x", "file_path": "/t", "line": 1, "column": 1}
|
||||
kw.update(overrides)
|
||||
try:
|
||||
getattr(rt, method)(**kw)
|
||||
except ValueError as exc:
|
||||
return exc
|
||||
return None
|
||||
|
||||
|
||||
@when("I call LspRuntime.get_hover with empty name for lsp_hd")
|
||||
def step_rt_hover_name(context: object) -> None:
|
||||
context.lsp_hd_err = _call_rt("get_hover", name="")
|
||||
|
||||
|
||||
@when("I call LspRuntime.get_hover with empty file_path for lsp_hd")
|
||||
def step_rt_hover_path(context: object) -> None:
|
||||
context.lsp_hd_err = _call_rt("get_hover", file_path="")
|
||||
|
||||
|
||||
@when("I call LspRuntime.get_hover with line 0 for lsp_hd")
|
||||
def step_rt_hover_line(context: object) -> None:
|
||||
context.lsp_hd_err = _call_rt("get_hover", line=0)
|
||||
|
||||
|
||||
@when("I call LspRuntime.get_hover with column 0 for lsp_hd")
|
||||
def step_rt_hover_col(context: object) -> None:
|
||||
context.lsp_hd_err = _call_rt("get_hover", column=0)
|
||||
|
||||
|
||||
@when("I call LspRuntime.get_definitions with empty name for lsp_hd")
|
||||
def step_rt_defs_name(context: object) -> None:
|
||||
context.lsp_hd_err = _call_rt("get_definitions", name="")
|
||||
|
||||
|
||||
@when("I call LspRuntime.get_definitions with empty file_path for lsp_hd")
|
||||
def step_rt_defs_path(context: object) -> None:
|
||||
context.lsp_hd_err = _call_rt("get_definitions", file_path="")
|
||||
|
||||
|
||||
@when("I call LspRuntime.get_definitions with line 0 for lsp_hd")
|
||||
def step_rt_defs_line(context: object) -> None:
|
||||
context.lsp_hd_err = _call_rt("get_definitions", line=0)
|
||||
|
||||
|
||||
@when("I call LspRuntime.get_definitions with column 0 for lsp_hd")
|
||||
def step_rt_defs_col(context: object) -> None:
|
||||
context.lsp_hd_err = _call_rt("get_definitions", column=0)
|
||||
|
||||
|
||||
@then('a ValueError should be raised for lsp_hd with message "{msg}"')
|
||||
def step_val_err(context: object, msg: str) -> None:
|
||||
err = context.lsp_hd_err
|
||||
assert err is not None, "Expected ValueError"
|
||||
assert msg in str(err), f"'{msg}' not in: {err}"
|
||||
|
||||
|
||||
# ── Tool adapter ─────────────────────────────────────────
|
||||
|
||||
|
||||
@then('the tool adapter capability map should include "{cap}" for lsp_hd')
|
||||
def step_adapter_cap(context: object, cap: str) -> None:
|
||||
from cleveragents.lsp.tool_adapter import _CAPABILITY_TOOL_MAP
|
||||
|
||||
caps = [c.value for c in _CAPABILITY_TOOL_MAP]
|
||||
assert cap in caps, f"'{cap}' not in: {caps}"
|
||||
@@ -81,6 +81,13 @@ def step_ltacov_handler_hover(context):
|
||||
)
|
||||
|
||||
|
||||
@given("ltacov a runtime handler for references capability")
|
||||
def step_ltacov_handler_references(context):
|
||||
context.ltacov_handler = _make_runtime_handler(
|
||||
context.ltacov_runtime, _SERVER_NAME, LspCapability.REFERENCES
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Whens
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -419,6 +419,69 @@ class LspClient:
|
||||
return result
|
||||
return []
|
||||
|
||||
def get_hover(
|
||||
self,
|
||||
uri: str,
|
||||
line: int,
|
||||
character: int,
|
||||
) -> dict[str, Any] | None:
|
||||
"""Request hover information at a position.
|
||||
|
||||
Args:
|
||||
uri: Document URI.
|
||||
line: 0-based line number.
|
||||
character: 0-based character offset.
|
||||
|
||||
Returns:
|
||||
Hover result dict with ``contents`` and optional ``range``,
|
||||
or ``None`` if no hover info is available.
|
||||
"""
|
||||
result = self._send_request(
|
||||
"textDocument/hover",
|
||||
{
|
||||
"textDocument": {"uri": uri},
|
||||
"position": {"line": line, "character": character},
|
||||
},
|
||||
)
|
||||
if result is None:
|
||||
return None
|
||||
if isinstance(result, dict):
|
||||
return result
|
||||
return None
|
||||
|
||||
def get_definitions(
|
||||
self,
|
||||
uri: str,
|
||||
line: int,
|
||||
character: int,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""Request go-to-definition at a position.
|
||||
|
||||
Args:
|
||||
uri: Document URI.
|
||||
line: 0-based line number.
|
||||
character: 0-based character offset.
|
||||
|
||||
Returns:
|
||||
List of Location dicts with ``uri`` and ``range`` keys.
|
||||
"""
|
||||
result = self._send_request(
|
||||
"textDocument/definition",
|
||||
{
|
||||
"textDocument": {"uri": uri},
|
||||
"position": {"line": line, "character": character},
|
||||
},
|
||||
)
|
||||
if result is None:
|
||||
return []
|
||||
# Result may be a single Location, a list of Locations, or
|
||||
# a list of LocationLink objects.
|
||||
if isinstance(result, dict):
|
||||
return [result]
|
||||
if isinstance(result, list):
|
||||
return result
|
||||
return []
|
||||
|
||||
|
||||
__all__ = [
|
||||
"LspClient",
|
||||
|
||||
@@ -232,6 +232,114 @@ class LspRuntime:
|
||||
)
|
||||
return completions
|
||||
|
||||
def get_hover(
|
||||
self,
|
||||
name: str,
|
||||
file_path: str,
|
||||
line: int,
|
||||
column: int,
|
||||
) -> dict[str, Any] | None:
|
||||
"""Retrieve hover information for a position in *file_path*.
|
||||
|
||||
Args:
|
||||
name: Namespaced server name.
|
||||
file_path: Path to the file.
|
||||
line: 1-based line number.
|
||||
column: 1-based column number.
|
||||
|
||||
Returns:
|
||||
Hover result dict or ``None`` if no info is available.
|
||||
"""
|
||||
if not name:
|
||||
raise ValueError("name must be a non-empty string")
|
||||
if not file_path:
|
||||
raise ValueError("file_path must be a non-empty string")
|
||||
if line < 1:
|
||||
raise ValueError("line must be >= 1")
|
||||
if column < 1:
|
||||
raise ValueError("column must be >= 1")
|
||||
|
||||
client = self._get_healthy_client(name)
|
||||
uri = self._path_to_uri(file_path)
|
||||
|
||||
try:
|
||||
text = self._read_file(file_path)
|
||||
except OSError as exc:
|
||||
raise LspError(
|
||||
f"Cannot read file for hover: {file_path}",
|
||||
details={"file": file_path, "error": str(exc)},
|
||||
) from exc
|
||||
|
||||
language_id = self._detect_language(file_path)
|
||||
client.did_open(uri, language_id, version=1, text=text)
|
||||
try:
|
||||
hover = client.get_hover(uri, line - 1, column - 1)
|
||||
finally:
|
||||
client.did_close(uri)
|
||||
|
||||
logger.info(
|
||||
"lsp.runtime.hover",
|
||||
server=name,
|
||||
file=file_path,
|
||||
position=f"{line}:{column}",
|
||||
has_result=hover is not None,
|
||||
)
|
||||
return hover
|
||||
|
||||
def get_definitions(
|
||||
self,
|
||||
name: str,
|
||||
file_path: str,
|
||||
line: int,
|
||||
column: int,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""Retrieve go-to-definition locations for a position.
|
||||
|
||||
Args:
|
||||
name: Namespaced server name.
|
||||
file_path: Path to the file.
|
||||
line: 1-based line number.
|
||||
column: 1-based column number.
|
||||
|
||||
Returns:
|
||||
List of Location dicts.
|
||||
"""
|
||||
if not name:
|
||||
raise ValueError("name must be a non-empty string")
|
||||
if not file_path:
|
||||
raise ValueError("file_path must be a non-empty string")
|
||||
if line < 1:
|
||||
raise ValueError("line must be >= 1")
|
||||
if column < 1:
|
||||
raise ValueError("column must be >= 1")
|
||||
|
||||
client = self._get_healthy_client(name)
|
||||
uri = self._path_to_uri(file_path)
|
||||
|
||||
try:
|
||||
text = self._read_file(file_path)
|
||||
except OSError as exc:
|
||||
raise LspError(
|
||||
f"Cannot read file for definitions: {file_path}",
|
||||
details={"file": file_path, "error": str(exc)},
|
||||
) from exc
|
||||
|
||||
language_id = self._detect_language(file_path)
|
||||
client.did_open(uri, language_id, version=1, text=text)
|
||||
try:
|
||||
definitions = client.get_definitions(uri, line - 1, column - 1)
|
||||
finally:
|
||||
client.did_close(uri)
|
||||
|
||||
logger.info(
|
||||
"lsp.runtime.definitions",
|
||||
server=name,
|
||||
file=file_path,
|
||||
position=f"{line}:{column}",
|
||||
count=len(definitions),
|
||||
)
|
||||
return definitions
|
||||
|
||||
def _get_healthy_client(self, name: str) -> Any:
|
||||
"""Get the client for a server, restarting if crashed.
|
||||
|
||||
|
||||
@@ -146,6 +146,18 @@ def _make_runtime_handler(
|
||||
items = runtime.get_completions(server_name, file_path, line, column)
|
||||
return {"completions": items}
|
||||
|
||||
if capability == LspCapability.HOVER:
|
||||
line = kwargs.get("line", 1)
|
||||
column = kwargs.get("column", 1)
|
||||
result = runtime.get_hover(server_name, file_path, line, column)
|
||||
return {"hover": result}
|
||||
|
||||
if capability == LspCapability.DEFINITIONS:
|
||||
line = kwargs.get("line", 1)
|
||||
column = kwargs.get("column", 1)
|
||||
items = runtime.get_definitions(server_name, file_path, line, column)
|
||||
return {"definitions": items}
|
||||
|
||||
# Capabilities not yet implemented raise an explicit error
|
||||
raise LspNotAvailableError(
|
||||
f"LSP capability '{capability.value}' is not yet implemented "
|
||||
|
||||
Reference in New Issue
Block a user