lsp 2025-05-26

Hi 👋 I have some custom macros I use with re-frame, of which I'm getting some Unused public var ... . I've tried fixing it with hooks but is not working

The macro expands something like

(def-sub :hello/world [db] ...)
To
(do (defn hello_SLASH_world [db] ...)
    (re-frame.core/reg-sub :hello/world hello_SLASH_world))
And is working properly. I tried creating a hook which expands to the same thing
(defn def-sub* [ast]
  (let [[_macro-name node-name & more] (:children ast)
        defn-name-node (-> node-name
                           (as-symbol)
                           (munge2 "-sub")
                           (api/token-node))
        defn-ast (api/list-node
                  (list* (api/token-node 'defn)
                         defn-name-node
                         more))]
    (api/list-node
     (list (api/token-node 'do)
           defn-ast
           (api/list-node
            (list (api/token-node 're-frame.core/reg-sub)
                  node-name
                  defn-name-node))))))

(defn def-sub [ast]
  {:node (def-sub* (:node ast))})
And setting the proper clj-kondo config
{:hooks {:analyze-calls {common.macros/def-sub hooks.re-frame/def-sub}}}
But I'm still getting the Unused public var... message. I think the problem is that the linter doesn't search hello_SLASH_world in the (def-sub :hello/world [db] ...) code. I'm thinking that's a bug of the linter?

no linter expand macros, so you need to tell that it should ignore the unused-public-var from things defined by that, check https://clojure-lsp.io/settings/#clojure-lspunused-public-var, probably this should work: .clj-kondo/config.edn

{:linters {:clojure-lsp/unused-public-var {:exclude-when-defined-by #{your-ns/def-sub}}}}

(Keep in mind that doc is from master which now recomends to configure under .lsp/config.edn but latest release still looks at .clj-kondo/config.edn)

> no linter expand macros Right, that's why I wrote the cjl-kondo hook

I don't think you needed to write a hook since you can just use the one from re-frame

if the macro usage is the same

not sure, @borkdude can confirm as I'm not sure re-frame hook is built-in kondo or comes from library

:exclude-when-defined-by doesn't seem to work for this case 🤔

I'll see if I can find the re-frame definitions, thanks!

this is a really specific setting so there is a chance to not work for some specific case, if you could make a public repro where I can try, I can help further more

Eric 👋 here's the https://github.com/frankitox/macro-headache/tree/master. You should just open the src/main.clj file to see the linting message. These are the relevant files:

├── deps.edn
└── src
    ├── macros.clj
    └── main.clj
└── .clj-kondo
    ├── /hooks/macros.clj
    └── config.edn
I put a little https://github.com/frankitox/macro-headache/blob/master/src/macros.clj#L12-L16 on the macro, so you can see what I intend to do.

I found a fix by just telling clj-kondo to ignore that linter in that particular macro. Via this https://github.com/frankitox/macro-headache/commit/64e4c28caecc433866b08a21ff997784508ea674. 😃

👍 1