diff --git a/src/serena/agent.py b/src/serena/agent.py index ef6e226..f2c740d 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -1744,16 +1744,16 @@ class InsertAfterSymbolTool(Tool, ToolMarkerCanEdit): Inserts the given body/content after the end of the definition of the given symbol (via the symbol's location). A typical use case is to insert a new class, function, method, field or variable assignment. - :param name_path: for finding the symbol to insert after, same logic as in the `find_symbol` tool. + :param name_path: name path of the symbol after which to insert content (definitions in the `find_symbol` tool apply) :param relative_path: the relative path to the file containing the symbol - :param body: the body/content to be inserted. Important: the inserted code will automatically have the - same indentation as the symbol's body, so you do not need to provide any additional indentation. + :param body: the body/content to be inserted. The inserted code shall begin with the next line after + the symbol. """ self.symbol_manager.insert_after_symbol( name_path, relative_file_path=relative_path, body=body, - use_same_indentation=True, + use_same_indentation=False, ) return SUCCESS_RESULT @@ -1774,16 +1774,15 @@ class InsertBeforeSymbolTool(Tool, ToolMarkerCanEdit): A typical use case is to insert a new class, function, method, field or variable assignment. It also can be used to insert a new import statement before the first symbol in the file. - :param name_path: for finding the symbol to insert before, same logic as in the `find_symbol` tool. + :param name_path: name path of the symbol before which to insert content (definitions in the `find_symbol` tool apply) :param relative_path: the relative path to the file containing the symbol - :param body: the body/content to be inserted. Important: the inserted code will automatically have the - same indentation as the symbol's body, so you do not need to provide any additional indentation. + :param body: the body/content to be inserted before the line in which the referenced symbol is defined """ self.symbol_manager.insert_before_symbol( name_path, relative_file_path=relative_path, body=body, - use_same_indentation=True, + use_same_indentation=False, ) return SUCCESS_RESULT diff --git a/src/serena/resources/config/modes/editing.yml b/src/serena/resources/config/modes/editing.yml index b50d3a5..a0ba5f7 100644 --- a/src/serena/resources/config/modes/editing.yml +++ b/src/serena/resources/config/modes/editing.yml @@ -23,8 +23,7 @@ prompt: | use `find_symbol` with the name path `Foo/__init__` and `include_body=True`. If you don't know yet which methods in `Foo` you need to read or edit, you can use `find_symbol` with the name path `Foo`, `include_body=False` and `depth=1` to get all (top-level) methods of `Foo` before proceeding to read the desired methods with `include_body=True`. - Note that you never need to add additional indentation, as all symbol editing tools will automatically add the indentation of the symbol that - you are replacing or inserting above or below. In particular, keep in mind the description of the `replace_symbol_body` tool. If you want to add some new code at the end of the file, you should + In particular, keep in mind the description of the `replace_symbol_body` tool. If you want to add some new code at the end of the file, you should use the `insert_after_symbol` tool with the last top-level symbol in the file. If you want to add an import, often a good strategy is to use `insert_before_symbol` with the first top-level symbol in the file. You can understand relationships between symbols by using the `find_referencing_symbols` tool. If not explicitly requested otherwise by a user, diff --git a/src/serena/symbol.py b/src/serena/symbol.py index f7cb194..66df7aa 100644 --- a/src/serena/symbol.py +++ b/src/serena/symbol.py @@ -751,11 +751,16 @@ class SymbolManager: raise ValueError(f"Symbol at {location} does not have a defined end position.") line, col = pos["line"], pos["character"] + if at_new_line: - line += 1 + # start at beginning of next line col = 0 - if not body.startswith("\n"): - body = "\n" + body + line += 1 + # make sure there is one empty line before the new symbol + body = "\n" + body.lstrip("\n") + # make sure the one line break succeeding the original symbol, which we repurposed as prefix, is replaced + body = body.rstrip("\n") + "\n" + if use_same_indentation: symbol_start_pos = symbol.body_start_position assert symbol_start_pos is not None, f"Symbol at {location=} does not have a defined start position." @@ -822,16 +827,16 @@ class SymbolManager: raise ValueError(f"Symbol at {location} does not have a defined start position.") line = symbol_start_pos["line"] col = symbol_start_pos["character"] + if use_same_indentation: indent = " " * (col) body = "\n".join(indent + line for line in body.splitlines()) - # similar problems as in insert_after_symbol_at_location, see comment there if at_new_line: col = 0 - line -= 1 - if not body.endswith("\n"): - body += "\n" + # ensure two newlines after inserted body (eol + empty line) + body = body.rstrip() + "\n\n" + assert location.relative_path is not None self._lang_server.insert_text_at_position(location.relative_path, line=line, column=col, text_to_be_inserted=body)