diff --git a/pyproject.toml b/pyproject.toml index be99a021..044a2872 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -114,7 +114,11 @@ warn_redundant_casts = true warn_unreachable = true warn_unused_configs = true warn_unused_ignores = false -exclude = "^build/|^docs/" +exclude = "^build/|^docs/|^test/resources/" + +[[tool.mypy.overrides]] +module = "test.*" +disallow_untyped_defs = false # untyped defs are OK in tests [tool.poe.env] PYDEVD_DISABLE_FILE_VALIDATION = "1" @@ -137,8 +141,9 @@ _black_format = "black src scripts test" _ruff_format = "ruff check --fix src scripts test" lint = ["_black_check", "_ruff_check"] format = ["_ruff_format", "_black_format"] -_mypy = "mypy src/serena src/solidlsp" -type-check = ["_mypy"] +_mypy_core = "mypy src/serena src/solidlsp" +_mypy_test = "mypy --disable-error-code no-untyped-def test" +type-check = ["_mypy_core", "_mypy_test"] # docs _autogen_rst = "python docs/autogen_rst.py" _sphinx_build = "sphinx-build -b html docs docs/_build -W --keep-going" diff --git a/test/serena/test_serena_agent.py b/test/serena/test_serena_agent.py index abd6bc2c..67a8bf14 100644 --- a/test/serena/test_serena_agent.py +++ b/test/serena/test_serena_agent.py @@ -126,13 +126,13 @@ class TestSerenaAgent: def test_find_symbol(self, serena_agent: SerenaAgent, symbol_name: str, expected_kind: str, expected_file: str): # skip flaky tests in CI # TODO: Revisit the flaky tests and re-enable once the LS issues are resolved #1039 - flaky_languages = {Language.FSHARP} + flaky_languages = {Language.FSHARP, Language.RUST} if set(serena_agent.get_active_lsp_languages()).intersection(flaky_languages) and is_ci: pytest.skip("Test is flaky and thus skipped in CI environment.") agent = serena_agent find_symbol_tool = agent.get_tool(FindSymbolTool) - result = find_symbol_tool.apply_ex(name_path_pattern=symbol_name, include_info=True) + result = find_symbol_tool.apply(name_path_pattern=symbol_name, include_info=True) symbols = json.loads(result) assert any( @@ -461,7 +461,6 @@ class TestSerenaAgent: needle = r'console.log("WebSocketManager initializing\nStatus OK");' repl = r'console.log("WebSocketManager initialized\nAll systems go!");' replace_content_tool = serena_agent.get_tool(ReplaceContentTool) - mode: Literal["literal", "regex"] with project_file_modification_context(serena_agent, relative_path): result = replace_content_tool.apply( needle=re.escape(needle) if mode == "regex" else needle, diff --git a/test/serena/test_symbol_editing.py b/test/serena/test_symbol_editing.py index b885c558..69cd2a77 100644 --- a/test/serena/test_symbol_editing.py +++ b/test/serena/test_symbol_editing.py @@ -218,7 +218,7 @@ class EditingTest(ABC): with open(file_path, encoding="utf-8") as f: return f.read() - def run_test(self, content_after_ground_truth: str | SnapshotAssertion) -> None: + def run_test(self, content_after_ground_truth: SnapshotAssertion) -> None: with self._setup() as symbol_retriever: content_before = self._read_file(self.rel_path) code_editor = LanguageServerCodeEditor(symbol_retriever) diff --git a/test/solidlsp/fsharp/test_fsharp_basic.py b/test/solidlsp/fsharp/test_fsharp_basic.py index 4e4e03c7..3e599ae5 100644 --- a/test/solidlsp/fsharp/test_fsharp_basic.py +++ b/test/solidlsp/fsharp/test_fsharp_basic.py @@ -2,6 +2,7 @@ import os import tempfile import threading from pathlib import Path +from typing import Any from unittest.mock import Mock, patch import pytest @@ -142,14 +143,14 @@ class TestFSharpLanguageServer: file_path = os.path.join("Program.fs") # Use threading for cross-platform timeout (signal.SIGALRM is Unix-only) - result = [None] - exception = [None] + result: dict[str, Any] = dict(value=None) + exception: dict[str, Any] = dict(value=None) def run_completion(): try: - result[0] = language_server.request_completions(file_path, 15, 10) + result["value"] = language_server.request_completions(file_path, 15, 10) except Exception as e: - exception[0] = e + exception["value"] = e thread = threading.Thread(target=run_completion, daemon=True) thread.start() @@ -160,10 +161,10 @@ class TestFSharpLanguageServer: # The important thing is that the language server doesn't crash return - if exception[0]: - raise exception[0] + if exception["value"]: + raise exception["value"] - assert isinstance(result[0], list), "Completions should be a list" + assert isinstance(result["value"], list), "Completions should be a list" @pytest.mark.parametrize("language_server", [Language.FSHARP], indirect=True) def test_diagnostics(self, language_server: SolidLanguageServer) -> None: diff --git a/test/solidlsp/groovy/test_groovy_basic.py b/test/solidlsp/groovy/test_groovy_basic.py index 0ebae30c..8792f1dc 100644 --- a/test/solidlsp/groovy/test_groovy_basic.py +++ b/test/solidlsp/groovy/test_groovy_basic.py @@ -12,13 +12,14 @@ from solidlsp.settings import SolidLSPSettings @pytest.mark.groovy class TestGroovyLanguageServer: + language_server: SolidLanguageServer | None = None + test_repo_path: Path = Path(__file__).parent.parent.parent / "resources" / "repos" / "groovy" / "test_repo" + @classmethod def setup_class(cls): """ Set up test class with Groovy test repository. """ - cls.test_repo_path = Path(__file__).parent.parent.parent / "resources" / "repos" / "groovy" / "test_repo" - if not cls.test_repo_path.exists(): pytest.skip("Groovy test repository not found") @@ -56,10 +57,11 @@ class TestGroovyLanguageServer: """ Clean up language server. """ - if hasattr(cls, "language_server"): + if cls.language_server is not None: cls.language_server.stop() def test_find_symbol(self) -> None: + assert self.language_server is not None symbols = self.language_server.request_full_symbol_tree() assert SymbolUtils.symbol_tree_contains_name(symbols, "Main"), "Main class not found in symbol tree" assert SymbolUtils.symbol_tree_contains_name(symbols, "Utils"), "Utils class not found in symbol tree" @@ -67,6 +69,7 @@ class TestGroovyLanguageServer: assert SymbolUtils.symbol_tree_contains_name(symbols, "ModelUser"), "ModelUser class not found in symbol tree" def test_find_referencing_class_symbols(self) -> None: + assert self.language_server is not None file_path = os.path.join("src", "main", "groovy", "com", "example", "Utils.groovy") refs = self.language_server.request_references(file_path, 3, 6) assert any("Main.groovy" in ref.get("relativePath", "") for ref in refs), "Utils should be referenced from Main.groovy" @@ -93,6 +96,7 @@ class TestGroovyLanguageServer: assert len(model_user_refs) >= 1, f"Model should be referenced from ModelUser.groovy at least 1 time, found {len(model_user_refs)}" def test_overview_methods(self) -> None: + assert self.language_server is not None symbols = self.language_server.request_full_symbol_tree() assert SymbolUtils.symbol_tree_contains_name(symbols, "Main"), "Main missing from overview" assert SymbolUtils.symbol_tree_contains_name(symbols, "Utils"), "Utils missing from overview" diff --git a/test/solidlsp/lua/test_lua_basic.py b/test/solidlsp/lua/test_lua_basic.py index 4d4849cf..633e3c45 100644 --- a/test/solidlsp/lua/test_lua_basic.py +++ b/test/solidlsp/lua/test_lua_basic.py @@ -137,7 +137,7 @@ class TestLuaLanguageServer: assert len(refs) >= 5, f"Should find at least 5 references to calculator.add, found {len(refs)}" # Verify exact reference locations - ref_files = {} + ref_files: dict[str, list[int]] = {} for ref in refs: filename = ref.get("uri", "").split("/")[-1] if filename not in ref_files: @@ -193,7 +193,7 @@ class TestLuaLanguageServer: assert len(refs) >= 1, f"Should find at least 1 reference to utils.trim, found {len(refs)}" # Verify exact reference locations - ref_files = {} + ref_files: dict[str, list[int]] = {} for ref in refs: filename = ref.get("uri", "").split("/")[-1] if filename not in ref_files: diff --git a/test/solidlsp/scala/test_scala_language_server.py b/test/solidlsp/scala/test_scala_language_server.py index 9c498416..bfc6d8f1 100644 --- a/test/solidlsp/scala/test_scala_language_server.py +++ b/test/solidlsp/scala/test_scala_language_server.py @@ -1,3 +1,4 @@ +# type: ignore import os import pytest diff --git a/test/solidlsp/swift/test_swift_basic.py b/test/solidlsp/swift/test_swift_basic.py index 5cd5616c..b0f6dc2a 100644 --- a/test/solidlsp/swift/test_swift_basic.py +++ b/test/solidlsp/swift/test_swift_basic.py @@ -89,7 +89,7 @@ class TestSwiftLanguageServerBasics: # First, let's check if Utils is used anywhere (it might not be in this simple test) # We'll test goto_definition on Utils struct itself symbols = language_server.request_document_symbols(utils_file).get_all_symbols_and_roots() - utils_symbol = next((s for s in symbols[0] if s.get("name") == "Utils"), None) + utils_symbol = next(s for s in symbols[0] if s.get("name") == "Utils") sel_start = utils_symbol["selectionRange"]["start"] definitions = language_server.request_definition(utils_file, sel_start["line"], sel_start["character"]) @@ -106,7 +106,7 @@ class TestSwiftLanguageServerBasics: file_path = os.path.join("src", "main.swift") symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots() - calculator_symbol = next((s for s in symbols[0] if s.get("name") == "Calculator"), None) + calculator_symbol = next(s for s in symbols[0] if s.get("name") == "Calculator") sel_start = calculator_symbol["selectionRange"]["start"] references = language_server.request_references(file_path, sel_start["line"], sel_start["character"]) @@ -128,7 +128,7 @@ class TestSwiftLanguageServerBasics: file_path = os.path.join("src", "main.swift") symbols = language_server.request_document_symbols(file_path).get_all_symbols_and_roots() - user_symbol = next((s for s in symbols[0] if s.get("name") == "User"), None) + user_symbol = next(s for s in symbols[0] if s.get("name") == "User") sel_start = user_symbol["selectionRange"]["start"] references = language_server.request_references(file_path, sel_start["line"], sel_start["character"])