Skip to content

Find occurrences asynchronously in rename and change-signature - #598

Merged
bbatsov merged 1 commit into
masterfrom
async-find-symbol
Jul 12, 2026
Merged

bbatsov merged 1 commit into
masterfrom
async-find-symbol

Conversation

@bbatsov

@bbatsov bbatsov commented Jul 12, 2026

Copy link
Copy Markdown
Member

The big async conversion. cljr-rename-symbol and cljr-change-function-signature used to locate every occurrence with a blocking call that analyses the whole project - on a cold cache or a large project that freezes Emacs, sometimes for a long time.

They now use a new cljr--find-symbol-occurrences, built on the streaming cljr--find-symbol that cljr-find-usages already uses. It accumulates the occurrences and, when the search finishes, hands the full list to a callback. The command returns immediately; the rename (or the change-signature edit buffer) happens in the callback, so Emacs stays responsive during the analysis.

The callback is deferred out of the nREPL process filter (via a zero-delay timer) so it can safely prompt - the preview confirmation - and pop up buffers. It completes on the middleware's count message or the nREPL done status, surfaces a middleware error instead of letting it escape the filter, and has a generous safety-net timeout so a dead connection can't wedge it forever (10 min - deliberately not a deadline on legitimately slow analysis). Side effect: these commands now honor cljr-middleware-ignored-paths.

Drops the now-unused cljr--find-symbol-sync and cljr--end-of-buffer-p.

Validated live against a real refactor-nrepl connection: rename returned immediately, then previewed + applied across two files on confirm and left them untouched on decline; change-signature returned before its edit buffer existed, the deferred callback opened it, and commit swapped params across two files. Buttercup covers the collector (collection, dedup, error path, done-fallback). This is the highest-value async target from the audit - the remaining sync calls are point-acting or fast, so this is likely where the async work stops.

cljr-rename-symbol and cljr-change-function-signature located every
occurrence with the blocking cljr--find-symbol-sync, freezing Emacs while
the middleware analysed the whole project - which on a cold cache or a
large project could be a long time.

They now use a new cljr--find-symbol-occurrences, which wraps the existing
streaming cljr--find-symbol: it accumulates the occurrences (deduping by
file:line:col), and once the search finishes hands the full list to a
callback. The command returns immediately and the rename (or the
change-signature edit buffer) happens in the callback, so Emacs stays
responsive. The callback is deferred out of the nREPL process filter so it
can safely prompt (the preview confirmation) and pop up buffers; it
completes on the middleware's `count' message or the nREPL `done' status,
reports a middleware error rather than letting it escape the filter, and
has a generous safety-net timeout. As a side effect these commands now
honor cljr-middleware-ignored-paths.

Removes the now-unused cljr--find-symbol-sync and cljr--end-of-buffer-p.

Validated live against a real refactor-nrepl connection: rename returned
immediately, then previewed and applied across two files on confirm (left
them untouched on decline); change-signature returned before its edit
buffer existed, the deferred callback opened it, and commit swapped params
across two files.
@bbatsov
bbatsov merged commit af61112 into master Jul 12, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant