From 21af8bf4517dbd858681d0c6309fec3d3ed76762 Mon Sep 17 00:00:00 2001 From: Michael Panchenko <35432522+MischaPanch@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:37:17 +0200 Subject: [PATCH] Removed LinesRead and mark_file_modified (#666) --- src/serena/agent.py | 23 ------------------- src/serena/code_editor.py | 3 --- src/serena/tools/file_tools.py | 4 ---- src/serena/tools/tools_base.py | 7 +----- .../custom_test/advanced_features.py | 2 +- test/solidlsp/al/test_al_basic.py | 6 ++--- test/solidlsp/bash/test_bash_basic.py | 10 ++++---- test/solidlsp/markdown/test_markdown_basic.py | 8 +++---- test/solidlsp/r/test_r_basic.py | 2 +- .../ruby/test_ruby_symbol_retrieval.py | 8 +++---- 10 files changed, 19 insertions(+), 54 deletions(-) diff --git a/src/serena/agent.py b/src/serena/agent.py index 90be1420..d8a491dd 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -8,7 +8,6 @@ import platform import sys import threading import webbrowser -from collections import defaultdict from collections.abc import Callable from concurrent.futures import Future, ThreadPoolExecutor from logging import Logger @@ -44,22 +43,6 @@ class ProjectNotFoundError(Exception): pass -class LinesRead: - def __init__(self) -> None: - self.files: dict[str, set[tuple[int, int]]] = defaultdict(lambda: set()) - - def add_lines_read(self, relative_path: str, lines: tuple[int, int]) -> None: - self.files[relative_path].add(lines) - - def were_lines_read(self, relative_path: str, lines: tuple[int, int]) -> bool: - lines_read_in_file = self.files[relative_path] - return lines in lines_read_in_file - - def invalidate_lines_read(self, relative_path: str) -> None: - if relative_path in self.files: - del self.files[relative_path] - - class MemoriesManager: def __init__(self, project_root: str): self._memory_dir = Path(get_serena_managed_in_project_dir(project_root)) / "memories" @@ -139,7 +122,6 @@ class SerenaAgent: self._active_project: Project | None = None self.language_server: SolidLanguageServer | None = None self.memories_manager: MemoriesManager | None = None - self.lines_read: LinesRead | None = None # adjust log level serena_log_level = self.serena_config.log_level @@ -444,7 +426,6 @@ class SerenaAgent: # initialize project-specific instances which do not depend on the language server self.memories_manager = MemoriesManager(project.project_root) - self.lines_read = LinesRead() def init_language_server() -> None: # start the language server @@ -604,10 +585,6 @@ class SerenaAgent: def print_tool_overview(self) -> None: ToolRegistry().print_tool_overview(self._active_tools.values()) - def mark_file_modified(self, relative_path: str) -> None: - assert self.lines_read is not None - self.lines_read.invalidate_lines_read(relative_path) - def __del__(self) -> None: """ Destructor to clean up the language server instance and GUI logger diff --git a/src/serena/code_editor.py b/src/serena/code_editor.py index 04e3c127..6fe41da1 100644 --- a/src/serena/code_editor.py +++ b/src/serena/code_editor.py @@ -60,9 +60,6 @@ class CodeEditor(Generic[TSymbol], ABC): abs_path = os.path.join(self.project_root, relative_path) with open(abs_path, "w", encoding="utf-8") as f: f.write(edited_file.get_contents()) - # notify agent (if provided) - if self.agent is not None: - self.agent.mark_file_modified(relative_path) @abstractmethod def _find_unique_symbol(self, name_path: str, relative_file_path: str) -> TSymbol: diff --git a/src/serena/tools/file_tools.py b/src/serena/tools/file_tools.py index d521512f..56d2cf94 100644 --- a/src/serena/tools/file_tools.py +++ b/src/serena/tools/file_tools.py @@ -43,7 +43,6 @@ class ReadFileTool(Tool): if end_line is None: result_lines = result_lines[start_line:] else: - self.lines_read.add_lines_read(relative_path, (start_line, end_line)) result_lines = result_lines[start_line : end_line + 1] result = "\n".join(result_lines) @@ -228,9 +227,6 @@ class DeleteLinesTool(Tool, ToolMarkerCanEdit, ToolMarkerOptional): :param start_line: the 0-based index of the first line to be deleted :param end_line: the 0-based index of the last line to be deleted """ - if not self.lines_read.were_lines_read(relative_path, (start_line, end_line)): - read_lines_tool = self.agent.get_tool(ReadFileTool) - return f"Error: Must call `{read_lines_tool.get_name_from_cls()}` first to read exactly the affected lines." code_editor = self.create_code_editor() code_editor.delete_lines(relative_path, start_line, end_line) return SUCCESS_RESULT diff --git a/src/serena/tools/tools_base.py b/src/serena/tools/tools_base.py index a914cf1d..3f2d2c25 100644 --- a/src/serena/tools/tools_base.py +++ b/src/serena/tools/tools_base.py @@ -18,7 +18,7 @@ from serena.util.inspection import iter_subclasses from solidlsp.ls_exceptions import SolidLSPException if TYPE_CHECKING: - from serena.agent import LinesRead, MemoriesManager, SerenaAgent + from serena.agent import MemoriesManager, SerenaAgent from serena.code_editor import CodeEditor log = logging.getLogger(__name__) @@ -64,11 +64,6 @@ class Component(ABC): else: return JetBrainsCodeEditor(project=self.project, agent=self.agent) - @property - def lines_read(self) -> "LinesRead": - assert self.agent.lines_read is not None - return self.agent.lines_read - class ToolMarker: """ diff --git a/test/resources/repos/python/test_repo/custom_test/advanced_features.py b/test/resources/repos/python/test_repo/custom_test/advanced_features.py index 07d4ae4e..b2fa7c9d 100644 --- a/test/resources/repos/python/test_repo/custom_test/advanced_features.py +++ b/test/resources/repos/python/test_repo/custom_test/advanced_features.py @@ -458,7 +458,7 @@ def main() -> None: processor.process(task.name) # Use advanced search - results, total = advanced_search(query="test", filters={"status": Status.PENDING}, sort_by="priority", page=1, include_metadata=True) + _results, _total = advanced_search(query="test", filters={"status": Status.PENDING}, sort_by="priority", page=1, include_metadata=True) # Create a tree root = TreeNode("root") diff --git a/test/solidlsp/al/test_al_basic.py b/test/solidlsp/al/test_al_basic.py index 44687bbc..1fb95e42 100644 --- a/test/solidlsp/al/test_al_basic.py +++ b/test/solidlsp/al/test_al_basic.py @@ -47,7 +47,7 @@ class TestALLanguageServer: # AL tables should have their fields as child symbols customer_table = None - all_symbols, root_symbols = symbols + _all_symbols, root_symbols = symbols for sym in root_symbols: if "TEST Customer" in sym.get("name", ""): customer_table = sym @@ -80,7 +80,7 @@ class TestALLanguageServer: # Find the codeunit symbol - AL returns 'Codeunit 50000 CustomerMgt' codeunit_symbol = None - all_symbols, root_symbols = symbols + _all_symbols, root_symbols = symbols for sym in root_symbols: if "CustomerMgt" in sym.get("name", ""): codeunit_symbol = sym @@ -104,7 +104,7 @@ class TestALLanguageServer: # Find the Customer table symbol customer_symbol = None - all_symbols, root_symbols = symbols + _all_symbols, root_symbols = symbols for sym in root_symbols: if "TEST Customer" in sym.get("name", ""): customer_symbol = sym diff --git a/test/solidlsp/bash/test_bash_basic.py b/test/solidlsp/bash/test_bash_basic.py index ebba71e0..4060f212 100644 --- a/test/solidlsp/bash/test_bash_basic.py +++ b/test/solidlsp/bash/test_bash_basic.py @@ -25,7 +25,7 @@ class TestBashLanguageServerBasics: def test_bash_request_document_symbols(self, language_server: SolidLanguageServer) -> None: """Test request_document_symbols for bash files.""" # Test getting symbols from main.sh - all_symbols, root_symbols = language_server.request_document_symbols("main.sh", include_body=False) + all_symbols, _root_symbols = language_server.request_document_symbols("main.sh", include_body=False) # Extract function symbols (LSP Symbol Kind 12) function_symbols = [symbol for symbol in all_symbols if symbol.get("kind") == 12] @@ -41,7 +41,7 @@ class TestBashLanguageServerBasics: def test_bash_request_document_symbols_with_body(self, language_server: SolidLanguageServer) -> None: """Test request_document_symbols with body extraction.""" # Test with include_body=True - all_symbols, root_symbols = language_server.request_document_symbols("main.sh", include_body=True) + all_symbols, _root_symbols = language_server.request_document_symbols("main.sh", include_body=True) function_symbols = [symbol for symbol in all_symbols if symbol.get("kind") == 12] @@ -58,7 +58,7 @@ class TestBashLanguageServerBasics: def test_bash_utils_functions(self, language_server: SolidLanguageServer) -> None: """Test function detection in utils.sh file.""" # Test with utils.sh as well - utils_all_symbols, utils_root_symbols = language_server.request_document_symbols("utils.sh", include_body=False) + utils_all_symbols, _utils_root_symbols = language_server.request_document_symbols("utils.sh", include_body=False) utils_function_symbols = [symbol for symbol in utils_all_symbols if symbol.get("kind") == 12] utils_function_names = [symbol["name"] for symbol in utils_function_symbols] @@ -84,12 +84,12 @@ class TestBashLanguageServerBasics: def test_bash_function_syntax_patterns(self, language_server: SolidLanguageServer) -> None: """Test that LSP detects different bash function syntax patterns correctly.""" # Test main.sh (has both 'function' keyword and traditional syntax) - main_all_symbols, main_root_symbols = language_server.request_document_symbols("main.sh", include_body=False) + main_all_symbols, _main_root_symbols = language_server.request_document_symbols("main.sh", include_body=False) main_functions = [symbol for symbol in main_all_symbols if symbol.get("kind") == 12] main_function_names = [func["name"] for func in main_functions] # Test utils.sh (all use 'function' keyword) - utils_all_symbols, utils_root_symbols = language_server.request_document_symbols("utils.sh", include_body=False) + utils_all_symbols, _utils_root_symbols = language_server.request_document_symbols("utils.sh", include_body=False) utils_functions = [symbol for symbol in utils_all_symbols if symbol.get("kind") == 12] utils_function_names = [func["name"] for func in utils_functions] diff --git a/test/solidlsp/markdown/test_markdown_basic.py b/test/solidlsp/markdown/test_markdown_basic.py index a3e8c42e..2f472638 100644 --- a/test/solidlsp/markdown/test_markdown_basic.py +++ b/test/solidlsp/markdown/test_markdown_basic.py @@ -25,7 +25,7 @@ class TestMarkdownLanguageServerBasics: def test_markdown_request_document_symbols(self, language_server: SolidLanguageServer) -> None: """Test request_document_symbols for markdown files.""" # Test getting symbols from README.md - all_symbols, root_symbols = language_server.request_document_symbols("README.md", include_body=False) + all_symbols, _root_symbols = language_server.request_document_symbols("README.md", include_body=False) # Extract heading symbols (LSP Symbol Kind 15 is String, but marksman uses kind 15 for headings) # Note: Different markdown LSPs may use different symbol kinds for headings @@ -38,7 +38,7 @@ class TestMarkdownLanguageServerBasics: @pytest.mark.parametrize("language_server", [Language.MARKDOWN], indirect=True) def test_markdown_request_symbols_from_guide(self, language_server: SolidLanguageServer) -> None: """Test symbol detection in guide.md file.""" - all_symbols, root_symbols = language_server.request_document_symbols("guide.md", include_body=False) + all_symbols, _root_symbols = language_server.request_document_symbols("guide.md", include_body=False) # At least some headings should be found assert len(all_symbols) > 0, f"Should find headings in guide.md, found {len(all_symbols)}" @@ -46,7 +46,7 @@ class TestMarkdownLanguageServerBasics: @pytest.mark.parametrize("language_server", [Language.MARKDOWN], indirect=True) def test_markdown_request_symbols_from_api(self, language_server: SolidLanguageServer) -> None: """Test symbol detection in api.md file.""" - all_symbols, root_symbols = language_server.request_document_symbols("api.md", include_body=False) + all_symbols, _root_symbols = language_server.request_document_symbols("api.md", include_body=False) # Should detect headings from api.md assert len(all_symbols) > 0, f"Should find headings in api.md, found {len(all_symbols)}" @@ -55,7 +55,7 @@ class TestMarkdownLanguageServerBasics: def test_markdown_request_document_symbols_with_body(self, language_server: SolidLanguageServer) -> None: """Test request_document_symbols with body extraction.""" # Test with include_body=True - all_symbols, root_symbols = language_server.request_document_symbols("README.md", include_body=True) + all_symbols, _root_symbols = language_server.request_document_symbols("README.md", include_body=True) # Should have found some symbols assert len(all_symbols) > 0, "Should find symbols in README.md" diff --git a/test/solidlsp/r/test_r_basic.py b/test/solidlsp/r/test_r_basic.py index 56ff345a..fc01d58c 100644 --- a/test/solidlsp/r/test_r_basic.py +++ b/test/solidlsp/r/test_r_basic.py @@ -27,7 +27,7 @@ class TestRLanguageServer: @pytest.mark.parametrize("language_server", [Language.R], indirect=True) def test_symbol_retrieval(self, language_server: SolidLanguageServer): """Test R document symbol extraction.""" - all_symbols, root_symbols = language_server.request_document_symbols(os.path.join("R", "utils.R")) + all_symbols, _root_symbols = language_server.request_document_symbols(os.path.join("R", "utils.R")) # Should find the three exported functions function_symbols = [s for s in all_symbols if s.get("kind") == 12] # Function kind diff --git a/test/solidlsp/ruby/test_ruby_symbol_retrieval.py b/test/solidlsp/ruby/test_ruby_symbol_retrieval.py index d75af32f..9ac4133e 100644 --- a/test/solidlsp/ruby/test_ruby_symbol_retrieval.py +++ b/test/solidlsp/ruby/test_ruby_symbol_retrieval.py @@ -89,7 +89,7 @@ class TestRubyLanguageServerSymbols: """Test request_containing_symbol for a module context.""" # Test that we can find the Services module in document symbols file_path = os.path.join("services.rb") - symbols, roots = language_server.request_document_symbols(file_path) + symbols, _roots = language_server.request_document_symbols(file_path) # Verify Services module appears in document symbols services_module = None @@ -141,7 +141,7 @@ class TestRubyLanguageServerSymbols: # Test referencing symbols for create_user method file_path = os.path.join("services.rb") # Line containing the create_user method definition - symbols, roots = language_server.request_document_symbols(file_path) + symbols, _roots = language_server.request_document_symbols(file_path) create_user_symbol = None # Find create_user method in the document symbols (Ruby returns flat list) @@ -169,7 +169,7 @@ class TestRubyLanguageServerSymbols: # Test referencing symbols for User class file_path = os.path.join("models.rb") # Find User class in document symbols - symbols, roots = language_server.request_document_symbols(file_path) + symbols, _roots = language_server.request_document_symbols(file_path) user_symbol = None for symbol in symbols: @@ -363,7 +363,7 @@ class TestRubyLanguageServerSymbols: # Test referencing symbols for a method parameter in get_user method file_path = os.path.join("services.rb") # Find get_user method and test parameter references - symbols, roots = language_server.request_document_symbols(file_path) + symbols, _roots = language_server.request_document_symbols(file_path) get_user_symbol = None for symbol in symbols: