clj-kondo

julienvincent 2025-12-18T13:35:11.036349Z

I have a question about unused vars warnings from custom clj-kondo hooks. Specifically I am struggling with clojure-lsp reporting unused vars from a macro hook I am writing:

(defn test-unused [{:keys [node]}]
  {:node (vary-meta
          (api/list-node [(api/token-node 'do)
                          (api/list-node [(api/token-node 'def)
                                          (api/token-node 'SomethingUnused)
                                          (api/token-node nil)])])
          assoc :clj-kondo/ignore [:unused-binding
                                   :clojure-lsp/unused-public-var])})
Here is a custom hook which reports that a (def SomethingUnused nil) def is created. But I want to silence the unused var warning I get. This doesn't seem to work, resulting in the following warning:
Diagnostics:
1. Unused public var 'io.julienvincent.kondo-test/SomethingUnused' [clojure-lsp/unused-public-var]
Anyone know how I can get this to work?

✅ 1
borkdude 2025-12-18T13:37:02.348199Z

the clojure-lsp linting rule is outside of the control of clj-kondo

borkdude 2025-12-18T13:37:31.034099Z

perhaps you can just generate a fake usage instead

julienvincent 2025-12-18T13:37:35.490779Z

But.. isn't is using clj-kondo to power it?

borkdude 2025-12-18T13:38:31.049519Z

yes, but clojure-lsp doesn't know anything about the :clj-kondo/ignore thing you add to the do expression

julienvincent 2025-12-18T13:38:32.396559Z

Yea I tried that too:

(defn test-unused [{:keys [node]}]
  {:node (vary-meta
          (api/list-node [(api/token-node 'do)
                          (api/list-node [(api/token-node 'def)
                                          (api/token-node 'SomethingUnused)
                                          (api/token-node nil)])
                          (api/token-node 'SomethingUnused)])

          assoc :clj-kondo/ignore [:unused-binding
                                   :clojure-lsp/unused-public-var])})
It didn't work

borkdude 2025-12-18T13:39:18.578009Z

well, that should work I think. let's see.

julienvincent 2025-12-18T13:39:59.912279Z

> yes, but clojure-lsp doesn't know anything about the :clj-kondo/ignore thing you add to the do expression Hmm but this works normally?

#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
(def thing nil)
How does that mechanism work then? Did clojure-lsp re-implement this or something?

julienvincent 2025-12-18T13:40:33.386569Z

I guess I don't know how this all glues together then haha

borkdude 2025-12-18T13:41:08.893259Z

that's a good question, I forgot that that example worked. FWIW, I don't use clojure-lsp unused public var myself

borkdude 2025-12-18T13:41:32.699019Z

let's quickly look at how those ignores are communicated to clojure-lsp

❤️ 1
julienvincent 2025-12-18T13:43:29.498759Z

> FWIW, I don't use clojure-lsp unused public var myself I.e you're turning it off somehow and using clj-kondos native ones instead? I'm trying to make a public lib and don't want people to have to do that ideally for this use-case

borkdude 2025-12-18T13:44:09.344019Z

I understand. @ericdallo do you remember how this works?

ericdallo 2025-12-18T13:49:32.848169Z

clojure-lsp had to re-implement this logic https://github.com/clojure-lsp/clojure-lsp/blob/f555e4b89a1a3aa8aa9f66809f0d5e4dc034c61d/lib/src/clojure_lsp/feature/diagnostics/built_in.clj#L38, but

#_{:clojure-lsp/ignore [:clojure-lsp/unused-public-var]}
;; or 
#_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]}
should work

ericdallo 2025-12-18T13:50:25.411199Z

let me test

borkdude 2025-12-18T13:51:09.534229Z

ah ok. so clojure-lsp is looking for a literal uneval there. adding it via metadata on a hook doesn't work in this case then.

borkdude 2025-12-18T13:51:33.878409Z

but emitting the extra usage should work

borkdude 2025-12-18T13:52:27.540059Z

possibly it's ignored by clojure-lsp since it doesn't have location metadata or so

julienvincent 2025-12-18T13:53:09.988209Z

Is that something that can be added in the hook?

borkdude 2025-12-18T13:53:54.442639Z

you could copy it from another node

borkdude 2025-12-18T13:54:15.846039Z

e.g. from the top level node

borkdude 2025-12-18T13:54:31.851959Z

(with-meta (api/token-node 'Something) (meta node))

borkdude 2025-12-18T13:55:10.389249Z

if that works, it will pop up as a reference in lsp too

julienvincent 2025-12-18T13:56:24.228979Z

trying

julienvincent 2025-12-18T13:56:58.278839Z

Works!

🎉 1
julienvincent 2025-12-18T13:57:17.318699Z

Amazing, thanks

borkdude 2025-12-18T13:57:33.131939Z

👍