From 0abb8be85a69921ad45a59f9bf304d612931dfe3 Mon Sep 17 00:00:00 2001 From: Bingbing Zhang Date: Thu, 24 Jul 2025 18:10:53 +0100 Subject: [PATCH] Adds request_document_diagnostic to solidlsp (#347) --- src/solidlsp/ls.py | 47 ++++++++++++++++++- src/solidlsp/ls_types.py | 23 +++++++++ .../lsp_protocol_handler/lsp_constants.py | 6 +++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/solidlsp/ls.py b/src/solidlsp/ls.py index d68331b0..3c1de8a5 100644 --- a/src/solidlsp/ls.py +++ b/src/solidlsp/ls.py @@ -153,7 +153,7 @@ class SolidLanguageServer(ABC): ls = CSharpLanguageServer(config, logger, repository_root_path) elif config.code_language == Language.CSHARP_OMNISHARP: - from solidlsp.language_servers.omnisharp.omnisharp import OmniSharp + from solidlsp.language_servers.omnisharp import OmniSharp ls = OmniSharp(config, logger, repository_root_path) elif config.code_language == Language.TYPESCRIPT: @@ -709,6 +709,50 @@ class SolidLanguageServer(ABC): ret.append(ls_types.Location(**new_item)) return ret + + def request_text_document_diagnostics( + self, relative_file_path: str + ) -> list[ls_types.Diagnostic]: + """ + Raise a [textDocument/diagnostic](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_diagnostic) request to the Language Server + to find diagnostics for the given file. Wait for the response and return the result. + + :param relative_file_path: The relative path of the file to retrieve diagnostics for + + :return: A list of diagnostics for the file + """ + if not self.server_started: + self.logger.log( + "request_text_document_diagnostics called before Language Server started", + logging.ERROR, + ) + raise LanguageServerException("Language Server not started") + + with self.open_file(relative_file_path): + response = self.server.send.text_document_diagnostic( + { + LSPConstants.TEXT_DOCUMENT: { + LSPConstants.URI: pathlib.Path(str(PurePath(self.repository_root_path, relative_file_path))).as_uri() + } + } + ) + + if response is None: + return [] + + assert isinstance(response, dict), f"Unexpected response from Language Server (expected list, got {type(response)}): {response}" + ret: list[ls_types.Diagnostic] = [] + for item in response["items"]: + new_item: ls_types.Diagnostic = { + "uri": pathlib.Path(str(PurePath(self.repository_root_path, relative_file_path))).as_uri(), + "severity": item["severity"], + "message": item["message"], + "range": item["range"], + "code": item["code"] + } + ret.append(ls_types.Diagnostic(new_item)) + + return ret def retrieve_full_file_content(self, file_path: str) -> str: """ @@ -1533,6 +1577,7 @@ class SolidLanguageServer(ABC): defining_symbol = self.request_containing_symbol(def_path, def_line, def_col, strict=False, include_body=include_body) return defining_symbol + @property def cache_path(self) -> Path: diff --git a/src/solidlsp/ls_types.py b/src/solidlsp/ls_types.py index 3d4d4658..6c9a2385 100644 --- a/src/solidlsp/ls_types.py +++ b/src/solidlsp/ls_types.py @@ -317,3 +317,26 @@ class Hover(TypedDict): range: NotRequired[Range] """ An optional range inside the text document that is used to visualize the hover, e.g. by changing the background color. """ + +class DiagnosticsSeverity(IntEnum): + ERROR = 1 + WARNING = 2 + INFORMATION = 3 + HINT = 4 + + +class Diagnostic(TypedDict): + """Diagnostic information for a text document.""" + + uri: DocumentUri + """ The URI of the text document to which the diagnostics apply. """ + range: Range + """ The range of the text document to which the diagnostics apply. """ + severity: NotRequired[DiagnosticsSeverity] + """ The severity of the diagnostic. """ + message: str + """ The diagnostic message. """ + code: str + """ The code of the diagnostic. """ + source: NotRequired[str] + """ The source of the diagnostic, e.g. the name of the tool that produced it. """ diff --git a/src/solidlsp/lsp_protocol_handler/lsp_constants.py b/src/solidlsp/lsp_protocol_handler/lsp_constants.py index 329c0039..467237dc 100644 --- a/src/solidlsp/lsp_protocol_handler/lsp_constants.py +++ b/src/solidlsp/lsp_protocol_handler/lsp_constants.py @@ -61,3 +61,9 @@ class LSPConstants: # key used to represent the location in symbols LOCATION = "location" + + # Severity level of the diagnostic + SEVERITY = "severity" + + # The message of the diagnostic + MESSAGE = "message"