From c3d4cb82d1869369fa8bf18bddafd79f28cd954b Mon Sep 17 00:00:00 2001 From: Tom Dalziel Date: Tue, 5 Nov 2024 14:13:07 +0100 Subject: [PATCH] Check for even number of clauses for cond-> and cond->> Fixes #2420 --- CHANGELOG.md | 1 + src/clj_kondo/impl/macroexpand.clj | 16 +++++++++++++--- test/clj_kondo/invalid_arity_test.clj | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8880b5fc1..17e0872d2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ For a list of breaking changes, check [here](#breaking-changes). - [#2410](https://github.com/clj-kondo/clj-kondo/issues/2410): add `--report-level` flag - [#2416](https://github.com/clj-kondo/clj-kondo/issues/2416): detect empty `require` and `:require` forms ([@NoahTheDuke](https://github.com/NoahTheDuke)) - [#1786](https://github.com/clj-kondo/clj-kondo/issues/1786): Support `gen-interface` (by suppressing unresolved symbols) +- [#2420](https://github.com/clj-kondo/clj-kondo/issues/2420): Detect uneven number of clauses in cond-> and cond->> ## 2024.09.27 diff --git a/src/clj_kondo/impl/macroexpand.clj b/src/clj_kondo/impl/macroexpand.clj index ff4c8c9a75..d1dc5f1fe6 100644 --- a/src/clj_kondo/impl/macroexpand.clj +++ b/src/clj_kondo/impl/macroexpand.clj @@ -1,7 +1,9 @@ (ns clj-kondo.impl.macroexpand {:no-doc true} (:require - [clj-kondo.impl.utils :refer [parse-string tag vector-node list-node token-node]] + [clj-kondo.impl.findings :as findings] + [clj-kondo.impl.utils :refer [parse-string tag vector-node list-node + token-node node->line]] [clojure.walk :as walk])) (set! *warn-on-reflection* true) @@ -54,7 +56,7 @@ (defn expand-cond-> "Expands cond-> and cond->>" - [_ctx expr resolved-as-name] + [ctx expr resolved-as-name] (let [[_ start-expr & clauses] (:children expr) thread-sym (case resolved-as-name cond-> 'clojure.core/-> @@ -74,7 +76,15 @@ (vector-node (list* g start-expr (interleave (repeat g) (butlast steps)))) - (if (empty? steps) g (last steps))])] + (if (empty? steps) g (last steps))]) + clauses-count (count clauses)] + (when (odd? clauses-count) + (findings/reg-finding! ctx + (node->line + (:filename ctx) + expr + :invalid-arity + (str resolved-as-name " requires even number of clauses")))) ret)) (defn expand-doto [_ctx expr] diff --git a/test/clj_kondo/invalid_arity_test.clj b/test/clj_kondo/invalid_arity_test.clj index b677bdb1a4..fd26057ce1 100644 --- a/test/clj_kondo/invalid_arity_test.clj +++ b/test/clj_kondo/invalid_arity_test.clj @@ -241,3 +241,17 @@ :level :error, :message "clojure.core/throw is called with 2 args but expects 1"}] (lint! "(throw 1 2)"))) + +(deftest cond-thread-test + (assert-submaps2 + [{:row 1, + :col 1, + :level :error, + :message "cond-> requires even number of clauses"}] + (lint! "(cond-> 42 inc)")) + (assert-submaps2 + [{:row 1, + :col 1, + :level :error, + :message "cond->> requires even number of clauses"}] + (lint! "(cond->> 42 (even? 7) inc (odd? 8))")))