Skip to content

Commit

Permalink
Merge branch 'master' into condition-always-true-if-let-etc
Browse files Browse the repository at this point in the history
  • Loading branch information
borkdude authored Nov 28, 2024
2 parents ff9c7ff + e439bfd commit 600f7da
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ For a list of breaking changes, check [here](#breaking-changes).
- [#2272](https://github.com/clj-kondo/clj-kondo/issues/2272): Report var usage in `if-not` condition as always truthy
- [#2433](https://github.com/clj-kondo/clj-kondo/issues/2433): false positive redundant ignore with hook
- Document `:cljc` config option. ([@NoahTheDuke](https://github.com/NoahTheDuke))
- [#2439](https://github.com/clj-kondo/clj-kondo/issues/2439): uneval may apply to nnext form if reader conditional doesn't yield a form ([@NoahTheDuke](https://github.com/NoahTheDuke))
- [#2431](https://github.com/clj-kondo/clj-kondo/issues/2431): only apply redundant-nested-call linter for nested exprs
- Relax `:redundant-nested-call` for `comp`, `concat`, `every-pred` and `some-fn` since it may affect performance

Expand Down
39 changes: 32 additions & 7 deletions parser/clj_kondo/impl/rewrite_clj/parser/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
[clj-kondo.impl.rewrite-clj.parser.string :refer [parse-string parse-regex]]
[clj-kondo.impl.rewrite-clj.parser.token :refer [parse-token]]
[clj-kondo.impl.rewrite-clj.parser.utils :as u]
[clj-kondo.impl.rewrite-clj.reader :as reader]))
[clj-kondo.impl.rewrite-clj.reader :as reader]
[clojure.string :as str]))

;; ## Base Parser

Expand Down Expand Up @@ -166,13 +167,37 @@
{:clj-kondo/ignore (assoc (meta node)
:linters v)}))))))

#_(defn spy [x]
(prn x)
x)

(defn- read-with-ignore-hint [reader]
(let [hint (parse-printables reader :uneval 1 true)
im (ignore-meta hint)]
(if im
(vary-meta (parse-next reader)
into im)
(parse-next reader))))
(let [[node] (parse-printables reader :uneval 1 true)
im (ignore-meta [node])
]
(cond im
(vary-meta (parse-next reader)
into im)
(and node
(= :reader-macro (node/tag node))
(let [sv (-> node :children first :string-value)]
(str/starts-with? sv "?")))
(let [features reader/*reader-features*
children (when features
(->> node :children last :children
(take-nth 2)
(keep :k)
(into #{})))]
;; If the reader conditional contains all features or :default,
;; then it can be ignored.
;; Otherwise, add :clj-kondo/uneval metadata to discard later.
(if (or (not features)
(every? children features)
(contains? children :default))
(parse-next reader)
(vary-meta node assoc :clj-kondo/uneval (set (remove children features)))))
:else
(parse-next reader))))

(defmethod parse-next* :sharp
[reader]
Expand Down
1 change: 1 addition & 0 deletions parser/clj_kondo/impl/rewrite_clj/reader.clj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
(:import [java.io PushbackReader]))

(def ^:dynamic *reader-exceptions* nil)
(def ^:dynamic *reader-features* nil)

;; ## Decisions

Expand Down
18 changes: 10 additions & 8 deletions src/clj_kondo/impl/analyzer.clj
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
[clj-kondo.impl.parser :as p]
[clj-kondo.impl.rewrite-clj.node.seq :as seq]
[clj-kondo.impl.rewrite-clj.node.token :as token]
[clj-kondo.impl.rewrite-clj.reader :refer [*reader-exceptions*]]
[clj-kondo.impl.rewrite-clj.reader :refer [*reader-exceptions* *reader-features*]]
[clj-kondo.impl.schema :as schema]
[clj-kondo.impl.types :as types]
[clj-kondo.impl.utils :as utils :refer
Expand Down Expand Up @@ -3331,7 +3331,12 @@
ctx (assoc ctx
:inline-configs (atom [])
:main-ns (atom nil))
parsed (binding [*reader-exceptions* reader-exceptions]
cljc-config (:cljc config)
features (when (identical? :cljc lang)
(or (:features cljc-config)
[:clj :cljs]))
parsed (binding [*reader-exceptions* reader-exceptions
*reader-features* features]
(p/parse-string input))
fname (fs/file-name filename)
ctx (case fname
Expand All @@ -3348,12 +3353,9 @@
(run! #(findings/reg-finding! ctx %) (->findings e filename))))
(case lang
:cljc
(let [cljc-config (:cljc config)
features (or (:features cljc-config)
[:clj :cljs])]
(doseq [lang features]
(analyze-expressions (assoc ctx :base-lang :cljc :lang lang :filename filename)
(:children (select-lang ctx parsed lang)))))
(doseq [lang features]
(analyze-expressions (assoc ctx :base-lang :cljc :lang lang :filename filename)
(:children (select-lang ctx parsed lang))))
(:clj :cljs :edn)
(let [ctx (assoc ctx :base-lang lang :lang lang :filename filename
:uri uri)]
Expand Down
27 changes: 17 additions & 10 deletions src/clj_kondo/impl/utils.clj
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,23 @@

(defn select-lang-children [ctx node lang]
(if-let [children (:children node)]
(let [new-children (reduce
(fn [acc node]
(let [splice? (= "?@" (some-> node :children first :string-value))]
(if-let [processed (select-lang ctx node lang splice?)]
(if splice?
(into acc (:children processed))
(conj acc processed))
acc)))
[]
children)]
(let [new-children (loop [acc []
children children]
(if-let [node (first children)]
(let [splice? (= "?@" (some-> node :children first :string-value))
node-meta (meta node)]
(cond
(not (:clj-kondo/uneval node-meta))
(if-let [processed (select-lang ctx node lang splice?)]
(if splice?
(recur (into acc (:children processed)) (next children))
(recur (conj acc processed) (next children)))
(recur acc (next children)))
(contains? (:clj-kondo/uneval node-meta) lang)
(recur acc (drop 2 children))
:else
(recur acc (next children))))
acc))]
(assoc node :children
new-children))
node))
Expand Down
8 changes: 6 additions & 2 deletions test/clj_kondo/impl/parser_test.clj
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
(ns clj-kondo.impl.parser-test
(:require [clj-kondo.impl.parser :as parser :refer [parse-string]]
[clj-kondo.impl.rewrite-clj.reader :refer [*reader-exceptions*]]
[clj-kondo.impl.rewrite-clj.reader :refer [*reader-exceptions*
*reader-features*]]
[clj-kondo.impl.utils :as utils]
[clojure.test :as t :refer [deftest is are]]))

(deftest omit-unevals-test
(is (zero? (count (:children (parse-string "#_#_1 2"))))))
(is (zero? (count (:children (parse-string "#_#_1 2")))))
(is (= 3 (count (:children
(binding [*reader-features* #{:clj :cljs}]
(parse-string "#_#?(:clj 1) 2 3")))))))

(deftest namespaced-maps-test
(is (= '#:it{:a 1} (utils/sexpr (utils/parse-string "#::it {:a 1}"))))
Expand Down
11 changes: 10 additions & 1 deletion test/clj_kondo/main_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,16 @@
(is (empty? (lint! "^#?(:clj :a :cljsr :b) [1 2 3]"
"--lang" "cljc")))
(assert-submaps [{:row 1, :col 1, :level :error, :message "Reader conditionals are only allowed in .cljc files"}]
(lint! "#?(:clj 1)" "--lang" "clj")))
(lint! "#?(:clj 1)" "--lang" "clj"))
(assert-submaps2 [{:file "<stdin>",
:row 1,
:col 19,
:level :error,
:message "Expected: number, received: keyword. [clj]"}]
(lint! "(+ 1 #_#?(:clj 2) :three 4)"
{:linters {:type-mismatch {:level :error}}
:output {:langs true}}
"--lang" "cljc")))

(deftest exclude-clojure-test
(let [linted (lint! (io/file "corpus" "exclude_clojure.clj"))]
Expand Down

0 comments on commit 600f7da

Please sign in to comment.