Refactoring: Rename Language to LanguageServerId

This resolves a long-standing naming issue in Serena & SolidLSP.
This commit is contained in:
Dominik Jain authored and Dominik Jain committed 2026-07-22 20:55:36 +02:00
1 parent ef0e218fb1
commit d2cf18ddcb
180 files changed
+1806 -1767

No files matched your search

+12 -9
View File
@@ -10,20 +10,23 @@ import os
import pytest
from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language
from solidlsp.ls_config import LanguageServerId
from solidlsp.ls_types import SymbolKind
from test.conftest import language_tests_enabled
from test.conftest import language_server_tests_enabled
from test.solidlsp.conftest import format_symbol_for_assert, has_malformed_name, request_all_symbols
from test.solidlsp.util.diagnostics import assert_file_diagnostics
# These marks will be applied to all tests in this module
pytestmark = [pytest.mark.elixir, pytest.mark.skipif(not language_tests_enabled(Language.ELIXIR), reason="Elixir tests are disabled")]
pytestmark = [
pytest.mark.elixir,
pytest.mark.skipif(not language_server_tests_enabled(LanguageServerId.ELIXIR), reason="Elixir tests are disabled"),
]
class TestElixirBasic:
"""Basic Elixir language server functionality tests."""
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_references_function_definition(self, language_server: SolidLanguageServer):
"""Test finding references to a function definition."""
file_path = os.path.join("lib", "models.ex")
@@ -52,7 +55,7 @@ class TestElixirBasic:
found_definition = any(ref["uri"].endswith("models.ex") for ref in references)
assert found_definition, "Should find the function definition"
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_references_create_user_function(self, language_server: SolidLanguageServer):
"""Test finding references to create_user function."""
file_path = os.path.join("lib", "services.ex")
@@ -77,7 +80,7 @@ class TestElixirBasic:
assert references is not None
assert len(references) > 0
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_referencing_symbols_function(self, language_server: SolidLanguageServer):
"""Test finding symbols that reference a specific function."""
file_path = os.path.join("lib", "models.ex")
@@ -101,7 +104,7 @@ class TestElixirBasic:
assert referencing_symbols is not None
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_timeout_enumeration_bug(self, language_server: SolidLanguageServer):
"""Test that enumeration doesn't timeout (regression test)."""
# This should complete without timing out
@@ -113,7 +116,7 @@ class TestElixirBasic:
symbols = language_server.request_document_symbols("lib/services.ex").get_all_symbols_and_roots()
assert symbols is not None
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_bare_symbol_names(self, language_server) -> None:
all_symbols = request_all_symbols(language_server)
malformed_symbols = []
@@ -139,7 +142,7 @@ class TestElixirBasic:
pytrace=False,
)
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_file_diagnostics(self, language_server: SolidLanguageServer) -> None:
assert_file_diagnostics(
language_server,
@@ -5,11 +5,14 @@ from pathlib import Path
import pytest
from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language
from test.conftest import language_tests_enabled, start_ls_context
from solidlsp.ls_config import LanguageServerId
from test.conftest import language_server_tests_enabled, start_ls_context
# These marks will be applied to all tests in this module
pytestmark = [pytest.mark.elixir, pytest.mark.skipif(not language_tests_enabled(Language.ELIXIR), reason="Elixir tests are disabled")]
pytestmark = [
pytest.mark.elixir,
pytest.mark.skipif(not language_server_tests_enabled(LanguageServerId.ELIXIR), reason="Elixir tests are disabled"),
]
# Skip slow tests in CI - they require multiple Expert instances which is too slow
IN_CI = bool(os.environ.get("CI") or os.environ.get("GITHUB_ACTIONS"))
@@ -26,7 +29,7 @@ def ls_with_ignored_dirs() -> Generator[SolidLanguageServer, None, None]:
Uses session scope to avoid restarting Expert for each test.
"""
ignored_paths = ["scripts", "ignored_dir"]
with start_ls_context(language=Language.ELIXIR, ignored_paths=ignored_paths) as ls:
with start_ls_context(ls_id=LanguageServerId.ELIXIR, ignored_paths=ignored_paths) as ls:
yield ls
@@ -81,7 +84,7 @@ def test_find_references_ignores_dir(ls_with_ignored_dirs: SolidLanguageServer):
@pytest.mark.slow
@SKIP_SLOW_IN_CI
@pytest.mark.parametrize("repo_path", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("repo_path", [LanguageServerId.ELIXIR], indirect=True)
def test_refs_and_symbols_with_glob_patterns(repo_path: Path) -> None:
"""Tests that refs and symbols with glob patterns are ignored.
@@ -89,7 +92,7 @@ def test_refs_and_symbols_with_glob_patterns(repo_path: Path) -> None:
which adds ~60-90s startup time.
"""
ignored_paths = ["*cripts", "ignored_*"] # codespell:ignore cripts
with start_ls_context(language=Language.ELIXIR, repo_path=str(repo_path), ignored_paths=ignored_paths) as ls:
with start_ls_context(ls_id=LanguageServerId.ELIXIR, repo_path=str(repo_path), ignored_paths=ignored_paths) as ls:
# Same as in the above tests
root = ls.request_full_symbol_tree()[0]
root_children = root["children"]
@@ -121,7 +124,7 @@ def test_refs_and_symbols_with_glob_patterns(repo_path: Path) -> None:
assert not any("ignored_dir" in ref["relativePath"] for ref in references), "ignored_dir should be ignored (glob)"
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_default_ignored_directories(language_server: SolidLanguageServer):
"""Test that default Elixir directories are ignored."""
# Test that Elixir-specific directories are ignored by default
@@ -142,7 +145,7 @@ def test_default_ignored_directories(language_server: SolidLanguageServer):
reason="Expert 0.1.0 bug: document_symbols may return nil for some files (flaky)",
raises=Exception,
)
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_symbol_tree_excludes_build_dirs(language_server: SolidLanguageServer):
"""Test that symbol tree excludes build and dependency directories."""
symbol_tree = language_server.request_full_symbol_tree()
@@ -12,11 +12,14 @@ import pytest
from serena.project import Project
from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language
from test.conftest import language_tests_enabled
from solidlsp.ls_config import LanguageServerId
from test.conftest import language_server_tests_enabled
# These marks will be applied to all tests in this module
pytestmark = [pytest.mark.elixir, pytest.mark.skipif(not language_tests_enabled(Language.ELIXIR), reason="Elixir tests are disabled")]
pytestmark = [
pytest.mark.elixir,
pytest.mark.skipif(not language_server_tests_enabled(LanguageServerId.ELIXIR), reason="Elixir tests are disabled"),
]
class TestElixirIntegration:
@@ -42,7 +45,7 @@ class TestElixirIntegration:
assert (repo_path / "test" / "test_repo_test.exs").exists(), "test file should exist"
assert (repo_path / "test" / "models_test.exs").exists(), "models test should exist"
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_cross_file_symbol_resolution(self, language_server: SolidLanguageServer):
"""Test that symbols can be resolved across different files."""
# Test that User struct from models.ex can be found when referenced in services.ex
@@ -67,7 +70,7 @@ class TestElixirIntegration:
# Should point to models.ex
assert "models.ex" in defining_symbol["location"]["uri"]
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_module_hierarchy_understanding(self, language_server: SolidLanguageServer):
"""Test that the language server understands Elixir module hierarchy."""
models_file = os.path.join("lib", "models.ex")
@@ -91,7 +94,7 @@ class TestElixirIntegration:
def test_file_extension_matching(self):
"""Test that the Elixir language recognizes the correct file extensions."""
language = Language.ELIXIR
language = LanguageServerId.ELIXIR
matcher = language.get_source_fn_matcher()
# Test Elixir file extensions
@@ -110,7 +113,7 @@ class TestElixirIntegration:
class TestElixirProject:
@pytest.mark.parametrize("project", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("project", [LanguageServerId.ELIXIR], indirect=True)
def test_comprehensive_symbol_search(self, project: Project):
"""Test comprehensive symbol search across the entire project."""
# Search for all function definitions
@@ -138,7 +141,7 @@ class TestElixirProject:
models_structs = [m for m in struct_matches if m.source_file_path and "models.ex" in m.source_file_path]
assert len(models_structs) > 0, "Should find struct definitions in models.ex"
@pytest.mark.parametrize("project", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("project", [LanguageServerId.ELIXIR], indirect=True)
def test_protocol_and_implementation_understanding(self, project: Project):
"""Test that the language server understands Elixir protocols and implementations."""
# Search for protocol definitions
@@ -12,12 +12,15 @@ import os
import pytest
from solidlsp import SolidLanguageServer
from solidlsp.ls_config import Language
from solidlsp.ls_config import LanguageServerId
from solidlsp.ls_types import SymbolKind
from test.conftest import language_tests_enabled
from test.conftest import language_server_tests_enabled
# These marks will be applied to all tests in this module
pytestmark = [pytest.mark.elixir, pytest.mark.skipif(not language_tests_enabled(Language.ELIXIR), reason="Elixir tests are disabled")]
pytestmark = [
pytest.mark.elixir,
pytest.mark.skipif(not language_server_tests_enabled(LanguageServerId.ELIXIR), reason="Elixir tests are disabled"),
]
class TestElixirLanguageServerSymbols:
@@ -26,7 +29,7 @@ class TestElixirLanguageServerSymbols:
@pytest.mark.xfail(
reason="Expert 0.1.0 bug: document_symbols returns nil for some files (FunctionClauseError in XPExpert.EngineApi.document_symbols/2)"
)
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_containing_symbol_function(self, language_server: SolidLanguageServer) -> None:
"""Test request_containing_symbol for a function."""
# Test for a position inside the create_user function
@@ -54,7 +57,7 @@ class TestElixirLanguageServerSymbols:
if "body" in containing_symbol:
assert "def create_user" in containing_symbol["body"].get_text()
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_containing_symbol_module(self, language_server: SolidLanguageServer) -> None:
"""Test request_containing_symbol for a module."""
# Test for a position inside the UserService module but outside any function
@@ -79,7 +82,7 @@ class TestElixirLanguageServerSymbols:
assert "UserService" in containing_symbol["name"]
assert containing_symbol["kind"] == SymbolKind.Module or containing_symbol["kind"] == SymbolKind.Class
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_containing_symbol_nested(self, language_server: SolidLanguageServer) -> None:
"""Test request_containing_symbol with nested scopes."""
# Test for a position inside a function which is inside a module
@@ -104,7 +107,7 @@ class TestElixirLanguageServerSymbols:
expected_names = ["create_user", "UserService"]
assert any(name in containing_symbol["name"] for name in expected_names)
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_containing_symbol_none(self, language_server: SolidLanguageServer) -> None:
"""Test request_containing_symbol for a position with no containing symbol."""
# Test for a position outside any function/module (e.g., in module doc)
@@ -116,7 +119,7 @@ class TestElixirLanguageServerSymbols:
# This is acceptable behavior for module-level positions
assert containing_symbol is None or containing_symbol == {} or "TestRepo.Services" in str(containing_symbol)
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_referencing_symbols_struct(self, language_server: SolidLanguageServer) -> None:
"""Test request_referencing_symbols for a struct."""
# Test referencing symbols for User struct
@@ -146,7 +149,7 @@ class TestElixirLanguageServerSymbols:
# We expect some references from services.ex
assert len(services_references) >= 0 # At least attempt to find references
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_referencing_symbols_none(self, language_server: SolidLanguageServer) -> None:
"""Test request_referencing_symbols for a position with no symbol."""
file_path = os.path.join("lib", "services.ex")
@@ -164,7 +167,7 @@ class TestElixirLanguageServerSymbols:
@pytest.mark.xfail(
reason="Expert 0.1.0 bug: definition request crashes (FunctionClauseError in XPExpert.Protocol.Conversions.to_elixir/2)"
)
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_defining_symbol_function_call(self, language_server: SolidLanguageServer) -> None:
"""Test request_defining_symbol for a function call."""
# Find a place where User.new is called in services.ex
@@ -191,7 +194,7 @@ class TestElixirLanguageServerSymbols:
@pytest.mark.xfail(
reason="Expert 0.1.0 bug: definition request crashes (FunctionClauseError in XPExpert.Protocol.Conversions.to_elixir/2)"
)
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_defining_symbol_struct_usage(self, language_server: SolidLanguageServer) -> None:
"""Test request_defining_symbol for a struct usage."""
# Find a place where User struct is used in services.ex
@@ -215,7 +218,7 @@ class TestElixirLanguageServerSymbols:
@pytest.mark.xfail(
reason="Expert 0.1.0 bug: definition request crashes (FunctionClauseError in XPExpert.Protocol.Conversions.to_elixir/2)"
)
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_defining_symbol_none(self, language_server: SolidLanguageServer) -> None:
"""Test request_defining_symbol for a position with no symbol."""
# Test for a position with no symbol (e.g., whitespace or comment)
@@ -226,7 +229,7 @@ class TestElixirLanguageServerSymbols:
# Should return None or empty
assert defining_symbol is None or defining_symbol == {}
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_symbol_methods_integration(self, language_server: SolidLanguageServer) -> None:
"""Test integration between different symbol methods."""
file_path = os.path.join("lib", "models.ex")
@@ -257,7 +260,7 @@ class TestElixirLanguageServerSymbols:
assert isinstance(refs, list)
@pytest.mark.xfail(reason="Flaky test, sometimes fails with an Expert-internal error")
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_symbol_tree_structure(self, language_server: SolidLanguageServer) -> None:
"""Test that symbol tree structure is correctly built."""
symbol_tree = language_server.request_full_symbol_tree()
@@ -283,7 +286,7 @@ class TestElixirLanguageServerSymbols:
found_modules = [name for name in expected_modules if name in file_names]
assert len(found_modules) > 0, f"Expected to find some modules from {expected_modules}, but got {file_names}"
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_request_dir_overview(self, language_server: SolidLanguageServer) -> None:
"""Test request_dir_overview functionality."""
lib_overview = language_server.request_dir_overview("lib")
@@ -321,7 +324,7 @@ class TestElixirLanguageServerSymbols:
# found_terms = [term for term in expected_terms if term in overview_text]
# assert len(found_terms) > 0, f"Expected to find some terms from {expected_terms} in overview"
@pytest.mark.parametrize("language_server", [Language.ELIXIR], indirect=True)
@pytest.mark.parametrize("language_server", [LanguageServerId.ELIXIR], indirect=True)
def test_containing_symbol_of_module_attribute(self, language_server: SolidLanguageServer) -> None:
"""Test containing symbol for module attributes."""
file_path = os.path.join("lib", "models.ex")