logseq/.clj-kondo/hooks/rum.clj

69 lines
2.4 KiB
Clojure
Raw Normal View History

(ns hooks.rum
(:require [clj-kondo.hooks-api :as api]))
(defn fn-body? [x]
(and (seq? x)
(vector? (first x))))
(defn rewrite-body [mixins body defcs?]
(if defcs?
(let [[binding-vec & body] (:children body)
[state-arg & rest-args] (:children binding-vec)
;; the original vector without the state argument
fn-args (assoc binding-vec :children rest-args)
body (api/list-node
(list* (api/token-node 'let*)
(api/vector-node [state-arg (api/token-node nil)])
state-arg
(concat mixins body)))
body (api/list-node [fn-args body])]
body)
(let [[binding-vec & body] (:children body)]
(api/list-node (cons binding-vec (concat mixins body))))))
(defn rewrite
([node] (rewrite node false))
([node defcs?]
(let [args (rest (:children node))
component-name (first args)
?docstring (when (string? (api/sexpr (second args)))
(second args))
args (if ?docstring
(nnext args)
(next args))
bodies
(loop [args* (seq args)
mixins []
bodies []]
(if args*
(let [a (first args*)
a-sexpr (api/sexpr a)]
(cond (vector? a-sexpr) ;; a-sexpr is a binding vec and the rest is the body of the function
[(rewrite-body mixins (api/list-node args*) defcs?)]
(fn-body? a-sexpr)
(recur (next args*)
mixins
(conj bodies (rewrite-body mixins a defcs?)))
;; assume mixin
:else (recur (next args*)
(conj mixins a)
bodies)))
bodies))
new-node (with-meta
(api/list-node
(list* (api/token-node 'defn)
component-name
(if ?docstring
(cons ?docstring bodies)
bodies)))
(meta node))]
new-node)))
(defn defc [{:keys [:node]}]
(let [new-node (rewrite node)]
{:node new-node}))
(defn defcs [{:keys [:node]}]
(let [new-node (rewrite node true)]
{:node new-node}))