From ef569c45ca23117c7f23bc0109321e61a62a74ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 18 Feb 2024 11:35:30 +0100 Subject: [PATCH 1/2] Add clj-kondo hook and config for linting `defcomponent` --- Readme.md | 13 ++++ deps.edn | 2 +- .../cjohansen/dumdom/config.edn | 2 + .../cjohansen/dumdom/dumdom/defcomponent.clj | 69 +++++++++++++++++++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 resources/clj-kondo.exports/cjohansen/dumdom/config.edn create mode 100644 resources/clj-kondo.exports/cjohansen/dumdom/dumdom/defcomponent.clj diff --git a/Readme.md b/Readme.md index 35820fd..ca36be8 100644 --- a/Readme.md +++ b/Readme.md @@ -181,6 +181,19 @@ would `devcards.core`: (my-dumdom-component {:value 0})) ``` +## Linting + +This library exports +[clj-kondo configuration](https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#importing) +for linting the `defcomponent` macro. You may need to import the config. If you +are using clojure-lsp, this should happen automatically. + +If you are not using clj-kondo, you could get away with using a `defcomponent` +macro that supports linting as `defn`. Like +[this one](https://gist.github.com/PEZ/357df3589dc49e83e49da77cb8943723). It +won't help you spot errors with using the wrong dumdom component options, +but at least will silence false positive warnings. + ## Contribute Feel free to report bugs and, even better, provide bug fixing pull requests! diff --git a/deps.edn b/deps.edn index d5dc5aa..386a270 100644 --- a/deps.edn +++ b/deps.edn @@ -1,4 +1,4 @@ -{:paths ["src"] +{:paths ["src" "resources"] :deps {org.clojure/clojure {:mvn/version "1.10.3"} org.clojure/clojurescript {:mvn/version "1.10.866"}} :aliases {:dev {:extra-paths ["dev" "test" "resources"] diff --git a/resources/clj-kondo.exports/cjohansen/dumdom/config.edn b/resources/clj-kondo.exports/cjohansen/dumdom/config.edn new file mode 100644 index 0000000..46448ec --- /dev/null +++ b/resources/clj-kondo.exports/cjohansen/dumdom/config.edn @@ -0,0 +1,2 @@ +{:linters {:dumdom/component-options {:level :warning}} + :hooks {:analyze-call {dumdom.core/defcomponent dumdom.defcomponent/defcomponent}}} diff --git a/resources/clj-kondo.exports/cjohansen/dumdom/dumdom/defcomponent.clj b/resources/clj-kondo.exports/cjohansen/dumdom/dumdom/defcomponent.clj new file mode 100644 index 0000000..78987f6 --- /dev/null +++ b/resources/clj-kondo.exports/cjohansen/dumdom/dumdom/defcomponent.clj @@ -0,0 +1,69 @@ +(comment ; add-libs + '{:deps {clj-kondo/clj-kondo {:mvn/version "2024.02.12"}}}) + +(ns dumdom.defcomponent + (:require [clj-kondo.hooks-api :as api])) + +(def valid-opts #{:on-mount + :on-update + :on-render + :on-unmount + :will-appear + :did-appear + :will-enter + :did-enter + :will-leave + :did-leave + :name}) + +(defn- extract-docstr + [[docstr? & forms :as remaining-forms]] + (if (api/string-node? docstr?) + [docstr? forms] + [(api/string-node "no docs") remaining-forms])) + +(defn- extract-opts + ([forms] + (extract-opts forms [])) + ([[k v & forms :as remaining-forms] opts] + (if (api/keyword-node? k) + (do + (when-not (valid-opts (api/sexpr k)) + (api/reg-finding! (assoc (meta k) + :message (str "Invalid option: `" k "`") + :type :dumdom/component-options))) + (extract-opts forms (into opts [k v]))) + [(api/map-node opts) remaining-forms]))) + +(defn ^:export defcomponent [{:keys [node]}] + (let [[name & forms] (rest (:children node)) + [docstr forms] (extract-docstr forms) + [opts forms] (extract-opts forms) + new-node (api/list-node + (list* + (api/token-node 'defn) + name + docstr + opts + forms))] + {:node new-node})) + +(comment + (def code (str '(defcomponent heading + "" + :on-render (fn [dom-node val old-val]) + :invalid (fn []) + [data] + (def data data) + [:h2 {:style {:background :black + :color :white}} + (pr-str (:text data))]))) + + (defcomponent {:node (api/parse-string code)}) + + (require '[clj-kondo.core :as clj-kondo]) + (:findings (with-in-str (str "(require '[dumdom.core :refer [defcomponent]])" + " " + code) + (clj-kondo/run! {:lint ["-"]}))) + :rcf) \ No newline at end of file From c186603fffef98287bc1e73af7fb32c2abb02901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Str=C3=B6mberg?= Date: Sun, 18 Feb 2024 12:24:22 +0100 Subject: [PATCH 2/2] Use exported clj-kondo config for library development --- .clj-kondo/config.edn | 1 + .gitignore | 1 + 2 files changed, 2 insertions(+) create mode 100644 .clj-kondo/config.edn diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn new file mode 100644 index 0000000..29315bc --- /dev/null +++ b/.clj-kondo/config.edn @@ -0,0 +1 @@ +{:config-paths ["../resources/clj-kondo.exports/cjohansen/dumdom"]} \ No newline at end of file diff --git a/.gitignore b/.gitignore index da5fa81..1cad171 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ target checkouts .cpcache cljs-test-runner-out +.clj-kondo/cjohansen/dumdom \ No newline at end of file