Skip to content

Conversation

@scottming
Copy link

@scottming scottming commented Jan 4, 2026

Context

While AI-assisted renaming is convenient, it's still slower than a native Language Server implementation. This PR ports the module rename feature from Lexical PR #636, which I've been using reliably for almost two years. Given that the Lexical repository is now archived, I wanted to bring this practical and well-tested feature to Expert.

Changes

Core Implementation (engine)

  • Add Engine.CodeMod.Rename module with submodules: Prepare, Module, Entry, File, and Diff
  • Add Engine.Commands.Rename GenServer for tracking rename progress and triggering reindex
  • Add Engine.Commands.RenameSupervisor for managing rename command lifecycle

LSP Integration (expert)

  • Add PrepareRename and Rename handlers for LSP protocol
  • Extend Expert.EngineApi with prepare_rename/3 and rename/5 APIs
  • Register rename_provider with prepare_provider: true in server capabilities

Infrastructure (forge)

  • Add RenameFile struct to Forge.Document.Changes for file rename operations
  • Add file_changed and file_saved message types to Forge.EngineApi.Messages

Key Differences from Lexical

  • Uses :erpc.call via Expert.EngineApi.call/4 instead of RemoteControl.call
  • Added reindexing mechanism after rename to keep search index consistent (see "Why These Changes")
  • Namespace mapping: Lexical.RemoteControl.*Engine.*, Lexical.Server.*Expert.*

Why These Changes

  • Progress tracking & reindex (59953157): Without reindexing after rename, the search index retains old module names. This causes subsequent renames to fail - e.g., renaming AccountsAccounts2 works, but renaming back fails because the index doesn't reflect the new names.

  • Temporary document opening (f08fd155): After a file rename, the new URI may not exist in Document.Store, causing "not_open" errors during reindex. Added ensure_open/1 to temporarily open files from disk when needed.

  • Expanded test coverage (a38652ef): Added comprehensive tests covering references, descendants, structs, edge cases, and file renaming with realistic module names.

Extra

A demo video is attached showing the smooth rename workflow - renaming a module and then renaming it back. Tested successfully in both VSCode and Neovim.

CleanShot.2026-01-04.at.15.43.19.mp4

- engine: add CodeMod.Rename module for module renaming with file rename support
- expert: add prepareRename and rename LSP handlers
- forge: extend Document.Changes to support RenameFile operations
- Refactor test descriptions to be concise
- Replace generic Foo/Bar/Baz with domain names (Users, Accounts, etc.)
- Add tests for references, descendants, structs, edge cases, and file renaming
Without reindexing after a rename operation, the search index still
contains old module names. This causes subsequent renames to fail -
e.g., renaming `Dummy.Accounts` to `Dummy.Accounts2` works, but renaming
back to `Dummy.Accounts` fails to update `Dummy.Accounts2.User` because
the index doesn't know about the new module names.

Add Commands.Rename GenServer to track file_changed/file_saved events
and trigger reindexing once all rename operations complete.
…name

After a file rename, the new file URI may not be open in Document.Store
when reindexing is triggered. This caused "not_open" errors and the
index was never updated, breaking references and go-to-definition for
renamed modules.

Add ensure_open/1 to temporarily open the file from disk if needed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant