clj-kondo

https://github.com/clj-kondo/clj-kondo
2021-02-12T08:04:59.147500Z

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 🙂

borkdude 2021-02-12T08:20:42.148Z

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

2021-02-12T08:21:57.148100Z

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 .

borkdude 2021-02-12T08:23:59.148300Z

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

2021-02-12T09:39:36.148500Z

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

borkdude 2021-02-12T09:42:02.148700Z

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

borkdude 2021-02-12T09:44:19.148900Z

What are you doing in the hook?

2021-02-12T10:00:46.149100Z

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

borkdude 2021-02-12T10:01:13.149300Z

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

2021-02-12T10:06:27.149500Z

Yes

borkdude 2021-02-12T10:06:44.149700Z

I think I understand the issue now. https://github.com/clj-kondo/clj-kondo/issues/1170

1
2021-02-12T10:08:28.150200Z

Awesome, thank you 🙂

borkdude 2021-02-12T10:13:13.150400Z

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

🚀 1
2021-02-12T10:26:28.151100Z

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

2021-02-12T11:56:35.151300Z

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).

borkdude 2021-02-12T11:58:13.151500Z

I think you should do the following:

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

borkdude 2021-02-12T11:58:42.151700Z

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

1
👀 1
2021-02-12T12:10:42.152200Z

That works!

🎉 1
borkdude 2021-02-12T12:17:24.152500Z

You are the same person as Jeroen de Jong right?

borkdude 2021-02-12T12:17:28.152700Z

Just for my info ;)

2021-02-12T12:18:17.152900Z

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

borkdude 2021-02-12T12:18:57.153400Z

:thumbsup:

ericdallo 2021-02-12T13:04:27.154100Z

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

ericdallo 2021-02-12T13:04:44.154200Z

I'd like to use the same hook from rewrite-clj on clojure-lsp : https://github.com/clj-commons/rewrite-clj/blob/v1/.clj-kondo/hooks/rewrite_clj/potemkin/import_vars_with_mods.clj

ericdallo 2021-02-12T13:05:01.154500Z

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

ericdallo 2021-02-12T13:17:47.154700Z

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}}

borkdude 2021-02-12T13:22:32.154900Z

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

ericdallo 2021-02-12T13:24:58.155100Z

oh, got it, I'll try that

ericdallo 2021-02-12T13:47:58.155300Z

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

ericdallo 2021-02-12T13:48:05.155500Z

my question is

ericdallo 2021-02-12T13:48:37.155700Z

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 ?

ericdallo 2021-02-12T13:48:48.155900Z

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

borkdude 2021-02-12T13:55:36.156100Z

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

borkdude 2021-02-12T13:56:40.156300Z

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

ericdallo 2021-02-12T13:56:47.156500Z

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

ericdallo 2021-02-12T13:57:14.156700Z

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

borkdude 2021-02-12T13:57:43.156900Z

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

ericdallo 2021-02-12T13:58:02.157100Z

humm, you are right

verma 2021-02-12T20:56:08.158200Z

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?

verma 2021-02-12T21:01:40.158400Z

yeah that worked :thumbsup:

borkdude 2021-02-12T22:16:56.158700Z

@dharrigan Thanks for the kind sponsorship on OpenCollective!