Skip to content

Instantly share code, notes, and snippets.

@ethpran
Last active July 21, 2023 21:27
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ethpran/e1741a5c408aec831b5e3a7e24f40fea to your computer and use it in GitHub Desktop.
Save ethpran/e1741a5c408aec831b5e3a7e24f40fea to your computer and use it in GitHub Desktop.
clj-kondo hook for mount/defstate
{:linters {:mount/defstate {:level :warning}}
:hooks {:analyze-call {mount.core/defstate hooks.defstate/defstate}}}
(ns hooks.defstate
(:require [clj-kondo.hooks-api :as api]))
(defn defstate [{:keys [:node]}]
(let [args (rest (:children node))
args (if (string? (api/sexpr (first args)))
(next args)
args)
[n & args] args
m (when-let [m (first (:meta n))]
(api/sexpr m))
m (if (map? m) m {})
ks (cond-> (take 1 args)
(> (count args) 2) (conj (nth args 2)))
invalid-key (first (remove (comp (partial contains? #{:start :stop}) api/sexpr) ks))]
(cond
invalid-key
(api/reg-finding!
{:message (str "lifecycle functions can only contain `:start` and `:stop`. illegal function found: " (api/sexpr invalid-key))
:type :mount/defstate
:row (:row (meta invalid-key))
:col (:col (meta invalid-key))})
(not (contains? (set (map api/sexpr ks)) :start))
(throw (ex-info "lifecycle functions must include `:start`" {}))
((complement contains?) #{2 4} (count args))
(throw (ex-info "lifecycle functions must consist of no more than 2 pair forms: `:start` and `:stop`" {}))
(and (contains? m :on-reload) (not (contains? #{:noop :stop} (:on-reload m))))
(api/reg-finding!
{:message "metadata `:on-reload` key can only have value of `noop` or `stop`"
:type :mount/defstate
:row (:row (meta n))
:col (:col (meta n))})
:else
{:node (api/list-node
(list*
(api/token-node 'fn*)
(api/vector-node [n])
n
args))})))
@brancusi
Copy link

brancusi commented Sep 8, 2021

Thank you for this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment