This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-04
Channels
- # announcements (19)
- # babashka (11)
- # babashka-sci-dev (9)
- # beginners (71)
- # calva (25)
- # cider (1)
- # clara (36)
- # clj-kondo (47)
- # clojure (65)
- # clojure-dev (64)
- # clojure-europe (9)
- # clojure-nl (2)
- # clojure-seattle (1)
- # clojure-uk (2)
- # clojured (8)
- # clojurescript (17)
- # cursive (9)
- # data-science (36)
- # datahike (11)
- # emacs (10)
- # figwheel-main (19)
- # fulcro (15)
- # graalvm (12)
- # humbleui (5)
- # introduce-yourself (3)
- # jobs (10)
- # leiningen (4)
- # lsp (24)
- # malli (7)
- # nextjournal (23)
- # off-topic (1)
- # pedestal (2)
- # polylith (6)
- # portal (1)
- # re-frame (3)
- # reitit (2)
- # releases (2)
- # remote-jobs (1)
- # reveal (9)
- # shadow-cljs (13)
- # spacemacs (6)
- # xtdb (3)
I'm looking to do some static analysis: collect all usages of foo.bar/translate
, and collect the following information:
1. literal value of the first argument (e.g. if called like (t/t "Hello")
I'd like to collect "Hello"
2. filename, line, column
I'm looking at the clj-kondo analysis option and in the output file I can see row
, col
/`end-col` which means I can probably read the source file manually, skip to row
and parse the Sexpr manually somehow. Am I missing something? Would I use something like edamame to safely parse the s-expression? (I guess clojure.edn could also work for 95% of the cases)...
I think you could do this using a hook. Just write a hook for your function, collect the first argument, call (api/reg-finding! (assoc (meta arg-node) :message "collect some info" :type :my-custom/linter))
and then register {:linters {:my-custom/linter {:level :info}}}
(Eventually we may write a custom linter if the approach holds, but for now we need to collect info)
and then call clj-kondo in the jvm and collect :type :my-custom/linter
from the :findings
An alternative without clj-kondo could be using https://github.com/borkdude/grasp
@orestis example:
$ clj-kondo --lint code.clj --config .clj-kondo/find_hello.edn
code.clj:4:20: info: Hello
$ cat code.clj
(ns code
(:require [foo.bar]))
(foo.bar/translate "Hello")
$ cat .clj-kondo/hooks/hello.clj
(ns hooks.hello
(:require [clj-kondo.hooks-api :as api]))
(defn translate-hook [{:keys [node]}]
(let [arg (second (:children node))]
(when (= "Hello" (api/sexpr arg))
(api/reg-finding! (assoc (meta arg)
:message "Hello"
:type :my-custom/linter)))))
$ cat .clj-kondo/find_hello.edn
{:linters ^:replace {:my-custom/linter {:level :info}}
:hooks {:analyze-call {foo.bar/translate hooks.hello/translate-hook}}}
Hm, I'm having trouble with the config. The file is getting linted with my main config...
Sorry, it gets linted with the new config in addition to the previous one. So I'm also getting warnings about unused requires etc.
Yep, it's there:
{:linters ^:replace {:nosco.i18n/translate {:level :info}}
:hooks {:analyze-call {nosco.i18n.translate-server/t hooks/translate-server}}}
Clearly the i18n-config.edn is picked up as the new linter doesn't exist in the base config.
$ clj-kondo --lint code.clj --config .clj-kondo/find_hello.edn --config '{:output {:format :edn}}'
{:findings [{:row 4, :col 20, :end-row 4, :end-col 27, :message "Hello", :type :my-custom/linter, :filename "code.clj", :level :info}]}
Good to know! In this case it doesn't really matter how does it get invoked - but it would be good to avoid other linters.
$ clj-kondo --lint code.clj --config .clj-kondo/find_hello.edn --config '{:output {:format :edn}}' | jet --func '#(->> % :findings (filter (comp #{:my-custom/linter} :type)))'
({:row 4, :col 20, :end-row 4, :end-col 27, :message "Hello", :type :my-custom/linter, :filename "code.clj", :level :info})
Interesting: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#disable-all-linters-but-one
If I put the ^:replace
on the outside of the map, I get this error WARNING: file hooks.clj not found while loading hook
Thanks for the guidance, this is promising. I will have to finish it some other time though
@borkdude for this issue https://github.com/sicmutils/sicmutils/pull/478, I wrote :kondo/ignore
but the actual code correctly used :clj-kondo/ignore
;
sounds good
repro achieved. my issue with overriding the error in the config was wrong, that was my mistake. but the inline override still does not work, and reproduces here on my machine
Even a bare #_:clj-kondo/ignore
seems to fail with my custom warning. You can see the linter triggering on the top form but not the bottom form:
awesome, thank you! I responded too and took your recommendation for all linters exported by sicmutils.