replace_symbol_body
Update symbol definitions in your codebase by specifying a name path and providing new body content, enabling direct code modifications within the Serena MCP Server environment.
Instructions
Replaces the body of the symbol with the given name_path.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name_path | Yes | For finding the symbol to replace, same logic as in the `find_symbol` tool. | |
| relative_path | Yes | The relative path to the file containing the symbol. | |
| body | Yes | The new symbol body. Important: Begin directly with the symbol definition and provide no leading indentation for the first line (but do indent the rest of the body according to the context). |
Implementation Reference
- src/serena/symbol.py:660-682 (handler)The handler function for replacing the body of a symbol identified by name_path in a specific file. It locates the symbol using the language server and delegates to replace_body_at_location for the edit.def replace_body(self, name_path: str, relative_file_path: str, body: str, *, use_same_indentation: bool = True) -> None: """ Replace the body of the symbol with the given name_path in the given file. :param name_path: the name path of the symbol to replace. :param relative_file_path: the relative path of the file in which the symbol is defined. :param body: the new body :param use_same_indentation: whether to use the same indentation as the original body. This means that the user doesn't have to provide the correct indentation, but can just write the body. """ symbol_candidates = self.find_by_name(name_path, within_relative_path=relative_file_path) if len(symbol_candidates) == 0: raise ValueError(f"No symbol with name {name_path} found in file {relative_file_path}") if len(symbol_candidates) > 1: raise ValueError( f"Found multiple {len(symbol_candidates)} symbols with name {name_path} in file {relative_file_path}. " "Will not replace the body of any of them, but you can use `replace_body_at_location`, the replace lines tool or other editing " "tools to perform your edits. Their locations are: \n " + json.dumps([s.location.to_dict() for s in symbol_candidates], indent=2) ) symbol = symbol_candidates[0] return self.replace_body_at_location(symbol.location, body, use_same_indentation=use_same_indentation)
- src/serena/symbol.py:683-711 (helper)Helper function that performs the actual text deletion and insertion to replace the symbol body using LSP operations.def replace_body_at_location(self, location: SymbolLocation, body: str, *, use_same_indentation: bool = True) -> None: """ Replace the body of the symbol at the given location with the given body :param location: the location of the symbol to replace. :param body: the new body :param use_same_indentation: whether to use the same indentation as the original body. This means that the user doesn't have to provide the correct indentation, but can just write the body. """ with self._edited_symbol_location(location) as symbol: assert location.relative_path is not None start_pos = symbol.body_start_position end_pos = symbol.body_end_position if start_pos is None or end_pos is None: raise ValueError(f"Symbol at {location} does not have a defined body range.") start_line, start_col = start_pos["line"], start_pos["character"] if use_same_indentation: indent = " " * start_col body_lines = body.splitlines() body = body_lines[0] + "\n" + "\n".join(indent + line for line in body_lines[1:]) # make sure the replacement adds no additional newlines (before or after) - all newlines # and whitespace before/after should remain the same, so we strip it entirely body = body.strip() self._lang_server.delete_text_between_positions(location.relative_path, start_pos, end_pos) self._lang_server.insert_text_at_position(location.relative_path, start_line, start_col, body)
- src/serena/symbol.py:168-197 (schema)Dataclass defining the SymbolLocation used as input for precise symbol identification in replace_body_at_location.class SymbolLocation: """ Represents the (start) location of a symbol identifier, which, within Serena, uniquely identifies the symbol. """ relative_path: str | None """ the relative path of the file containing the symbol; if None, the symbol is defined outside of the project's scope """ line: int | None """ the line number in which the symbol identifier is defined (if the symbol is a function, class, etc.); may be None for some types of symbols (e.g. SymbolKind.File) """ column: int | None """ the column number in which the symbol identifier is defined (if the symbol is a function, class, etc.); may be None for some types of symbols (e.g. SymbolKind.File) """ def __post_init__(self) -> None: if self.relative_path is not None: self.relative_path = self.relative_path.replace("/", os.path.sep) def to_dict(self) -> dict[str, Any]: return asdict(self) def has_position_in_file(self) -> bool: return self.relative_path is not None and self.line is not None and self.column is not None