Skip to content

Commit

Permalink
[#78] Implement with-monkeypatches, use to "fix" core.logic
Browse files Browse the repository at this point in the history
  • Loading branch information
arrdem committed Nov 10, 2016
1 parent e751aff commit 5142744
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 16 deletions.
45 changes: 29 additions & 16 deletions src/kibit/driver.clj
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
(ns kibit.driver
"The (leiningen) facing interface for Kibit. Provides helpers for finding files in a project, and
linting a list of files."
(:require [clojure.java.io :as io]
[kibit.rules :refer [all-rules]]
[kibit.check :refer [check-file]]
[kibit.reporters :refer :all]
[clojure.tools.cli :refer [cli]])
(:import [java.io File]))
[clojure.tools.cli :refer [cli]]
[kibit
[check :refer [check-file]]
[reporters :refer :all]
[rules :refer [all-rules]]
[monkeypatch :refer :all]])
(:import java.io.File))

(def cli-specs [["-r" "--reporter"
"The reporter used when rendering suggestions"
Expand All @@ -31,18 +35,27 @@
(sort-by #(.getAbsolutePath ^File %)
(filter clojure-file? (file-seq dir))))

(defn run [source-paths rules & args]
(defn run
"Runs the kibit checker against the given paths, rules and args.
Paths is expected to be a sequence of io.File objects.
Rules is either a collection of rules or nil. If Rules is nil, all of kibit's checkers are used.
Optionally accepts a :reporter keyword argument, defaulting to \"text\"."
[source-paths rules & args]
(let [[options file-args usage-text] (apply (partial cli args) cli-specs)
source-files (mapcat #(-> % io/file find-clojure-sources-in-dir)
(if (empty? file-args) source-paths file-args))]
(mapcat (fn [file] (try (check-file file
:reporter (name-to-reporter (:reporter options)
cli-reporter)
:rules (or rules all-rules))
(catch Exception e
(binding [*out* *err*]
(println "Check failed -- skipping rest of file")
(println (.getMessage e))))))
source-files (mapcat #(-> % io/file find-clojure-sources-in-dir)
(if (empty? file-args) source-paths file-args))]
(mapcat (fn [file]
(with-monkeypatches kibit-redefs
(check-file file
:reporter (name-to-reporter (:reporter options) cli-reporter)
:rules (or rules all-rules))
(catch Exception e
(binding [*out* *err*]
(println "Check failed -- skipping rest of file")
(println (.getMessage e))))))
source-files)))

(defn external-run
Expand Down
40 changes: 40 additions & 0 deletions src/kibit/monkeypatch.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
(ns kibit.monkeypatch
"Various helpers providing a with-monkeypatches form which wraps"
(:require [clojure.core.logic :as c.c.l])
(:import [clojure.lang
Var
IPersistentSet]
[clojure.core.logic.protocols
ITreeTerm]))

(defn ^:pivate tree-term? [x]
(and (or (coll? x)
(instance? ITreeTerm x))
(not (instance? IPersistentSet x))))

(def kibit-redefs
{#'c.c.l/tree-term? tree-term?})

(defmacro with-monkeypatches
"Builds a try/finally which captures Var bindings (and ^:macro tags) comming in, creates new Var
bindings within the try and in the finally restores the original bindings. This allows users to
establish stack-local patched contexts."
{:style/indent [1]}
[redefs & forms]
(let [redefs (eval redefs)
original-bindings (into {}
(for [k (keys redefs)]
[k (gensym)]))]
`(let [~@(for [[k v] original-bindings
f [v `(deref ~k)]]
f)]
(try ~@(for [[k v] redefs]
`(do (.bindRoot ~k ~v)
~(if (.isMacro ^Var k)
`(.setMacro ~k))))
~@forms
(finally
~@(for [[k v] redefs]
`(do (.bindRoot ~k ~(get original-bindings k))
~(if (.isMacro ^Var k)
`(.setMacro ~k)))))))))
4 changes: 4 additions & 0 deletions test/kibit/test/driver.clj
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@
(deftest find-clojure-sources-are
(is (= [(io/file "test/resources/first.clj")
(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")))))

(deftest test-set-file
(is (driver/run ["test/resources/sets.clj"] nil)))
4 changes: 4 additions & 0 deletions test/resources/sets.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(ns resources.sets)

(defn killit [coll]
(not-any? #{"string1" "string2"} (map ffirst coll)))

0 comments on commit 5142744

Please sign in to comment.