mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-12 14:15:14 +00:00
Merge pull request #863 from oraios/improved_overview_tools
Improved overview tools
This commit is contained in:
3 files changed
+79
-9
No files matched your search
@@ -178,11 +178,12 @@ class JetBrainsPluginClient(ToStringMixin):
|
||||
request_data = {"namePath": name_path, "relativePath": relative_path}
|
||||
return self._make_request("POST", "/findReferences", request_data)
|
||||
|
||||
def get_symbols_overview(self, relative_path: str) -> dict[str, Any]:
|
||||
def get_symbols_overview(self, relative_path: str, depth: int) -> dict[str, Any]:
|
||||
"""
|
||||
:param relative_path: the relative path to a source file
|
||||
:param depth: the depth of children to include (0 = no children)
|
||||
"""
|
||||
request_data = {"relativePath": relative_path}
|
||||
request_data = {"relativePath": relative_path, "depth": depth}
|
||||
return self._make_request("POST", "/getSymbolsOverview", request_data)
|
||||
|
||||
def rename_symbol(
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
from collections import defaultdict
|
||||
from typing import Any
|
||||
|
||||
from serena.tools import Tool, ToolMarkerOptional, ToolMarkerSymbolicRead
|
||||
from serena.tools.jetbrains_plugin_client import JetBrainsPluginClient
|
||||
|
||||
@@ -98,9 +101,41 @@ class JetBrainsGetSymbolsOverviewTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOp
|
||||
Retrieves an overview of the top-level symbols within a specified file using the JetBrains backend
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _transform_symbols_to_compact_format(symbols: list[dict[str, Any]]) -> dict[str, list]:
|
||||
"""
|
||||
Transform symbol overview from verbose format to compact grouped format.
|
||||
|
||||
Groups symbols by kind and uses names instead of full symbol objects.
|
||||
For symbols with children, creates nested dictionaries.
|
||||
|
||||
The name_path can be inferred from the hierarchical structure:
|
||||
- Top-level symbols: name_path = name
|
||||
- Nested symbols: name_path = parent_name + "/" + name
|
||||
For example, "convert" under class "ProjectType" has name_path "ProjectType/convert".
|
||||
"""
|
||||
result = defaultdict(list)
|
||||
|
||||
for symbol in symbols:
|
||||
kind = symbol.get("type", "Unknown")
|
||||
name_path = symbol["name_path"]
|
||||
name = name_path.split("/")[-1]
|
||||
children = symbol.get("children", [])
|
||||
|
||||
if children:
|
||||
# Symbol has children: create nested dict {name: children_dict}
|
||||
children_dict = JetBrainsGetSymbolsOverviewTool._transform_symbols_to_compact_format(children)
|
||||
result[kind].append({name: children_dict})
|
||||
else:
|
||||
# Symbol has no children: just add the name
|
||||
result[kind].append(name)
|
||||
|
||||
return result
|
||||
|
||||
def apply(
|
||||
self,
|
||||
relative_path: str,
|
||||
depth: int = 0,
|
||||
max_answer_chars: int = -1,
|
||||
) -> str:
|
||||
"""
|
||||
@@ -111,13 +146,14 @@ class JetBrainsGetSymbolsOverviewTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOp
|
||||
or by using the `list_dir` and `find_file` tools (or similar).
|
||||
|
||||
:param relative_path: the relative path to the file to get the overview of
|
||||
:param depth: depth up to which descendants shall be retrieved (e.g., use 1 to also retrieve immediate children).
|
||||
:param max_answer_chars: max characters for the JSON result. If exceeded, no content is returned.
|
||||
-1 means the default value from the config will be used.
|
||||
:return: a JSON object containing the symbols
|
||||
:return: a JSON object containing the symbols grouped by kind in a compact format.
|
||||
"""
|
||||
with JetBrainsPluginClient.from_project(self.project) as client:
|
||||
response_dict = client.get_symbols_overview(
|
||||
relative_path=relative_path,
|
||||
)
|
||||
result = self._to_json(response_dict)
|
||||
response_dict = client.get_symbols_overview(relative_path=relative_path, depth=depth)
|
||||
symbols = response_dict["symbols"]
|
||||
compact_symbols = self._transform_symbols_to_compact_format(symbols)
|
||||
result = self._to_json(compact_symbols)
|
||||
return self._limit_length(result, max_answer_chars)
|
||||
@@ -3,6 +3,7 @@ Language server-related tools
|
||||
"""
|
||||
|
||||
import os
|
||||
from collections import defaultdict
|
||||
from collections.abc import Sequence
|
||||
from copy import copy
|
||||
from typing import Any
|
||||
@@ -61,7 +62,7 @@ class GetSymbolsOverviewTool(Tool, ToolMarkerSymbolicRead):
|
||||
:param max_answer_chars: if the overview is longer than this number of characters,
|
||||
no content will be returned. -1 means the default value from the config will be used.
|
||||
Don't adjust unless there is really no other way to get the content required for the task.
|
||||
:return: a JSON object containing info about top-level symbols in the file
|
||||
:return: a JSON object containing symbols grouped by kind in a compact format.
|
||||
"""
|
||||
symbol_retriever = self.create_language_server_symbol_retriever()
|
||||
file_path = os.path.join(self.project.project_root, relative_path)
|
||||
@@ -73,9 +74,41 @@ class GetSymbolsOverviewTool(Tool, ToolMarkerSymbolicRead):
|
||||
if os.path.isdir(file_path):
|
||||
raise ValueError(f"Expected a file path, but got a directory path: {relative_path}. ")
|
||||
result = symbol_retriever.get_symbol_overview(relative_path, depth=depth)[relative_path]
|
||||
result_json_str = self._to_json(result)
|
||||
# Transform to compact format
|
||||
compact_result = self._transform_symbols_to_compact_format(result)
|
||||
result_json_str = self._to_json(compact_result)
|
||||
return self._limit_length(result_json_str, max_answer_chars)
|
||||
|
||||
@staticmethod
|
||||
def _transform_symbols_to_compact_format(symbols: list[dict[str, Any]]) -> dict[str, list]:
|
||||
"""
|
||||
Transform symbol overview from verbose format to compact grouped format.
|
||||
|
||||
Groups symbols by kind and uses names instead of full symbol objects.
|
||||
For symbols with children, creates nested dictionaries.
|
||||
|
||||
The name_path can be inferred from the hierarchical structure:
|
||||
- Top-level symbols: name_path = name
|
||||
- Nested symbols: name_path = parent_name + "/" + name
|
||||
For example, "convert" under class "ProjectType" has name_path "ProjectType/convert".
|
||||
"""
|
||||
result = defaultdict(list)
|
||||
|
||||
for symbol in symbols:
|
||||
kind = symbol.get("kind", "Unknown")
|
||||
name = symbol.get("name", "unknown")
|
||||
children = symbol.get("children", [])
|
||||
|
||||
if children:
|
||||
# Symbol has children: create nested dict {name: children_dict}
|
||||
children_dict = GetSymbolsOverviewTool._transform_symbols_to_compact_format(children)
|
||||
result[kind].append({name: children_dict})
|
||||
else:
|
||||
# Symbol has no children: just add the name
|
||||
result[kind].append(name)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class FindSymbolTool(Tool, ToolMarkerSymbolicRead):
|
||||
"""
|
||||
|
||||
Reference in new issue
Block a user