mirror of
https://github.com/tiennm99/serena.git
synced 2026-07-13 23:07:55 +00:00
Formatting, minor ruff fixes
This commit is contained in:
@@ -6,7 +6,6 @@ import logging
|
||||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
import shlex
|
||||
import shutil
|
||||
import stat
|
||||
import subprocess
|
||||
@@ -56,17 +55,17 @@ def find_solution_or_project_file(root_dir) -> str | None:
|
||||
"""
|
||||
sln_file = None
|
||||
csproj_file = None
|
||||
|
||||
|
||||
for filename in breadth_first_file_scan(root_dir):
|
||||
if filename.endswith(".sln") and sln_file is None:
|
||||
sln_file = filename
|
||||
elif filename.endswith(".csproj") and csproj_file is None:
|
||||
csproj_file = filename
|
||||
|
||||
|
||||
# If we found a .sln file, return it immediately
|
||||
if sln_file:
|
||||
return sln_file
|
||||
|
||||
|
||||
# If no .sln file was found, return the first .csproj file
|
||||
return csproj_file
|
||||
|
||||
@@ -83,39 +82,39 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
Use LanguageServer.create() instead.
|
||||
"""
|
||||
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 requires specific parameters
|
||||
cmd_parts = [dotnet_path, language_server_path]
|
||||
|
||||
|
||||
# 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:
|
||||
logger.log(f"Found solution/project file: {solution_or_project}", logging.INFO)
|
||||
else:
|
||||
logger.log("No .sln or .csproj file found, language server will attempt auto-discovery", logging.WARNING)
|
||||
|
||||
|
||||
# Join command parts with spaces
|
||||
# ProcessLaunchInfo expects a simple string command, not shell-quoted
|
||||
cmd = " ".join(cmd_parts)
|
||||
|
||||
|
||||
logger.log(f"Language server command: {cmd}", logging.DEBUG)
|
||||
|
||||
|
||||
super().__init__(
|
||||
config,
|
||||
logger,
|
||||
@@ -123,7 +122,7 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
ProcessLaunchInfo(cmd=cmd, cwd=repository_root_path),
|
||||
"csharp",
|
||||
)
|
||||
|
||||
|
||||
self.initialization_complete = threading.Event()
|
||||
|
||||
@override
|
||||
@@ -136,15 +135,15 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
Returns a tuple of (dotnet_path, language_server_dll_path, cache_dir).
|
||||
"""
|
||||
import json
|
||||
|
||||
|
||||
# Load runtime dependencies configuration
|
||||
with open(os.path.join(os.path.dirname(__file__), "runtime_dependencies.json"), encoding="utf-8") as f:
|
||||
runtime_deps = json.load(f)
|
||||
|
||||
|
||||
# Determine the runtime ID based on the platform
|
||||
system = platform.system().lower()
|
||||
machine = platform.machine().lower()
|
||||
|
||||
|
||||
# Map platform info to runtime ID
|
||||
if system == "windows":
|
||||
runtime_id = "win-x64" if machine in ["amd64", "x86_64"] else "win-arm64"
|
||||
@@ -154,80 +153,78 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
runtime_id = "linux-x64" if machine in ["x86_64", "amd64"] else "linux-arm64"
|
||||
else:
|
||||
raise LanguageServerException(f"Unsupported platform: {system} {machine}")
|
||||
|
||||
|
||||
# Set up cache directory
|
||||
cache_dir = Path.home() / ".cache" / "serena" / "language-servers" / "csharp"
|
||||
cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
# Find the appropriate language server dependency
|
||||
lang_server_dep = None
|
||||
dotnet_runtime_dep = None
|
||||
|
||||
|
||||
for dep in runtime_deps["runtimeDependencies"]:
|
||||
if dep["id"] == "CSharpLanguageServer" and dep["platformId"] == runtime_id:
|
||||
lang_server_dep = dep
|
||||
elif dep["id"] == "DotNetRuntime" and dep["platformId"] == runtime_id:
|
||||
dotnet_runtime_dep = dep
|
||||
|
||||
|
||||
if not lang_server_dep:
|
||||
raise LanguageServerException(f"No C# language server dependency found for platform {runtime_id}")
|
||||
if not dotnet_runtime_dep:
|
||||
raise LanguageServerException(f"No .NET runtime dependency found for platform {runtime_id}")
|
||||
|
||||
|
||||
# First, ensure we have .NET 9 runtime
|
||||
dotnet_path = self._ensure_dotnet_runtime_from_config(logger, cache_dir, dotnet_runtime_dep)
|
||||
|
||||
|
||||
# Then set up the language server
|
||||
package_name = lang_server_dep["packageName"]
|
||||
package_version = lang_server_dep["packageVersion"]
|
||||
|
||||
|
||||
server_dir = cache_dir / f"{package_name}.{package_version}"
|
||||
server_dll = server_dir / lang_server_dep["binaryName"]
|
||||
|
||||
|
||||
if server_dll.exists():
|
||||
logger.log(f"Using cached Microsoft.CodeAnalysis.LanguageServer from {server_dll}", logging.INFO)
|
||||
return dotnet_path, str(server_dll), cache_dir
|
||||
|
||||
|
||||
# Download the language server package
|
||||
logger.log(f"Downloading {package_name} version {package_version}...", logging.INFO)
|
||||
|
||||
|
||||
# Check if nuget or dotnet is available
|
||||
nuget_cmd = shutil.which("nuget")
|
||||
dotnet_cmd = shutil.which("dotnet")
|
||||
|
||||
|
||||
if not nuget_cmd and not dotnet_cmd:
|
||||
raise LanguageServerException(
|
||||
"Neither nuget nor dotnet CLI is available. "
|
||||
"Please install .NET SDK from https://dotnet.microsoft.com/download"
|
||||
"Neither nuget nor dotnet CLI is available. " "Please install .NET SDK from https://dotnet.microsoft.com/download"
|
||||
)
|
||||
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
temp_path = Path(temp_dir)
|
||||
|
||||
|
||||
# Try to download directly from the NuGet API first
|
||||
direct_download_url = f"https://api.nuget.org/v3-flatcontainer/{package_name.lower()}/{package_version}/{package_name.lower()}.{package_version}.nupkg"
|
||||
|
||||
|
||||
package_path = None
|
||||
try:
|
||||
nupkg_path = temp_path / f"{package_name}.{package_version}.nupkg"
|
||||
logger.log(f"Attempting direct download from {direct_download_url}", logging.INFO)
|
||||
|
||||
|
||||
urllib.request.urlretrieve(direct_download_url, nupkg_path)
|
||||
|
||||
|
||||
# Extract the nupkg (it's a zip file)
|
||||
package_path = temp_path / f"{package_name}.{package_version}"
|
||||
with zipfile.ZipFile(nupkg_path, 'r') as zip_ref:
|
||||
with zipfile.ZipFile(nupkg_path, "r") as zip_ref:
|
||||
zip_ref.extractall(package_path)
|
||||
|
||||
|
||||
logger.log("Successfully downloaded and extracted package", logging.INFO)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.log(f"Direct download failed: {e}, falling back to package manager", logging.WARNING)
|
||||
package_path = None
|
||||
|
||||
|
||||
if package_path is None and dotnet_cmd:
|
||||
# Use dotnet restore to download the package
|
||||
nuget_sources = " ".join([f"--source {src}" for src in runtime_deps["nugetSources"]])
|
||||
project_content = f"""<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
@@ -241,84 +238,90 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
</RestoreAdditionalProjectSources>
|
||||
</PropertyGroup>
|
||||
</Project>"""
|
||||
|
||||
|
||||
project_file = temp_path / "temp.csproj"
|
||||
project_file.write_text(project_content)
|
||||
|
||||
|
||||
try:
|
||||
# Use dotnet restore with no dependencies
|
||||
subprocess.run(
|
||||
[dotnet_cmd, "restore", str(project_file), "--packages", str(temp_path),
|
||||
"--no-dependencies", "--ignore-failed-sources"],
|
||||
[
|
||||
dotnet_cmd,
|
||||
"restore",
|
||||
str(project_file),
|
||||
"--packages",
|
||||
str(temp_path),
|
||||
"--no-dependencies",
|
||||
"--ignore-failed-sources",
|
||||
],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True
|
||||
text=True,
|
||||
)
|
||||
package_path = temp_path / package_name.lower() / package_version
|
||||
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.log(f"Dotnet restore stdout: {e.stdout}", logging.ERROR)
|
||||
logger.log(f"Dotnet restore stderr: {e.stderr}", logging.ERROR)
|
||||
raise LanguageServerException(f"Failed to download package: stdout={e.stdout}, stderr={e.stderr}")
|
||||
|
||||
|
||||
elif package_path is None and nuget_cmd:
|
||||
# Use nuget to download the package
|
||||
try:
|
||||
subprocess.run(
|
||||
[
|
||||
nuget_cmd, "install", package_name,
|
||||
"-Version", package_version,
|
||||
"-OutputDirectory", str(temp_path),
|
||||
"-NonInteractive"
|
||||
nuget_cmd,
|
||||
"install",
|
||||
package_name,
|
||||
"-Version",
|
||||
package_version,
|
||||
"-OutputDirectory",
|
||||
str(temp_path),
|
||||
"-NonInteractive",
|
||||
],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True
|
||||
text=True,
|
||||
)
|
||||
|
||||
|
||||
# Find the downloaded package
|
||||
package_path = temp_path / f"{package_name}.{package_version}"
|
||||
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise LanguageServerException(f"Failed to download package: {e.stderr}")
|
||||
|
||||
|
||||
if package_path is None or not package_path.exists():
|
||||
raise LanguageServerException("Failed to download Microsoft.CodeAnalysis.LanguageServer package")
|
||||
|
||||
|
||||
# Extract the language server files
|
||||
extract_path = lang_server_dep.get("extractPath", "lib/net9.0")
|
||||
source_dir = package_path / extract_path
|
||||
|
||||
|
||||
if not source_dir.exists():
|
||||
# Try alternative locations
|
||||
for possible_dir in [
|
||||
package_path / "tools" / "net9.0" / "any",
|
||||
package_path / "lib" / "net9.0",
|
||||
package_path / "contentFiles" / "any" / "net9.0"
|
||||
package_path / "contentFiles" / "any" / "net9.0",
|
||||
]:
|
||||
if possible_dir.exists():
|
||||
source_dir = possible_dir
|
||||
break
|
||||
else:
|
||||
raise LanguageServerException(
|
||||
f"Could not find language server files in package. "
|
||||
f"Searched in {package_path}"
|
||||
)
|
||||
|
||||
raise LanguageServerException(f"Could not find language server files in package. " f"Searched in {package_path}")
|
||||
|
||||
# Copy files to cache directory
|
||||
server_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
shutil.copytree(source_dir, server_dir, dirs_exist_ok=True)
|
||||
|
||||
|
||||
if not server_dll.exists():
|
||||
raise LanguageServerException(
|
||||
"Microsoft.CodeAnalysis.LanguageServer.dll not found after extraction"
|
||||
)
|
||||
|
||||
raise LanguageServerException("Microsoft.CodeAnalysis.LanguageServer.dll not found after extraction")
|
||||
|
||||
# Make the DLL executable on Unix-like systems
|
||||
if system != "windows":
|
||||
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), cache_dir
|
||||
|
||||
@@ -332,22 +335,17 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
if system_dotnet:
|
||||
# Check if it's .NET 9
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[system_dotnet, "--list-runtimes"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
result = subprocess.run([system_dotnet, "--list-runtimes"], capture_output=True, text=True, check=True)
|
||||
if "Microsoft.NETCore.App 9." in result.stdout:
|
||||
logger.log("Found system .NET 9 runtime", logging.INFO)
|
||||
return system_dotnet
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
|
||||
|
||||
# Download .NET 9 runtime using config
|
||||
dotnet_dir = cache_dir / "dotnet-runtime-9.0"
|
||||
dotnet_exe = dotnet_dir / runtime_dep["binaryName"]
|
||||
|
||||
|
||||
if dotnet_exe.exists():
|
||||
# Verify it still works
|
||||
try:
|
||||
@@ -357,75 +355,73 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
except subprocess.CalledProcessError:
|
||||
logger.log("Cached .NET runtime is corrupted, re-downloading", logging.WARNING)
|
||||
shutil.rmtree(dotnet_dir, ignore_errors=True)
|
||||
|
||||
|
||||
# Download .NET runtime
|
||||
logger.log("Downloading .NET 9 runtime...", logging.INFO)
|
||||
dotnet_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
url = runtime_dep["url"]
|
||||
archive_type = runtime_dep["archiveType"]
|
||||
|
||||
|
||||
# Download the runtime
|
||||
download_path = dotnet_dir / f"dotnet-runtime.{archive_type}"
|
||||
try:
|
||||
logger.log(f"Downloading from {url}", logging.DEBUG)
|
||||
urllib.request.urlretrieve(url, download_path)
|
||||
|
||||
|
||||
# Extract the archive
|
||||
if archive_type == "zip":
|
||||
with zipfile.ZipFile(download_path, 'r') as zip_ref:
|
||||
with zipfile.ZipFile(download_path, "r") as zip_ref:
|
||||
zip_ref.extractall(dotnet_dir)
|
||||
else:
|
||||
# tar.gz
|
||||
with tarfile.open(download_path, 'r:gz') as tar_ref:
|
||||
with tarfile.open(download_path, "r:gz") as tar_ref:
|
||||
tar_ref.extractall(dotnet_dir)
|
||||
|
||||
|
||||
# Remove the archive
|
||||
download_path.unlink()
|
||||
|
||||
|
||||
# Make dotnet executable on Unix
|
||||
if platform.system().lower() != "windows":
|
||||
dotnet_exe.chmod(dotnet_exe.stat().st_mode | stat.S_IEXEC)
|
||||
|
||||
|
||||
logger.log(f"Successfully installed .NET 9 runtime to {dotnet_exe}", logging.INFO)
|
||||
return str(dotnet_exe)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
raise LanguageServerException(f"Failed to download .NET 9 runtime from {url}: {e}") from e
|
||||
|
||||
|
||||
|
||||
def _get_initialize_params(self, repository_absolute_path: str) -> InitializeParams:
|
||||
"""
|
||||
Returns the initialize params for the Microsoft.CodeAnalysis.LanguageServer.
|
||||
"""
|
||||
import json
|
||||
|
||||
|
||||
# Load initialization parameters from JSON file
|
||||
with open(os.path.join(os.path.dirname(__file__), "initialize_params.json"), encoding="utf-8") as f:
|
||||
initialize_params_template = json.load(f)
|
||||
|
||||
|
||||
# Convert the template string to actual values
|
||||
initialize_params_str = json.dumps(initialize_params_template)
|
||||
|
||||
|
||||
# Replace template variables
|
||||
root_uri = pathlib.Path(repository_absolute_path).as_uri()
|
||||
root_name = os.path.basename(repository_absolute_path)
|
||||
|
||||
|
||||
initialize_params_str = initialize_params_str.replace("$rootPath", repository_absolute_path)
|
||||
initialize_params_str = initialize_params_str.replace("$rootUri", root_uri)
|
||||
initialize_params_str = initialize_params_str.replace("$rootName", root_name)
|
||||
initialize_params_str = initialize_params_str.replace('"os.getpid()"', str(os.getpid()))
|
||||
|
||||
|
||||
# Parse back to dictionary
|
||||
initialize_params = json.loads(initialize_params_str)
|
||||
|
||||
|
||||
return initialize_params
|
||||
|
||||
def _start_server(self):
|
||||
"""
|
||||
Starts the Microsoft.CodeAnalysis.LanguageServer.
|
||||
|
||||
|
||||
Usage:
|
||||
```
|
||||
async with lsp.start_server():
|
||||
@@ -436,7 +432,7 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
# LanguageServer has been shutdown cleanly
|
||||
```
|
||||
"""
|
||||
|
||||
|
||||
def do_nothing(params):
|
||||
return
|
||||
|
||||
@@ -444,17 +440,12 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
"""Log messages from the language server."""
|
||||
message_text = msg.get("message", "")
|
||||
level = msg.get("type", 4) # Default to Log level
|
||||
|
||||
|
||||
# Map LSP message types to Python logging levels
|
||||
level_map = {
|
||||
1: logging.ERROR, # Error
|
||||
2: logging.WARNING, # Warning
|
||||
3: logging.INFO, # Info
|
||||
4: logging.DEBUG # Log
|
||||
}
|
||||
|
||||
level_map = {1: logging.ERROR, 2: logging.WARNING, 3: logging.INFO, 4: logging.DEBUG} # Error # Warning # Info # Log
|
||||
|
||||
self.logger.log(f"LSP: {message_text}", level_map.get(level, logging.DEBUG))
|
||||
|
||||
|
||||
# Also print important messages to console
|
||||
if level <= 3: # Error, Warning, or Info
|
||||
print(f"C# Language Server: {message_text}")
|
||||
@@ -463,36 +454,36 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
"""Handle progress notifications from the language server."""
|
||||
token = params.get("token", "")
|
||||
value = params.get("value", {})
|
||||
|
||||
|
||||
# Log raw progress for debugging
|
||||
self.logger.log(f"Progress notification received: {params}", logging.DEBUG)
|
||||
|
||||
|
||||
# Handle different progress notification types
|
||||
kind = value.get("kind")
|
||||
|
||||
|
||||
if kind == "begin":
|
||||
title = value.get("title", "Operation in progress")
|
||||
message = value.get("message", "")
|
||||
percentage = value.get("percentage")
|
||||
|
||||
|
||||
if percentage is not None:
|
||||
self.logger.log(f"Progress [{token}]: {title} - {message} ({percentage}%)", logging.INFO)
|
||||
print(f"C# Language Server: {title} - {message} ({percentage}%)")
|
||||
else:
|
||||
self.logger.log(f"Progress [{token}]: {title} - {message}", logging.INFO)
|
||||
print(f"C# Language Server: {title} - {message}")
|
||||
|
||||
|
||||
elif kind == "report":
|
||||
message = value.get("message", "")
|
||||
percentage = value.get("percentage")
|
||||
|
||||
|
||||
if percentage is not None:
|
||||
self.logger.log(f"Progress [{token}]: {message} ({percentage}%)", logging.INFO)
|
||||
if percentage % 10 == 0: # Print every 10%
|
||||
print(f"C# Language Server: {message} ({percentage}%)")
|
||||
elif message:
|
||||
self.logger.log(f"Progress [{token}]: {message}", logging.INFO)
|
||||
|
||||
|
||||
elif kind == "end":
|
||||
message = value.get("message", "Operation completed")
|
||||
self.logger.log(f"Progress [{token}]: {message}", logging.INFO)
|
||||
@@ -502,12 +493,12 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
"""Handle workspace/configuration requests from the server."""
|
||||
items = params.get("items", [])
|
||||
result = []
|
||||
|
||||
|
||||
for item in items:
|
||||
section = item.get("section", "")
|
||||
|
||||
|
||||
# Provide default values based on the configuration section
|
||||
if section.startswith("dotnet") or section.startswith("csharp"):
|
||||
if section.startswith(("dotnet", "csharp")):
|
||||
# Default configuration for C# settings
|
||||
if "enable" in section or "show" in section or "suppress" in section or "navigate" in section:
|
||||
# Boolean settings
|
||||
@@ -524,7 +515,7 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
# ImplementTypeInsertionBehavior enum
|
||||
result.append("with_other_members_of_the_same_kind")
|
||||
elif section == "dotnet_property_generation_behavior":
|
||||
# ImplementTypePropertyGenerationBehavior enum
|
||||
# ImplementTypePropertyGenerationBehavior enum
|
||||
result.append("prefer_throwing_properties")
|
||||
elif "location" in section or "behavior" in section:
|
||||
# Other enum settings - return null to avoid parsing errors
|
||||
@@ -541,18 +532,18 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
else:
|
||||
# Unknown configuration - return null
|
||||
result.append(None)
|
||||
|
||||
|
||||
return result
|
||||
|
||||
def handle_work_done_progress_create(params):
|
||||
"""Handle work done progress create requests."""
|
||||
# Just acknowledge the request
|
||||
return None
|
||||
return
|
||||
|
||||
def handle_register_capability(params):
|
||||
"""Handle client/registerCapability requests."""
|
||||
# Just acknowledge the request - we don't need to track these for now
|
||||
return None
|
||||
return
|
||||
|
||||
# Set up notification handlers
|
||||
self.server.on_notification("window/logMessage", window_log_message)
|
||||
@@ -561,18 +552,18 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
self.server.on_request("workspace/configuration", handle_workspace_configuration)
|
||||
self.server.on_request("window/workDoneProgress/create", handle_work_done_progress_create)
|
||||
self.server.on_request("client/registerCapability", handle_register_capability)
|
||||
|
||||
|
||||
self.logger.log("Starting Microsoft.CodeAnalysis.LanguageServer process", logging.INFO)
|
||||
|
||||
|
||||
try:
|
||||
self.server.start()
|
||||
except Exception as e:
|
||||
self.logger.log(f"Failed to start language server process: {e}", logging.ERROR)
|
||||
raise LanguageServerException(f"Failed to start C# language server: {e}")
|
||||
|
||||
|
||||
# Send initialization
|
||||
initialize_params = self._get_initialize_params(self.repository_root_path)
|
||||
|
||||
|
||||
self.logger.log("Sending initialize request to language server", logging.INFO)
|
||||
try:
|
||||
init_response = self.server.send.initialize(initialize_params)
|
||||
@@ -584,19 +575,19 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
self.logger.log("2. Microsoft.CodeAnalysis.LanguageServer not found", logging.ERROR)
|
||||
self.logger.log("3. Project too large or complex for default timeout", logging.ERROR)
|
||||
raise
|
||||
|
||||
|
||||
# Verify required capabilities
|
||||
capabilities = init_response.get("capabilities", {})
|
||||
assert "textDocumentSync" in capabilities
|
||||
assert "definitionProvider" in capabilities
|
||||
assert "referencesProvider" in capabilities
|
||||
assert "documentSymbolProvider" in capabilities
|
||||
|
||||
|
||||
# Complete initialization
|
||||
self.server.notify.initialized({})
|
||||
self.initialization_complete.set()
|
||||
self.completions_available.set()
|
||||
|
||||
|
||||
self.logger.log("Microsoft.CodeAnalysis.LanguageServer initialized and ready", logging.INFO)
|
||||
self.logger.log("Waiting for language server to index project files...", logging.INFO)
|
||||
self.logger.log("This may take a while for large projects", logging.INFO)
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ class SolidLanguageServer(ABC):
|
||||
# But OmniSharp seems to crash and has some issues with newer C# versions
|
||||
# from solidlsp.language_servers.omnisharp.omnisharp import OmniSharp
|
||||
# ls = OmniSharp(config, logger, repository_root_path)
|
||||
|
||||
|
||||
from solidlsp.language_servers.csharp_language_server.csharp_language_server import CSharpLanguageServer
|
||||
|
||||
ls = CSharpLanguageServer(config, logger, repository_root_path)
|
||||
|
||||
@@ -36,14 +36,14 @@ class TestCSharpBasic:
|
||||
"""Test getting document symbols from a C# file."""
|
||||
file_path = os.path.join("Program.cs")
|
||||
symbols = csharp_ls.request_document_symbols(file_path)
|
||||
|
||||
|
||||
# Check that we have symbols
|
||||
assert len(symbols) > 0
|
||||
|
||||
|
||||
# Flatten the symbols if they're nested
|
||||
if isinstance(symbols[0], list):
|
||||
symbols = symbols[0]
|
||||
|
||||
|
||||
# Look for expected classes
|
||||
class_names = [s.get("name") for s in symbols if s.get("kind") == 5] # 5 is class
|
||||
assert "Program" in class_names
|
||||
@@ -52,12 +52,12 @@ class TestCSharpBasic:
|
||||
def test_find_definition(self, csharp_ls: SolidLanguageServer):
|
||||
"""Test finding definition of a symbol."""
|
||||
file_path = os.path.join("Program.cs")
|
||||
|
||||
|
||||
# Open the file first
|
||||
with csharp_ls.open_file(file_path):
|
||||
# Find usage of Calculator class (line 11, column 28)
|
||||
definitions = csharp_ls.request_definition(file_path, 11, 28)
|
||||
|
||||
|
||||
# Should find the Calculator class definition
|
||||
assert len(definitions) > 0
|
||||
assert any("Calculator" in str(d) for d in definitions)
|
||||
@@ -65,12 +65,12 @@ class TestCSharpBasic:
|
||||
def test_find_references(self, csharp_ls: SolidLanguageServer):
|
||||
"""Test finding references to a symbol."""
|
||||
file_path = os.path.join("Program.cs")
|
||||
|
||||
|
||||
# Open the file first
|
||||
with csharp_ls.open_file(file_path):
|
||||
# Find references to the Add method (line 19)
|
||||
references = csharp_ls.request_references(file_path, 19, 20, include_declaration=True)
|
||||
|
||||
|
||||
# Should find at least the definition and one usage
|
||||
assert len(references) >= 2
|
||||
|
||||
@@ -78,17 +78,17 @@ class TestCSharpBasic:
|
||||
"""Test getting symbols from nested namespace."""
|
||||
file_path = os.path.join("Models", "Person.cs")
|
||||
symbols = csharp_ls.request_document_symbols(file_path)
|
||||
|
||||
|
||||
# Check that we have symbols
|
||||
assert len(symbols) > 0
|
||||
|
||||
|
||||
# Flatten the symbols if they're nested
|
||||
if isinstance(symbols[0], list):
|
||||
symbols = symbols[0]
|
||||
|
||||
|
||||
# Check that we have the Person class
|
||||
assert any(s.get("name") == "Person" and s.get("kind") == 5 for s in symbols)
|
||||
|
||||
|
||||
# Check for properties and methods
|
||||
symbol_names = [s.get("name") for s in symbols]
|
||||
assert "Name" in symbol_names
|
||||
|
||||
Reference in New Issue
Block a user