From b9be3054ba7069bb317e0447207803a4c255cf3c Mon Sep 17 00:00:00 2001 From: Nick Juszczak Date: Fri, 5 Jan 2024 21:48:18 -0600 Subject: [PATCH 1/3] Fix clj-kondo linter generation when using pred :fn's When using a predicate fn schema inside of a function schema, it would output a the type as :fn, such that clj-kondo checked that the arg provided is a fn and not of type any. Ex: ``` (defn times [x y z] (* x y z)) (m/=> times [:=> [:cat int? [:fn #(int? %)] int?] [:fn #(int? %)]]) (times 1 2 3) ;; clj-kondo warns that `2` should be a function, not an integer. ``` --- src/malli/clj_kondo.cljc | 2 +- test/malli/clj_kondo_test.cljc | 37 +++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/malli/clj_kondo.cljc b/src/malli/clj_kondo.cljc index 83694d3ed..4b3e90935 100644 --- a/src/malli/clj_kondo.cljc +++ b/src/malli/clj_kondo.cljc @@ -103,7 +103,7 @@ (defmethod accept :tuple [_ _ _ _] :seqable) (defmethod accept :multi [_ _ _ _] :any) ;;?? (defmethod accept :re [_ _ _ _] :string) -(defmethod accept :fn [_ _ _ _] :fn) +(defmethod accept :fn [_ _ _ _] :any) (defmethod accept :ref [_ _ _ _] :any) ;;?? (defmethod accept :=> [_ _ _ _] :fn) (defmethod accept :function [_ _ _ _] :fn) diff --git a/test/malli/clj_kondo_test.cljc b/test/malli/clj_kondo_test.cljc index 147fec527..b3a3f3b6f 100644 --- a/test/malli/clj_kondo_test.cljc +++ b/test/malli/clj_kondo_test.cljc @@ -4,6 +4,15 @@ [malli.core :as m] [malli.util :as mu])) +(defn- cljk-collect-for-test + "Collect up all of the clj-kondo linters generated for fn's in this test ns." + [] + (-> 'malli.clj-kondo-test + #?(:clj (clj-kondo/collect)) + #?(:cljs (clj-kondo/collect-cljs)) + (clj-kondo/linter-config) + (get-in [:linters :type-mismatch :namespaces]))) + (def Schema (m/schema [:map {:registry {::id string? @@ -78,7 +87,13 @@ :tuple-of-ints :nilable/seqable}} (clj-kondo/transform Schema))) - (let [expected-out + (let [it-fn-defs ['kikka + 'siren + 'clj-kondo-issue-1922-1 + 'clj-kondo-issue-1922-2 + 'clj-kondo-issue-1922-3 + 'clj-kondo-issue-1922-4] + expected-out {'malli.clj-kondo-test {'kikka {:arities {1 {:args [:int], @@ -113,17 +128,13 @@ #?(:clj (is (= expected-out - (-> 'malli.clj-kondo-test - (clj-kondo/collect) - (clj-kondo/linter-config) - (get-in [:linters :type-mismatch :namespaces]))))) + (-> (cljk-collect-for-test) + (update 'malli.clj-kondo-test #(select-keys % it-fn-defs)))))) #?(:cljs (is (= expected-out - (-> 'malli.clj-kondo-test - (clj-kondo/collect-cljs) - (clj-kondo/linter-config) - (get-in [:linters :type-mismatch :namespaces])))))) + (-> (cljk-collect-for-test) + (update 'malli.clj-kondo-test #(select-keys % it-fn-defs))))))) (testing "sequential elements" (is (= :seqable (clj-kondo/transform [:repeat :int]))) @@ -135,3 +146,11 @@ (testing "regular expressions" (is (= :string (clj-kondo/transform [:re "kikka"])) "the :re schema models a string, clj-kondo's :regex a Pattern object"))) + +(defn clj-kondo-issue-836-1 [x y z] (* x y z)) +(m/=> clj-kondo-issue-836-1 [:=> [:cat int? [:fn #(int? %)] int?] [:fn #(int? %)]]) + +(deftest fn-predicate-schema-generation + (is (= {:arities {3 {:args [:int :any :int], :ret :any}}} + (get-in (cljk-collect-for-test) ['malli.clj-kondo-test 'clj-kondo-issue-836-1])) + "should output `:any` for `:fn` predicate schema's, not `:fn`")) From 4969f6457622563c2e9c0268710f9860f42b8cc8 Mon Sep 17 00:00:00 2001 From: Nick Juszczak Date: Sat, 6 Jan 2024 11:31:48 -0600 Subject: [PATCH 2/3] Upd to follow test code standards, upd kondo to use IT test Malli generally uses single IT deftests (e.g. swagger-tests), so follow that pattern. --- test/malli/clj_kondo_test.cljc | 55 +++++++++++++--------------------- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/test/malli/clj_kondo_test.cljc b/test/malli/clj_kondo_test.cljc index b3a3f3b6f..8c0630456 100644 --- a/test/malli/clj_kondo_test.cljc +++ b/test/malli/clj_kondo_test.cljc @@ -4,15 +4,6 @@ [malli.core :as m] [malli.util :as mu])) -(defn- cljk-collect-for-test - "Collect up all of the clj-kondo linters generated for fn's in this test ns." - [] - (-> 'malli.clj-kondo-test - #?(:clj (clj-kondo/collect)) - #?(:cljs (clj-kondo/collect-cljs)) - (clj-kondo/linter-config) - (get-in [:linters :type-mismatch :namespaces]))) - (def Schema (m/schema [:map {:registry {::id string? @@ -68,8 +59,21 @@ [:=> [:cat :int :int] :nil] [:=> [:cat :int :int [:repeat :int]] :nil]]) -(deftest clj-kondo-integration-test +(defn clj-kondo-issue-836-1 + "Predicate `:fn` schema's should be type-checked as expecting to be passed `:any`, not a fn." + [x y z] (* x y z)) +(m/=> clj-kondo-issue-836-1 [:=> [:cat int? [:fn #(int? %)] int?] [:fn #(int? %)]]) +(defn- cljk-collect-for-test + "Collect up all of the clj-kondo linters generated for fn's in this test ns." + [] + (-> 'malli.clj-kondo-test + #?(:clj (clj-kondo/collect)) + #?(:cljs (clj-kondo/collect-cljs)) + (clj-kondo/linter-config) + (get-in [:linters :type-mismatch :namespaces]))) + +(deftest clj-kondo-integration-test (is (= {:op :keys, :opt {::price :double, :tags :set, ::y :boolean}, :req {::id :string, @@ -87,13 +91,7 @@ :tuple-of-ints :nilable/seqable}} (clj-kondo/transform Schema))) - (let [it-fn-defs ['kikka - 'siren - 'clj-kondo-issue-1922-1 - 'clj-kondo-issue-1922-2 - 'clj-kondo-issue-1922-3 - 'clj-kondo-issue-1922-4] - expected-out + (let [expected-out {'malli.clj-kondo-test {'kikka {:arities {1 {:args [:int], @@ -124,17 +122,14 @@ :ret :nil} :varargs {:args [:int :int {:op :rest :spec :int}] :ret :nil - :min-arity 2}}}}}] - + :min-arity 2}}} + ;; should output `:any` for `:fn` predicate schema's, not `:fn` + 'clj-kondo-issue-836-1 + {:arities {3 {:args [:int :any :int], :ret :any}}}}}] #?(:clj - (is (= expected-out - (-> (cljk-collect-for-test) - (update 'malli.clj-kondo-test #(select-keys % it-fn-defs)))))) - + (is (= expected-out (cljk-collect-for-test)))) #?(:cljs - (is (= expected-out - (-> (cljk-collect-for-test) - (update 'malli.clj-kondo-test #(select-keys % it-fn-defs))))))) + (is (= expected-out (cljk-collect-for-test))))) (testing "sequential elements" (is (= :seqable (clj-kondo/transform [:repeat :int]))) @@ -146,11 +141,3 @@ (testing "regular expressions" (is (= :string (clj-kondo/transform [:re "kikka"])) "the :re schema models a string, clj-kondo's :regex a Pattern object"))) - -(defn clj-kondo-issue-836-1 [x y z] (* x y z)) -(m/=> clj-kondo-issue-836-1 [:=> [:cat int? [:fn #(int? %)] int?] [:fn #(int? %)]]) - -(deftest fn-predicate-schema-generation - (is (= {:arities {3 {:args [:int :any :int], :ret :any}}} - (get-in (cljk-collect-for-test) ['malli.clj-kondo-test 'clj-kondo-issue-836-1])) - "should output `:any` for `:fn` predicate schema's, not `:fn`")) From 2caabf1f2aafb79a32808eb0f1fb99ea8810e1ff Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sun, 7 Jan 2024 11:14:46 +0200 Subject: [PATCH 3/3] fix eager mi/check --- test/malli/instrument_test.clj | 5 +++++ test/malli/instrument_test.cljs | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/malli/instrument_test.clj b/test/malli/instrument_test.clj index 85df57d37..e440ca416 100644 --- a/test/malli/instrument_test.clj +++ b/test/malli/instrument_test.clj @@ -90,6 +90,11 @@ (mi/-schema #'f2))) (is (= nil (mi/-schema #'f3)))) +(deftest check-test + (testing "all registered function schemas in this namespace" + (let [results (mi/check {:filters [(mi/-filter-ns 'malli.instrument-test)]})] + (is (map? results))))) + (deftest instrument-external-test (testing "Without instrumentation" diff --git a/test/malli/instrument_test.cljs b/test/malli/instrument_test.cljs index fbe6b30b1..94a792c87 100644 --- a/test/malli/instrument_test.cljs +++ b/test/malli/instrument_test.cljs @@ -194,8 +194,9 @@ (is (= 9 (minus-small-int 10))))) (deftest ^:simple check-test - (let [results (mi/check)] - (is (map? results)))) + (testing "all registered function schemas in this namespace" + (let [results (mi/check {:filters [(mi/-filter-ns 'malli.instrument-test)]})] + (is (map? results))))) (deftest ^:simple instrument-external-test