Fork me on GitHub
#clj-kondo
<
2021-02-12
>
thumbnail08:02:59

Hey; I'm creating an linter (for personal use) for clj-kondo using the hooks.api. First off; props 🍻! I use a replacement for clojure/defn in some cases. Right now I add my macro to :lint-as and add a hook for clojure.core/defn. This works nicely as mything/defn is now recognised and linted properly. I want to detect when clojure/defn is used instead of mything/defn and got a POC working based on the hooks-api. My issue is that i have to match the tag of the node exactly; which can change with other requires/refers. Is there a better way to do this? Thanks 🙂

borkdude08:02:42

@jeroen.dejong I'm not sure what you mean with "match the tag of the node exactly"

thumbnail08:02:57

In the hook i receive a node, which is the exact symbol it is in the sourcecode. Because mything/defn is linted as clojure/defn, i can't differentiate the two if they're both referred as defn .

borkdude08:02:59

Why do you use both lint-as + a hook?

thumbnail09:02:36

I want the clj-kondo built-in defn-linting to keep working

borkdude09:02:02

@jeroen.dejong What do you need the hook for?

borkdude09:02:19

What are you doing in the hook?

thumbnail10:02:46

My macro uses metadata to do some assertions, (which don't do anything for clj/defn). I'd like a linter which reminds me that i tried to use certain metadata so i should probably use my/defn

borkdude10:02:13

so you want a hook on clojure.core/defn?

thumbnail10:02:28

Awesome, thank you 🙂

borkdude10:02:13

I just pushed a commit to master. You can download a new binary from the builds in a few minutes for testing

🚀 3
thumbnail10:02:28

That's amazing. I'll check it out in a min

thumbnail11:02:35

Not quite sure how this should work yet, I tried the following: Given these two functions

(my/defn foo [^:tag x] x)
(defn bar [y] y)
(defn fizz [^:tag z] z)
bar is a simple fn,`my/defn` is expected usage (and should be treated as normal defn` , and fizz should report as "did you mean my/defn" because of the ^:tag. I configured condo:
{:hooks {:analyze-call {clojure.core/defn hooks/defn-hook}}
hooks/defn-hook reports fizz correctly :thumbsup::skin-tone-2: . In order to make clj-kondo recognise my/defn as defn, I made a hook which transforms the node as defn. unfortunately that triggers defn-hook too (similar to the lint-as approach).

borkdude11:02:13

I think you should do the following:

{:hooks {:analyze-call {clojure.core/defn your-hook}
 :lint-as {your/defn clojure.core/defn}}

borkdude11:02:42

so your your/defn calls will be processed as defn (without going through your hook), but the vanilla clojure.core/defn goes through your hook

👀 3
3
thumbnail12:02:42

That works!

🎉 3
borkdude12:02:24

You are the same person as Jeroen de Jong right?

borkdude12:02:28

Just for my info ;)

thumbnail12:02:17

Yes 🙂 Figured i'd share it on GH too, for prosperities sake

ericdallo13:02:27

Is there any way to use a hook from other project or something like that?

ericdallo13:02:01

do I need to copy that file or is there a better way to handle that?

ericdallo13:02:47

Also even copying that, it seems to not work for clojure-lsp project 😕 I have this on my .clj-kondo/.config :

{:hooks {:analyze-call {rewrite-clj.potemkin.clojure/import-vars-with-mods
                        hooks.rewrite-clj.potemkin.import-vars-with-mods/import-vars-with-mods}}

borkdude13:02:32

@UKFSJSM38 Yes, you can copy/move the hook code to a common directory and then add that directory to :config-paths

ericdallo13:02:58

oh, got it, I'll try that

ericdallo13:02:58

So, not sure what I'm doing wrong, I tryed changing config-paths, or using with ^replace [] just like rewrite-clj does but it's not recognizing the macros

ericdallo13:02:05

my question is

ericdallo13:02:37

Should I have that rewrite-clj.potemkin.clojure/import-vars-with-mods copied besides the hooks.rewrite-clj.potemkin.import-vars-with-mods/import-vars-with-mods ?

ericdallo13:02:48

I thought clj-kondo would search on classpath and find it

borkdude13:02:36

no, clj-kondo doesn't search hook code on a classpath. it only searches it within your .clj-kondo directory and by extension in :config-paths

borkdude13:02:40

note that hook code does not need the code that it is about to be available anywhere

ericdallo13:02:47

I see, so it'd be necessary to copy the code from rewrite-clj.potemkin.clojure/import-vars-with-mods too?

ericdallo13:02:14

yeah, I could add it too on .clj-kondo/hooks right?

borkdude13:02:43

> rewrite-clj.potemkin.clojure/import-vars-with-mods this is not hook code right, just JVM code?

ericdallo13:02:02

humm, you are right

verma20:02:08

is there a way for me to return more than one form through my hook function, or I could just do a (do (defn ...) (defn ..)) right?

verma21:02:40

yeah that worked :thumbsup:

borkdude22:02:56

@dharrigan Thanks for the kind sponsorship on OpenCollective!