Skip to content
Snippets Groups Projects
Unverified Commit 9f690db2 authored by Ngoc Khuat's avatar Ngoc Khuat Committed by GitHub
Browse files

Kondo: ignore all libraries config (#36889)

* Kondo: ignore all libraries config

* Add README

* Update .gitignore
parent 5f968e6b
No related branches found
No related tags found
No related merge requests found
Showing
with 0 additions and 363 deletions
{:lint-as {babashka.fs/with-temp-dir clojure.core/let}}
{:hooks {:macroexpand {sci.core/copy-ns sci.core/copy-ns}}}
(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)]))
(ns better-cond.core
"A clj-kondo hook to allow linting of better-cond `cond` macro.
This supports better-cond version 2.0.0+.
To use in a project, change the namespace to hooks.better-cond,
put this code in file .clj-kondo/hooks/better_cond.clj, and include
a config.edn entry in the :hooks key like:
:hooks {:analyze-call {better-cond.core/cond hooks.better-cond/cond}}
Note that the expansion of :when-let and :when-some forms currently
takes a shortcut that *would* lead to incorrect values in some
cases of restructuring during actual expansion/evaluation, e.g.,
:when-let [[x y] nil] would not abort the cond, though :when-let
[[x y] [nil nil]] would. However, for linting purposes, the current
expansion approach works just fine. It seems unnecessary to do the
full expansion in these cases for linting purposes, though that could
be done if needed."
(:refer-clojure :exclude [cond])
(:require
[clj-kondo.hooks-api :as api]
[clojure.string :as str]))
(def better-cond-simple-keys
"Special constructs in better cond, either as keywords or symbols.
This includes those keys that are simply transformed. Note that
:when-let and :when-some are *not* included as better-cond allows
multiple bindings but clojure does not. These two must be handled
separately."
#{:let :when :do
'let 'when 'do})
(def better-cond-complex-keys
"Special constructs in better cond, either as keywords or symbols.
This includes those keys that require a multi-step transformation.
For example, :when-let and :when-some get converted to a let
wrapping a when, wrapping the continuing cond. Note that clojure
does not support multiple bindings in the standard when-let and
when-some macros."
{:when-let 'identity
'when-let 'identity
:when-some 'some?
'when-some 'some?})
(defn extract-binding-forms
[bindings]
(keep-indexed #(when (even? %1) %2) bindings))
(defn process-pairs
"Transforms a `cond` with the clauses given as a collection of explicit pairs.
Handles all the special better-cond constructs as keywords or symbols.
Returns a rewrite-clj list-node representing the transformed code."
[node-pairs]
(loop [[[lhs rhs :as pair] & pairs] node-pairs
new-body [(api/token-node 'clojure.core/cond)]] ; Avoid reprocessing the cond with ns here
(if pair
(let [lhs-sexpr (api/sexpr lhs)]
(clojure.core/cond
(= 1 (count pair)) ;; better-cond allows single clause for default
, (api/list-node (conj new-body (api/keyword-node :else) lhs))
(better-cond-simple-keys lhs-sexpr) ;; Handle special better-cond constructs
, (api/list-node
(conj new-body
(api/keyword-node :else)
(api/list-node [(api/token-node (symbol #_"clojure.core" (name lhs-sexpr)))
rhs
(process-pairs pairs)])))
(better-cond-complex-keys lhs-sexpr) ;; Multi stage constructs
, (api/list-node
(conj new-body
(api/keyword-node :else)
(api/list-node [(api/token-node 'let)
rhs
(api/list-node [(api/token-node 'when)
(api/list-node ;; ATTN: shortcut here; fine for linting
[(api/token-node 'every?)
(api/token-node (better-cond-complex-keys lhs-sexpr))
(api/vector-node (->> rhs
api/sexpr
extract-binding-forms
(map api/token-node)))])
(process-pairs pairs)])])))
:else
, (recur pairs (conj new-body lhs rhs))))
(api/list-node new-body))))
(defn cond-hook
[{:keys [node]}]
(let [expr (let [args (rest (:children node))
pairs (partition-all 2 args)]
(process-pairs pairs))]
{:node (with-meta expr
(meta node))}))
(defn process-if-let-pairs [pairs then else]
(if (seq pairs)
(let [[lhs rhs] (first pairs)]
(if (and (api/keyword-node? lhs)
(= :let (api/sexpr lhs)))
(api/list-node (conj [(api/token-node 'clojure.core/let) rhs
(process-if-let-pairs (next pairs) then else)]))
(let [test (api/token-node (gensym "test"))]
(api/list-node
(conj [(api/token-node 'clojure.core/let) (api/vector-node [test rhs])
(api/list-node [(api/token-node 'if) test
(api/list-node
[(api/token-node 'clojure.core/let)
(api/vector-node [lhs test])
(process-if-let-pairs (next pairs) then else)])
else])])))))
then))
(defn if-let-hook
[{:keys [node]}]
(let [expr (let [[binding-vec then else] (rest (:children node))
pairs (partition-all 2 (:children binding-vec))
node (process-if-let-pairs pairs then else)]
node)]
{:node (with-meta expr
(meta node))}))
(defn when-let-hook
[{:keys [node]}]
(let [expr (let [[binding-vec & body] (rest (:children node))]
(api/list-node
[(api/token-node 'better-cond.core/if-let)
binding-vec
(api/list-node (list* (api/token-node 'do)
body))]))]
{:node (with-meta expr
(meta node))}))
(defn defnc-hook [{:keys [node]}]
(let [[defnc-node name-node arg-node & body]
(:children node)
new-node (api/list-node [(api/token-node (if (str/ends-with? (str defnc-node)
"defnc-")
'clojure.core/defn-
'clojure.core/defn))
name-node
arg-node
(api/list-node
(list* (api/token-node 'better-cond.core/cond)
body))])]
{:node new-node}))
{:hooks
{:analyze-call
{better-cond.core/cond better-cond.core/cond-hook
better-cond.core/defnc better-cond.core/defnc-hook
better-cond.core/defnc- better-cond.core/defnc-hook
better-cond.core/if-let better-cond.core/if-let-hook
better-cond.core/if-some better-cond.core/if-let-hook
better-cond.core/when-let better-cond.core/when-let-hook
better-cond.core/when-some better-cond.core/when-let-hook}}}
(ns clj-kondo.com.gfredericks.test.chuck.checking
(:require
[clj-kondo.hooks-api :as api]))
(defn checking
[{{:keys [children]} :node}]
(let [[_checking desc & opt+bindings+body] children
[opts binding-vec & body] (if (api/vector-node? (first opt+bindings+body))
(into [(api/map-node {})] opt+bindings+body)
opt+bindings+body)]
(when-not (even? (count (:children binding-vec)))
(throw (ex-info "checking requires an even number of bindings" {})))
{:node (api/list-node
(list*
(api/token-node 'let)
(api/vector-node (into [(api/token-node (symbol (gensym "_checking-desc"))) desc]
(:children binding-vec)))
opts
body))}))
{:hooks
{:analyze-call
{com.gfredericks.test.chuck.clojure-test/checking
clj-kondo.com.gfredericks.test.chuck.checking/checking}}}
{:lint-as
{humane-are.core/are+ clojure.test/are}}
{:config-paths
["macros"]
:lint-as
{toucan2.core/build clojure.core/identity
toucan2.core/compile clojure.core/identity
toucan2.query/with-built-query clojure.core/let
toucan2.tools.compile/build clojure.core/identity
toucan2.tools.compile/compile clojure.core/identity}
:hooks
{:analyze-call
{toucan2.connection/with-connection hooks.toucan2.connection/with-connection
toucan2.connection/with-transaction hooks.toucan2.connection/with-transaction
toucan2.core/with-connection hooks.toucan2.connection/with-connection
toucan2.core/with-transaction hooks.toucan2.connection/with-transaction
toucan2.tools.simple-out-transform/define-out-transform hooks.toucan2.tools.simple-out-transform/define-out-transform
toucan2.tools.with-temp/with-temp hooks.toucan2.tools.with-temp/with-temp}
:macroexpand
{toucan.db/with-call-counting macros.toucan2.execute/with-call-count
toucan.models/defmodel macros.toucan.models/defmodel
toucan2.core/define-after-insert macros.toucan2.tools.after-insert/define-after-insert
toucan2.core/define-after-select macros.toucan2.tools.helpers/define-after-select
toucan2.core/define-after-update macros.toucan2.tools.after-update/define-after-update
toucan2.core/define-before-delete macros.toucan2.tools.helpers/define-before-delete
toucan2.core/define-before-insert macros.toucan2.tools.before-insert/define-before-insert
toucan2.core/define-before-select macros.toucan2.tools.helpers/define-before-select
toucan2.core/define-before-update macros.toucan2.tools.before-update/define-before-update
toucan2.execute/with-call-count macros.toucan2.execute/with-call-count
toucan2.tools.after-insert/define-after-insert macros.toucan2.tools.after-insert/define-after-insert
toucan2.tools.after-select/define-after-select macros.toucan2.tools.helpers/define-after-select
toucan2.tools.after-update/define-after-update macros.toucan2.tools.after-update/define-after-update
toucan2.tools.before-delete/define-before-delete macros.toucan2.tools.helpers/define-before-delete
toucan2.tools.before-insert/define-before-insert macros.toucan2.tools.before-insert/define-before-insert
toucan2.tools.before-select/define-before-select macros.toucan2.tools.helpers/define-before-select
toucan2.tools.before-update/define-before-update macros.toucan2.tools.before-update/define-before-update
toucan2.tools.default-fields/define-default-fields macros.toucan2.tools.default-fields/define-default-fields
toucan2.tools.named-query/define-named-query macros.toucan2.tools.named-query/define-named-query}}}
(ns hooks.toucan2.connection
(:require [clj-kondo.hooks-api :as hooks]))
(defn with-connection [{{[_ bindings & body] :children} :node}]
(let [[conn-binding connectable] (:children bindings)]
{:node (hooks/list-node
(list*
(hooks/token-node 'let)
(hooks/vector-node [conn-binding (or connectable
(hooks/token-node 'nil))])
body))}))
(defn with-transaction [node]
(with-connection node))
(ns hooks.toucan2.tools.simple-out-transform
(:require [clj-kondo.hooks-api :as hooks]))
(defn- ignore-unused-binding [x]
(vary-meta x assoc :clj-kondo/ignore [:unused-binding]))
(defn define-out-transform
[{{[_define-out-transform dispatch-value {[instance-binding] :children, :as bindings} & body] :children, :as node} :node}]
{:node (-> (hooks/list-node
[(hooks/token-node 'do)
dispatch-value
(hooks/list-node
(list*
(hooks/token-node 'fn)
(-> (hooks/vector-node
[(ignore-unused-binding (with-meta (hooks/token-node '&query-type) (meta bindings)))
(ignore-unused-binding (with-meta (hooks/token-node '&model) (meta bindings)))
instance-binding])
(with-meta (meta bindings)))
body))])
(with-meta (meta node)))})
(comment
(defn test-define-out-transform []
(as-> '(tools.simple-out-transform/define-out-transform [:toucan.query-type/select.instances ::after-select]
[instance]
(let [wow 1000]
;; don't do after-select if this select is a result of doing something like insert-returning instances
(if (isa? &query-type :toucan2.pipeline/select.instances-from-pks)
instance
(after-select instance)))) <>
(hooks/parse-string (pr-str <>))
(define-out-transform {:node <>})
(:node <>)
(hooks/sexpr <>)
(binding [*print-meta* false #_true]
(clojure.pprint/pprint <>)))))
(ns hooks.toucan2.tools.with-temp
(:require [clj-kondo.hooks-api :as hooks]))
(defn with-temp [{{[_with-temp {bindings :children} & body] :children} :node}]
(let [bindings* (into
[]
(comp (partition-all 3)
(mapcat (fn [[model binding attributes]]
(let [binding (or binding (hooks/token-node '_))
attributes (or attributes (hooks/token-node 'nil))]
[binding (hooks/list-node
(list
(hooks/token-node 'do)
model
attributes))]))))
bindings)
node* (hooks/list-node
(list*
(hooks/token-node 'let)
(hooks/vector-node bindings*)
body))]
{:node node*}))
(ns macros.toucan.models)
(defmacro defmodel
[model _table-name]
`(def ~model "Docstring." ~(keyword (name model))))
(ns macros.toucan2.common)
(defn ignore-unused [symb]
(vary-meta symb assoc :clj-kondo/ignore [:unused-binding]))
(ns macros.toucan2.execute)
(defmacro with-call-count
[[call-count-fn-binding] & body]
`(let [~call-count-fn-binding (fn [])]
~@body))
(ns macros.toucan2.tools.after-insert
(:require [macros.toucan2.common :as common]))
(defmacro define-after-insert
[model [instance-binding] & body]
`(do
~model
(fn [~(common/ignore-unused '&model)
~instance-binding]
~@body)))
(ns macros.toucan2.tools.after-update
(:require [macros.toucan2.common :as common]))
(defmacro define-after-update
[model [instance-binding] & body]
`(do
~model
(fn [~(common/ignore-unused '&model)
~instance-binding]
~@body)))
(ns macros.toucan2.tools.before-insert
(:require [macros.toucan2.common :as common]))
(defmacro define-before-insert
[model [instance-binding] & body]
`(do
~model
(fn [~(common/ignore-unused '&model)
~instance-binding]
~@body)))
(ns macros.toucan2.tools.before-update
(:require [macros.toucan2.common :as common]))
(defmacro define-before-update
[model [instance-binding] & body]
`(do
~model
(fn [~(common/ignore-unused '&model)
~instance-binding]
~@body)))
(ns macros.toucan2.tools.default-fields
(:require [macros.toucan2.common :as common]))
(defmacro define-default-fields [model & body]
`(let [~(common/ignore-unused '&model) ~model]
~@body))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment