From e6c97b99deca67cfe2551046c868a8f08255356e Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Wed, 1 Apr 2026 12:13:11 +0200 Subject: [PATCH] Split off JBRenameTool from the RenameSymbolTool The JB variant has more options, the difference to the LS variant will likely grow in the future --- src/serena/code_editor.py | 33 +++++++++++-------- .../config/internal_modes/jetbrains.yml | 2 ++ src/serena/tools/jetbrains_tools.py | 17 ++++++++++ src/serena/tools/symbol_tools.py | 12 +++---- 4 files changed, 45 insertions(+), 19 deletions(-) diff --git a/src/serena/code_editor.py b/src/serena/code_editor.py index 202efe0f..da397dcb 100644 --- a/src/serena/code_editor.py +++ b/src/serena/code_editor.py @@ -230,16 +230,8 @@ class CodeEditor(Generic[TSymbol], ABC): edited_file.delete_text_between_positions(start_pos, end_pos) @abstractmethod - def rename_symbol(self, name_path: str | None, relative_path: str, new_name: str) -> str: - """ - Renames a symbol, file, or directory throughout the codebase. - - :param name_path: the name path of the symbol to rename - :param relative_path: if `name_path` is passed, the relative path of the file containing the symbol. - Otherwise, the path to the directory or file to rename. - :param new_name: the new name - :return: a status message - """ + def rename_symbol(self, name_path: str, relative_path: str, new_name: str) -> str: + pass class LanguageServerCodeEditor(CodeEditor[LanguageServerSymbol]): @@ -348,9 +340,15 @@ class LanguageServerCodeEditor(CodeEditor[LanguageServerSymbol]): operation.apply() return len(operations) - def rename_symbol(self, name_path: str | None, relative_path: str, new_name: str) -> str: - if name_path is None: - raise NotImplementedError("Renaming files/directories is not yet implemented for in the language server backend.") + def rename_symbol(self, name_path: str, relative_path: str, new_name: str) -> str: + """ + Renames a symbol, file, or directory throughout the codebase. + + :param name_path: the name path of the symbol to rename + :param relative_path: the relative path of the file containing the symbol. + :param new_name: the new name + :return: a status message + """ symbol = self._find_unique_symbol(name_path, relative_path) if not symbol.location.has_position_in_file(): raise ValueError(f"Symbol '{name_path}' does not have a valid position in file for renaming") @@ -429,6 +427,15 @@ class JetBrainsCodeEditor(CodeEditor[JetBrainsSymbol]): return JetBrainsSymbol(symbols[0], self._project) def rename_symbol(self, name_path: str | None, relative_path: str, new_name: str) -> str: + """ + Renames a code symbol, file, or directory throughout the codebase. + + :param name_path: the name path of the symbol to rename. Set to None for renaming a file or directory. + :param relative_path: if `name_path` is passed, the relative path of the file containing the symbol. + Otherwise, the path to the directory or file to rename. + :param new_name: the new name + :return: a status message + """ with JetBrainsPluginClient.from_project(self._project) as client: client.rename_symbol( name_path=name_path, diff --git a/src/serena/resources/config/internal_modes/jetbrains.yml b/src/serena/resources/config/internal_modes/jetbrains.yml index f9e60a4b..f7b2dd85 100644 --- a/src/serena/resources/config/internal_modes/jetbrains.yml +++ b/src/serena/resources/config/internal_modes/jetbrains.yml @@ -10,6 +10,7 @@ excluded_tools: - get_symbols_overview - restart_language_server - safe_delete_symbol + - rename_symbol included_optional_tools: - jet_brains_find_symbol - jet_brains_find_referencing_symbols @@ -18,3 +19,4 @@ included_optional_tools: - jet_brains_type_hierarchy - jet_brains_safe_delete - jet_brains_inline_symbol + - jet_brains_rename diff --git a/src/serena/tools/jetbrains_tools.py b/src/serena/tools/jetbrains_tools.py index 33b4ac66..afb70283 100644 --- a/src/serena/tools/jetbrains_tools.py +++ b/src/serena/tools/jetbrains_tools.py @@ -3,6 +3,7 @@ from collections import Counter from typing import Any, Literal import serena.jetbrains.jetbrains_types as jb +from serena.code_editor import JetBrainsCodeEditor from serena.jetbrains.jetbrains_plugin_client import JetBrainsPluginClient from serena.jetbrains.jetbrains_types import SymbolDTO from serena.symbol import JetBrainsSymbolDictGrouper @@ -468,3 +469,19 @@ class JetBrainsFindImplementationsTool(Tool, ToolMarkerSymbolicRead): ) result = self._to_json(symbol_collection) return result + + +class JetBrainsRenameTool(Tool, ToolMarkerSymbolicEdit): + def apply(self, relative_path: str, new_name: str, name_path: str | None = None) -> str: + """ + Renames a symbol, file, or directory throughout the codebase. + + :param relative_path: if `name_path` is passed, the relative path of the file containing the symbol. + Otherwise, the path to the directory or file to rename. + :param new_name: the new name + :param name_path: the name path of the symbol to rename or None if renaming a file or directory. + :return: a status message + """ + code_editor = JetBrainsCodeEditor(self.project) + result = code_editor.rename_symbol(name_path=name_path, relative_path=relative_path, new_name=new_name) + return self._to_json(result) diff --git a/src/serena/tools/symbol_tools.py b/src/serena/tools/symbol_tools.py index e17b74a0..bff6f2fd 100644 --- a/src/serena/tools/symbol_tools.py +++ b/src/serena/tools/symbol_tools.py @@ -408,27 +408,27 @@ class InsertBeforeSymbolTool(Tool, ToolMarkerSymbolicEdit): class RenameSymbolTool(Tool, ToolMarkerSymbolicEdit): """ - Renames a symbol, file, or directory throughout the codebase using language server refactoring capabilities. + Renames a symbol throughout the codebase using language server refactoring capabilities. + For JB, we use a separate tool. """ def apply( self, + name_path: str, relative_path: str, new_name: str, - name_path: str | None = None, ) -> str: """ - Renames the symbol with the given `name_path` or a file/directory (if no `name_path` is passed) - to `new_name` throughout the entire codebase. + Renames the symbol with the given `name_path` to `new_name` throughout the entire codebase. Note: for languages with method overloading, like Java, name_path may have to include a method's signature to uniquely identify a method. + :param name_path: name path of the symbol to rename (definitions in the `find_symbol` tool apply) :param relative_path: the relative path to the file containing the symbol to rename :param new_name: the new name for the symbol - :param name_path: name path of the symbol to rename (definitions in the `find_symbol` tool apply) :return: result summary indicating success or failure """ - code_editor = self.create_code_editor() + code_editor = self.create_ls_code_editor() status_message = code_editor.rename_symbol(name_path, relative_path=relative_path, new_name=new_name) return status_message