mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 20:15:20 +00:00
New tool and LS method: get_document_overview
This commit is contained in:
1 parent
eb3d2d3ec4
commit
1afe45805f
4 files changed
+60
-9
No files matched your search
@@ -843,16 +843,7 @@ class LanguageServer:
|
||||
Maps relative paths of all contained files to info about top-level symbols in the file
|
||||
(name, kind, line, column).
|
||||
"""
|
||||
if not self.server_started:
|
||||
self.logger.log(
|
||||
"request_dir_overview called before Language Server started",
|
||||
logging.ERROR,
|
||||
)
|
||||
raise MultilspyException("Language Server not started")
|
||||
|
||||
# Get the full symbol tree for the directory
|
||||
symbol_tree = await self.request_full_symbol_tree(relative_dir_path)
|
||||
|
||||
# Initialize result dictionary
|
||||
result: dict[str, list[tuple[str, multilspy_types.SymbolKind, int, int]]] = defaultdict(list)
|
||||
|
||||
@@ -879,6 +870,22 @@ class LanguageServer:
|
||||
process_symbol(root)
|
||||
return result
|
||||
|
||||
async def request_document_overview(self, relative_file_path: str) -> list[tuple[str, multilspy_types.SymbolKind, int, int]]:
|
||||
"""
|
||||
An overview of the given file.
|
||||
Returns the the list of tuples (name, kind, line, column) of all top-level symbols in the file.
|
||||
"""
|
||||
_, document_roots = await self.request_document_symbols(relative_file_path)
|
||||
return [
|
||||
(
|
||||
root["name"],
|
||||
root["kind"],
|
||||
root["selectionRange"]["start"]["line"], # type: ignore
|
||||
root["selectionRange"]["start"]["character"] # type: ignore
|
||||
)
|
||||
for root in document_roots
|
||||
]
|
||||
|
||||
async def request_hover(self, relative_file_path: str, line: int, column: int) -> Union[multilspy_types.Hover, None]:
|
||||
"""
|
||||
Raise a [textDocument/hover](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_hover) request to the Language Server
|
||||
@@ -1528,6 +1535,18 @@ class SyncLanguageServer:
|
||||
self.language_server.request_dir_overview(relative_dir_path), self.loop
|
||||
).result()
|
||||
return result
|
||||
|
||||
def request_document_overview(self, relative_file_path: str) -> list[tuple[str, multilspy_types.SymbolKind, int, int]]:
|
||||
"""
|
||||
An overview of the given file.
|
||||
|
||||
Returns the the list of tuples (name, kind, line, column) of all top-level symbols in the file.
|
||||
"""
|
||||
assert self.loop
|
||||
result = asyncio.run_coroutine_threadsafe(
|
||||
self.language_server.request_document_overview(relative_file_path), self.loop
|
||||
).result()
|
||||
return result
|
||||
|
||||
def request_hover(self, relative_file_path: str, line: int, column: int) -> Union[multilspy_types.Hover, None]:
|
||||
"""
|
||||
|
||||
@@ -17,6 +17,8 @@ def ensure_all_methods_implemented(
|
||||
|
||||
def check_all_methods_implemented(target_cls: R) -> R:
|
||||
for name, _ in inspect.getmembers(source_cls, inspect.isfunction):
|
||||
if name.startswith("_"):
|
||||
continue
|
||||
if name not in target_cls.__dict__ or not callable(target_cls.__dict__[name]):
|
||||
raise NotImplementedError(f"{name} is not implemented in {target_cls}")
|
||||
|
||||
|
||||
@@ -244,6 +244,27 @@ def get_dir_overview(ctx: Context, relative_path: str, max_answer_chars: int = _
|
||||
return GetDirOverviewTool(ctx).execute(max_answer_chars=max_answer_chars)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def get_document_overview(ctx: Context, relative_path: str, max_answer_chars: int = _DEFAULT_MAX_ANSWER_LENGTH) -> str:
|
||||
"""
|
||||
Get an overview of the given file.
|
||||
|
||||
:param ctx: the context object, which will be created and provided automatically
|
||||
:param relative_path: the relative path to the file to get the overview of
|
||||
:param max_answer_chars: if the overview is longer than this number of characters,
|
||||
no content will be returned. Don't adjust unless there is really no other way to get the content
|
||||
required for the task.
|
||||
:return: a JSON object with the list of tuples (name, kind, line, column) of all top-level symbols in the file.
|
||||
"""
|
||||
log.info(f"get_document_overview: {relative_path=}")
|
||||
|
||||
class GetDocumentOverviewTool(Tool):
|
||||
def _execute(self) -> str:
|
||||
return json.dumps(self.langsrv.request_document_overview(relative_path))
|
||||
|
||||
return GetDocumentOverviewTool(ctx).execute(max_answer_chars=max_answer_chars)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def find_symbol(
|
||||
ctx: Context,
|
||||
|
||||
@@ -407,3 +407,12 @@ class TestLanguageServerSymbols:
|
||||
|
||||
for symbol in expected_symbols:
|
||||
assert symbol in services_symbols
|
||||
|
||||
def test_request_document_overview(self, language_server: SyncLanguageServer, repo_path: Path):
|
||||
"""Test that request_document_overview returns correct symbol information for a file."""
|
||||
# Get overview of the user_management.py file
|
||||
overview = language_server.request_document_overview(os.path.join("examples", "user_management.py"))
|
||||
|
||||
# Verify that we have entries for both files
|
||||
symbol_names = {s_info[0] for s_info in overview}
|
||||
assert {"UserStats", "UserManager", "process_user_data", "main"}.issubset(symbol_names)
|
||||
Reference in new issue
Block a user