Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes and clean up #260

Merged
merged 5 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clj-kondo/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{:lint-as {kibit.rules.util/defrules clj-kondo.lint-as/def-catch-all}}
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. This change

## [Unreleased]

* Update to Clojure 1.11 to handle ##Inf etc. [#237](https://github.com/clj-commons/kibit/pull/237)
* Switch to borkdude/edamame for side-effect free parsing. [#235](https://github.com/clj-commons/kibit/pull/235), [#246](https://github.com/clj-commons/kibit/pull/246)
* Correctly gather options-spec require vectors as maps so we can check for :as and :as-alias. [#238](https://github.com/clj-commons/kibit/pull/238)
* Moved all of the test/resources files to a new corpus folder which isn't loaded by default on test runs.

## 0.1.10 / 2024-05-09

* Fix scm information in generated pom.xml.
Expand Down
5 changes: 5 additions & 0 deletions corpus/as_alias.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(ns resources.as-alias
(:require
[foo.bar :a :b :as-alias fb]))

::fb/example
1 change: 1 addition & 0 deletions corpus/double_pound_reader_macros.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[##Inf ##-Inf ##NaN]
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions corpus/namespaced_maps.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#:car{:make "Jeep" :model "Wrangler"}
1 change: 1 addition & 0 deletions corpus/read_eval.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(if true (do #=(prn :hello :world!) :a))
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#?(:clj (+ 1 1)
:cljs (+ 2 2)
:default (+ 3 3))

{:a 1 :b 2 #?@(:clj [:c 3 :d 4])}
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 4 additions & 6 deletions deps.edn
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
{:paths ["src"]
:deps {org.clojure/clojure {:mvn/version "1.8.0"}
:deps {org.clojure/clojure {:mvn/version "1.11.1"}
org.clojure/core.logic {:mvn/version "1.1.0"}
org.clojure/tools.cli {:mvn/version "1.1.230"}
org.clojure/tools.reader {:mvn/version "1.4.2"}
borkdude/edamame {:mvn/version "1.4.25"}
rewrite-clj/rewrite-clj {:mvn/version "1.1.47"}}
;; At least Clojure v1.9 is required to run `clojure -X:`. Run this as
;; `clojure -X:exec` or `clojure -X:exec -i -r markdown`, for example.
:aliases {:exec {:extra-deps {org.clojure/clojure {:mvn/version "1.9.0"}
org.babashka/cli {:mvn/version "0.7.51"}}
;; Run this as `clojure -X:exec` or `clojure -X:exec -i -r markdown`, for example.
:aliases {:exec {:extra-deps {org.babashka/cli {:mvn/version "0.7.51"}}
:exec-fn kibit.driver/exec
:exec-args {:paths ["."]}
:main-opts ["-m" "babashka.cli.exec"]}}}
3 changes: 2 additions & 1 deletion lein-kibit/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/tools.namespace "1.5.0"]
[jonase/kibit ~(clojure.string/trim-newline (slurp "../resources/jonase/kibit/VERSION"))]]
:deploy-repositories [["releases" :clojars]
:deploy-repositories [["clojars" {:url "https://clojars.org/repo"
:sign-releases false}]
["snapshots" :clojars]]
:eval-in-leiningen true)
5 changes: 2 additions & 3 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@
:url "https://github.com/clj-commons/kibit"
:connection "scm:git:git://github.com/clj-commons/kibit.git"
:developerConnection "scm:git:ssh://[email protected]/clj-commons/kibit.git"}
:dependencies [[org.clojure/clojure "1.8.0"]
:dependencies [[org.clojure/clojure "1.11.1"]
[org.clojure/core.logic "1.1.0"]
[org.clojure/tools.cli "1.1.230"]
[rewrite-clj "1.1.47"]
[org.clojure/tools.reader "1.4.2"]]
:profiles {:dev {:resource-paths ["test/resources"]}}
[borkdude/edamame "1.4.25"]]
:deploy-repositories [["clojars" {:url "https://clojars.org/repo"
:sign-releases false}]
["snapshots" :clojars]]
Expand Down
19 changes: 7 additions & 12 deletions src/kibit/check.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
(ns kibit.check
"Kibit's integration point and public API"
(:require [clojure.java.io :as io]
[clojure.core.logic.unifier :as unifier]
[kibit.core :as core]
[kibit.rules :as core-rules]
[kibit.reporters :as reporters]
Expand Down Expand Up @@ -67,12 +66,13 @@
"Construct the canonical simplify-map
given an expression and a simplified expression."
[expr simplified-expr]
{:expr expr
:line (-> expr meta :line)
:column (-> expr meta :column)
:end-line (-> expr meta :end-line)
:end-column (-> expr meta :end-column)
:alt simplified-expr})
(let [expr-meta (meta expr)]
{:expr expr
:line (:line expr-meta)
:column (:column expr-meta)
:end-line (:end-line expr-meta)
:end-column (:end-column expr-meta)
:alt simplified-expr}))

;; ### Guarding the check

Expand Down Expand Up @@ -164,23 +164,19 @@

;; The default resolution is overridden via the `merge`
(defn check-expr
""
[expr & kw-opts]
(let [{:keys [rules guard resolution]}
(merge default-args
{:resolution :toplevel}
(apply hash-map kw-opts))
rules (map unifier/prep rules)
simplify-fn #((res->simplify resolution) % rules)]
(check-aux expr simplify-fn guard)))

(defn check-reader
""
[reader & kw-opts]
(let [{:keys [rules guard resolution init-ns]}
(merge default-args
(apply hash-map kw-opts))
rules (map unifier/prep rules)
simplify-fn #((res->simplify resolution) % rules)]
(keep #(check-aux % simplify-fn guard)
((res->read-seq resolution) reader init-ns))))
Expand All @@ -190,7 +186,6 @@
{(resolve '*default-data-reader-fn*) (fn [tag val] val)}))

(defn check-file
""
[source-file & kw-opts]
(let [{:keys [rules guard resolution reporter init-ns]
:or {reporter reporters/cli-reporter}}
Expand Down
36 changes: 28 additions & 8 deletions src/kibit/check/reader.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(ns kibit.check.reader
(:require [clojure.tools.reader :as reader])
(:require [edamame.core :as e])
(:import [clojure.lang LineNumberingPushbackReader]))

;; Preprocessing
Expand Down Expand Up @@ -69,8 +69,8 @@
(rest form))

(option-spec? form)
(let [[_ as? form-alias] form]
(deps-from-libspec prefix (first form) (when (= :as as?) form-alias)))
(let [opts (apply hash-map (next form))]
(deps-from-libspec prefix (first form) (or (:as opts) (:as-alias opts))))

(symbol? form)
(list (with-meta
Expand Down Expand Up @@ -142,18 +142,38 @@ into the namespace."

(def eof (Object.))

(defn- make-edamame-opts [alias-map]
(e/normalize-opts
{:all true
:read_eval true
:eof eof
:row-key :line
:col-key :column
:end-row-key :end-line
:end-col-key :end-column
:end-location true
:features #{:clj :cljs}
:read-cond :allow
:readers (fn reader [r]
(fn reader-value [v]
(list r v)))
:auto-resolve (fn [x]
(if (= :current x)
*ns*
(get alias-map x)))}))

(defn read-file
"Generate a lazy sequence of top level forms from a
LineNumberingPushbackReader"
[^LineNumberingPushbackReader r init-ns]
(let [ns (careful-refer (create-ns init-ns))
do-read (fn do-read [ns alias-map]
(lazy-seq
(let [form (binding [*ns* ns
reader/*alias-map* (merge (ns-aliases ns)
(alias-map ns))]
(reader/read {:eof eof :read-cond :preserve} r))
[ns? new-ns k] (when (sequential? form) form)
(let [form (binding [*ns* ns]
(e/parse-next r (make-edamame-opts
(merge (ns-aliases ns)
(alias-map ns)))))
[ns? new-ns] (when (sequential? form) form)
new-ns (unquote-if-quoted new-ns)
ns (if (and (symbol? new-ns)
(#{'ns 'in-ns} ns?))
Expand Down
2 changes: 1 addition & 1 deletion src/kibit/driver.clj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
(defn ends-with?
"Returns true if the java.io.File ends in any of the strings in coll"
[file coll]
(some #(.endsWith (.getName ^File file) %) coll))
(boolean (some #(.endsWith (.getName ^File file) %) coll)))

(defn clojure-file?
"Returns true if the java.io.File represents a Clojure source file.
Expand Down
5 changes: 1 addition & 4 deletions src/kibit/rules/arithmetic.clj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,4 @@
[(dec (Math/exp ?x)) (Math/expm1 ?x)]

;;ugly rounding tricks
[(long (+ ?x 0.5)) (Math/round ?x)]
)


[(long (+ ?x 0.5)) (Math/round ?x)])
21 changes: 0 additions & 21 deletions src/kibit/rules/control_structures.clj
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,3 @@
(while ?test . ?exprs)]
[(let ?binding (do . ?exprs)) (let ?binding . ?exprs)]
[(loop ?binding (do . ?exprs)) (loop ?binding . ?exprs)])

(comment
(when (not (pred? x y)) (f x y))

(if (all-streams-complete?)
(do
(deliver @all-clear :true)
(info "All streams complete.")))

(if (pred? x)
(do (action a)
(action b)
(if-let [x (f a b c)
y (g a b c)
z (h a b c)]
(do (+ 1 0)
(= 1 1)
(< 1 0)))
(action d)
(action f))
nil))
7 changes: 4 additions & 3 deletions src/kibit/rules/util.clj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@

(defmacro defrules [name & rules]
`(let [rules# (for [rule# '~rules]
(if (raw-rule? rule#)
(eval rule#) ;; raw rule, no need to compile
(compile-rule rule#)))]
(unifier/prep
(if (raw-rule? rule#)
(eval rule#) ;; raw rule, no need to compile
(compile-rule rule#))))]
(def ~name (vec rules#))))
3 changes: 2 additions & 1 deletion test/kibit/test/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"Hello" '(do "Hello")
'(when test then) '(do (when test then))
:one '(do :one)
{:one 1} '(do {:one 1})))
{:one 1} '(do {:one 1})
#{:a :b} '#{(do :a) (do :b)}))

;; This test confirms when checking will happen and when it won't
(deftest simplify-exprs
Expand Down
64 changes: 47 additions & 17 deletions test/kibit/test/driver.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,33 @@

(deftest clojure-file-are
(are [expected file] (= expected (driver/clojure-file? (io/file file)))
true "test/resources/first.clj"
true "test/resources/second.cljx"
true "test/resources/third.cljs"
false "test.resources/fourth.txt"))
true "corpus/first.clj"
true "corpus/second.cljx"
true "corpus/third.cljs"
false "corpus/fourth.txt"))

(deftest find-clojure-sources-are
(is (= [(io/file "test/resources/first.clj")
(io/file "test/resources/keyword_suggestions.clj")
(io/file "test/resources/keywords.clj")
(io/file "test/resources/reader_conditionals.cljc")
(io/file "test/resources/second.cljx")
(io/file "test/resources/sets.clj")
(io/file "test/resources/third.cljs")]
(driver/find-clojure-sources-in-dir (io/file "test/resources")))))
(is (= [(io/file "corpus/as_alias.clj")
(io/file "corpus/double_pound_reader_macros.clj")
(io/file "corpus/first.clj")
(io/file "corpus/keyword_suggestions.clj")
(io/file "corpus/keywords.clj")
(io/file "corpus/namespaced_maps.clj")
(io/file "corpus/read_eval.clj")
(io/file "corpus/reader_conditionals.cljc")
(io/file "corpus/second.cljx")
(io/file "corpus/sets.clj")
(io/file "corpus/third.cljs")]
(driver/find-clojure-sources-in-dir (io/file "corpus")))))

(deftest test-set-file
(is (driver/run ["test/resources/sets.clj"] nil)))
(is (driver/run ["corpus/sets.clj"] nil)))

(deftest test-keywords-file
(let [test-buf (ByteArrayOutputStream.)
test-err (PrintWriter. test-buf)]
(binding [*err* test-err]
(driver/run ["test/resources/keywords.clj"] nil))
(driver/run ["corpus/keywords.clj"] nil))
(is (zero? (.size test-buf))
(format "Test err buffer contained '%s'" (.toString test-buf)))))

Expand All @@ -42,7 +46,33 @@
{:alt (vec [:clojure.pprint/printing-key :resources.keyword-suggestions/local-key4 :some/other-key4])
:expr (into [] [:clojure.pprint/printing-key :resources.keyword-suggestions/local-key4 :some/other-key4])})
(map #(select-keys % [:expr :alt])
(driver/run ["test/resources/keyword_suggestions.clj"] nil "--reporter" "no-op")))))
(driver/run ["corpus/keyword_suggestions.clj"] nil "--reporter" "no-op")))))

(deftest process-cljc-file
(is (driver/run ["test/resources/reader_conditionals.cljc"] nil)))
(defmacro with-err-str
[& body]
`(let [s# (java.io.StringWriter.)]
(binding [*err* s#]
~@body
(str s#))))

(deftest process-reader-macros
(is (= ["" "" "" ""]
[(with-err-str
(driver/run ["corpus/reader_conditionals.cljc"] nil "--reporter" "no-op"))
(with-err-str
(driver/run ["corpus/double_pound_reader_macros.clj"] nil "--reporter" "no-op"))
(with-err-str
(driver/run ["corpus/namespaced_maps.clj"] nil "--reporter" "no-op"))
(with-err-str
(driver/run ["corpus/as_alias.clj"] nil "--reporter" "no-op"))])))

(deftest no-read-eval-test
(is (= [{:expr
'(if true (do (edamame.core/read-eval (prn :hello :world!)) :a))
:line 1
:column 1
:end-line 1
:end-column 41
:alt '(when true (edamame.core/read-eval (prn :hello :world!)) :a)}]
(map #(dissoc % :file)
(driver/run ["corpus/read_eval.clj"] nil "--reporter" "no-op")))))
Loading