clojure-emacs / cider

The Clojure Interactive Development Environment that Rocks for Emacs
https://cider.mx
GNU General Public License v3.0
3.52k stars 643 forks source link

`cider-locals` - false positives #3657

Open vemv opened 2 months ago

vemv commented 2 months ago

For the following input:

(def foo-routes
  [["/foos"
    {:get {:handler (fn [{{{:keys [archived]} :query} :parameters
                          :keys [sub]
                          :as req}]
                      {:pre [sub]}
                      (let [foo (reduce + (range 4))]
                        {:status 200}))}}]])

...if I hover over range and M-x describe-char, I'll get:

There are text properties here:
  cider-locals         ("200" "4" "range" "+" "reduce" "foos" "let" "sub" "req" "sub" "archived" "fn" "/foos" "req" "sub" "archived" "collections")
  fontified            t

A lot of those aren't locals (e.g. number/string literals, function names).

This happens because of the def x [[ format, which the cider-locals code isn't prepared for.

As a consequence, there can be subtle bugs with font locking.

vemv commented 2 months ago

@bbatsov: wondering if this cider-locals code (which presumably will never be perfect - hard problem to tackle with Elisp) could be replaced with a simpler approach, namely regarding any symbol that doesn't belong to the namespace interns (defs, refers, imports) as a local.

(this can be queried instantly as there's a per-ns cache with that data)

There's the case of var shadowing, but these days local shadowing is less common and there are kondo/etc linters that guard against it.

The worst case is that we sometimes font-lock slightly badly for code that shadows vars, but that bug can also be considered a feature (as it nudges people to do the right thing if they want pretty highlighting).

As a bonus, by not running cider-locals code constantly as the user types stuff, there should be a slight performance/reliability improvement.

vemv commented 2 months ago

Hammocking it a bit, a very easy change for now would be to introduce a defcustom controlling

https://github.com/clojure-emacs/cider/blob/176a8e748540705b9229870be1ebe8a77f756966/cider-mode.el#L777-L782

i.e. optionally make it a no-op.

I wouldn't change the default behavior and simply document in the manual when/how to change this.

bbatsov commented 2 months ago

@bbatsov: wondering if this cider-locals code (which presumably will never be perfect - hard problem to tackle with Elisp) could be replaced with a simpler approach, namely regarding any symbol that doesn't belong to the namespace interns (defs, refers, imports) as a local.

Yeah, I guess that's not a bad idea, although it might highlight as locals misspelled names. Not a big deal in the end, though.

The idea with the defcustom is a good one IMO, as it will also make it possible to disable this completely if someone runs into problems.

vemv commented 2 months ago

Yeah, I guess that's not a bad idea, although it might highlight as locals misspelled names. Not a big deal in the end, though.

Yes, it might also be the case that clj-kondo indicates a non-resolved var as a "squiggly", anyway.

The idea with the defcustom is a good one IMO, as it will also make it possible to disable this completely if someone runs into problems.

Nice, I'll bundle this as part of https://github.com/clojure-emacs/cider/pull/3646 .

(when time allows - still running tight in terms of availability)