Fork me on GitHub

Hi. Need some advice, here. At Pitch we want to catch a possible library usage error at development and CI time, and we wonder if we can create some clj-kondo linters for it. Here's some pseudo-ish code, the library:

(ns foo-lib.core)

(def all-things (atom #{}))

(defn init! [valid-things]
  (reset! all-things (set valid-things)))

(defn foo? [thing]
  (when-let [my-thing (all-the-things thing)] ; not finding `thing` is bad
    (figure-thing-out my-thing)))
App 1:
(ns app-1.some-ns
  (:require [foo-lib.core :as foo-lib]
            [re-frame.core :as rf]))

(def app-1-foo-things [:a])

(foo-lib/init! app-1-foo-things)

(defn hello []
  (foo-lib/foo? :a) ; valid use
  (foo-lib/foo? :b) ; invalid use
  @(rf/subscribe [:foo-lib-foo? :a]) ; valid use
  @(rf/subscribe [:foo-lib-foo? :b]) ; invalid use
App 2:
(ns app-2.some-ns
  (:require [foo-lib.core :as foo-lib]
            [re-frame.core :as rf]))

(def app-2-foo-things [:a :b])

(foo-lib/init! app-2-foo-things)

(defn hello []
  (foo-lib/foo? :a) ; valid use
  (foo-lib/foo? :b) ; valid use
  (foo-lib/foo? :c) ; invalid use
  @(rf/subscribe [:foo-lib-foo? :a]) ; valid use
  @(rf/subscribe [:foo-lib-foo? :b]) ; valid use
  @(rf/subscribe [:foo-lib-foo? :c]) ; invalid use
In ”prose” the challenge is something like so: • We have a library that is initialized with a list of things. • It is an error to call some of the library's functions passing things not present in the initialization list. • Some usages of the library goes via re-frame subscriptions, some are ”regular” function calls. • The library is only initialized once during the application life cycle. • The codebase using the library is shared between several apps. I imagine that we'll have at least one linter per app we build, and that we would be hardcoding the initialization list in the linter. Please let me know if I can clarify something, it was surprisingly hard to describe this.


Here are the things I’d question about the above if this was in a PR I’m reviewing: • Is it necessary for the library to manage/hold runtime state? I normally like to place the app in charge of that. • It appears you are trying to make a static analyzer check something that is dependent on runtime state. I’m not sure that is fully possible

Roman Liutikov10:06:32

@U0ETXRFEW We actually have re-frame subs linter at Pitch and its implementation can be used for this purpose as well 🙂


A while ago @U0FR82FU1 also reached out about something similar, but I haven't heard back. So I assume it was covered already, but if not, please let me know


@U04V15CAJ I'm pretty sure that @U0FR82FU1 reached out about a different use case, but very cool to find that we have this experience in-house! 😃


ok, then I will assume that @U0FR82FU1 can help you with the internal linter and if you need anything from clj-kondo, let me know


The reason I wonder if the linter I am describing above is even possible is the dynamic nature of the what our library works on. Maybe it is similar to how re-frame subscriptions are registered, idk. What I mostly want to know now is the feasibility aspect. If it is even worth trying.

Søren Sjørup20:06:08

With clj-kondo v2022.06.22 I’m getting error: Unresolved symbol: parse-long in cljc and cljs files. Is that to be expected or do I need to change a config?


This symbol is only unresolved if you have an older version of clojurescript on your classpath and the classpath is analyzed by clj-kondo

Søren Sjørup21:06:02

Hmm ok. I’m using nbb for the cljs, not sure where I’ve set a clojurescript on my path. Will look into it, thanks!


@U021UJJ3CQ6 I can't reproduce this problem here locally. Can you try from the command line?

Søren Sjørup21:06:30

Yes I see it both in command line and VSCode.


Is your nbb project in the same directory as some other project perhaps? What does clojure -Spath display, is cljs in there?

Søren Sjørup21:06:59

Yes it’s in the same dir, it’s quite a mess I must admit. This is my path. src:/Users/soren/.m2/repository/borkdude/edamame/1.0.0/edamame-1.0.0.jar:/Users/soren/.m2/repository/org/clojure/clojure/1.11.1/clojure-1.11.1.jar:/Users/soren/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar:/Users/soren/.m2/repository/org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar:/Users/soren/.m2/repository/org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar


No worries. But no CLJS it seems in there right?


You could try to delete .clj-kondo/.cache and restart your editor / reload workspace


Perhaps some older stale cache

Søren Sjørup21:06:10

That worked! 🙂