clj-kondo

2025-07-01T13:34:40.801759Z

i'm writing a complex hook for #splint's patterns, and i need to postwalk the clj-kondo nodes. has anyone written a postwalk for clj-kondo nodes?

✅ 1
borkdude 2025-07-01T13:38:15.192809Z

Are you writing a hook for a macro in splint or ..?

2025-07-01T13:38:22.230769Z

yes

borkdude 2025-07-01T13:38:51.132899Z

maybe it's easier to use :macroexpand hook so you can use normal postwalk? it's not as accurate but a lot easier

2025-07-01T13:39:23.110769Z

well, i don't want to macroexpand, i want to call api/reg-finding! for mistakes

2025-07-01T13:39:32.397489Z

the macroexpansion would be......... very big

borkdude 2025-07-01T13:39:54.137239Z

I see. do you have an example perhaps, so I can better understand your use case?

2025-07-01T13:39:59.395109Z

sure

2025-07-01T13:40:53.742979Z

(defrule performance/into-transducer
  "..."
  {:pattern '(into [] ((? trans transducers) ?f ?coll))
   ...}

borkdude 2025-07-01T13:42:24.453389Z

and what is an example of a finding you want to catch?

2025-07-01T13:42:38.138259Z

:pattern doesn't need to be quoted but i do quote it because that stops clj-kondo for yelling. i'd like to lint it.

2025-07-01T13:42:54.900499Z

one sec while i write an example

borkdude 2025-07-01T13:43:00.660669Z

since it's a macro you can also do the check in your macro :)

borkdude 2025-07-01T13:43:11.108479Z

but why do you need postwalk for this?

2025-07-01T13:43:24.222599Z

oh i do, i throw lots of errors, but i use clj-kondo and want the faster linting as well

borkdude 2025-07-01T13:44:02.598109Z

yes understood, why not both

2025-07-01T13:49:33.678949Z

the :pattern is like a sexpr regex, where it matches literal forms in the given shape, except for symbols that start with ? (like ?coll), or lists that start with ? (like (? trans transducers)). the symbols are just captures which are stored in a context map, but the lists have special rules about them

2025-07-01T13:50:54.548989Z

(? trans transducers) binds x to ?trans if it matches the predicate (transducers x) , so it requires transducers to exist.

borkdude 2025-07-01T13:51:30.585979Z

ok, so it's more than just the quote, right

borkdude 2025-07-01T13:51:36.732289Z

that you want to lint

2025-07-01T13:53:01.013989Z

right, i need to walk the form and find the lists that start with ? (or other special forms i won't get into), and then check if they're broken in some way lol

borkdude 2025-07-01T13:56:34.257569Z

What I meant with the :macroexpand hook is that this may be way easier to implement. :macroexpand isn't just about macroexpansion, you can still return nil and call findings/reg-finding!

borkdude 2025-07-01T13:56:40.057699Z

but you get to operate on normal s-expressions

2025-07-01T13:56:57.278839Z

and it all carries metadata?

borkdude 2025-07-01T13:57:11.347259Z

in sofar possible. numbers can't carry metadata but symbols will

👍 1
2025-07-01T14:52:22.292489Z

(defn walk
  [inner outer form]
  (cond
    (:children form) (outer (assoc form :children (mapv inner (:children form))))
    :else (outer form)))

(defn postwalk
  [f form]
  (walk #(postwalk f %) f form))
did what i need it to do lol

2025-07-01T14:52:32.683609Z

much simpler than clojure.walk's impl

borkdude 2025-07-01T14:55:10.626429Z

nice :)

borkdude 2025-07-01T14:55:58.204739Z

I think this might mess up some nodes that don't have a :tag keyword on them but implement the protocol in a different way

borkdude 2025-07-01T14:56:14.975029Z

but I'm not sure about that

2025-07-01T14:56:21.314079Z

good to know

2025-07-01T14:56:53.064489Z

i'm merely using this as a way to step through the whole thing, i return the original object each time

borkdude 2025-07-01T14:57:08.869549Z

ah then it's ok for sure

👍 1
2025-07-01T14:57:26.099329Z

(postwalk (fn [obj] (...) obj) node)

2025-07-01T14:56:08.776289Z

i have a bunch of s/def specs for a macro i have, which validates things like "is this a number?" and "either pattern OR patterns but not both". is it possible to get clj-kondo to use the specs to check my macro without writing a hook?

✅ 1
borkdude 2025-07-01T14:59:23.472569Z

unfortunately not since specs usually aren't very static in nature

👍 1