Skip to content

Commit

Permalink
Add clj-kondo configs
Browse files Browse the repository at this point in the history
  • Loading branch information
borkdude committed Oct 27, 2023
1 parent ffb8063 commit 1027686
Show file tree
Hide file tree
Showing 13 changed files with 246 additions and 2 deletions.
1 change: 1 addition & 0 deletions .clj-kondo/babashka/sci/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{:hooks {:macroexpand {sci.core/copy-ns sci.core/copy-ns}}}
9 changes: 9 additions & 0 deletions .clj-kondo/babashka/sci/sci/core.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(ns sci.core)

(defmacro copy-ns
([ns-sym sci-ns]
`(copy-ns ~ns-sym ~sci-ns nil))
([ns-sym sci-ns opts]
`[(quote ~ns-sym)
~sci-ns
(quote ~opts)]))
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
(ns com.fulcrologic.fulcro.clj-kondo-hooks
(:require [clj-kondo.hooks-api :as api]))

(defn defmutation
[{:keys [node]}]
(let [args (rest (:children node))
mutation-name (first args)
?docstring (when (string? (api/sexpr (second args)))
(second args))
args (if ?docstring
(nnext args)
(next args))
params (first args)
handlers (rest args)
handler-syms (map (comp first :children) handlers)
bogus-usage (api/vector-node (vec handler-syms))
letfn-node (api/list-node
(list
(api/token-node 'letfn)
(api/vector-node (vec handlers))
bogus-usage))
new-node (api/list-node
(list
(api/token-node 'defn)
mutation-name
params
letfn-node))]
(doseq [handler handlers]
(let [hname (some-> handler :children first api/sexpr str)
argv (some-> handler :children second)]
(when-not (= 1 (count (api/sexpr argv)))
(api/reg-finding! (merge
(meta argv)
{:message (format "defmutation handler '%s' should be a fn of 1 arg" hname)
:type :clj-kondo.fulcro.defmutation/handler-arity})))))
{:node new-node}))

(defn >defn
[{:keys [node]}]
(let [args (rest (:children node))
fn-name (first args)
?docstring (when (string? (api/sexpr (second args)))
(second args))
args (if ?docstring
(nnext args)
(next args))
argv (first args)
gspec (second args)
body (nnext args)
new-node (api/list-node
(list*
(api/token-node 'defn)
fn-name
argv
gspec
body))]
(when (not= (count (api/sexpr argv))
(count (take-while #(not= '=> %) (api/sexpr gspec))))
(api/reg-finding! (merge (meta gspec)
{:message "Guardrail spec does not match function signature"
:type :clj-kondo.fulcro.>defn/signature-mismatch})))
{:node new-node}))
20 changes: 20 additions & 0 deletions .clj-kondo/com.fulcrologic/fulcro/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{:hooks {:analyze-call {com.fulcrologic.fulcro.mutations/defmutation com.fulcrologic.fulcro.clj-kondo-hooks/defmutation
com.fulcrologic.guardrails.core/>defn com.fulcrologic.fulcro.clj-kondo-hooks/>defn}}
:linters {:clj-kondo.fulcro.defmutation/handler-arity {:level :error}
:clj-kondo.fulcro.>defn/signature-mismatch {:level :error}}
:lint-as {com.fulcrologic.fulcro.algorithms.normalized-state/swap!-> clojure.core/->
com.fulcrologic.fulcro.components/defsc clojure.core/defn
com.fulcrologic.fulcro.inspect.inspect-client/ido clojure.core/do
com.fulcrologic.fulcro.inspect.inspect-client/ilet clojure.core/let
com.fulcrologic.fulcro.mutations/declare-mutation clojure.core/def
com.fulcrologic.fulcro.raw.components/defnc clojure.core/def
com.fulcrologic.fulcro.routing.dynamic-routing/defrouter clojure.core/defn
com.fulcrologic.fulcro.routing.legacy-ui-routers/defsc-router clojure.core/defn
com.fulcrologic.fulcro.ui-state-machines/defstatemachine clojure.core/def
com.fulcrologic.guardrails.core/>def clojure.core/def
com.fulcrologic.guardrails.core/>defn clojure.core/defn
com.fulcrologic.guardrails.core/>defn- clojure.core/defn-
com.fulcrologic.rad.attributes/defattr clojure.core/def
com.fulcrologic.rad.authorization/defauthenticator clojure.core/def
com.fulcrologic.rad.form/defsc-form clojure.core/defn
com.fulcrologic.rad.report/defsc-report clojure.core/defn}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
(ns com.fulcrologic.guardrails.clj-kondo-hooks
(:require [clj-kondo.hooks-api :as api]))

(def =>? #{'=> :ret})
(def |? #{'| :st})
(def known-sym? #{'=> '| '<-})

(defn args+gspec+body [nodes]
(let [argv (first nodes)
gspec (second nodes)
body (nnext nodes)
gspec' (->> gspec
(:children)
(filterv #(-> % :value known-sym? not))
(api/vector-node))
new-nodes (list* argv gspec' body)]
;; gspec: [arg-specs* (| arg-preds+)? => ret-spec (| fn-preds+)? (<- generator-fn)?]
(if (not= 1 (count (filter =>? (api/sexpr gspec))))
(api/reg-finding! (merge (meta gspec)
{:message (str "Gspec requires exactly one `=>` or `:ret`")
:type :clj-kondo.fulcro.>defn/invalid-gspec}))
(let [p (partition-by (comp not =>? api/sexpr) (:children gspec))
[arg [=>] [ret-spec & _output]] (if (-> p ffirst api/sexpr =>?)
(cons [] p) ; arg-specs might be empty
p)
[arg-specs [| & arg-preds]] (split-with (comp not |? api/sexpr) arg)]

(when-not ret-spec
(println =>)
(api/reg-finding! (merge (meta =>)
{:message "Missing return spec."
:type :clj-kondo.fulcro.>defn/invalid-gspec})))

;; (| arg-preds+)?
(when (and | (empty? arg-preds))
(api/reg-finding! (merge (meta |)
{:message "Missing argument predicates after |."
:type :clj-kondo.fulcro.>defn/invalid-gspec})))


(let [len-argv (count (remove #{'&} (api/sexpr argv))) ; [a & more] => 2 arguments
arg-difference (- (count arg-specs) len-argv)]
(when (not (zero? arg-difference))
(let [too-many-specs? (pos? arg-difference)]
(api/reg-finding! (merge
(meta (if too-many-specs?
(nth arg-specs (+ len-argv arg-difference -1)) ; first excess spec
gspec)) ; The gspec is wrong, not the surplus argument.
{:message (str "Guardrail spec does not match function signature. "
"Too " (if too-many-specs? "many" "few") " specs.")
:type :clj-kondo.fulcro.>defn/invalid-gspec})))))))
new-nodes))

(defn >defn
[{:keys [node]}]
(let [args (rest (:children node))
fn-name (first args)
?docstring (when (some-> (second args) api/sexpr string?)
(second args))
args (if ?docstring
(nnext args)
(next args))
post-docs (if (every? #(-> % api/sexpr list?) args)
(mapv #(-> % :children args+gspec+body api/list-node) args)
(args+gspec+body args))
post-name (if ?docstring
(list* ?docstring post-docs)
post-docs)
new-node (api/list-node
(list*
(api/token-node 'defn)
fn-name
post-name))]
{:node new-node}))
6 changes: 6 additions & 0 deletions .clj-kondo/com.fulcrologic/guardrails/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{:hooks {:analyze-call {com.fulcrologic.guardrails.core/>defn
com.fulcrologic.guardrails.clj-kondo-hooks/>defn
com.fulcrologic.guardrails.core/>defn-
com.fulcrologic.guardrails.clj-kondo-hooks/>defn}}
:linters {:clj-kondo.fulcro.>defn/invalid-gspec {:level :error}}
:lint-as {com.fulcrologic.guardrails.core/>def clojure.spec.alpha/def}}
1 change: 1 addition & 0 deletions .clj-kondo/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{:lint-as {sci.configs.macros/defmacro clojure.core/defmacro}}
9 changes: 9 additions & 0 deletions .clj-kondo/funcool/promesa/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{:lint-as {promesa.core/-> clojure.core/->
promesa.core/->> clojure.core/->>
promesa.core/as-> clojure.core/as->
promesa.core/let clojure.core/let
promesa.core/plet clojure.core/let
promesa.core/loop clojure.core/loop
promesa.core/recur clojure.core/recur
promesa.core/with-redefs clojure.core/with-redefs
promesa.core/doseq clojure.core/doseq}}
36 changes: 36 additions & 0 deletions .clj-kondo/hoplon/hoplon/clj_kondo/hoplon.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
(ns clj-kondo.hoplon
(:require [clj-kondo.hooks-api :as api]))

(defn hoplon-core-defelem
[{:keys [node]}]
(let [[_defelem name & forms] (:children node)
[docstr & [args & body]] (if (api/string-node? (first forms))
forms
(concat [""] forms))]
{:node (api/list-node
(list*
(api/token-node 'defn)
name
docstr
(api/vector-node
[(api/token-node '&) args])
body))}))

(defn hoplon-core-elem
[{:keys [node]}]
(let [[_elem & [args & body]] (:children node)]
{:node (api/list-node
(list*
(api/token-node 'fn)
(api/vector-node
[(api/token-node '&) args])
body))}))

(defn hoplon-core-loop-tpl
[{:keys [node]}]
(let [[_loop-tpl _bindings-kw bind & body] (:children node)]
{:node (api/list-node
(list*
(api/token-node 'for)
bind
body))}))
11 changes: 11 additions & 0 deletions .clj-kondo/hoplon/hoplon/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{:lint-as {castra.core/defrpc clojure.core/defn
hoplon.core/for-tpl clojure.core/for
javelin.core/cell-let clojure.core/let
javelin.core/cell-doseq clojure.core/doseq
javelin.core/defc clojure.core/def
javelin.core/defc= clojure.core/def
javelin.core/formulet clojure.core/let
javelin.core/with-let clojure.core/let}
:hooks {:analyze-call {hoplon.core/elem clj-kondo.hoplon/hoplon-core-elem
hoplon.core/defelem clj-kondo.hoplon/hoplon-core-defelem
hoplon.core/loop-tpl clj-kondo.hoplon/hoplon-core-loop-tpl}}}
1 change: 1 addition & 0 deletions .clj-kondo/taoensso/encore/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{:hooks {:analyze-call {taoensso.encore/defalias taoensso.encore/defalias}}}
16 changes: 16 additions & 0 deletions .clj-kondo/taoensso/encore/taoensso/encore.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
(ns taoensso.encore
(:require
[clj-kondo.hooks-api :as hooks]))

(defn defalias [{:keys [node]}]
(let [[sym-raw src-raw] (rest (:children node))
src (if src-raw src-raw sym-raw)
sym (if src-raw
sym-raw
(symbol (name (hooks/sexpr src))))]
{:node (with-meta
(hooks/list-node
[(hooks/token-node 'def)
(hooks/token-node (hooks/sexpr sym))
(hooks/token-node (hooks/sexpr src))])
(meta src))}))
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
.clj-kondo
.cache
.lsp
.DS_Store
.cpcache
cljs-test-runner-out
Expand Down

0 comments on commit 1027686

Please sign in to comment.