I'm trying to write a hook for a macro I wrote that is "function like". I'm not succeeding ๐ Details in ๐งต
I figured out how to reproduce it at least! If the macro is defined in a cljc file, it stops working consistently for me: https://github.com/cjohansen/kondo-macro-woe
what if you add to this:
(:require-macros [mylib.core])
:refer [defthing]?I thought that is how it works normally in CLJS
and then wrap the macro in a :clj reader conditional
to avoid adding a macro like thing at runtime in CLJS
I'm not an expert in this, but I do have :require-macros in mylib.core, and this all compiles and runs as expected.
can you try it though?
I think this is what clj-kondo might expect
To put that in the test namespace?
no in the macro namespace
I think I'm misunderstanding, because it's already there? https://github.com/cjohansen/kondo-macro-woe/blob/main/src/mylib/core.cljc
(ns mylib.core
#?(:cljs (:require-macros [mylib.core :refer [defthing]])))ah, add refer
Still fails
ok, I'm afk most of today, I'll take a look when I can
Sure, no hurry
What's interesting to me is that it even fails usage/linting in a clj file. It seems to be related to the macro coming from a cljc file. If I rename the core file to core.clj, test.clj lints as expected.
yeah it might be a cljc + inline config related bug
I have a macro in src/myproject/api.clj that, in use, looks like this:
(defthing some-name [args]
,,,)
I want clj-kondo to recognize this as defining a var some-name in the current namespace, and to evaluate the body with the argument bindings available.
There is src/no.cjohansen/myproject/config.edn with:
{:linters {:myproject/api {:level :warning}}
:hooks {:analyze-call {myproject.api/defthing myproject.defs/defthing}}}
There is also src/no.cjohansen/myproject/defs.clj with:
(ns nexus.defs
(:require [clj-kondo.hooks-api :as api]))
(defn- extract-docstr
[[docstr? & forms :as remaining-forms]]
(if (api/string-node? docstr?)
[docstr? forms]
[(api/string-node "no docs") remaining-forms]))
(defn defthing [{:keys [node]}]
(let [[fname & forms] (rest (:children node))
[docstr [attr-map & body]] (extract-docstr forms)]
{:node
(api/list-node
(list*
(api/token-node 'defn)
fname
docstr
attr-map
body))}))
I then have this test code:
(require '[clj-kondo.core :as clj-kondo])
(defn get-findings [code]
(:findings
(with-in-str
(str
'(require '[myproject.api :as myp])
code)
(clj-kondo.core/run! {:lint ["-"]}))))
(def code
'(myp/defthing doit [a b]
))
(get-findings code)
And it returns all the warnings - unused binding doit etc. What am I missing? I copied everything from replicant, where things are working ๐คis the syntax the same as clojure.core/defn?
Yes
you could just do this:
{:lint-as {your.macro-ns/macro clojure.core/defn}}hah
Can I put that as meta data on the macro itself? This is for a library.
yeah, in your lib:
(defmacro defthing
{:clj-kondo/lint-as 'clojure.core/defn}
[...] ...)
(let me double check if that is correct)
yeah this should work: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#inline-macro-configuration
That seems way easier. Wondering why I've opted for this complicated solution in Replicant ๐
Perhaps there are subtle syntax changes between your macro and defn
else why would you first extract docstring etc and then pass it on to defn
you might as well could pass the whole body to clojure.core/defn straightaway
I couldn't tell you - I don't remember why I wrote it the way I did ๐
if your test suite lints correctly using this config, I'd say you should be fine ;)
you do need to lint the macro ns first before the config takes effect
but in a normal clj-kondo workflow you first lint your dependencies, which is where this configuration is detected
I mainly use clj-kondo via lsp, not sure what it does
via lsp that's the same
it automatically does it
So now I have it partially working. Code evaluates, and go-to definition works, but lsp is still throwing squigglies ๐ค
can you restart the lsp server to double check and then make a screenshot?
Squigglies are unresolved symbols
could it be that you have another clj-kondo thing running in your emacs, e.g. flycheck-clj-kondo with an old clj-kondo version?
best to try it on the command line and see what it spits out
along with clj-kondo --version
clj-kondo --version clj-kondo v2025.01.16 Ancient, by your tempo, I would assume ๐
that sounds ok, do you see the same on the command line, warnings?
Yeah, same warnings
Same with 2025.06.05
do you have a .clj-kondo directory in the root of your project?
I do
good
would you mind makeing a github repro of this that I could clone locally? I'll take a look either tomorrow or monday
Sure!
do you perhaps still have the old hook activated?
Could be?
Or not really, I made a new macro to test now
I'm trying it in a fresh repo, that'll answer it
I'm trying in a scratch buffer. Before:
Well, that didn't work ๐
After:
yeah, I also got it working in a blank project
I'll try to clean up my other project a little then
WTF. I cleared out both .clj-kondo, .lsp and src/no.cjohansen and it's still failing ๐คฏ
you could also zip your project and give it to me, so I can see it happening here perhaps
if it's open source
It's about to be ๐
Thanks for your kind support! I will have one more look at this with a fresh eye tomorrow, and if I still can't figure it out I'll take you up on your offer and send you the code ๐
sure, I'm going to ๐ค now too!
if all else fails you could always not use the inline config but a {:lint-as {...}} thing in a config file
The inline config seems to me to be the ideal solution. And it worked in a fresh directory, so I must be doing something stupid.
you can check your .clj-kondo directory for inline configs
either directly in it or inside imports (not sure)
there are some in imports, but not for the afflicted namespace
there should be, else it's not going to work
$ ls .clj-kondo/inline-configs
scratch.clj$ cat .clj-kondo/inline-configs/scratch.clj/config.edn
{:lint-as #:scratch{my-defn clojure.core/defn}}%something like that should appear but for your macro file
afk now
Thanks for the help so far! Sleep well ๐
Sorry, I forgot all about this due to other stuff coming up. Would you mind filing a github issue and meanwhile probably it's best to use a config file rather than an inline config
until I find out what's the issue
No worries ๐ I'll file an issue, but the good news is that I've ditched the idea of this specific macro ๐
heheh