Fork me on GitHub

I see a warning thrown for completely normal spec

echo '(ns user (:require [foo.common :as common] [clojure.spec.alpha :as s])) (s/def ::x (s/keys :req-un [::common/x]))' | clj-kondo --lint -
<stdin>:1:21: warning: namespace foo.common is required but never used
linting took 21ms, errors: 0, warnings: 1
I think it happens because s/def expands to something like that:
... :req-specs '[:foo.common/x] ...


this is a bug introduced by a new feature which has already been fixed on master


I can make a new release since this is annoying


but maybe I'll wait a day in case there are any other regressions


I can wait until next release ) thanks!


if there will be a third person reporting this, I'll make a release ;)


you were the second


)) reasonable enough


@borkdude third person here

😅 3


🙌 3

confirmed the lint runs good in the latest version 👍

🎉 3
Joshua Suskalo16:06:25

Hey, I'm playing around with hooks in another project and it seems like they're just not getting run at all. As far as I can tell the only difference is that I've got them directly in the .clj-kondo directory rather than inside an exports section. I'm using the binary release on the AUR from today. Is there anything I have to do to make sure it actually tries to run it?


@suskeyhose It depends on your config. What do you have in {:hooks {:analyze-call ...}}

Joshua Suskalo16:06:46

{:hooks {:analyze-call {noah.transformer/deftransformer hooks.noah/deftransformer}}}

Joshua Suskalo16:06:06

then in that directory there's a hooks directory with the noah.clj file in it which has a deftransformer function

Joshua Suskalo16:06:49

(this is working on adding hooks to the noah library, which is a clojure wrapper for kafka streams)


do you have a file in a directory noah/transformer.clj in the local .clj-kondo dir?


sorry, my bad, hooks/noah.clj

Joshua Suskalo16:06:36

it's where the hook function is


can you make some deliberate typos in this file to see if it crashes or something


or add some printlns


and call it from the command line

Joshua Suskalo16:06:10

I have a println at the top of it before I do any code


stick the println inside your function

Joshua Suskalo16:06:34

Yup, that's where it is

Joshua Suskalo16:06:45

(defn deftransformer
  [{:keys [node]}]
  (println "Being run!")
  (let [[name & more] (rest (:children node))
        [_docstring store-names & more]
        (if (api/string-node? (first more))


do you have a ns form at the top?

Joshua Suskalo16:06:16

I was observing similar behavior when I was working on farolero, except I could fix it by swapping the key in the analyze-call map for one that used a . rather than a fully-qualified symbol, like farolero.core.restart-case instead of farolero.core/restart-case, but this doesn't fix the issue here.


well, you're welcome to make a small repro

Joshua Suskalo16:06:45

The difference between this one and that one was that in that one I was doing --copy-config on every call to get it out of the resources directory

Joshua Suskalo16:06:51

Alright, I'll try for it

Joshua Suskalo16:06:52

Honestly since everything that I'm actually working on is OSS I can just extract it from the containing repo and it should work the same

Joshua Suskalo16:06:40

Dang it, I move it over to a small reproduction case and it runs.

Joshua Suskalo16:06:32

At least this gives me a chance to debug the hook and make it work right, then I can try and figure out why it wasn't being run in the bigger project.

Joshua Suskalo16:06:24

What am I supposed to use for a map node in the resulting code?


often just (token-node nil) works


So far I haven't seen a single case where hooks should actually create a map. In the future this might be possible, but the API doesn't allow it right now because the API in rewrite-clj around this wasn't very stable yet

Joshua Suskalo17:06:11

Is there any way that I can suppress unused-symbols for particular symbols in sections of code produced by a hook?

Joshua Suskalo17:06:09

Like there's some code that's got an unhygenic macro, so there's some let blocks that have symbols that may or may not be used in the body, and I don't want it to emit warnings either way.

Joshua Suskalo17:06:25

Oh btw, one place you'll need a map node is if someone wants to emit a with-bindings call. Sure, technically you could also emit a bindings call, but it'll technically be incorrect because if you emit bindings then ordering matters and previously-seen bindings will be assumed to be used in later ones, making certain classes of lints that pay attention to the values attached to bindings impossible.

Joshua Suskalo17:06:11

(I figured out why it didn't run in the bigger project, I accidentally called it config.clj rather than config.edn)

Joshua Suskalo18:06:47

Okay, looks like I can emit a comment node in order to ignore the unused binding warning on the unhygenic macro

Joshua Suskalo18:06:50

Only issue is that I can't import the namespace which exposes comment nodes

Joshua Suskalo18:06:58

@borkdude do you have any suggestions for this?


@suskeyhose > Is there any way that I can suppress unused-symbols for particular symbols in sections of code produced by a hook? Yes, you can start the symbol names with underscore, (gensym "_")


or you can just emit code that uses them

Joshua Suskalo20:06:40

That doesn't exactly work for making hooks for unhygenic macros though.


oh you said unhygienic :) well, I guess you can generate:

(let [x ..] x ...)

Joshua Suskalo20:06:23

Why didn't I think of that


why do you want to generate something with with-bindings btw? afaik clj-kondo doesn't really have any special linting around this


the generated code doesn't really have to reflect the original macro, as long as the input nodes are used in a way that makes sense for linting

Joshua Suskalo20:06:20

I actually don't have anything in particular about with-bindings that I want to generate, I was just pointing out that certain classes of linters (which you may or may not ever want to implement) would be impossible to represent atm because we lack a concept of unordered bindings, which with-bindings has.


True. Eventually we will get it, but afaik there is no reason to specifically emit this for any reason


unless there is some linter checking that "with-bindings must be used because this and that"