Skip to content

zls: rename_symbol silently omits edits in files that are not open (cross-file renames leave stale references) #1744

Description

@AmirF194

Preconditions:

  • I have made sure it's an actual issue, not a question (use GitHub Discussions instead).
  • I have consulted the user guide and verified that the issue cannot be resolved by adjusting configuration/following recommended workflows.
  • I have looked for similar issues and discussions, including closed ones.

Issue details:

  • I have provided a meaningful title and description.
  • I have explained how the issue arose and, where possible, added instructions on how to reproduce it.
  • I have added details on my setup: Serena version, MCP client, OS, the programming language(s), relevant configuration adjustments and project specifics.
  • If the issue relates to an application of Serena to an open-source project, I have added the link.

Summary

rename_symbol on a Zig project can silently return a WorkspaceEdit that is missing edits in files that reference the renamed symbol but are not currently open in ZLS. Serena applies the edit as-is and reports success with no indication that other files were skipped, leaving the project in a broken (non-compiling) state after a rename that reads as fully successful.

Setup

  • HEAD ac256f36 (main as of 2026-07-23)
  • Zig 0.14.1, ZLS 0.14.0 (versions pinned in .github/workflows/pytest.yml), run inside a python:3.11-slim Docker container, no live editor involved
  • Reproduced against the repo's own test fixture, test/resources/repos/zig/test_repo

Root cause

ZLS only reports rename edits for files it has open (same restriction already documented for textDocument/references in test/solidlsp/zig/test_zig_basic.py: "ZLS requires files to be open in the editor to find cross-file references (performance optimization)"). ZigLanguageServer (src/solidlsp/language_servers/zls.py) has no override for rename, so it falls through to the shared SolidLanguageServer.request_rename_symbol_edit (src/solidlsp/ls.py:3083-3107), which only opens the target file before calling textDocument/rename:

def request_rename_symbol_edit(self, relative_file_path, line, column, new_name):
    ...
    with self.open_file(relative_file_path):
        return self.server.send.rename(params)

It never opens the other files that reference the symbol, so ZLS's response covers only the target file. code_editor.py's rename_symbol then applies whatever edit comes back and reports success as long as num_changes > 0, with no check for whether all known references were covered.

This is the same defect shape as #1333 and #1348 (TypeScript/Vue rename silently skipping .vue files unless the companion server had already indexed them), both fixed by ensuring the relevant files are opened/indexed before the rename request is sent. ZLS was not covered by either fix.

Reproduction

Using the repo's own fixture, renaming isPrime (defined in src/math_utils.zig, used once in src/main.zig at math_utils.isPrime(17)), without opening main.zig first:

from test.conftest import start_default_ls_context
from solidlsp.ls_config import LanguageServerId

with start_default_ls_context(LanguageServerId.ZIG) as ls:
    with ls.open_file("src/math_utils.zig"):
        result = ls.request_rename_symbol_edit("src/math_utils.zig", 14, 9, "is_prime_check")
        print(list(result["changes"].keys()))

Output: only src/math_utils.zig is present in changes; src/main.zig, which contains a live call to isPrime, is absent. If this edit is applied via rename_symbol, main.zig still calls the now-nonexistent isPrime, and the project no longer compiles, with no warning from the tool.

For contrast, a same-file rename (target and all usages in one file, e.g. Calculator in calculator.zig, or factorial/isPrime's own in-file test usages) returns a complete edit, since the only file involved is already open. This also means the exact "no rename edits at all" symptom from #799 does not reproduce here: ZLS does return edits when it can see the symbol's file; the risk is a silently incomplete edit for symbols used outside the file being renamed. (I could not reproduce #799 itself with these pinned versions; the reporter there used ZLS 0.15.0, and I did not test that version.)

Expected behavior

A rename should either include edits for every known reference, or the tool should refuse / warn when it cannot guarantee full coverage, the same guarantee the fix for #1333 established for Vue/TypeScript.

Possible fix

Before calling request_rename_symbol_edit for Zig, open the files known to reference the symbol (via request_references) so ZLS includes them in the response, mirroring _ensure_vue_files_indexed_on_ts_server()'s role in the Vue fix. Whether that belongs in ZigLanguageServer specifically or as a general helper other single-process language servers with the same "only sees open files" restriction could reuse is a design call I'd rather leave to a maintainer; happy to open a PR once there's agreement on where it should live.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions