False positive: unused-public-var with #(fn) and macroexpand hook
mrkam2 opened this issue · comments
Describe the bug
clojure-lsp/unused-public-var reports a function as unused when it is used in an anonymous function literal inside a macro configured with a hook.
a.clj
:
(ns a)
(defn my-fn [x] x)
(defmacro my-do [& body]
`(do ~@body))
(defn -main []
; Leaving only this line will trigger the unused public var message.
(my-do (map #(my-fn %) (range 10))))
To Reproduce
- Unzip issue.zip
- Run
clojure-lsp diagnostics
- See error
src/a.clj:3:7: info: [clojure-lsp/unused-public-var] Unused public var 'a/my-fn'
Expected behavior
No such error should be reported.
When either :analyze-call
hook is used, or #(my-fn %)
is replaced with (fn [x] (my-fn [x]))
, unused variable is not reported.
Thanks for the detailed repro @mrkam2, that happens because clj-kondo doesn't provide the var-definition when using the :macroexpand like you mentioned in the .clj-kondo/config.edn file, I can't see anything to do on clojure-lsp, we would need to make clj-kondo export that.
@borkdude could you try that zip project and confirm it's a desired behavior?
The var is available in the analysis but has a :derived-location
because #(...)
cannot be represented as an s-expression, so when going through macro-expansion the position is derived. Probably lsp ignores this usage, but that's not clj-kondo's issue.
Yeah, we ignore :derived-location otherwise we will cause a breaking change on custom hooks, this was implemented here, so not sure how to fix that in clojure-lsp without breaking custom hooks that was why we ignored derived-location
.
You don't need a location to know that a var is used, even if the var usage has a derived location.