From e7b51173bccbdf52a747f3002203bfecd402643e Mon Sep 17 00:00:00 2001 From: TheSmallKiwi Date: Sat, 11 Apr 2026 19:57:25 -0400 Subject: [PATCH] HLSL: bump to shader-language-server v1.3.1, remove CRLF workaround The upstream fix for the CRLF stale-tree crash (antaalt/shader-sense#44) was merged and released as v1.3.1. This commit: - Removes the client-side CRLF workaround (open_file override and _preload_crlf_content helper) added in #1305, along with the now-unused imports. - Bumps _DEFAULT_VERSION to 1.3.1 and updates SHA-256 checksums for all three pre-built platform archives (win-x64, linux-x64, win-arm64). The regression test (test_include_file_document_symbols_directly) that exercises the original crash scenario passes against v1.3.1 without the workaround. Co-Authored-By: Claude Sonnet 4.6 --- docs/02-usage/050_configuration.md | 2 +- .../language_servers/hlsl_language_server.py | 99 +------------------ 2 files changed, 5 insertions(+), 96 deletions(-) diff --git a/docs/02-usage/050_configuration.md b/docs/02-usage/050_configuration.md index fe2b0d9e..060f0249 100644 --- a/docs/02-usage/050_configuration.md +++ b/docs/02-usage/050_configuration.md @@ -472,7 +472,7 @@ Supported settings: | Setting | Default | Description | |---|---|---| | `ls_path` | managed install or build | Override the `shader-language-server` executable path. | -| `version` | `1.3.0` | Override the bundled version Serena downloads, or builds from source on macOS, when `ls_path` is not set. | +| `version` | `1.3.1` | Override the bundled version Serena downloads, or builds from source on macOS, when `ls_path` is not set. | #### Haxe diff --git a/src/solidlsp/language_servers/hlsl_language_server.py b/src/solidlsp/language_servers/hlsl_language_server.py index 2857055b..b6eb7e05 100644 --- a/src/solidlsp/language_servers/hlsl_language_server.py +++ b/src/solidlsp/language_servers/hlsl_language_server.py @@ -7,9 +7,6 @@ import logging import os import pathlib import shutil -from collections.abc import Iterator -from contextlib import contextmanager -from pathlib import Path from typing import Any, cast import psutil @@ -18,11 +15,9 @@ from overrides import override from solidlsp.ls import ( LanguageServerDependencyProvider, LanguageServerDependencyProviderSinglePath, - LSPFileBuffer, SolidLanguageServer, ) from solidlsp.ls_config import LanguageServerConfig -from solidlsp.ls_exceptions import SolidLSPException from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams from solidlsp.settings import SolidLSPSettings @@ -31,13 +26,13 @@ from .common import RuntimeDependency, RuntimeDependencyCollection log = logging.getLogger(__name__) # GitHub release version to download when not installed locally -_DEFAULT_VERSION = "1.3.0" +_DEFAULT_VERSION = "1.3.1" _GITHUB_RELEASE_BASE = "https://github.com/antaalt/shader-sense/releases/download" _HLSL_ALLOWED_HOSTS = ("github.com", "release-assets.githubusercontent.com", "objects.githubusercontent.com") _HLSL_SHA256_BY_ASSET = { - "shader-language-server-x86_64-pc-windows-msvc.zip": "a945b000c296cdeebb9ee2d4452cec2a0f26544dd076bb08bfdcade2278296a6", - "shader-language-server-x86_64-unknown-linux-gnu.zip": "8c0a7b36f51cc58593762db3592ae13e21ca3cb982b2526cfaaf7c82e92ca089", - "shader-language-server-aarch64-pc-windows-msvc.zip": "cdbd7b41e71cf6040d5cdb7e211ba4b76671a404ee0f7add281d72d3ab8dfa65", + "shader-language-server-x86_64-pc-windows-msvc.zip": "49081c5547ddde1b8b3b17295282a80ddacbca1d6f5dcd834e2788c02bafa997", + "shader-language-server-x86_64-unknown-linux-gnu.zip": "61710df7ca17a2d063b598936c57c56c49fbf837707a1aa886f9b0193a35be3c", + "shader-language-server-aarch64-pc-windows-msvc.zip": "a3b3799affe2cad27652e788376b46fe76e1a6c2ce45946a486dcb26c9091412", } @@ -277,92 +272,6 @@ class HlslLanguageServer(SolidLanguageServer): log.debug(f"Error cleaning up shader-language-server process tree: {e}") super().stop(shutdown_timeout) - @contextmanager - def open_file(self, relative_file_path: str, open_in_ls: bool = True) -> Iterator[LSPFileBuffer]: - """Open a file for LSP, preserving on-disk CRLF line endings. - - Workaround for an upstream bug in shader-language-server - (antaalt/shader-sense) where `watch_main_file` replaces an already-cached - module's content without re-parsing the tree-sitter tree. When a file is - first pulled into the server's cache via an `#include` from another - shader (where it's read via `std::fs::read_to_string`, preserving CRLF), - and then later opened directly via `textDocument/didOpen` with the - client-normalized LF text, the stored tree still references byte offsets - into the longer CRLF content. The next symbol query slices the new - (shorter) content with stale offsets and panics with - `byte index N is out of bounds` in `shader-sense/src/symbols/symbol_parser.rs`. - - The root-cause fix belongs upstream (the server should call - `update_module` instead of assigning `content` raw). Until then, we - ensure the text we send in `didOpen` matches byte-for-byte what the - server reads from disk by preloading the file buffer with a - CRLF-preserving read before the LSP notification is sent. - - This is the only place in Serena that overrides `open_file`; the fix is - deliberately scoped to the HLSL language server. It mirrors the base - class logic in `SolidLanguageServer.open_file` verbatim except for the - buffer construction branch, where creation is deferred (`open_in_ls=False`) - so the buffer's contents can be preloaded before `ensure_open_in_ls` runs. - """ - if not self.server_started: - log.error("open_file called before Language Server started") - raise SolidLSPException("Language Server not started") - - absolute_file_path = Path(self.repository_root_path, relative_file_path) - uri = absolute_file_path.as_uri() - - if uri in self.open_file_buffers: - fb = self.open_file_buffers[uri] - assert fb.uri == uri - assert fb.ref_count >= 1 - - fb.ref_count += 1 - if open_in_ls: - fb.ensure_open_in_ls() - yield fb - fb.ref_count -= 1 - else: - version = 0 - language_id = self._get_language_id_for_file(relative_file_path) - # Defer the didOpen so we can preload CRLF-preserved content first. - fb = LSPFileBuffer( - abs_path=absolute_file_path, - uri=uri, - encoding=self._encoding, - version=version, - language_id=language_id, - ref_count=1, - language_server=self, - open_in_ls=False, - ) - self._preload_crlf_content(fb) - self.open_file_buffers[uri] = fb - if open_in_ls: - fb.ensure_open_in_ls() - yield fb - fb.ref_count -= 1 - - if self.open_file_buffers[uri].ref_count == 0: - self.open_file_buffers[uri].close() - del self.open_file_buffers[uri] - - def _preload_crlf_content(self, fb: LSPFileBuffer) -> None: - """Populate an LSPFileBuffer with a CRLF-preserving read of its backing file. - - Python's default text-mode open applies universal-newlines translation - (CRLF -> LF), which would desync the client's `didOpen` text from the - server-side `std::fs::read_to_string` view that parsed the dependency - tree. Passing `newline=""` disables the translation so bytes match. - """ - with open(fb.abs_path, encoding=fb.encoding, newline="") as f: - raw = f.read() - # Set the buffer's cached state directly: the contents, the mtime - # (required by the contents property's staleness check), and clear the - # hash so it's recomputed against the new bytes. - fb._contents = raw - fb._read_file_modified_date = fb.abs_path.stat().st_mtime - fb._content_hash = None - @override def is_ignored_dirname(self, dirname: str) -> bool: """Ignore Unity-specific directories that contain no user-authored shaders."""