Skip to content

Commit

Permalink
lint for non-reactive re-frame subscriptions in UIx components
Browse files Browse the repository at this point in the history
  • Loading branch information
roman01la committed Jul 6, 2022
1 parent 2c054d4 commit 0716507
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 17 deletions.
18 changes: 3 additions & 15 deletions core/src/uix/dev.clj
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
(ns uix.dev
(:require [clojure.string :as str]
[uix.hooks.linter :as hooks.linter]))
[uix.hooks.linter :as hooks.linter]
[uix.lib]))

(def ^:private goog-debug (with-meta 'goog.DEBUG {:tag 'boolean}))

(defn find-hooks
"Takes body of a component as sexpr and returns
a collection of sexprs for hook calls"
[body]
(let [hooks (atom [])]
(clojure.walk/prewalk
(fn [x]
(when (hooks.linter/hook-call? x)
(swap! hooks conj x))
x)
body)
@hooks))

(defn with-fast-refresh [var-sym fdecl]
(let [signature `(when ~goog-debug
(when-let [f# (.-fast-refresh-signature ~var-sym)]
Expand All @@ -30,6 +18,6 @@
`(when ~goog-debug
(when (cljs.core/exists? js/window.uix.dev)
(let [sig# (js/window.uix.dev.signature!)]
(sig# ~var-sym ~(str/join (find-hooks body)) nil nil)
(sig# ~var-sym ~(str/join (uix.lib/find-form hooks.linter/hook-call? body)) nil nil)
(js/window.uix.dev.register! ~var-sym (.-displayName ~var-sym))
(set! (.-fast-refresh-signature ~var-sym) sig#)))))
23 changes: 22 additions & 1 deletion core/src/uix/hooks/linter.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
[cljs.analyzer :as ana]
[clojure.string :as str]
[clojure.pprint :as pp]
[cljs.analyzer.api :as ana-api])
[cljs.analyzer.api :as ana-api]
[uix.lib])
(:import (cljs.tagged_literals JSValue)
(java.io Writer)))

Expand Down Expand Up @@ -160,9 +161,29 @@
"every component render.\n"
"Found in " name ", at " line ":" column))

;; re-frame linter

(defn- rf-subscribe-call? [form]
(and (list? form)
(symbol? (first form))
(= "subscribe" (name (first form)))))

(defn lint-re-frame! [form env]
(let [sources (->> (uix.lib/find-form rf-subscribe-call? form)
(keep #(let [v (ana/resolve-var env (first %))]
(when (contains? '#{re-frame.core pitch.app.core pitch.app.re-frame} (:ns v))
(assoc v :source %)))))]
(run! #(ana/warning ::non-reactive-re-frame-subscribe env %)
sources)))

(defmethod ana/error-message ::non-reactive-re-frame-subscribe [_ {:keys [source] :as v}]
(str "re-frame subscription " source " is non-reactive in UIx components when called via "
(:name v) ", use `use-subscribe` hook instead."))

(defn lint! [sym form env]
(binding [*component-context* (atom {:errors []})]
(lint-hooks! form)
(lint-re-frame! form env)
(let [{:keys [errors]} @*component-context*
{:keys [column line]} env]
(run! #(ana/warning (:type %) env (into {:name (str (-> env :ns :name) "/" sym)
Expand Down
14 changes: 13 additions & 1 deletion core/src/uix/lib.cljc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns uix.lib
#?(:cljs (:require-macros [uix.lib :refer [doseq-loop]]))
#?(:cljs (:require [goog.object :as gobj])))
#?(:cljs (:require [goog.object :as gobj]))
#?(:clj (:require [clojure.walk])))

#?(:clj
(defmacro assert! [x message]
Expand Down Expand Up @@ -29,3 +30,14 @@
#?(:clj
(defn cljs-env? [env]
(boolean (:ns env))))

#?(:clj
(defn find-form [pred sexp]
(let [forms (atom [])]
(clojure.walk/prewalk
(fn [x]
(when (pred x)
(swap! forms conj x))
x)
sexp)
@forms)))

0 comments on commit 0716507

Please sign in to comment.