Can I have a hook in my ~/.clj-kondo
dir? I'd like to create a hook for a common macro used on hundred of clojure projects
yes, you can
It might even better to check the hook code into those projects or into the libraries for which the hook code is written for, so your co-workers can re-use them too
Yes, we already have a common config for clj-kondo 🙂 my idea is add a hook there as well
Is there a example of a hook that defines a var-definition
?
I have a macro that behaves similar to defn with some minor differences, How can I tell to the clj-kondo in the hook that the first arg is the var-definition name ?
@ericdallo Write a hook that expands into a clojure.core/defn
or clojure.core/def
node
Oh got it, I'll give a try
It's basically a macro-expansion with rewrite-clj nodes
And then you return that node using {:node your-new-node}
It worked, thanks! 🙂
BTW, I needed to manually add the with-meta
to the analysis correctly work
@ericdallo That is expected and documented. Maybe for your custom defn you also could have used {:lint-as {... clj-kondo.lint-as/def-catch-all}}
I was using that :lint-as
for months, but now I want to fix some things from that macro
We could maybe change the behavior of newly created nodes automatically taking over the position of the outer original node, but that might also confuse people when there is a linting warning on the wrong position
it's a integration test macro:
(defflow my-integration-test
[a (my-func)]
(some-flow)
[b (other-func)]
(other-flow))
cool
https://github.com/nubank/state-flow#clojuretest-and-matcher-combinators
you can add your hook to this library
when you lint your classpath, then clj-kondo will recognize it
as in: copy it to your config dir
you will still have to opt in to the config yourself
oh, really cool! So I'd just need to add to my config the :hooks map, but not the hooks folder with the hooks since it'd be present on the lib, right?
The docs for this are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration
oh, it's like magic! really cool
yes, and when you have a new version of your library, the hook code is updated as well
really amazing indeed, could I open a PR for https://github.com/clj-kondo/config/tree/master/resources/clj-kondo.exports/clj-kondo adding that state-flow
macro later?
yeah you could do that, but you could also just add it to state-flow itself
Yes, I'll certainly add to the state-flow, so maybe we don't need to add to the clj-kondo/config so?
yeah, clj-kondo/config is only for hooks that are contributed without being it part of the libraries themselves
FTR this is the final hook
(defn ^:private defflow-bindings [nodes]
(->> nodes
(filter api/vector-node?)
(map (fn [node]
(let [[sym val] (:children node)]
[sym val])))
flatten
vec))
(defn ^:private defflow-flows [nodes]
(filter (complement api/vector-node?) nodes))
(defn defflow [{:keys [:node]}]
(let [[name & flows] (rest (:children node))
new-node (api/list-node
(list
(with-meta (api/token-node 'defn) (meta name))
(with-meta (api/token-node (api/sexpr name)) (meta name))
(api/vector-node [])
(api/list-node (list* (api/token-node 'let)
(api/vector-node (defflow-bindings flows))
(defflow-flows flows)))))]
(prn (api/sexpr new-node))
{:node new-node}))
And a sample of usage:
(defflow my-flow
[a (+ 1 2)]
(flow "flow-1"
(match? a
1))
[b (+ 1 2)]
(flow "flow-2"
(match? a
b)))
you can probably combine map + flatten into mapcat
looking good, don't forget to remove the prn
thanks!
I tried to change the defn
to clojure.test/deftest
but it seems to not work
you should probably generate (do (require 'clojure.test) (clojure.test/deftest ...))
in that case
if clojure.test has not been required yet
oh, I see, let me try
Not sure if I did correctly the export config
does that looks correct for you? https://github.com/nubank/state-flow/pull/149
lemme check
@ericdallo I would use a multi-segment namespace like nubank.state-flow
for the hook namespace
e.g. check here: https://github.com/clj-kondo/config/tree/master/resources/clj-kondo.exports/clj-kondo/claypoole
note that here clj-kondo is the org, because this hook is written on behalf of the clj-kondo org
got it, let me change it
Done, still looks odd to me the path:
resources/clj-kondo.exports/nubank/state-flow/nubank/state_flow.clj
is that right?yeah, that's right :)
Also I included a:
resources/clj-kondo.exports/nubank/state-flow/config.edn
not sure if this should be in the lib or manually set by useronly the parts that are relevant for the lib should be in there, including the hook config
so it seems correct to me
I'll try to generate a snapshot release local and test it
yes
Hum, it didn't work
I tried to add to my home config:
{ :hooks {:analyze-call {
state-flow.cljtest/defflow nubank.state-flow/defflow
state-flow.core/flow nubank.state-flow/flow}}}
but it didn't work as well
You should not have to add this to your home config if you opt-in to your library config
Yes that's what I thought
so maybe the folders hierarchy in the lib are not right
Read the part about how to opt in: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration
I already did it, I tried adding a :config-paths ["nubank/state-flow"]
but didn't work 😕
is this dir present in your .clj-kondo
dir?
you mean the one in the lib or on my home?
in the project where you imported it
or did you import it in your home dir?
just tell me where you see the copied files
So, that's what I did: • generated a local release in this branch: https://github.com/nubank/state-flow/pull/149/files • Changed a local project to usethe local release • when I start lsp on the file it does not handle the macro, it was handling when the hook was on my home dir before I move it to the lib
You should read the last part of https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration better
Where is the copied file (if at all)
Just give me the full path
sorry, that last part is not clear to me, should I add that
{:config-paths ["nubank/state-flow"]}
in the lib config.edn?I don't see any Copied config to
message anywhere
oh found a log message on clojure-lsp:
WARNING: error while trying to read hook for integration.aux.init/defflow: Could not find namespace: nubank.state-flow.
Just try to walk through the docs step by step for the clj-kondo config project example, it should explain itself
It works now, I renamed only the hook file not the ns inside it :man-facepalming: Thanks for the help and sorry for bother you 🙂
glad you found it ;)
is there any way to show globally unused publics in linting output? I think the answer is no, but I could swear there was a point in time where this was possible…
@devn This isn't supported out of the box, but you can do this using analysis output: https://github.com/clj-kondo/clj-kondo/blob/master/analysis/README.md#unused-vars Private unused vars are reported though.
There is also https://github.com/borkdude/carve to do this for you
nice. i was mostly asking because in older versions of clojure-lsp, it’d highlight public global unused vars, and that was very handy for knocking out dead code
it can continue to do so, the information is there
you get this with the lens-mode now
yes, we could do the same logic from lenses indeed, just don't know if we should always present that as a warning
like for api usages and etc
maybe that can be a config, but IMO lens-mode is sufficient
yes, a config would work
Actually, a flag for that looks good, I just wonder the default
The default should probably be: disabled
it could just be an "info" diagnostic as well, the level could maybe be similarly set as how clj-kondo does it
I think I would turn it on sometimes, but not all the time, similar to lens-mode
(which for me personally is enough)
yeah, i can use the lens (and I have been), but the highlight was nice IMO. I’m actually a bit surprised y’all think the default should be disabled.
When I think about it, I’m not sure why you’d have an unused public fn that is part of an API that doesn’t have a matching test (even if the level of test is as simple as “it exists”).
but I mean, if it’s configurable, no sweat either way
highlight as in: not a warning like clj-kondo but something more subtle?
Yeah, I think the same, I think I'll add something like :public-vars-lint-level :info
we could do a highlight the same as when you are on a local?
some different color maybe?
not sure how this is done. Maybe take it to #lsp?
Detect unreachable specs - has this idea already been proposed / implemented? https://stackoverflow.com/questions/45819346/how-to-check-the-resolvability-of-clojure-specs
unreachable as in unused or unresolvable as undefined - two different things ?