Added safe_delete and inline_symbol tools (JB backend)

This commit is contained in:
Michael Panchenko committed 2026-03-27 14:07:10 +01:00
1 parent 20e14fa158
commit 2aa6603dbb
4 files changed
+111 -2

No files matched your search

+13 -2
View File
@@ -4,6 +4,7 @@ for testing or development. Here the tools will be operation the serena repo its
"""
import json
from pathlib import Path
from pprint import pprint
from serena.agent import SerenaAgent
@@ -14,13 +15,17 @@ from serena.tools import (
FindReferencingSymbolsTool,
JetBrainsFindSymbolTool,
JetBrainsGetSymbolsOverviewTool,
JetBrainsInlineSymbol,
JetBrainsSafeDeleteTool,
SearchForPatternTool,
)
if __name__ == "__main__":
serena_config = SerenaConfig.from_config_file()
serena_config.web_dashboard = False
agent = SerenaAgent(project=REPO_ROOT, serena_config=serena_config)
# project = Path(REPO_ROOT).parent / "serena-jetbrains-plugin-copy"
project = Path(REPO_ROOT) / "test/resources/repos/python/test_repo"
agent = SerenaAgent(project=str(project), serena_config=serena_config)
# apply a tool
find_symbol_tool = agent.get_tool(JetBrainsFindSymbolTool)
@@ -28,9 +33,15 @@ if __name__ == "__main__":
find_file_tool = agent.get_tool(FindFileTool)
search_pattern_tool = agent.get_tool(SearchForPatternTool)
overview_tool = agent.get_tool(JetBrainsGetSymbolsOverviewTool)
safe_delete_tool = agent.get_tool(JetBrainsSafeDeleteTool)
inline_symbol = agent.get_tool(JetBrainsInlineSymbol)
result = agent.execute_task(
lambda: find_symbol_tool.apply("SerenaAgent/get_tool_description_override"),
lambda: inline_symbol.apply(
relative_path="test_repo/nested.py",
name_path="OuterClass/NestedClass",
keep_definition=True,
)
)
pprint(json.loads(result))
# input("Press Enter to continue...")
@@ -519,6 +519,42 @@ class JetBrainsPluginClient(ToStringMixin):
}
return cast(jb.TypeHierarchyResponse, self._make_request("POST", "/getSubtypes", request_data))
def safe_delete(self, name_path: str | None, relative_path: str, delete_even_if_used: bool, propagate: bool) -> dict[str, Any]:
"""
Safely deletes a symbol, checking for usages first.
:param name_path: the name path of the symbol to delete
:param relative_path: the relative path to the file containing the symbol
:param delete_even_if_used: if True, delete the symbol even if it has usages
"""
request_data = {
"namePath": name_path,
"relativePath": relative_path,
"deleteEvenIfUsed": delete_even_if_used,
"propagate": propagate,
}
return self._make_request("POST", "/safeDelete", request_data)
def inline_symbol(
self,
name_path: str,
relative_path: str,
keep_definition: bool,
) -> dict[str, Any]:
"""
Inlines a method, replacing all call sites with the method body.
:param name_path: the name path of the method to inline
:param relative_path: the relative path to the file containing the method
:param keep_definition: if True, keep the original method definition after inlining
"""
request_data = {
"namePath": name_path,
"relativePath": relative_path,
"keepDefinition": keep_definition,
}
return self._make_request("POST", "/inlineSymbol", request_data)
def rename_symbol(
self, name_path: str, relative_path: str, new_name: str, rename_in_comments: bool, rename_in_text_occurrences: bool
) -> None:
@@ -13,4 +13,7 @@ included_optional_tools:
- jet_brains_find_symbol
- jet_brains_find_referencing_symbols
- jet_brains_get_symbols_overview
- jet_brains_move_symbol
- jet_brains_type_hierarchy
- jet_brains_safe_delete
- jet_brains_inline_symbol
+59
View File
@@ -141,6 +141,65 @@ class JetBrainsMoveSymbolTool(Tool, ToolMarkerSymbolicEdit, ToolMarkerOptional):
return self._to_json(response_dict)
class JetBrainsSafeDeleteTool(Tool, ToolMarkerSymbolicEdit, ToolMarkerOptional):
def apply(
self,
relative_path: str,
name_path: str | None = None,
delete_even_if_used: bool = False,
propagate: bool = False,
) -> str:
"""
Safely deletes a symbol, checking for usages first. It is also
possible to request deleting of usages and cleaning up of unused code.
:param relative_path: the relative path to the file containing the symbol to delete.
:param name_path: the name path of the symbol to delete.
A name path identifies a symbol within a source file, e.g. "MyClass/my_method".
:param delete_even_if_used: whether to force deletion even if the symbol still has usages.
Default is False (safe mode: will report usages instead of deleting).
:param propagate: whether to propagate the deletion to usages of the symbol and also
remove symbols that become unused after the deletion. Default is False.
:return: JSON string with the result of the operation.
"""
with JetBrainsPluginClient.from_project(self.project) as client:
response_dict = client.safe_delete(
name_path=name_path,
relative_path=relative_path,
delete_even_if_used=delete_even_if_used,
propagate=propagate,
)
return self._to_json(response_dict)
class JetBrainsInlineSymbol(Tool, ToolMarkerSymbolicEdit, ToolMarkerOptional):
def apply(
self,
name_path: str,
relative_path: str,
keep_definition: bool = False,
) -> str:
"""
Inlines a symbol (usually method, but also classes may be amenable to inlining,
which turns invocation into anonymous class creation),
replacing all call sites with the method's body.
An error is raised when requested on a symbol that cannot be inlined.
:param name_path: the name path of the method to inline.
:param relative_path: the relative path to the file containing the method to inline.
:param keep_definition: whether to keep the original method definition after inlining all call sites.
May be ignored in some cases (e.g., when inlining a class)..
:return: JSON string with the result of the operation.
"""
with JetBrainsPluginClient.from_project(self.project) as client:
response_dict = client.inline_symbol(
name_path=name_path,
relative_path=relative_path,
keep_definition=keep_definition,
)
return self._to_json(response_dict)
class JetBrainsFindReferencingSymbolsTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptional):
"""
Finds symbols that reference the given symbol using the JetBrains backend