From a5071d776ba8d2d46df3b653e197006a3531dca9 Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Thu, 20 Nov 2025 14:09:10 +0700 Subject: [PATCH] Fix type errors and actual errors in ALLanguageServer Actual errors: timeout kwarg passed to send_request (no such kwarg exists in the method) --- .../language_servers/al_language_server.py | 72 ++++++++++--------- src/solidlsp/lsp_protocol_handler/server.py | 2 +- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/src/solidlsp/language_servers/al_language_server.py b/src/solidlsp/language_servers/al_language_server.py index 6dade714..d941d7a3 100644 --- a/src/solidlsp/language_servers/al_language_server.py +++ b/src/solidlsp/language_servers/al_language_server.py @@ -1,4 +1,3 @@ -# type: ignore """AL Language Server implementation for Microsoft Dynamics 365 Business Central.""" import logging @@ -9,6 +8,7 @@ import stat import time import zipfile from pathlib import Path +from typing import cast import requests from overrides import override @@ -17,6 +17,7 @@ from solidlsp.language_servers.common import quote_windows_path from solidlsp.ls import SolidLanguageServer from solidlsp.ls_config import LanguageServerConfig from solidlsp.ls_logger import LanguageServerLogger +from solidlsp.ls_types import UnifiedSymbolInformation from solidlsp.lsp_protocol_handler.lsp_types import Definition, DefinitionParams, LocationLink from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo from solidlsp.settings import SolidLSPSettings @@ -486,7 +487,7 @@ class ALLanguageServer(SolidLanguageServer): return initialize_params @override - def _start_server(self): + def _start_server(self) -> None: """ Starts the AL Language Server process and initializes it. @@ -496,19 +497,19 @@ class ALLanguageServer(SolidLanguageServer): """ # Set up event handlers - def do_nothing(params): + def do_nothing(params: str) -> None: return - def window_log_message(msg): + def window_log_message(msg: str) -> None: self.logger.log(f"AL LSP: window/logMessage: {msg}", logging.INFO) - def publish_diagnostics(params): + def publish_diagnostics(params: dict) -> None: # AL server publishes diagnostics during initialization uri = params.get("uri", "") diagnostics = params.get("diagnostics", []) self.logger.log(f"AL LSP: Diagnostics for {uri}: {len(diagnostics)} issues", logging.DEBUG) - def handle_al_notifications(params): + def handle_al_notifications(params: dict) -> None: # AL server sends custom notifications during project loading self.logger.log("AL LSP: Notification received", logging.DEBUG) @@ -636,8 +637,8 @@ class ALLanguageServer(SolidLanguageServer): "workspacePath": self.repository_root_path, "setActiveWorkspace": True, }, + "timeout": 2, # Quick timeout since this is optional }, - timeout=2, # Quick timeout since this is optional ) self.logger.log(f"Set active workspace result: {result}", logging.DEBUG) except Exception as e: @@ -681,7 +682,7 @@ class ALLanguageServer(SolidLanguageServer): return super().is_ignored_dirname(dirname) or dirname in al_ignore_dirs @override - def request_full_symbol_tree(self, within_relative_path: str | None = None) -> list[dict]: + def request_full_symbol_tree(self, within_relative_path: str | None = None) -> list[UnifiedSymbolInformation]: """ Override to handle AL's requirement of opening files before requesting symbols. @@ -750,7 +751,7 @@ class ALLanguageServer(SolidLanguageServer): return [] # Collect all symbols from all files - all_file_symbols = [] + all_file_symbols: list[UnifiedSymbolInformation] = [] for file_path, relative_path in al_files: try: @@ -760,32 +761,38 @@ class ALLanguageServer(SolidLanguageServer): if root_syms: # Create a file-level symbol containing the document symbols - file_symbol = { - "name": file_path.stem, # Just the filename without extension - "kind": 1, # File - "children": root_syms, - "location": { - "uri": file_path.as_uri(), - "relativePath": relative_path, - "absolutePath": str(file_path), - "range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 0}}, + file_symbol = cast( + UnifiedSymbolInformation, + { + "name": file_path.stem, # Just the filename without extension + "kind": 1, # File + "children": root_syms, + "location": { + "uri": file_path.as_uri(), + "relativePath": relative_path, + "absolutePath": str(file_path), + "range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 0}}, + }, }, - } + ) all_file_symbols.append(file_symbol) self.logger.log(f"AL: Added {len(root_syms)} symbols from {relative_path}", logging.DEBUG) elif all_syms: # If we only got all_syms but not root, use all_syms - file_symbol = { - "name": file_path.stem, - "kind": 1, # File - "children": all_syms, - "location": { - "uri": file_path.as_uri(), - "relativePath": relative_path, - "absolutePath": str(file_path), - "range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 0}}, + file_symbol = cast( + UnifiedSymbolInformation, + { + "name": file_path.stem, + "kind": 1, # File + "children": all_syms, + "location": { + "uri": file_path.as_uri(), + "relativePath": relative_path, + "absolutePath": str(file_path), + "range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 0}}, + }, }, - } + ) all_file_symbols.append(file_symbol) self.logger.log(f"AL: Added {len(all_syms)} symbols from {relative_path}", logging.DEBUG) @@ -796,10 +803,11 @@ class ALLanguageServer(SolidLanguageServer): self.logger.log(f"AL: Returning symbols from {len(all_file_symbols)} files", logging.DEBUG) # Group files by directory - directory_structure = {} + directory_structure: dict[str, list] = {} for file_symbol in all_file_symbols: rel_path = file_symbol["location"]["relativePath"] + assert rel_path is not None path_parts = rel_path.split("/") if len(path_parts) > 1: @@ -861,7 +869,7 @@ class ALLanguageServer(SolidLanguageServer): # Use custom AL command instead of standard LSP response = self.server.send_request("al/gotodefinition", al_params) self.logger.log(f"AL gotodefinition response: {response}", logging.DEBUG) - return response + return response # type: ignore[return-value] except Exception as e: self.logger.log(f"Failed to use al/gotodefinition, falling back to standard: {e}", logging.WARNING) # Fallback to standard LSP method if custom command fails @@ -890,7 +898,7 @@ class ALLanguageServer(SolidLanguageServer): try: # Use a very short timeout since this is just a status check - response = self.server.send_request("al/hasProjectClosureLoadedRequest", {}, timeout=1) + response = self.server.send_request("al/hasProjectClosureLoadedRequest", {"timeout": 1}) # Response can be boolean directly, dict with 'loaded' field, or None if isinstance(response, bool): return response diff --git a/src/solidlsp/lsp_protocol_handler/server.py b/src/solidlsp/lsp_protocol_handler/server.py index 3cdb2fea..219135b7 100644 --- a/src/solidlsp/lsp_protocol_handler/server.py +++ b/src/solidlsp/lsp_protocol_handler/server.py @@ -37,7 +37,7 @@ from typing import Any, Union from .lsp_types import ErrorCodes StringDict = dict[str, Any] -PayloadLike = Union[list[StringDict], StringDict, None] +PayloadLike = Union[list[StringDict], StringDict, None, bool] CONTENT_LENGTH = "Content-Length: " ENCODING = "utf-8" log = logging.getLogger(__name__)