Fork me on GitHub
#clj-kondo
<
2023-09-14
>
gordon11:09:59

Is it possible to use hooks to tell clj-kondo that a namespace is used? For hysterical raisins, we have some ancient code with circular dependencies which are extremely complicated to unwind. I'd like to unwind as much as I can, but the way these circular dependencies were added currently defeats clj-kondo's analysis, which makes finding unused code with carve harder. Back in the mists of time a macro was added to our codebase that implements a lazy definition of a function in another namespace: (declare-fn other.namespace/function) This macro will create the namespace if necessary, and define a function which on first invocation requires the namespace if necessary, resolves the function's symbol in that namespace, and then invokes the real function. What I'm looking to do is to teach clj-kondo's analyser that the namespace passed to declare-fn should be considered as required My first attempt was to use a hook to rewrite (declare-fn other.namespace/function) into (require '[other.namespace :refer [function]), but that doesn't seem to impact namespace analysis. Is what I'm looking to do possible? Thanks again for the suite of super-useful tooling, I use carve and clj-kondo every day.

borkdude11:09:30

"hysterical raisins" 🍇 great typo 😃

😁 1
☝️ 1
😂 1
borkdude11:09:37

(declare-fn other.namespace/function)
does hooking this as requiring-resolve work?

gordon11:09:56

Let me check

borkdude11:09:05

I don't think it does, unfortunately

borkdude11:09:14

but what you can do... (this will take me a time to type)

🙏 1
gordon11:09:16

Confirmed that requiring-resolve doesn't work

borkdude11:09:38

There's no easy way to do this, but if you add the namespaces to {:linters {:unresolved-namespace {:exclude [...]}}} then clj-kondo will assume that those are loaded by you

gordon11:09:19

👍 great, thanks for the help 🙂

borkdude11:09:47

but carve likely won't see that it's being used... this could be improved though

gordon11:09:03

No bother, I'm sure this is a very niche use-case, most folks don't go to these lengths to add circular dependencies to their codebases 🙂

borkdude11:09:18

you can always add them to the ignore list of carve

gordon11:09:45

Thanks I'll give that a shot

reefersleep13:09:51

I'm very curious; why was the circular dependence deemed necessary? (Maybe you don't know 😄 )

gordon16:09:42

The honest answer is "poorly structured code". It was allowed to last long enough that it's deeply entrenched.

reefersleep16:09:02

It happens. You're busy building, and don't realize that the foundation is being eroded.

borkdude16:09:31

I have some of this in clj-kondo. The analyzer.clj namespace is huge so I wanted to chop it into a few subparts, but those sub parts also need functions from analyzer.clj

borkdude16:09:07

What I did is create a analyzer/common.clj namespace and put a bunch of atoms in there in which I set the functions which I then use from the sub-namespaces

borkdude16:09:41

it breaks clj-kondo/lsp references but at least it's not cyclic

reefersleep21:09:24

Heh, that's funny that you're actively preventing your own tool from working on itself.

borkdude21:09:32

well, not actively. clojure-lsp didn't even exist when I did it like that ;)

reefersleep21:09:34

Ah 😅 well, doesn't it also prevent some analysis that clj-kondo could otherwise have done? Of function usage and such.

borkdude21:09:50

yes, but a man's gotta do what a man's gotta do when you want to prevent cyclic dependencies and still split things up

reefersleep22:09:15

Sure sure, whatever makes sense in a context. The notion just made me smile 😊

borkdude22:09:42

these are those things: https://github.com/clj-kondo/clj-kondo/blob/master/src/clj_kondo/impl/analyzer/common.clj I still get arity warnings and I only use them from a limited number of places, so it's ok-ish

reefersleep11:09:41

Also, you're the boss, so that helps

lilactown15:09:41

I can't seem to get clj-kondo to copy the config for helix into a new project.

;; shadow-cljs.edn
{:source-paths ["src"]
 :dependencies [[lilactown/helix "0.1.10"]
                [binaryage/devtools "1.0.7"]]}
output of copy config command:
$ clj-kondo --lint "$(shadow-cljs classpath)" --dependencies --parallel --copy-configs
shadow-cljs - config: /Users/lilactown/Code/helix-fundamentals/shadow-cljs.edn
No configs copied.

borkdude15:09:05

do you have a .clj-kondo directory?

borkdude15:09:38

you have to create one yourself, this is clj-kondo's way of giving it permission to write to a local folder

lilactown15:09:53

I see. is that documented somewhere?

lilactown15:09:03

if it is, I must have missed it

lilactown15:09:31

$ mkdir .clj-kondo
$ clj-kondo --lint "$(shadow-cljs classpath)" --dependencies --parallel --copy-configs
shadow-cljs - config: /Users/lilactown/Code/helix-fundamentals/shadow-cljs.edn
Configs copied:
- .clj-kondo/lilactown/helix
🎉

lilactown15:09:16

> To detect lint errors across namespaces in your project, a cache is needed. To let clj-kondo know where to create one, make a .clj-kondo directory in the root of your project, meaning on the same level as your project.clj, deps.edn or build.boot. missed it in my skimming then 🙂

👍 1
borkdude15:09:08

clj-kondo could make this clearer though in its error message; issue welcome