diff --git a/src/jonase/kibit/control_structures.clj b/src/jonase/kibit/control_structures.clj index b4bde2b..3aeced5 100644 --- a/src/jonase/kibit/control_structures.clj +++ b/src/jonase/kibit/control_structures.clj @@ -7,5 +7,5 @@ (if (not ?x) ?y ?z) (if-not ?x ?y ?z) (when (not ?x) . ?y) (when-not ?x ?y) (if true ?x . ?y) ?x - (when true ?x) ?x}) + (when true ?x) ?x}) ; Maybe this should be (do ?x) diff --git a/src/jonase/kibit/core.clj b/src/jonase/kibit/core.clj index 111e897..4771764 100644 --- a/src/jonase/kibit/core.clj +++ b/src/jonase/kibit/core.clj @@ -4,23 +4,13 @@ [clojure.string :as string] [jonase.kibit.arithmetic :as arith] [jonase.kibit.control-structures :as control] - [jonase.kibit.misc :as misc])) + [jonase.kibit.misc :as misc]) + (:import [clojure.lang LineNumberingPushbackReader])) (def all-rules (merge control/rules arith/rules misc/rules)) -(defn src [path] - (if-let [res (io/resource path)] - (clojure.lang.LineNumberingPushbackReader. (io/reader res)) - (throw (RuntimeException. (str "File not found: " path))))) - -(defn source-file [ns-sym] - (-> (name ns-sym) - (string/replace "." "/") - (string/replace "-" "_") - (str ".clj"))) - (defn read-ns [r] (lazy-seq (let [form (read r false ::eof) @@ -28,41 +18,38 @@ (when-not (= form ::eof) (cons (with-meta form {:line line-num}) (read-ns r)))))) +(defn unify [expr rule] + (let [[r s] (#'logic/prep rule) + alt (first (logic/run* [alt] + (logic/== expr r) + (logic/== s alt)))] + (when alt + {:expr expr + :rule rule + :alt (seq alt) + :line (-> expr meta :line)}))) + (defn check-form ([expr] - (check-form expr all-rules)) + (check-form expr all-rules)) ([expr rules] - (for [rule rules - ; See if a rule is broken, if it is, show a unified alternative - :let [[_ alt :as unified-rule] (logic/unifier rule [expr '?alt]) - rule-broke (not (nil? - (and (sequential? expr) - unified-rule)))] - :when rule-broke] - {:expr expr - :alt alt - :rule rule - :unified-rule unified-rule - :line (-> expr meta :line)}))) - -(defn check - "This is a presentation version of check-form, - used to print broken-rules to stdout" - ([expr] - (check expr all-rules)) - ([expr rules] - (doseq [{:keys [line alt expr]} (check-form expr rules)] - (printf "[Kibit:%s] Consider %s instead of %s\n" line (reverse (into '() alt)) expr)))) + (when (sequential? expr) + (loop [expr expr + alt-map nil] + (if-let [new-alt-map (some #(unify expr %) rules)] + (recur (:alt new-alt-map) + new-alt-map) + alt-map))))) (defn expr-seq [expr] (tree-seq sequential? seq expr)) -(defn check-ns - ([ns-sym rules] - (with-open [reader (-> ns-sym source-file src)] - (doseq [form (mapcat expr-seq (read-ns reader))] - (check form rules)))) - ([ns-sym] - (check-ns ns-sym all-rules))) +(defn check-file + ([reader] + (check-file reader all-rules)) + ([reader rules] + (keep check-form + (mapcat expr-seq (read-ns (LineNumberingPushbackReader. reader)))))) + diff --git a/src/leiningen/kibit.clj b/src/leiningen/kibit.clj index 93b7760..df33d19 100644 --- a/src/leiningen/kibit.clj +++ b/src/leiningen/kibit.clj @@ -7,11 +7,12 @@ "Suggest idiomatic replacements for patterns of code." [project] (let [paths (or (:source-paths project) [(:source-path project)]) - namespaces (apply concat (for [path paths] - (clj-ns/find-namespaces-in-dir (io/file path))))] - (doseq [ns-sym namespaces] - (try - (println "==" ns-sym "==") - (kibit/check-ns ns-sym) - (catch RuntimeException e (println ns-sym "not found."))) - (println "done.")))) + source-files (mapcat #(-> % io/file clj-ns/find-clojure-sources-in-dir) + paths)] + (doseq [source-file source-files] + (printf "== %s ==\n" + (or (second (clj-ns/read-file-ns-decl source-file)) source-file)) + (with-open [reader (io/reader source-file)] + (doseq [{:keys [line expr alt]} (kibit/check-file reader)] + (printf "[%s] Consider %s instead of %s\n" line alt expr))) + (flush)))) diff --git a/test/kibit/test/control_structures.clj b/test/kibit/test/control_structures.clj index 548f4dc..6a3ccb9 100644 --- a/test/kibit/test/control_structures.clj +++ b/test/kibit/test/control_structures.clj @@ -11,10 +11,11 @@ ;; Please ensure that new rules generate fully expected results across all ;; rule sets. -(deftest control-structures - (helper/check-form-test '(if true (println "X")) ['(println "X")]) - (helper/check-form-test '(if true (println "X") nil) ['(when true (println "X")) - '(println "X")]) - (helper/check-form-test '(if test nil else) ['(when-not test else)]) - (helper/check-form-test '(if test then nil) ['(when test then)])) +(deftest control-structures-are + (are [expected-alt-form test-form] + (= expected-alt-form (:alt (kibit/check-form test-form))) + '(println "X") '(if true (println "X") nil) + '(println "X") '(if true (println "X")) + '(when-not test else) '(if test nil else) + '(when test then) '(if test then nil)))