Skip to content

Unnecessary refreshing / incorrect application of dynamic font-lock  #3345

@yuhan0

Description

@yuhan0

Expected behavior

Cider precompiles font lock keywords per buffer for dynamic highlighting of the macros / deprecated / instrumented vars etc. in scope.

This can be an expensive operation, and should be recomputed at minimum when the buffer's namespace or its requires have changed, and perhaps even delayed when the buffer is not visible.

Dynamic font lock should not apply to any config files like project.clj, edn files, and various other background temp buffers.

Actual behavior

After certain commands (jack-in, eval, load-file), cider-refresh-dynamic-font-lock gets called indiscrimately on background buffers that do not require refreshing. With large numbers of clojure-mode buffers open in the background, this leads to periods of Emacs freezing up.

The main causes are

Since clojure.core is a universally referred ns, an initial connection will trigger a simultaneous refresh in all background buffers. Subsequent evals may also cause refreshes in buffers in unrelated connections that share dependencies with overlapping ns names. This manifests as regular eval commands periodically freezing up for a few seconds for no apparent reason, and then behaving normally afterwards.

The user ns is especially affected, since it is the default for *cider-repl* connection buffers. The use of (cider-current-ns) also causes config files like deps.edn / project.clj to be reported as user, this causes vars from the user ns to be incorrectly font-locked in these contexts.

Steps to reproduce the problem

;; the default config:
(setq cider-font-lock-dynamically '(macro core deprecated)) 

Open hundreds of .clj files in project A with a connected REPL, then switch to project B and jack into it from a single file buffer.

There should be a noticeable period of the interface freezing up after the new REPL appears and begins its initialization, refreshing the font-lock in all the background project A buffers.


In the *cider-repl* buffer, enter

user> (def ^:deprecated oops)
;; => #'user/oops

Navigate to a deps.edn / project.clj in either project A or B, and observe that the symbol oops is incorrectly highlighted with cider-deprecated-face.

Environment & Version information

CIDER version information

;; CIDER 1.7.0 (Côte d'Azur), nREPL 1.0.0
;; Clojure 1.11.1, Java 20

Lein / Clojure CLI version

Clojure CLI version 1.11.1.1273

Emacs version

GNU Emacs 29.0.90

Operating system

macOS 12.5.1

JDK distribution

Temurin jdk-20.0.1+9

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions