Fork me on GitHub
#clj-kondo
<
2023-08-22
>
fuad13:08:16

Hi! I recently found myself in a situation where I'd like to have some deftest calls inside of a let : the namespace contains a huge number of tests and I want to create some local bindings that only apply to a handful of them. Doing deftest inside of a let throws clj-kondo off, raising a "unused value" problem for all deftests except for the last one. I tried addressing this by telling kondo to resolve deftest as def (since the linter does not complain about def ) but that didn't have any effect. A few questions: • is the unused-value behavior for deftest expected? • if so, should resolving deftest as def be a reasonable way to address it?

borkdude14:08:38

deftest + unused value was fixed recently, are you using the newest clj-kondo version?

💡 2
👀 2
fuad14:08:36

I believe it is the latest version

~/S/e/ellipsus-service ❯❯❯ clj-kondo --version
clj-kondo v2023.07.13
I also observe the same behavior with kondo over lsp:
~/.l/s/n/m/bin ❯❯❯ ./clojure-lsp --version
clojure-lsp 2023.08.06-00.33.37-nightly
clj-kondo 2023.07.14-SNAPSHOT

borkdude14:08:26

and can you make a full standalone but minimal repro (code)?

fuad14:08:31

should I submit an issue?

borkdude14:08:28

yeah, makes sense. you can suppress this for now with:

(ns deftest
  (:require
   [clojure.test :refer [deftest is]]))

#_{:clj-kondo/ignore [:unused-value]}
(let [some-var "some-value"]
  (deftest this-one-is-flagged-as-unused
    (is (= some-var "some-value")))
  (deftest this-one-is-fine
    (is (= some-var "some-value"))))

fuad14:08:59

yes! that's what I've done. I also tried the namespace level ignore but to no avail:

(ns deftest-unused-val-repro
  {:clj-kondo/ignore [:unused-val]}

  (:require
    [clojure.test :refer [deftest is]]))

(let [some-var "some-value"]
  (deftest this-one-is-flagged-as-unused
    (is (= some-var "some-value")))

  (deftest this-one-is-fine
    (is (= some-var "some-value"))))

borkdude14:08:17

:unused-value , not :unused-val

2
borkdude14:08:17

but yeah that still doesn't work

fuad14:08:36

yeah, I also tried :config-in-ns

fuad14:08:46

ignore works for other linters without any issue, so I'm assuming it's something specific to :unused-value

borkdude14:08:07

yep, also mention this in the issue, or make a separate issue about it

🙌 2
2
fuad14:08:55

I included a comment in the same one as it seems related to the original problem as opposed to a completely separate problem (although I'm not familiar enough with kondo's internals to rule that out).

Nick McAvoy15:08:48

We use some macros from clojure.algo.monads. I'm currently looking at usage of domonad, which has two arities

Usage: (domonad steps expr)
       (domonad name steps expr)
We currently have this linting as clojure.core/loop, but loop matches the first arity, and not the second. Is there an "easy" answer here, apart from finding another macro with the same semantics, or writing the config custom?

borkdude16:08:50

no easy answer, other than: ignoring lint warnings completely or to write a hook for it

borkdude16:08:22

probably a hook would not be so difficult, you just expand into a loop expression and let the name drop

💡 2
Nick McAvoy16:08:42

That sounds worth trying

Nick McAvoy01:08:30

This alone took care of 10% of our total warnings!

(defn- domonad-helper
  ;; This arity of domonad takes a name,
  ;; but for the purposes of linting,
  ;; we can just throw that out.
  ([domonad _ steps expr]
   (domonad-helper domonad steps expr))
  ([_ steps expr]
   {:node
    (api/list-node
     (list
      (api/token-node 'let)
      steps
      expr))}))

(defn domonad [{{children :children} :node}]
  (apply domonad-helper children))

Nick McAvoy01:08:29

..Though I just learned my assumption that name was unimportant was incorrect. It should be a token that exists, and is usually from another ns. So now I have many fewer warnings overall, but some false positive "referred but never used" warnings where the name parameter above had been referred, and this is the only place it's used.

borkdude07:08:27

Then you can just emit a usage of that name?

Nick McAvoy14:08:30

That sounds right. Can you please point me in the direction of how to do that? I just spent a bit of time but didn't turn it up.

borkdude14:08:54

Just insert it between steps and expr maybe ?

Nick McAvoy14:08:55

It was as simple as that. Thank you again!

(defn- domonad-helper
  ([_ steps expr]
   (list
    (api/token-node 'let)
    steps
    expr))
  ([_ name steps expr]
   (list
    (api/token-node 'let)
    steps
    name
    expr)))

(defn domonad [{{children :children} :node}]
  {:node (api/list-node (apply domonad-helper children))})

👍 2