This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-05
Channels
- # announcements (23)
- # babashka (23)
- # beginners (48)
- # calva (41)
- # clj-kondo (41)
- # cljs-dev (75)
- # cljsrn (5)
- # clojure (85)
- # clojure-europe (46)
- # clojure-nl (2)
- # clojure-spec (70)
- # clojure-uk (4)
- # clojurescript (52)
- # core-async (2)
- # cursive (16)
- # datahike (2)
- # datomic (4)
- # emacs (15)
- # figwheel-main (2)
- # fulcro (5)
- # gratitude (5)
- # helix (14)
- # introduce-yourself (2)
- # jackdaw (13)
- # keyboards (2)
- # lsp (8)
- # luminus (5)
- # malli (3)
- # meander (12)
- # nextjournal (52)
- # off-topic (19)
- # other-languages (1)
- # overtone (3)
- # pathom (4)
- # podcasts-discuss (1)
- # re-frame (6)
- # reitit (1)
- # releases (2)
- # ring (3)
- # sci (22)
- # shadow-cljs (3)
- # specter (1)
- # testing (3)
- # tools-deps (100)
- # uncomplicate (2)
hi Can clj-kondo lint on unused fns? (eg with zero refs)
@kirill.salykin you can do this in two ways: ā¢ Use https://github.com/borkdude/carve as a tool to get a report for unused functions ā¢ Use #lsp in your editor to see how many references there are for a function (in emacs lsp it's called lens mode)
Actually you don't need lens enabled, clojure-lsp will return a diagnostic saying that function is unused public var
I was more in running it on CI already have it in my emacs š
carve seems exactly what i needed, thanks!
for CI you can check this as well: https://clojure-lsp.io/api/#ci
So the question I mistakenly posted in #babashka @borkdude you say, use macroexpand hook instead of analyze-call, but I can't figure out, say for example, how do I write a hook for compojure.api things? e.g.:
(context "/api" []
:tags ["api"]
(GET "/plus" []
:return {:result Long}
:query-params [x :- Long, y :- Long]
:summary "adds two numbers together"
(ok {:result (+ x y)}))
(POST "/echo" []
:return Pizza
:body [pizza Pizza]
:summary "echoes a Pizza"
(ok pizza)))))
How do I get pizza
and x
, and y
to "be resolved"?There are various ways to deal with this.
From easy + less precise to hard/more work + more precise errors:
1. Suppress unresolved symbols in compojure.api/context
or compojure.api/GET
etc, using the configuration.
https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#unresolved-symbol
2. :lint-as
can be used if there is a function/macro that behaves syntactically the same (but that doesn't seem to be applicable here)
3. use :macroexpand
hook to write a macro to transform the code into simpler code that clj-kondo can understand. it does not have to transform into code that "works", just into expressions that clj-kondo will lint and make sense for linting. The macro does not have to correspond to the real macro.
4. use :analyze-call
hook. Similar to 3. but this gives you more precise locations for errors.
So let's say if we shoot for 3, can you come up with a macro that receives the above expression and turns it into something that doesn't have special syntax?
I've tried 1 and 2 and it didn't work perfectly for me, because then things used within the POST
block would not be recognized as used and kondo flags them as unused references.
macro I tried, but couldn't figure it out (forgot exact reasons)
thought I'm gonna need analyze-call for that, but that turned out to be even more tangled
(ns foo
{:clj-kondo/config '{:linters {:unresolved-symbol {:exclude [(compojure.api/GET)]}}}}
(:require [compojure.api :refer [GET]]))
(GET "/plus" []
:return {:result Long}
:query-params [x :- Long, y :- Long]
:summary "adds two numbers together"
(ok {:result (+ x y)}))
Also when you type:
(let [foo 3]
(GET "/plus" []
:return {:result Long}
:query-params [x :- Long, y :- Long]
:summary "adds two numbers together"
(ok {:result (+ x y foo)})))
then foo
isn't marked as unusedare you using the :refer :all
like in their README? this could cause problems as clj-kondo has to do guesswork where stuff is coming from
Right. okay. I'll keep playing with this. Sorry for being fuzzy on that. I'm space out a bit, because my last attempt was a couple of weeks ago. And cleaning up things with kondo in a huge project is not "a real work", but I'm doing it as a "side-project"
Just come back with one isolated small piece of code where 1 doesn't work for you and I'm confident we can fix it
Alright! I guess I was overly excited and wanted to learn how to make custom hooks with :analyze-call, even though might be an overkill for this task š
@U0G75ARHC I think this could be a good start for a macro for GET
:
(defmacro GET [path args & {:as opts}]
[path args (update opts :query-params
(fn [params]
(list 'fn (vec (remove #{':-} params)))))])
(macroexpand '(GET "/plus" []
:return {:result Long}
:query-params [x :- Long, y :- Long]
:summary "adds two numbers together"))
["/plus" [] {:return {:result Long}, :query-params (fn [x Long y Long]), :summary "adds two numbers together"}]
you'll have to wrap the body of the GET into the function and then it will also understand the usages within the body
Thank you. I'll try this. Really appreciate your help. I think this gives me enough food for thought. I'm sure I'll have to come back again and ask some more questions.
So, I have something like this:
(context "/:id" []
:query-params [{wait_for :- s/Bool}]
:path-params [id :- s/Str]
(PATCH "/" []
;; ... id an wait_for are used somewhere here
Using :unresolved-symbol {:exclude
would then ignore the actual errors within. So for example I rename id
to foo
- instead of telling me that foo
is unused, it would just ignore that entire block.
If I use :hooks :macroexpand
, then (even if I do it right) if there's something wrong, it will show the errors all the way at the beginning of the block.
These blocks can get too long, it will be annoying to try to find a misplaced var(s).Yes,
1) this is a trade-off, you will ignore all false positives, but won't get additional errors.
2) yes, this is also a trade-off of :macroexpand
. if you want precise locations you should make this an :analyze-call
hook. The implementation is similar to your macro but is based on nodes rather than s-expressions.