clj-kondo

https://github.com/clj-kondo/clj-kondo
Karol Wójcik 2020-08-07T07:38:11.297500Z

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 Wójcik 2020-08-07T07:38:21.297700Z

Thank you for help @borkdude you are golden!

borkdude 2020-08-07T07:41:01.297900Z

Cool! What is the partial state for?

Karol Wójcik 2020-08-07T07:43:09.298100Z

It's for making sure that state is provided

borkdude 2020-08-07T07:43:40.298300Z

I think this generates something like:

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

Karol Wójcik 2020-08-07T07:44:14.298600Z

Is there a difference?

borkdude 2020-08-07T07:44:40.298800Z

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

Karol Wójcik 2020-08-07T07:45:13.299Z

So in partial it's not seen?

borkdude 2020-08-07T07:45:15.299200Z

You might want to do:

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

borkdude 2020-08-07T07:45:24.299400Z

No

Karol Wójcik 2020-08-07T07:45:35.299600Z

Hmm....

Karol Wójcik 2020-08-07T07:46:52.299800Z

Frankly I want the state to be reported

borkdude 2020-08-07T07:47:02.300Z

ah

borkdude 2020-08-07T07:47:07.300200Z

that's ok then, don't use it

Karol Wójcik 2020-08-07T07:47:34.300400Z

Ahh wait.

borkdude 2020-08-07T07:47:39.300600Z

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

Karol Wójcik 2020-08-07T07:47:43.300800Z

So I can just ignore the first arg?

borkdude 2020-08-07T07:48:06.301Z

why would you want to ignore the first arg?

Karol Wójcik 2020-08-07T07:49:13.301200Z

I think that we are talking past each other 😄

borkdude 2020-08-07T07:49:40.301400Z

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 Wójcik 2020-08-07T07:57:21.301700Z

@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?

borkdude 2020-08-07T08:33:15.302Z

@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

borkdude 2020-08-07T10:01:19.302200Z

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

borkdude 2020-08-07T10:02:23.302400Z

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.

borkdude 2020-08-07T10:03:12.302700Z

and (f 1 2) should trigger an arity warning

Karol Wójcik 2020-08-07T10:05:02.302900Z

Thanks.. Will try to do it in free time

borkdude 2020-08-07T10:06:49.303100Z

:thumbsup: