📎 Improve clj-kondo hooks, including if-let

This commit is contained in:
Miguel de Benito Delgado 2026-10-05 12:10:14 +02:00
parent d5272e3179
commit cddccf6338
4 changed files with 140 additions and 20 deletions

View File

@ -24,9 +24,10 @@
shadow.lazy/loadable hooks.export/rumext-lazycomponent
app.util.i18n/tr hooks.i18n/tr-dynamic
app.common.i18n/tr hooks.i18n/tr-dynamic
benches.render-wasm.declarations/defscene hooks.export/benches-defscene
benches.render-wasm.declarations/defcase hooks.export/benches-defcase
}}
clojure.core/let hooks.core/check-let
cljs.core/let hooks.core/check-let
benches.render-wasm.declarations/defscene hooks.benches/defscene
benches.render-wasm.declarations/defcase hooks.benches/defcase}}
:output
{:exclude-files
@ -103,6 +104,10 @@
:unused-binding
{:exclude-destructured-as true
:exclude-destructured-keys-in-fn-args false
}
}}
:exclude-destructured-keys-in-fn-args false}
:core/use-if-let
{:level :warning}
:core/use-when-let
{:level :warning}}}

View File

@ -0,0 +1,26 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS SUBSIDIARY SL
(ns hooks.benches
(:require [clj-kondo.hooks-api :as api]))
(defn defscene
"Analyzes scene options and its compiled builder body."
[{:keys [node]}]
(let [[_ _ opts argv & body] (:children node)]
(if (and argv (api/vector-node? argv))
{:node (api/list-node [(api/token-node (quote do)) opts
(api/list-node (into [(api/token-node (quote fn)) argv] body))])}
{:node node})))
(defn defcase
"Analyzes case options and its compiled operation body."
[{:keys [node]}]
(let [[_ _ opts argv & body] (:children node)]
(if (and (seq body) argv (api/vector-node? argv))
{:node (api/list-node [(api/token-node (quote do)) opts
(api/list-node (into [(api/token-node (quote fn)) argv] body))])}
{:node node})))

97
.clj-kondo/hooks/core.clj Normal file
View File

@ -0,0 +1,97 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS SUBSIDIARY SL
(ns hooks.core
(:require [clj-kondo.hooks-api :as api]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; if-let, when-let
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- use-if-let?
[form]
(let [[_ bindings & body] form]
(and
;; Exactly one binding pair.
(vector? bindings)
(= 2 (count bindings))
;; Exactly one body form.
(= 1 (count body))
(let [[binding-sym _] bindings
if-form (first body)]
(and
;; Exclude destructuring for v0.
(symbol? binding-sym)
;; Exactly: (if binding-sym then else)
(seq? if-form)
(= 4 (count if-form))
(= 'if (first if-form))
(= binding-sym (second if-form)))))))
(defn- use-if-let
"Flags:
(let [x (foo)]
(if x
(bar x)
(baz)))
"
[{:keys [node]}]
(when (use-if-let? (api/sexpr node))
(api/reg-finding!
(assoc (meta (first (:children node)))
:type :core/use-if-let
:message "Use if-let instead of let followed by if.")))
nil)
(defn- use-when-let?
[form]
(let [[_ bindings & body] form]
(and
;; Exactly one binding pair.
(vector? bindings)
(= 2 (count bindings))
;; Exactly one body form.
(= 1 (count body))
(let [[binding-sym _] bindings
when-form (first body)]
(and
;; Exclude destructuring for v0.
(symbol? binding-sym)
;; (when binding-sym & body) with at least one body form.
(seq? when-form)
(<= 3 (count when-form))
(= 'when (first when-form))
(= binding-sym (second when-form)))))))
(defn- use-when-let
"Flags:
(let [x (foo)]
(when x
(bar x)))
"
[{:keys [node]}]
(when (use-when-let? (api/sexpr node))
(api/reg-finding!
(assoc (meta (first (:children node)))
:type :core/use-when-let
:message "Use when-let instead of let followed by when.")))
nil)
(defn check-let
"Runs the let-body checks (if-let, when-let)."
[{:keys [node] :as m}]
(use-if-let m)
(use-when-let m)
nil)

View File

@ -1,3 +1,9 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS SUBSIDIARY SL
(ns hooks.export
(:require [clj-kondo.hooks-api :as api]))
@ -10,20 +16,6 @@
sname])]
{:node result}))
(defn benches-defscene
[{:keys [node]}]
(let [[_ _ opts argv & body] (:children node)]
(if (and argv (api/vector-node? argv))
{:node (api/list-node (into [(api/token-node (quote fn)) argv] body))}
{:node node})))
(defn benches-defcase
[{:keys [node]}]
(let [[_ _ opts argv & body] (:children node)]
(if (and (seq body) argv (api/vector-node? argv))
{:node (api/list-node (into [(api/token-node (quote fn)) argv] body))}
{:node node})))
(def registry (atom {}))