Fork me on GitHub
#clj-kondo
<
2020-08-06
>
cnly13:08:14

Quick question, does clj-kondo give warnings about unused public functions?

borkdude13:08:29

@cnly No. But there is a tool for this based on clj-kondo: https://github.com/borkdude/carve

cnly13:08:19

👍 Thanks!

karol.wojcik16:08:22

@borkdude Is there a tutorial or docs how to test & write custom hooks? I would love to tweak rum.core/defcs in free time

karol.wojcik17:08:07

Thank you very much! Why there is :node in keys instead of node?

karol.wojcik17:08:48

@borkdude Btw I'm trying to find the exact source of clj-kondo.hooks-api. This is what I got so far:

(defn defcs
  [{:keys [node]}]
  (let [args (rest (:children node))
        component-name (first args)
        args (next args)
        body
        (loop [args* args
               mixins []]
          (if (seq args*)
            (let [a (first args*)]
              (if (vector? (api/sexpr a))
                (do
                  (println a)
                  (println (api/vector-node (vec (rest (api/sexpr a)))))
                  (cons (api/vector-node (vec (rest (api/sexpr a)))) (concat mixins (rest args*))))
                (recur (rest args*)
                       (conj mixins a))))
            args))
        new-node (with-meta
                   (api/list-node (list* (api/token-node 'defn) component-name body))
                   (meta node))]
    ;; (println (api/token-node 'defn))
    ;; (println new-node)
    {:node new-node}))
But this throws unsupported binding form input

borkdude18:08:03

:node or node are both supported, doesn't matter

karol.wojcik20:08:56

@borkdude I think that I should ignore state somehow, but dunno how to do it. Can you please give me a hint? For instance simply ignoring the first argument results in input not being known.

borkdude20:08:42

Yes. You should probably wrap the body in an artificial let expression that has a binding state, like (let [state nil] ... body ...)

borkdude20:08:00

Take a look at the hook for slingshot, which also does something similar

borkdude20:08:04

@ @ Any ideas?

karol.wojcik07:08:11

Finally got it working

(defn defcs
  [{:keys [node]}]
  (let [args (rest (:children node))
        component-name (first args)
        args (next args)
        body (loop [args* args
                    mixins []]
               (if (seq args*)
                 (let [a (first args*)]
                   (if (vector? (api/sexpr a))
                     (cons a (concat mixins (rest args*)))
                     (recur (rest args*)
                            (conj mixins a))))
                 args))
        partial-state (api/list-node [(api/token-node 'partial)
                                    (api/list-node (list* (api/token-node 'fn) body))
                                    (api/token-node 'state)])
        new-node (api/list-node
                  [(api/token-node 'let)
                   (api/vector-node
                    [(api/token-node 'state) (api/token-node {})])
                   (with-meta (api/list-node [(api/token-node 'def)
                                              component-name
                                              partial-state])
                     (meta node))])]
    {:node new-node}))

karol.wojcik07:08:21

Thank you for help @borkdude you are golden!

borkdude07:08:01

Cool! What is the partial state for?

karol.wojcik07:08:09

It's for making sure that state is provided

borkdude07:08:40

I think this generates something like:

(let [state {}] (def my-component (partial (fn [...] ...) state)))
Why not:
(defn my-component [args] (let [state {}] body)
?

karol.wojcik07:08:14

Is there a difference?

borkdude07:08:40

Syntactically yes, clj-kondo can see the argument count this way for example?

karol.wojcik07:08:13

So in partial it's not seen?

borkdude07:08:15

You might want to do:

(defn my-component [args] (let [state {}] state ... body ...)
to make state being used, so it won't be reported.

karol.wojcik07:08:52

Frankly I want the state to be reported

borkdude07:08:07

that's ok then, don't use it

borkdude07:08:39

so if you don't use state, then you're going to use def-something-else in rum right?

karol.wojcik07:08:43

So I can just ignore the first arg?

borkdude07:08:06

why would you want to ignore the first arg?

karol.wojcik07:08:13

I think that we are talking past each other 😄

borkdude07:08:40

I think so too. Maybe it's better to talk in examples. Paste an example of Rum usage and the desired sexpr for clj-kondo

karol.wojcik07:08:21

@borkdude My goal is to make sure that both not used state is reported and function that takes like 2 (except state) args then when I provide only one argument then I want clj-kondo to report that not all function parameters are passed. Let the demo.cljs be defined like so:

(rum/defcs SomeComponent <
  {:did-mount (fn [state] state)}
  [state input another]
  (let [x "Hello"]
    nil))

(rum/defc SomeComponent1 <
  {:did-mount (fn [state] state)}
  [input]
  input)


(SomeComponent "hello")
After running clj-kondo I got the following things reported:
demo.cljs:9:4: warning: unused binding state
demo.cljs:9:10: warning: unused binding input
demo.cljs:9:16: warning: unused binding another
demo.cljs:10:9: warning: unused binding x
linting took 17ms, errors: 0, warnings: 4
That's perfectly fine. What I need more is just the warning that not all parameters to function has been passed. My question is how I can have that last warning working? What I understand is that I should not use 'partial, but how should I construct sexpr?

borkdude08:08:15

@karol.wojcik I think more like (defn my-component [args] (let [state {}] body), so more like how it was originally, but with the extra let around the body

borkdude10:08:19

(defsc foo [state x] body1 body2) => (defn foo [x] (let [state {}] body1 body2)

borkdude10:08:23

So you call it as (f 1) and clj-kondo will think this is correct, since the generated form only receives one arg (or n-1 args in general) and state is still recognized as a valid binding.

borkdude10:08:12

and (f 1 2) should trigger an arity warning

karol.wojcik10:08:02

Thanks.. Will try to do it in free time

borkdude17:08:14

@karol.wojcik Note: I edited the link, posted an old one earlier