Skip to content

Instantly share code, notes, and snippets.

@ethpran
Last active July 21, 2023 21:27
Show Gist options
  • Select an option

  • Save ethpran/e1741a5c408aec831b5e3a7e24f40fea to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

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