├── rum
├── rum.png
├── .clj-kondo
│ └── config.edn
├── README.md
└── test
│ └── clj_kondo
│ └── rum_test.cljs
├── mockery
├── .clj-kondo
│ └── config.edn
├── README.md
└── test
│ └── clj_kondo
│ └── mockery_test.clj
├── claypoole
├── .clj-kondo
│ └── config.edn
├── README.md
└── test
│ └── clj_kondo
│ └── claypoole_test.clj
├── slingshot
├── .clj-kondo
│ └── config.edn
├── README.md
└── test
│ └── clj_kondo
│ └── slingshot_test.clj
├── resources
└── clj-kondo.exports
│ └── clj-kondo
│ ├── slingshot
│ ├── config.edn
│ └── clj_kondo
│ │ └── slingshot
│ │ └── try_plus.clj
│ ├── rum
│ ├── config.edn
│ └── clj_kondo
│ │ └── rum.clj
│ ├── mockery
│ ├── config.edn
│ └── clj_kondo
│ │ └── mockery
│ │ ├── with_mock.clj
│ │ └── with_mocks.clj
│ └── claypoole
│ ├── clj_kondo
│ └── claypoole.clj
│ └── config.edn
├── deps.edn
├── hugsql
└── README.md
├── .gitignore
├── README.md
├── src
└── clj_kondo
│ └── config.clj
└── LICENSE
/rum/rum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clj-kondo/config/HEAD/rum/rum.png
--------------------------------------------------------------------------------
/rum/.clj-kondo/config.edn:
--------------------------------------------------------------------------------
1 | {:config-paths ["../../resources/clj-kondo.exports/clj-kondo/rum"]}
2 |
--------------------------------------------------------------------------------
/mockery/.clj-kondo/config.edn:
--------------------------------------------------------------------------------
1 | {:config-paths ["../../resources/clj-kondo.exports/clj-kondo/mockery"]}
2 |
--------------------------------------------------------------------------------
/claypoole/.clj-kondo/config.edn:
--------------------------------------------------------------------------------
1 | {:config-paths ["../../resources/clj-kondo.exports/clj-kondo/claypoole"]}
2 |
--------------------------------------------------------------------------------
/slingshot/.clj-kondo/config.edn:
--------------------------------------------------------------------------------
1 | {:config-paths ["../../resources/clj-kondo.exports/clj-kondo/slingshot"]}
2 |
--------------------------------------------------------------------------------
/resources/clj-kondo.exports/clj-kondo/slingshot/config.edn:
--------------------------------------------------------------------------------
1 | {:hooks
2 | {:analyze-call {slingshot.slingshot/try+ clj-kondo.slingshot.try-plus/try+}}}
3 |
--------------------------------------------------------------------------------
/deps.edn:
--------------------------------------------------------------------------------
1 | {:paths ["src" "resources"]
2 | :deps {org.clojure/tools.cli {:mvn/version "1.0.194"}
3 | cpath-clj/cpath-clj {:mvn/version "0.1.2"}}}
4 |
--------------------------------------------------------------------------------
/mockery/README.md:
--------------------------------------------------------------------------------
1 | # Mockery
2 |
3 | See the `.clj-kondo` directory for configuration for the [Mockery](https://github.com/igrishaev/mockery) library.
4 |
--------------------------------------------------------------------------------
/slingshot/README.md:
--------------------------------------------------------------------------------
1 | # Slingshot
2 |
3 | See the `.clj-kondo` directory for configuration for the
4 | [Slingshot](https://github.com/scgilardi/slingshot) library.
5 |
--------------------------------------------------------------------------------
/rum/README.md:
--------------------------------------------------------------------------------
1 | # Rum
2 |
3 | See the `.clj-kondo` directory for configuration for the [Rum](https://github.com/tonsky/rum) library.
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/resources/clj-kondo.exports/clj-kondo/rum/config.edn:
--------------------------------------------------------------------------------
1 | {:hooks {:analyze-call {rum.core/defc clj-kondo.rum/defc
2 | rum.core/defcs clj-kondo.rum/defcs}}
3 | :lint-as {rum.core/defcc rum.core/defc}}
4 |
--------------------------------------------------------------------------------
/resources/clj-kondo.exports/clj-kondo/mockery/config.edn:
--------------------------------------------------------------------------------
1 | {:linters {:mockery {:level :warning}}
2 | :hooks {:analyze-call {mockery.core/with-mock clj-kondo.mockery.with-mock/with-mock
3 | mockery.core/with-mocks clj-kondo.mockery.with-mocks/with-mocks}}}
4 |
--------------------------------------------------------------------------------
/slingshot/test/clj_kondo/slingshot_test.clj:
--------------------------------------------------------------------------------
1 | (ns math.expression
2 | (:require [slingshot.slingshot :refer [throw+ try+]]))
3 |
4 | (defn read-file [file]
5 | (try+
6 | (prn file)
7 | (catch [:type :tensor.parse/bad-tree] {:keys [tree hint]}
8 | (prn tree hint)
9 | (throw+))
10 | (catch Object _
11 | (throw+))))
12 |
--------------------------------------------------------------------------------
/hugsql/README.md:
--------------------------------------------------------------------------------
1 | # HugSQL
2 |
3 | The [HugSQL](https://github.com/layerware/hugsql) macro `def-db-fns` introduces
4 | vars into the namespace in which it is called. You can teach clj-kondo about
5 | these vars by using `declare`. Example:
6 |
7 | ``` clojure
8 | (ns foo.db
9 | (:require [hugsql.core :as hugsql]))
10 |
11 | (declare select-things)
12 |
13 | ;; this will define a var #'select-things:
14 | (hugsql/def-db-fns "select_things.sql")
15 |
16 | (defn get-my-things [conn params]
17 | (select-things conn params))
18 | ```
19 |
20 | If the amount of symbols introduced by HugSQL becomes too unwieldy, consider
21 | introducing a separate namespace in which HugSQL generates the vars:
22 |
23 | ``` clojure
24 | (ns foo.db.hugsql
25 | (:require [hugsql.core :as hugsql]))
26 |
27 | (hugsql/def-db-fns "select_things.sql")
28 | ```
29 |
30 | You can then use this namespace like:
31 |
32 | ``` clojure
33 | (ns foo.db
34 | (:require [foo.db.hugsql :as sql]))
35 |
36 | (defn get-my-things [conn params]
37 | (sql/select-things conn params))
38 | ```
39 |
40 | and clj-kondo will not complain about this.
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/emacs,clojure
3 |
4 | ### Clojure ###
5 | pom.xml
6 | pom.xml.asc
7 | *.jar
8 | *.class
9 | /lib/
10 | /classes/
11 | /target/
12 | /checkouts/
13 | .lein-deps-sum
14 | .lein-repl-history
15 | .lein-plugins/
16 | .lein-failures
17 | .nrepl-port
18 | .cpcache/
19 |
20 | ### IntelliJ/Cursive ###
21 | .idea/
22 | *.iml
23 |
24 | ### Emacs ###
25 | # -*- mode: gitignore; -*-
26 | *~
27 | \#*\#
28 | /.emacs.desktop
29 | /.emacs.desktop.lock
30 | *.elc
31 | auto-save-list
32 | tramp
33 | .\#*
34 |
35 | # Org-mode
36 | .org-id-locations
37 | *_archive
38 |
39 | # flymake-mode
40 | *_flymake.*
41 |
42 | # eshell files
43 | /eshell/history
44 | /eshell/lastdir
45 |
46 | # elpa packages
47 | /elpa/
48 |
49 | # reftex files
50 | *.rel
51 |
52 | # AUCTeX auto folder
53 | /auto/
54 |
55 | # cask packages
56 | .cask/
57 | dist/
58 |
59 | # Flycheck
60 | flycheck_*.el
61 |
62 | # server auth directory
63 | /server/
64 |
65 | # projectiles files
66 | .projectile
67 |
68 | # directory configuration
69 | .dir-locals.el
70 |
71 |
72 | # End of https://www.gitignore.io/api/emacs,clojure
73 | .cache
74 | .clj-kondo
75 | .lsp
76 |
--------------------------------------------------------------------------------
/claypoole/README.md:
--------------------------------------------------------------------------------
1 | # Claypoole
2 |
3 | See the `.clj-kondo` directory for configuration for the [Claypoole](https://github.com/TheClimateCorporation/claypoole) library.
4 |
5 | The example effectively remaps the following to their `clojure.core` counterparts:
6 |
7 |
8 |
9 | | Original | Remapped |
10 | |--------------------------------------------|-----------|
11 | | `com.climate.claypoole/future` | `future` |
12 | | `com.climate.claypoole/completable-future` | `future` |
13 | | `com.climate.claypoole/pdoseq` | `doseq` |
14 | | `com.climate.claypoole/pmap` | `map` |
15 | | `com.climate.claypoole/upmap` | `map` |
16 | | `com.climate.claypoole/pvalues` | `pvalues` |
17 | | `com.climate.claypoole/upvalues` | `pvalues` |
18 | | `com.climate.claypoole/pfor` | `for` |
19 | | `com.climate.claypoole/upfor` | `for` |
20 | | `com.climate.claypoole.lazy/pdoseq` | `doseq` |
21 | | `com.climate.claypoole.lazy/pmap` | `map` |
22 | | `com.climate.claypoole.lazy/upmap` | `map` |
23 | | `com.climate.claypoole.lazy/pvalues` | `pvalues` |
24 | | `com.climate.claypoole.lazy/upvalues` | `pvalues` |
25 | | `com.climate.claypoole.lazy/pfor` | `for` |
26 | | `com.climate.claypoole.lazy/upfor` | `for` |
27 |
--------------------------------------------------------------------------------
/resources/clj-kondo.exports/clj-kondo/mockery/clj_kondo/mockery/with_mock.clj:
--------------------------------------------------------------------------------
1 | (ns clj-kondo.mockery.with-mock
2 | (:require [clj-kondo.hooks-api :as api]))
3 |
4 | (defn with-mock [{:keys [:node]}]
5 | (let [[mock map & body] (rest (:children node))]
6 | (try
7 | (when-not (symbol? (api/sexpr mock))
8 | (throw (ex-info "Mock is not a symbol" (meta mock))))
9 | (when-not (map? (api/sexpr map))
10 | (throw (ex-info "Mock binding is not a map" (meta map))))
11 | (if-let [target (:target (api/sexpr map))]
12 | (when-not (qualified-keyword? target)
13 | (throw (ex-info (str target " must be fully qualified") (meta map))))
14 | (throw (ex-info "no target specified" (meta map))))
15 | (when-not body
16 | (api/reg-finding! (assoc (meta (first (:children node)))
17 | :message "with-mock with empty body"
18 | :type :mockery)))
19 | {:node (api/list-node
20 | (list*
21 | (api/token-node 'let*)
22 | (api/vector-node [mock map])
23 | mock
24 | body))}
25 | (catch Exception e
26 | (api/reg-finding! (assoc (ex-data e) :message (ex-message e) :type :hook))
27 | ;; when there is an error, ignore macro and only return body (in vector to prevent redundant do)
28 | {:node (api/vector-node body)}))))
29 |
--------------------------------------------------------------------------------
/resources/clj-kondo.exports/clj-kondo/claypoole/clj_kondo/claypoole.clj:
--------------------------------------------------------------------------------
1 | (ns clj-kondo.claypoole
2 | (:refer-clojure :exclude [future pmap pvalues])
3 | (:require [clj-kondo.hooks-api :as api]))
4 |
5 | (defn pool-and-body
6 | [token]
7 | (fn [{:keys [:node]}]
8 | (let [[pool & body] (rest (:children node))
9 | new-node (api/list-node
10 | (list*
11 | (api/token-node token)
12 | (api/list-node
13 | (list* (api/token-node 'do)
14 | pool
15 | body))))]
16 | {:node (with-meta new-node
17 | (meta node))})))
18 |
19 | (defn pool-with-binding-vec-or-exprs-and-body
20 | [token]
21 | (fn [{:keys [:node]}]
22 | (let [[pool binding-vec-or-exprs & body] (rest (:children node))
23 | new-node (api/list-node
24 | [(api/token-node token)
25 | binding-vec-or-exprs
26 | (api/list-node
27 | (list* (api/token-node 'do)
28 | pool
29 | body))])]
30 | {:node (with-meta new-node
31 | (meta node))})))
32 |
33 | (def future (pool-and-body 'future))
34 | (def completable-future (pool-and-body 'future))
35 | (def pdoseq (pool-with-binding-vec-or-exprs-and-body 'doseq))
36 | (def pmap (pool-and-body 'map))
37 | (def upmap (pool-and-body 'map))
38 | (def pvalues (pool-and-body 'pvalues))
39 | (def upvalues (pool-and-body 'pvalues))
40 | (def pfor (pool-with-binding-vec-or-exprs-and-body 'for))
41 | (def upfor (pool-with-binding-vec-or-exprs-and-body 'for))
42 |
--------------------------------------------------------------------------------
/resources/clj-kondo.exports/clj-kondo/claypoole/config.edn:
--------------------------------------------------------------------------------
1 | {:linters {:claypoole {:level :warning}}
2 | :lint-as {com.climate.claypoole/with-shutdown! clojure.core/let}
3 | :hooks {:analyze-call {com.climate.claypoole/future clj-kondo.claypoole/future
4 | com.climate.claypoole/completable-future clj-kondo.claypoole/completable-future
5 | com.climate.claypoole/pdoseq clj-kondo.claypoole/pdoseq
6 | com.climate.claypoole/pmap clj-kondo.claypoole/pmap
7 | com.climate.claypoole/upmap clj-kondo.claypoole/upmap
8 | com.climate.claypoole/pvalues clj-kondo.claypoole/pvalues
9 | com.climate.claypoole/upvalues clj-kondo.claypoole/upvalues
10 | com.climate.claypoole/pfor clj-kondo.claypoole/pfor
11 | com.climate.claypoole/upfor clj-kondo.claypoole/upfor
12 | com.climate.claypoole.lazy/pdoseq clj-kondo.claypoole/pdoseq
13 | com.climate.claypoole.lazy/pmap clj-kondo.claypoole/pmap
14 | com.climate.claypoole.lazy/upmap clj-kondo.claypoole/upmap
15 | com.climate.claypoole.lazy/pvalues clj-kondo.claypoole/pvalues
16 | com.climate.claypoole.lazy/upvalues clj-kondo.claypoole/upvalues
17 | com.climate.claypoole.lazy/pfor clj-kondo.claypoole/pfor
18 | com.climate.claypoole.lazy/upfor clj-kondo.claypoole/upfor}}}
19 |
--------------------------------------------------------------------------------
/mockery/test/clj_kondo/mockery_test.clj:
--------------------------------------------------------------------------------
1 | (ns clj-kondo.mockery-test
2 | (:require [clojure.test :refer [is]]
3 | [example.foo :as example]
4 | [mockery.core :as mockery :refer [with-mock with-mocks]]))
5 |
6 | (with-mock _
7 | {:target ::test-fn
8 | :return (fn [& _] 100500)}
9 | (example/test-fn 10))
10 |
11 | (with-mock _
12 | {:target :test-fn ;; :test-fn must be fully qualified
13 | :return (fn [& _] 100500)}
14 | (example/test-fn 10))
15 |
16 | (with-mock _
17 | {:return (fn [& _] 100500)} ;; no target specified
18 | (example/test-fn 10))
19 |
20 | ;; all valid
21 | (with-mocks
22 | [foo {:target ::test-fn}
23 | bar {:target :example/test-fn-2}]
24 | (example/test-fn 1)
25 | (example/test-fn-2 1 2)
26 | (is (= @foo
27 | {:called? true
28 | :call-count 1
29 | :call-args '(1)
30 | :call-args-list '[(1)]
31 | :target ::test-fn}))
32 | (is (= @bar
33 | {:called? true
34 | :call-count 1
35 | :call-args '(1 2)
36 | :call-args-list '[(1 2)]
37 | :target ::test-fn-2})))
38 |
39 | (with-mocks
40 | ;; no target specified
41 | [foo {:target ::test-fn}
42 | bar {}]
43 | (example/test-fn 1)
44 | (example/test-fn-2 1 2)
45 | (is (= @foo ;; no warning about foo, despite error in bindings
46 | {:called? true
47 | :call-count 1
48 | :call-args '(1)
49 | :call-args-list '[(1)]
50 | :target ::test-fn}))
51 | (is (= @bar ;; no warning about foo, despite error in bindings
52 | {:called? true
53 | :call-count 1
54 | :call-args '(1 2)
55 | :call-args-list '[(1 2)]
56 | :target ::test-fn-2})))
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Clj-kondo config
2 |
3 | **Deprecated**
4 |
5 | Use [configs](https://github.com/clj-kondo/configs) instead.
6 |
7 | This repo contains configurations and/or recommendations that can be used with
8 | [clj-kondo](https://github.com/borkdude/clj-kondo/). Check the `resources` folder for available configs.
9 |
10 | ## Installation
11 |
12 | This repo has an **experimental** main entrypoint that copies library specific config and hooks to your `.clj-kondo`.
13 |
14 | Assuming the following alias in your `deps.edn`:
15 |
16 | ``` clojure
17 | :clj-kondo/config
18 | {:extra-deps {clj-kondo/config {:git/url "https://github.com/clj-kondo/config"
19 | :sha ""}}
20 | :main-opts ["-m" "clj-kondo.config"]}
21 | ```
22 |
23 | you can invoke it with:
24 |
25 | ``` shell
26 | $ clojure -M:clj-kondo/config --lib rum --lib slingshot
27 | ```
28 |
29 | This then copies Rum and Slingshot config into `.clj-kondo/configs/rum` and `.clj-kondo/configs/slingshot` respectively:
30 |
31 | ``` shell
32 | $ clojure -M:clj-kondo/config --lib rum --lib slingshot
33 | Copying rum config to .clj-kondo/configs/rum
34 | Copying slingshot config to .clj-kondo/configs/slingshot
35 | Add "configs/rum", "configs/slingshot" to :config-paths in .clj-kondo/config.edn to activate configs.
36 | ```
37 |
38 | To activate, you then add `"configs/rum"` and `"configs/slingshot"` to your `:config-paths` in `config.edn` and Rum and Slinghot syntax will be recognized.
39 |
40 | Also see the
41 | [config.md](https://github.com/borkdude/clj-kondo/blob/master/doc/config.md#exporting-and-importing-configuration)
42 | section on importing and exporting configs.
43 |
44 | ## License
45 |
46 | Copyright © 2020 Michiel Borkent
47 |
48 | Distributed under the EPL License, same as Clojure. See LICENSE.
49 |
--------------------------------------------------------------------------------
/src/clj_kondo/config.clj:
--------------------------------------------------------------------------------
1 | (ns clj-kondo.config
2 | (:require [clojure.java.io :as io]
3 | [clojure.string :as str]
4 | [clojure.tools.cli :refer [parse-opts]]
5 | [cpath-clj.core :as cp]))
6 |
7 | (def cli-options
8 | [["-l" "--lib LIBRARY" "Library"
9 | :default []
10 | :assoc-fn (fn [m k v]
11 | (update m k (fnil conj []) v))]])
12 |
13 | (defn delete-files-recursively
14 | ([f1] (delete-files-recursively f1 false))
15 | ([f1 silently]
16 | (when (.isDirectory (io/file f1))
17 | (doseq [f2 (.listFiles (io/file f1))]
18 | (delete-files-recursively f2 silently)))
19 | (io/delete-file f1 silently)))
20 |
21 | (defn -main [& args]
22 | (let [{:keys [:lib ]} (:options (parse-opts args cli-options))]
23 | (doseq [l lib]
24 | (if-let [resource (io/resource (str "clj-kondo.exports/clj-kondo/" l))]
25 | (let [config-dir (io/file ".clj-kondo" "configs" l)]
26 | (when (.exists config-dir)
27 | (println "Removing previous" l "config in" (.getPath config-dir))
28 | (delete-files-recursively config-dir))
29 | (println "Copying" l "config to" (.getPath config-dir))
30 | (doseq [[path uris] (cp/resources resource)
31 | :let [uri (first uris)
32 | relative-path (subs path 1)
33 | output-file (io/file config-dir relative-path)]]
34 | (io/make-parents output-file)
35 | (with-open [in (io/input-stream uri)]
36 | (io/copy in output-file))))
37 | (println "No config found for " l)))
38 | (println "Add" (str/join
39 | ", "
40 | (map (fn [lib]
41 | (pr-str (.getPath (io/file "configs" lib))))
42 | lib))
43 | "to :config-paths in .clj-kondo/config.edn to activate configs.")))
44 |
--------------------------------------------------------------------------------
/resources/clj-kondo.exports/clj-kondo/slingshot/clj_kondo/slingshot/try_plus.clj:
--------------------------------------------------------------------------------
1 | (ns clj-kondo.slingshot.try-plus
2 | (:require [clj-kondo.hooks-api :as api]))
3 |
4 | (defn expand-catch [catch-node]
5 | (let [[catch catchee & exprs] (:children catch-node)
6 | catchee-sexpr (api/sexpr catchee)]
7 | (cond (vector? catchee-sexpr)
8 | (let [[selector & exprs] exprs]
9 | (api/list-node
10 | [catch (api/token-node 'Exception) (api/token-node '_e#)
11 | (api/list-node
12 | (list* (api/token-node 'let)
13 | (api/vector-node [selector (api/token-node nil)])
14 | exprs))]))
15 | :else catch-node)))
16 |
17 | (defn try+ [{:keys [node]}]
18 | (let [children (rest (:children node))
19 | [body catches]
20 | (loop [body children
21 | body-exprs []
22 | catches []]
23 | (if (seq body)
24 | (let [f (first body)
25 | f-sexpr (api/sexpr f)]
26 | (if (and (seq? f-sexpr) (= 'catch (first f-sexpr)))
27 | (recur (rest body)
28 | body-exprs
29 | (conj catches (expand-catch f)))
30 | (recur (rest body)
31 | (conj body-exprs f)
32 | catches)))
33 | [body-exprs catches]))
34 | new-node (api/list-node
35 | [(api/token-node 'let)
36 | (api/vector-node
37 | [(api/token-node '&throw-context) (api/token-node nil)])
38 | (api/token-node '&throw-context) ;; use throw-context to avoid warning
39 | (with-meta (api/list-node (list* (api/token-node 'try)
40 | (concat body catches)))
41 | (meta node))])]
42 | ;; (prn (api/sexpr new-node))
43 | {:node new-node}))
44 |
45 |
--------------------------------------------------------------------------------
/rum/test/clj_kondo/rum_test.cljs:
--------------------------------------------------------------------------------
1 | (ns clj-kondo.rum-test
2 | (:require [rum.core :as rum]))
3 |
4 | ;;;; defc
5 |
6 | (rum/defc label [text] ;; text is recognized as a binding
7 | [:div {:class "label"} text])
8 |
9 | (rum/defc label ;; redefined var
10 | [text] ;; unused binding
11 | [:div {:class "label"} text']) ;; unresolved binding text'
12 |
13 | (rum/defc with-docstring
14 | "docstring" ;; docstring is placed correctly
15 | < { :will-mount (fn [x] ;; mixin is parsed correctly
16 | (assoc x ::time (js/Date.))) }
17 | [_text])
18 |
19 | (rum/defc defc-multiple-bodies
20 | "docstring" ;; docstring is placed correctly
21 | < { :will-mount (fn [x] ;; mixin is parsed correctly
22 | (assoc x ::time (js/Date.))) }
23 | ([foo] (if foo
24 | (defc-multiple-bodies foo nil)
25 | (defc-multiple-bodies))) ;; invalid arity
26 | ([foo bar] ;; bar is unused
27 | foo))
28 |
29 | ;;;; defcs
30 |
31 | (rum/defcs time-label ;; defcs is linted as defc
32 | < { :will-mount (fn [x] ;; mixin is parsed correctly
33 | (assoc x ::time (js/Date.))) }
34 | [state x] ;; unused
35 | [:div y ;; unresolved
36 | ": " (str (::time state))])
37 |
38 | (rum/defcs SomeComponent <
39 | {:did-mount (fn [state] state)}
40 | [state input another]
41 | input ;; binding input is used, another is unused
42 | (let [x "Hello"] ;; binding is unused
43 | nil))
44 |
45 | (SomeComponent "hello") ;; amount of args is invalid
46 | (SomeComponent "hello" "there") ;; amount of args is correct
47 |
48 | (rum/defcs ComponentWithDocString
49 | "docstring" ;; docstring is placed correctly
50 | < {:did-mount (fn [state] state)}
51 | [state input]
52 | input)
53 |
54 | (rum/defcs defcs-multiple-bodies
55 | "docstring" ;; docstring is placed correctly
56 | < {:dir-mount (fn [state] state)}
57 | ([state foo]) ;; foo is unused, but state isn't
58 | ([state foo bar]))
59 |
60 | (defcs-multiple-bodies) ;; invalid arity
61 | (defcs-multiple-bodies "hello") ;; valid arity
62 |
--------------------------------------------------------------------------------
/claypoole/test/clj_kondo/claypoole_test.clj:
--------------------------------------------------------------------------------
1 | (ns example
2 | (:require
3 | [com.climate.claypoole :as cp]))
4 |
5 | (def pool (cp/threadpool 8))
6 | (def coll [1 2 3])
7 |
8 | (defn -main
9 | [& _]
10 | ;; future
11 | (cp/future pool (println "Hi from future"))
12 |
13 | ;; pdoseq
14 | (cp/pdoseq 8 [x coll]
15 | (println "Doseqing over" x))
16 | (cp/pdoseq pool [x coll :when (= x 1)]
17 | (println "Doseqing over" x))
18 |
19 | ;; pmap
20 | (cp/pmap 8
21 | (fn [x] (println "Mapping over" x))
22 | coll)
23 | (cp/pmap pool
24 | (fn [x y] (println "Mapping over" [x y]))
25 | coll
26 | coll)
27 |
28 | ;; upmap
29 | (cp/upmap 8
30 | (fn [x] (println "Mapping over" x))
31 | coll)
32 | (cp/upmap pool
33 | (fn [x y] (println "Mapping over" [x y]))
34 | coll
35 | coll)
36 |
37 | ;; pvalues
38 | (println "Parallel values"
39 | (cp/pvalues 8
40 | (do (Thread/sleep 100)
41 | (+ 1 2))
42 | (+ 3 4)))
43 | (println "Parallel values"
44 | (cp/pvalues pool
45 | (do (Thread/sleep 100)
46 | (+ 1 2))
47 | (+ 3 4)))
48 |
49 | ;; upvalues
50 | (println "Ordered parallel values"
51 | (cp/upvalues 8
52 | (do (Thread/sleep 100)
53 | (+ 1 2))
54 | (+ 3 4)))
55 | (println "Ordered parallel values"
56 | (cp/upvalues pool
57 | (do (Thread/sleep 100)
58 | (+ 1 2))
59 | (+ 3 4)))
60 |
61 | ;; pfor
62 | (cp/pfor 8 [x coll]
63 | (println "For over" x))
64 | (cp/pfor pool [x coll
65 | y coll
66 | :when (and (= x 1) (= y 1))]
67 | (println "For over" [x y]))
68 |
69 | ;; upfor
70 | (cp/upfor 8 [x coll]
71 | (println "Ordered for over" x))
72 | (cp/upfor pool [x coll
73 | y coll
74 | :when (and (= x 1) (= y 1))]
75 | (println "Ordered for over" [x y]))
76 |
77 | (cp/upfor 8) ;; arity warning with correct location
78 |
79 | (let [x 8] ;; binding is used
80 | (cp/upfor x [y coll] (println y)))
81 | )
82 |
--------------------------------------------------------------------------------
/resources/clj-kondo.exports/clj-kondo/mockery/clj_kondo/mockery/with_mocks.clj:
--------------------------------------------------------------------------------
1 | (ns clj-kondo.mockery.with-mocks
2 | (:require [clj-kondo.hooks-api :as api]))
3 |
4 | (defn with-mocks [{:keys [:node]}]
5 | (let [[binding-vec & body] (rest (:children node))
6 | bindings (:children binding-vec)
7 | binding-count (count bindings)
8 | bvec (api/sexpr binding-vec)]
9 | (try
10 | (when-not binding-vec
11 | (throw (ex-info "No mocks provided" (meta node))))
12 | (when-not (vector? bvec)
13 | (throw (ex-info "with-mocks requires vector for its bindings" (meta binding-vec))))
14 | (when (zero? binding-count)
15 | (api/reg-finding! (assoc (meta (first (:children node)))
16 | :message "with-mocks with no mocks"
17 | :type :mockery)))
18 | (when-not (and binding-vec
19 | (even? binding-count))
20 | (throw (ex-info "Mock vector requires an even number of forms"
21 | (meta binding-vec))))
22 | (when-let [mock (first (drop-while #(symbol? (api/sexpr %))
23 | (take-nth 2 bindings)))]
24 | (throw (ex-info "Mock is not a symbol" (meta mock))))
25 | (when-let [value (first (drop-while #(map? (api/sexpr %))
26 | (take-nth 2 (drop 1 bindings))))]
27 | (throw (ex-info "Mock binding is not a map" (meta value))))
28 | (doseq [m (take-nth 2 (drop 1 bvec))]
29 | (if-let [target (:target m)]
30 | (when-not (qualified-keyword? target)
31 | (throw (ex-info (str target " must be fully qualified") (meta binding-vec))))
32 | (throw (ex-info "no target specified" (meta binding-vec)))))
33 | (when-not body
34 | (api/reg-finding! (assoc (meta (first (:children node)))
35 | :message "with-mocks with empty body"
36 | :type :mockery)))
37 | {:node (api/list-node
38 | (list*
39 | (api/token-node 'let*)
40 | (api/vector-node bindings)
41 | `(~(into [] (take-nth 2 bindings))
42 | ~@body)))}
43 | (catch Exception e
44 | (api/reg-finding! (assoc (ex-data e) :message (ex-message e) :type :hook))
45 | ;; when there is an error, use this fallback node
46 | (let [fallback (api/list-node (list* (api/token-node 'let*) binding-vec body))]
47 | ;; (println fallback)
48 | {:node fallback})))))
49 |
--------------------------------------------------------------------------------
/resources/clj-kondo.exports/clj-kondo/rum/clj_kondo/rum.clj:
--------------------------------------------------------------------------------
1 | (ns clj-kondo.rum
2 | (:require [clj-kondo.hooks-api :as api]))
3 |
4 | (defn fn-body? [x]
5 | (and (seq? x)
6 | (vector? (first x))))
7 |
8 | (defn rewrite-body [mixins body defcs?]
9 | (if defcs?
10 | (let [[binding-vec & body] (:children body)
11 | [state-arg & rest-args] (:children binding-vec)
12 | ;; the original vector without the state argument
13 | fn-args (assoc binding-vec :children rest-args)
14 | body (api/list-node
15 | (list* (api/token-node 'let*)
16 | (api/vector-node [state-arg (api/token-node nil)])
17 | state-arg
18 | (concat mixins body)))
19 | body (api/list-node [fn-args body])]
20 | body)
21 | (let [[binding-vec & body] (:children body)]
22 | (api/list-node (cons binding-vec (concat mixins body))))))
23 |
24 | (defn rewrite
25 | ([node] (rewrite node false))
26 | ([node defcs?]
27 | (let [args (rest (:children node))
28 | component-name (first args)
29 | ?docstring (when (string? (api/sexpr (second args)))
30 | (second args))
31 | args (if ?docstring
32 | (nnext args)
33 | (next args))
34 | bodies
35 | (loop [args* (seq args)
36 | mixins []
37 | bodies []]
38 | (if args*
39 | (let [a (first args*)
40 | a-sexpr (api/sexpr a)]
41 | (cond (vector? a-sexpr) ;; a-sexpr is a binding vec and the rest is the body of the function
42 | [(rewrite-body mixins (api/list-node args*) defcs?)]
43 | (fn-body? a-sexpr)
44 | (recur (next args*)
45 | mixins
46 | (conj bodies (rewrite-body mixins a defcs?)))
47 | ;; assume mixin
48 | :else (recur (next args*)
49 | (conj mixins a)
50 | bodies)))
51 | bodies))
52 | new-node (with-meta
53 | (api/list-node
54 | (list* (api/token-node 'defn)
55 | component-name
56 | (if ?docstring
57 | (cons ?docstring bodies)
58 | bodies)))
59 | (meta node))]
60 | new-node)))
61 |
62 | (defn defc [{:keys [:node]}]
63 | (let [new-node (rewrite node)]
64 | {:node new-node}))
65 |
66 | (defn defcs [{:keys [:node]}]
67 | (let [new-node (rewrite node true)]
68 | {:node new-node}))
69 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Eclipse Public License - v 1.0
2 |
3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
6 |
7 | 1. DEFINITIONS
8 |
9 | "Contribution" means:
10 |
11 | a) in the case of the initial Contributor, the initial code and documentation
12 | distributed under this Agreement, and
13 | b) in the case of each subsequent Contributor:
14 | i) changes to the Program, and
15 | ii) additions to the Program;
16 |
17 | where such changes and/or additions to the Program originate from and are
18 | distributed by that particular Contributor. A Contribution 'originates' from
19 | a Contributor if it was added to the Program by such Contributor itself or
20 | anyone acting on such Contributor's behalf. Contributions do not include
21 | additions to the Program which: (i) are separate modules of software
22 | distributed in conjunction with the Program under their own license
23 | agreement, and (ii) are not derivative works of the Program.
24 |
25 | "Contributor" means any person or entity that distributes the Program.
26 |
27 | "Licensed Patents" mean patent claims licensable by a Contributor which are
28 | necessarily infringed by the use or sale of its Contribution alone or when
29 | combined with the Program.
30 |
31 | "Program" means the Contributions distributed in accordance with this Agreement.
32 |
33 | "Recipient" means anyone who receives the Program under this Agreement,
34 | including all Contributors.
35 |
36 | 2. GRANT OF RIGHTS
37 | a) Subject to the terms of this Agreement, each Contributor hereby grants
38 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
39 | reproduce, prepare derivative works of, publicly display, publicly perform,
40 | distribute and sublicense the Contribution of such Contributor, if any, and
41 | such derivative works, in source code and object code form.
42 | b) Subject to the terms of this Agreement, each Contributor hereby grants
43 | Recipient a non-exclusive, worldwide, royalty-free patent license under
44 | Licensed Patents to make, use, sell, offer to sell, import and otherwise
45 | transfer the Contribution of such Contributor, if any, in source code and
46 | object code form. This patent license shall apply to the combination of the
47 | Contribution and the Program if, at the time the Contribution is added by
48 | the Contributor, such addition of the Contribution causes such combination
49 | to be covered by the Licensed Patents. The patent license shall not apply
50 | to any other combinations which include the Contribution. No hardware per
51 | se is licensed hereunder.
52 | c) Recipient understands that although each Contributor grants the licenses to
53 | its Contributions set forth herein, no assurances are provided by any
54 | Contributor that the Program does not infringe the patent or other
55 | intellectual property rights of any other entity. Each Contributor
56 | disclaims any liability to Recipient for claims brought by any other entity
57 | based on infringement of intellectual property rights or otherwise. As a
58 | condition to exercising the rights and licenses granted hereunder, each
59 | Recipient hereby assumes sole responsibility to secure any other
60 | intellectual property rights needed, if any. For example, if a third party
61 | patent license is required to allow Recipient to distribute the Program, it
62 | is Recipient's responsibility to acquire that license before distributing
63 | the Program.
64 | d) Each Contributor represents that to its knowledge it has sufficient
65 | copyright rights in its Contribution, if any, to grant the copyright
66 | license set forth in this Agreement.
67 |
68 | 3. REQUIREMENTS
69 |
70 | A Contributor may choose to distribute the Program in object code form under its
71 | own license agreement, provided that:
72 |
73 | a) it complies with the terms and conditions of this Agreement; and
74 | b) its license agreement:
75 | i) effectively disclaims on behalf of all Contributors all warranties and
76 | conditions, express and implied, including warranties or conditions of
77 | title and non-infringement, and implied warranties or conditions of
78 | merchantability and fitness for a particular purpose;
79 | ii) effectively excludes on behalf of all Contributors all liability for
80 | damages, including direct, indirect, special, incidental and
81 | consequential damages, such as lost profits;
82 | iii) states that any provisions which differ from this Agreement are offered
83 | by that Contributor alone and not by any other party; and
84 | iv) states that source code for the Program is available from such
85 | Contributor, and informs licensees how to obtain it in a reasonable
86 | manner on or through a medium customarily used for software exchange.
87 |
88 | When the Program is made available in source code form:
89 |
90 | a) it must be made available under this Agreement; and
91 | b) a copy of this Agreement must be included with each copy of the Program.
92 | Contributors may not remove or alter any copyright notices contained within
93 | the Program.
94 |
95 | Each Contributor must identify itself as the originator of its Contribution, if
96 | any, in a manner that reasonably allows subsequent Recipients to identify the
97 | originator of the Contribution.
98 |
99 | 4. COMMERCIAL DISTRIBUTION
100 |
101 | Commercial distributors of software may accept certain responsibilities with
102 | respect to end users, business partners and the like. While this license is
103 | intended to facilitate the commercial use of the Program, the Contributor who
104 | includes the Program in a commercial product offering should do so in a manner
105 | which does not create potential liability for other Contributors. Therefore, if
106 | a Contributor includes the Program in a commercial product offering, such
107 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
108 | every other Contributor ("Indemnified Contributor") against any losses, damages
109 | and costs (collectively "Losses") arising from claims, lawsuits and other legal
110 | actions brought by a third party against the Indemnified Contributor to the
111 | extent caused by the acts or omissions of such Commercial Contributor in
112 | connection with its distribution of the Program in a commercial product
113 | offering. The obligations in this section do not apply to any claims or Losses
114 | relating to any actual or alleged intellectual property infringement. In order
115 | to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
116 | Contributor in writing of such claim, and b) allow the Commercial Contributor to
117 | control, and cooperate with the Commercial Contributor in, the defense and any
118 | related settlement negotiations. The Indemnified Contributor may participate in
119 | any such claim at its own expense.
120 |
121 | For example, a Contributor might include the Program in a commercial product
122 | offering, Product X. That Contributor is then a Commercial Contributor. If that
123 | Commercial Contributor then makes performance claims, or offers warranties
124 | related to Product X, those performance claims and warranties are such
125 | Commercial Contributor's responsibility alone. Under this section, the
126 | Commercial Contributor would have to defend claims against the other
127 | Contributors related to those performance claims and warranties, and if a court
128 | requires any other Contributor to pay any damages as a result, the Commercial
129 | Contributor must pay those damages.
130 |
131 | 5. NO WARRANTY
132 |
133 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
134 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
135 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
136 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
137 | Recipient is solely responsible for determining the appropriateness of using and
138 | distributing the Program and assumes all risks associated with its exercise of
139 | rights under this Agreement , including but not limited to the risks and costs
140 | of program errors, compliance with applicable laws, damage to or loss of data,
141 | programs or equipment, and unavailability or interruption of operations.
142 |
143 | 6. DISCLAIMER OF LIABILITY
144 |
145 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
146 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
147 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
148 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
149 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
150 | OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
151 | GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
152 |
153 | 7. GENERAL
154 |
155 | If any provision of this Agreement is invalid or unenforceable under applicable
156 | law, it shall not affect the validity or enforceability of the remainder of the
157 | terms of this Agreement, and without further action by the parties hereto, such
158 | provision shall be reformed to the minimum extent necessary to make such
159 | provision valid and enforceable.
160 |
161 | If Recipient institutes patent litigation against any entity (including a
162 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself
163 | (excluding combinations of the Program with other software or hardware)
164 | infringes such Recipient's patent(s), then such Recipient's rights granted under
165 | Section 2(b) shall terminate as of the date such litigation is filed.
166 |
167 | All Recipient's rights under this Agreement shall terminate if it fails to
168 | comply with any of the material terms or conditions of this Agreement and does
169 | not cure such failure in a reasonable period of time after becoming aware of
170 | such noncompliance. If all Recipient's rights under this Agreement terminate,
171 | Recipient agrees to cease use and distribution of the Program as soon as
172 | reasonably practicable. However, Recipient's obligations under this Agreement
173 | and any licenses granted by Recipient relating to the Program shall continue and
174 | survive.
175 |
176 | Everyone is permitted to copy and distribute copies of this Agreement, but in
177 | order to avoid inconsistency the Agreement is copyrighted and may only be
178 | modified in the following manner. The Agreement Steward reserves the right to
179 | publish new versions (including revisions) of this Agreement from time to time.
180 | No one other than the Agreement Steward has the right to modify this Agreement.
181 | The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation
182 | may assign the responsibility to serve as the Agreement Steward to a suitable
183 | separate entity. Each new version of the Agreement will be given a
184 | distinguishing version number. The Program (including Contributions) may always
185 | be distributed subject to the version of the Agreement under which it was
186 | received. In addition, after a new version of the Agreement is published,
187 | Contributor may elect to distribute the Program (including its Contributions)
188 | under the new version. Except as expressly stated in Sections 2(a) and 2(b)
189 | above, Recipient receives no rights or licenses to the intellectual property of
190 | any Contributor under this Agreement, whether expressly, by implication,
191 | estoppel or otherwise. All rights in the Program not expressly granted under
192 | this Agreement are reserved.
193 |
194 | This Agreement is governed by the laws of the State of New York and the
195 | intellectual property laws of the United States of America. No party to this
196 | Agreement will bring a legal action under this Agreement more than one year
197 | after the cause of action arose. Each party waives its rights to a jury trial in
198 | any resulting litigation.
199 |
--------------------------------------------------------------------------------