Fork me on GitHub
#clj-kondo
<
2020-09-22
>
hugod11:09:38

Is it possible to disable the arity-check for keywords? We have an embedded language that uses keywords in function position, with an arbitrary number of arguments.

borkdude11:09:40

@hugod yes, let me get back to you after a meeting

hugod12:09:03

No urgency. Thanks for the config pointers. I see how to disable the check for a specific function/macro, but not for keywords in general. The set of keywords we use like this is open, although there is a limited set that probably covers most usage. Maybe that is good enough.

borkdude12:09:08

Writing a hook is probably the best solution, but requires some work

borkdude12:09:03

I assume these keywords are only used within a macro right?

hugod12:09:21

Within various macros, right. I’ll have a look at hooks. Thanks

hugod13:09:37

Um, looks like it is not possible to define a hook on an unqualified symbol pulled in via a :refer :all

borkdude13:09:08

it depends if clj-kondo knows that namespace (e.g. it's been linted before)

borkdude13:09:14

btw, I think I have a hook here:

borkdude13:09:53

I assume the macro you use is required?

borkdude13:09:17

This is the code:

(ns hooks.kw-macro
  (:require [clj-kondo.hooks-api :as api]))

(defn rewrite [node]
  (let [sexpr (api/sexpr node)]
    (if (and (seq? sexpr)
             (keyword? (first sexpr)))
      (let [children (rest (:children node))
            children (mapv rewrite children)]
        (with-meta (api/vector-node children)
          (meta node)))
      (with-meta
        (update node :children #(mapv rewrite %))
        (meta node)))))

(defn kw-macro [{:keys [:node]}]
  (let [new-node (api/vector-node (mapv rewrite (rest (:children node))))]
    ;; for debugging:
    ;;(prn :new-node new-node)
    {:node new-node}))

borkdude13:09:32

I basically rewrite (my/kw-macro (:foo 1 2 3) (:bar 1 2 3)) to [[:foo 1 2 3] [:bar 1 2 3]]

hugod13:09:16

That should work with some modification to use walk to pick up nested forms. 🙂

borkdude13:09:46

walk unfortunately doesn't preserve metadata

hugod14:09:18

I think I have a walk that does - thanks for the reminder

hugod14:09:06

the macro is required with a :refer :all and is actually defined in a different namespace via an import-vars like mechanism.

hugod14:09:18

I can’t get the hook to trigger at all

borkdude14:09:51

you're out of luck there, clj-kondo has no way of knowing what var you are calling

borkdude14:09:39

it does have support for import-vars (the widely used one). so if you use the same syntax as that one and use lint-as AND lint all of your namespaces, it might work

hugod14:09:17

Is there any existing macro to inspect how clj-kondo is currently parsing an expression? eg, something I can insert around a form that prints the rewrite map

borkdude14:09:12

yes, look at the example I provided you

borkdude14:09:20

;;(prn :new-node new-node)

hugod15:09:23

duh, upgrading clj-kondo helps a lot

hugod18:09:19

How do you develop hooks? clj-kondo seems to just silently ignore the hook if it fails to load.

borkdude19:09:16

Clj-kondo will print a warning if the hook isn’t found but is in your config

borkdude19:09:40

e.g. with this config:

{:hooks {:analyze-call {my/kw-macro hooks.kw-macro/kw-macro2}}}
[email protected] /tmp/proj $ clj-kondo --lint example.clj
WARNING: error while trying to read hook for my/kw-macro: Could not resolve symbol: hooks.kw-macro/kw-macro2 [at line 2, column 1]
example.clj:4:14: error: keyword :foo is called with 3 args but expects 1 or 2
example.clj:5:14: error: clojure.core/inc is called with 3 args but expects 1
example.clj:6:15: error: keyword :foo is called with 3 args but expects 1 or 2
example.clj:6:28: error: clojure.core/inc is called with 3 args but expects 1
linting took 59ms, errors: 4, warnings: 0
^ @hugod

borkdude19:09:16

and correcting it:

$ clj-kondo --lint example.clj
example.clj:5:14: error: clojure.core/inc is called with 3 args but expects 1
example.clj:6:28: error: clojure.core/inc is called with 3 args but expects 1
linting took 33ms, errors: 2, warnings: 0

hugod20:09:29

if there is a compile error in the hook itself, it seems to be silently ignored.

borkdude20:09:05

let me make a deliberate mistake

borkdude20:09:29

I'm putting a random x in my hook code:

$ clj-kondo --lint example.clj
WARNING: error while trying to read hook for my/kw-macro: Could not resolve symbol: x [at /private/tmp/proj/.clj-kondo/hooks/kw_macro.clj, line 5, column 3]

hugod20:09:09

um, I wonder what’s different here

borkdude20:09:15

yeah, you might have hit a different case. repro welcome, maybe something could be improved

hugod20:09:48

hooks are very flexible :)

borkdude20:09:11

powered by the same interpreter as babashka

borkdude20:09:25

@hugod could also be a laziness issue so the error is never reached?

hugod20:09:51

Good thought. I’ll try and investigate more later.

borkdude11:09:44

alternatively you could write a hook for your macro, but that's more work than just suppressing warnings