Fork me on GitHub
#clj-kondo
<
2022-11-24
>
seancorfield18:11:16

So I created this hook:

(ns hooks.ws.clojure.extensions.condp->
  (:require [clj-kondo.hooks-api :as api]))

(defn condp-> [{:keys [node]}]
  (let [[expr pred & tail] (rest (:children node))
        rewritten
        (api/list-node
         (list*
          (api/token-node 'cond->)
          expr
          (api/list-node (list pred expr))
          tail))]
    {:node rewritten}))
and it's in hooks/ws/clojure/extensions/condp__GT_.clj and it works -- clj-kondo correctly processes condp-> invocations everywhere -- but clj-kondo complains that the ns in that file does not match the file name (namespace-name-mismatch) which seems like a bug?

Noah Bogart18:11:14

Clojure can handle that natively? That’s pretty cool!

borkdude18:11:56

clj-kondo uses namespace-munge to detects if the filename corresponds to the namespace name:

user=> (namespace-munge "foo->")
"foo_>"

borkdude18:11:33

that it works, might be accidental, since the reverse operation is probably just the general demunge

borkdude18:11:03

user=> (doc namespace-munge)
-------------------------
clojure.core/namespace-munge
([ns])
  Convert a Clojure namespace name to a legal Java package name.

borkdude18:11:31

To play it on the safe side, I'd just name the file condp_thread or so

borkdude18:11:15

having > in filenames can be awkward in bash and I don't even want to know what happens in Windows :)

seancorfield19:11:54

Oh, weird. namespace-munge and munge do not match?

borkdude19:11:49

no, there are some subtle differences, I can find the related clj-kondo issue for you

borkdude19:11:06

but if your hook worked, this is actually a bug in the clj-kondo SCI env, since it should also use namespace-munge for looking up that file :)

borkdude19:11:59

and I think I have this bug in babashka then too

seancorfield19:11:37

I guess I got the impression from earlier discussions and examples that a hook for x.y.z/abc needed to be in hooks.x.y.z.abc/abc but I gather that's not true? What are the constraints on the namespace/function name for hooks?

borkdude19:11:41

you can make up any namespace name in the local .clj-kondo directory, as long as the namespace name corresponds to the filename.

borkdude19:11:56

hooks. is just a convention

borkdude19:11:50

clj-kondo has a kind of classspath. the local .clj-kondo directory is added to that classpath, as are all two-level deep directories: acme/lib

seancorfield19:11:29

OK, so I don't need a separate file for each hook function? If a ns in my code has multiple macros that need hook definitions, I could have hooks.whatever/something.clj and that could contain all the hook fns for those macros?

borkdude19:11:58

correct, you can stuff as many hook functions in the same file as you want

seancorfield19:11:17

Cool. I can do quite a simplification of our hook setup then 🙂

imre20:11:12

@U04V70XH6 would you consider adopting the .clj_kondo extension for hooks? I've come across a https://github.com/clj-kondo/clj-kondo/issues/1685 related to having hook code in .clj files.

seancorfield20:11:16

@U08BJGV6E I'm talking about hooks within our monorepo at work, to handle macros in our own code, or 3rd party libraries we use that don't have clj-kondo support.

imre20:11:04

oh, I misunderstood then. I was under the impression some of these were for your OSS projects

imre20:11:08

apologies

seancorfield20:11:26

I'm puzzled by your issue: I don't have the .clj-kondo folder on my classpath so I can't see how an IDE would ever confuse the hook code with actual Clojure code?

seancorfield20:11:17

And even if .clj-kondo is on your classpath, the ns would be different and would not be something any of your code nses would ever require -- so, again, how on earth can be IDE get confused about that?

imre20:11:57

It isn't normal for .clj-kondo to be on the classpath and my issue isn't about that. The problem comes out when a library distributes its own clj-kondo hooks (among its resources), and that library is used by a consumer via a git dep.

👍 1
imre20:11:40

a quick repro case is

clj -Srepro -Sdeps \
 '{:deps {org.clojure/tools.namespace {:mvn/version "1.2.0"} seancorfield/next.jdbc {:git/url "" :git/sha "24bf1dbaa441d62461f980e9f880df5013f295dd"}}}' \
 -M -e "((requiring-resolve 'clojure.tools.namespace.repl/refresh-all))"

seancorfield20:11:06

Heh, yeah, well a) don't use c.t.n.r and b) don't use Cursive 🙂

imre20:11:18

There's a tools.build repro as well 🙂

borkdude20:11:18

since you prefixed that with "hooks" there is no problem

seancorfield20:11:44

Well, that's what I thought @U04V15CAJ so I'm surprised it's a problem...

borkdude20:11:05

well maybe there is, if c.t.n.r tries to load every .clj file there is on the classpath, but why would it do that, if nothing else refers to it?

imre20:11:02

that's just how c.t.n.r works, I asked about it https://ask.clojure.org/index.php/11434/could-namespace-refresh-sophisticated-directory-filtering but core aren't interested in changing that

seancorfield20:11:30

c.t.n.r is just broken (in many ways). I wish it didn't exist 😕

imre20:11:40

According to Alex: But why are those in :paths? The whole meaning of :paths is "paths containing source to be put on the classpath". Seems like these source files should not be there if they are not source.

imre20:11:02

(referring to hook code in resources)

seancorfield20:11:04

@U04V15CAJ To be clear, clj-kondo will find an import foo.clj_kondo as a hook in that resources tree (as well as bar.clj)? So I could change them and it would all still work? (that extension is news to me)

borkdude20:11:48

@U04V70XH6 Yes, this was implemented to solve this c.t.n.r problem

seancorfield20:11:20

@U08BJGV6E Feel free to create issues on any of my OSS projects you use that have hooks in resources and I'll make the change next time I'm working on them...

seancorfield20:11:19

next.jdbc may be the only one?

imre21:11:00

Thank you Sean, will do. That's the only one among yours where I came across it

imre21:11:17

And apologies again for hijacking the discussion

seancorfield21:11:06

I just renamed it, and it is the only hook in any of my projects as far as I can see.

seancorfield21:11:02

Currently, the only other unreleased change in next.jdbc is a small doc example so it may be a while before I release an update for that.

imre21:11:50

Thanks a bunch. Since the problem only comes out when referring a lib via git coordinates, it's already fixed

borkdude21:11:33

> Since the problem only comes out when referring a lib via git coordinates Why is that?

seancorfield21:11:00

Yeah, that surprises me since the JAR files contains that same file/path:

655 Fri Nov 04 22:22:36 PDT 2022 clj-kondo.exports/com.github.seancorfield/next.jdbc/hooks/com/github/seancorfield/next_jdbc.clj

imre21:11:32

Because clojure tools differentiate between namespaces coming from a directory path vs a jar path

imre21:11:47

And git deps end up as directory paths

borkdude21:11:13

So maybe that was the root problem that should have been fixed ;)

imre21:11:17

Well at least ctnr and toolsbuild do

imre21:11:01

Well, Alex's comment overrides that I think

imre21:11:09

He basically says if a .clj file isn't to be loaded it shouldn't be on the classpath

imre21:11:27

And I wasn't successful in convincing him otherwise

borkdude21:11:34

I think compiling all namespaces, unrestricted, is usually a bad idea.

borkdude21:11:50

better be explicit about all entrypoints (which is usually just one)

borkdude21:11:16

I've had problems with this in both lein and tools.build with duplicate compiled namespaces + graalvm native-image and since then I always use an explicit list

seancorfield21:11:21

deps-new has a bunch of .clj files in resources because they are templates for generating new projects -- but they are mostly illegal Clojure code and the ns in particular is not a valid symbol... but almost no one would have deps-new on their classpath while working on other stuff 🙂

seancorfield21:11:11

(`clj-new`, boot-new, and lein new code all do the same -- and those .clj files are in the codebase, not even just restricted to resources)

imre21:11:17

Alex responded to it

imre21:11:30

And his suggestion was to use a different extension

imre21:11:24

Which is why I created the kondo issue in the end

seancorfield21:11:03

I'm reminded of https://corfield.org/blog/2018/04/18/all-the-paths/ wherein I examine how different tools deal with different "types" of paths -- and Leiningen in particular had :source-paths and :resource-paths (Boot also had these two keys but they meant different things of course).

👀 1
1
borkdude21:11:05

haha yes, I could never figure out what boot meant with which key

imre21:11:04

Nice article, Sean. In the end it all comes down to what is on the classpath at runtime.

1
dharrigan20:11:40

Do you think it might be worthwhile for the clj-kondo --lint src command to output just the filenames (if it finds warnings/errors) for loading up into an editor? For example, something like vim $(clj-kondo --lint src --raw), then when it's loaded into an editor (in my case, vim with clojure-lsp), those errors would flag up when the analysis has been done?

borkdude20:11:48

@dharrigan the format that is currently spit out is already made in a standard way that editors recognize

dharrigan20:11:17

errr, not really

dharrigan20:11:32

doing "vim clj-kondo --lint src"

dharrigan20:11:39

shows me over 24 files to edit....

dharrigan20:11:39

vim certainly can't parse output like linting took 158ms, errors: 0, warnings: 4

Noah Bogart20:11:34

Using :cfile, you can just load a file with kondo’s normal output

borkdude20:11:20

what I mean is that when you open this format in an editor, it usually knows what to do with it. https://github.com/borkdude/carve#report-mode

dharrigan20:11:20

That report mode would not be recognised by vim

dharrigan20:11:24

Just tried it with vim and well, no.

borkdude20:11:23

@dharrigan clj-kondo --lint src --config '{:output {:pattern "{{filename}}"}}'

dharrigan20:11:25

That would still fail for me

dharrigan20:11:43

since it outputs

dharrigan20:11:48

linting took 157ms, errors: 0, warnings: 4

borkdude20:11:25

clj-kondo --lint src --config '{:output {:pattern "{{filename}}" :summary false}}'

dharrigan20:11:18

That works for sure, but mamma mia, so much typing...

dharrigan20:11:26

I suppose I could alias it

borkdude20:11:37

dude, I'm giving you a solution, when are you finally satisfied? ;)

dharrigan20:11:09

My apologies.

borkdude20:11:42

I guess we could print the summary to stderr instead of stdout

borkdude20:11:05

but since we have a config option and it might break existing tools somehow, maybe not necessary

borkdude20:11:21

you can put this command in a bb.edn tasks file or makefile or a bash alias

borkdude20:11:09

@dharrigan sorry I sounded a little agitated

borkdude21:11:42

@dharrigan I guess what I meant earlier is that when you command click in your terminal, and you have the right default editor set, the file will open at the right location with the current output. This works at least for me + VSCode (for some reason that editor is set for my terminal right now), but of course your terminal has to support this too

borkdude21:11:37

Here's what I'm seeing: