Fix C# language server startup and test configuration

- Add required --stdio flag for Microsoft.CodeAnalysis.LanguageServer
- Add required --extensionLogDirectory parameter to avoid startup failure
- Fix test fixture to properly start/stop language server
- Remove skip markers from C# tests to enable testing
- Return cache_dir from setup_runtime_dependencies for log directory creation

The language server now starts successfully and the first test passes.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude AssistantandClaude committed 2025-06-25 23:49:54 +01:00
1 parent aa0fb79208
commit 723b7cb175
2 files changed
+23 -14

No files matched your search

@@ -82,17 +82,27 @@ class CSharpLanguageServer(SolidLanguageServer):
Creates a CSharpLanguageServer instance. This class is not meant to be instantiated directly.
Use LanguageServer.create() instead.
"""
dotnet_path, language_server_path = self.setup_runtime_dependencies(logger, config)
dotnet_path, language_server_path, cache_dir = self.setup_runtime_dependencies(logger, config)
# Find solution or project file
solution_or_project = find_solution_or_project_file(repository_root_path)
# Build command - Microsoft.CodeAnalysis.LanguageServer uses stdio by default
# Build command - Microsoft.CodeAnalysis.LanguageServer requires specific parameters
cmd_parts = [dotnet_path, language_server_path]
# Add logging level if debug is enabled
# Required parameters
cmd_parts.extend(["--stdio"]) # Use stdio for communication
# Set log level based on logger settings
if logger.logger.level <= logging.DEBUG:
cmd_parts.extend(["--logLevel", "Information"])
else:
cmd_parts.extend(["--logLevel", "Warning"])
# Create log directory
log_dir = cache_dir / "logs"
log_dir.mkdir(parents=True, exist_ok=True)
cmd_parts.extend(["--extensionLogDirectory", str(log_dir)])
# The language server will discover the solution/project from the workspace root
if solution_or_project:
@@ -120,10 +130,10 @@ class CSharpLanguageServer(SolidLanguageServer):
def is_ignored_dirname(self, dirname: str) -> bool:
return super().is_ignored_dirname(dirname) or dirname in ["bin", "obj", "packages", ".vs"]
def setup_runtime_dependencies(self, logger: LanguageServerLogger, config: LanguageServerConfig) -> tuple[str, str]:
def setup_runtime_dependencies(self, logger: LanguageServerLogger, config: LanguageServerConfig) -> tuple[str, str, Path]:
"""
Set up .NET 9 runtime and Microsoft.CodeAnalysis.LanguageServer by downloading the NuGet package.
Returns a tuple of (dotnet_path, language_server_dll_path).
Returns a tuple of (dotnet_path, language_server_dll_path, cache_dir).
"""
# Determine the runtime ID based on the platform
system = platform.system().lower()
@@ -158,7 +168,7 @@ class CSharpLanguageServer(SolidLanguageServer):
if server_dll.exists():
logger.log(f"Using cached Microsoft.CodeAnalysis.LanguageServer from {server_dll}", logging.INFO)
return dotnet_path, str(server_dll)
return dotnet_path, str(server_dll), cache_dir
# Download the package
logger.log(f"Downloading {package_name} version {package_version}...", logging.INFO)
@@ -322,7 +332,7 @@ class CSharpLanguageServer(SolidLanguageServer):
server_dll.chmod(server_dll.stat().st_mode | stat.S_IEXEC)
logger.log(f"Successfully installed Microsoft.CodeAnalysis.LanguageServer to {server_dll}", logging.INFO)
return dotnet_path, str(server_dll)
return dotnet_path, str(server_dll), cache_dir
def _ensure_dotnet_runtime(self, logger: LanguageServerLogger, cache_dir: Path, runtime_id: str) -> str:
"""
@@ -611,8 +621,6 @@ class CSharpLanguageServer(SolidLanguageServer):
self.server.on_request("window/workDoneProgress/create", handle_work_done_progress_create)
self.logger.log("Starting Microsoft.CodeAnalysis.LanguageServer process", logging.INFO)
self.logger.log(f"Command: {self.process_launch_info.cmd}", logging.DEBUG)
self.logger.log(f"Working directory: {self.process_launch_info.cwd}", logging.DEBUG)
try:
self.server.start()
+6 -5
View File
@@ -16,7 +16,12 @@ from test.conftest import create_ls
def csharp_ls() -> SolidLanguageServer:
"""Create a C# language server instance for testing."""
repo_path = Path(__file__).parent.parent.parent / "resources" / "repos" / "csharp" / "test_repo"
return create_ls(Language.CSHARP, str(repo_path))
server = create_ls(Language.CSHARP, str(repo_path))
server.start()
try:
yield server
finally:
server.stop()
class TestCSharpBasic:
@@ -27,7 +32,6 @@ class TestCSharpBasic:
assert csharp_ls is not None
assert csharp_ls.language == Language.CSHARP
@pytest.mark.skip(reason="Requires running language server")
def test_get_document_symbols(self, csharp_ls: SolidLanguageServer):
"""Test getting document symbols from a C# file."""
file_path = os.path.join("Program.cs")
@@ -45,7 +49,6 @@ class TestCSharpBasic:
assert "Program" in class_names
assert "Calculator" in class_names
@pytest.mark.skip(reason="Requires running language server")
def test_find_definition(self, csharp_ls: SolidLanguageServer):
"""Test finding definition of a symbol."""
file_path = os.path.join("Program.cs")
@@ -59,7 +62,6 @@ class TestCSharpBasic:
assert len(definitions) > 0
assert any("Calculator" in str(d) for d in definitions)
@pytest.mark.skip(reason="Requires running language server")
def test_find_references(self, csharp_ls: SolidLanguageServer):
"""Test finding references to a symbol."""
file_path = os.path.join("Program.cs")
@@ -72,7 +74,6 @@ class TestCSharpBasic:
# Should find at least the definition and one usage
assert len(references) >= 2
@pytest.mark.skip(reason="Requires running language server")
def test_nested_namespace_symbols(self, csharp_ls: SolidLanguageServer):
"""Test getting symbols from nested namespace."""
file_path = os.path.join("Models", "Person.cs")