Skip to content

Commit

Permalink
add: auto replace fn
Browse files Browse the repository at this point in the history
  • Loading branch information
ertugrulcetin committed Nov 9, 2020
1 parent 4ca561a commit 0ef9812
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 32 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ Leiningen plugin that checks that order of namespace declarations for Clojure fi

### Adding the dependency to `:plugins`

Add `[lein-nsort "0.1.11"]` into the `:plugins` vector of your
Add `[lein-nsort "0.1.12"]` into the `:plugins` vector of your
`project.clj` or `~/.lein/profiles.clj`.

```clj
(defproject my-project
:plugins [[lein-nsort "0.1.11"]])
:plugins [[lein-nsort "0.1.12"]])
```

### Running the checker
Expand Down Expand Up @@ -44,6 +44,15 @@ the `{:nsort {:src-dir "src"}}` of your project (default `./src/`).

```

## Automatically replacing namespace declarations in source files
```
lein nsort --replace
```
OR
```
lein nsort -r
```

## Configuration (Optional)

Add a `:nsort` key to your `project.clj` to customize the checker.
Expand Down
5 changes: 3 additions & 2 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(defproject lein-nsort "0.1.11"
(defproject lein-nsort "0.1.12"

:description "Leiningen plugin that checks that order of namespace declarations for Clojure files\n\n"

Expand All @@ -11,6 +11,7 @@

:dependencies [[org.clojure/clojure "1.10.1"]
[org.clojure/tools.namespace "1.0.0"]
[com.rpl/specter "1.1.3"]]
[com.rpl/specter "1.1.3"]
[rewrite-clj "0.6.1"]]

:eval-in-leiningen true)
101 changes: 79 additions & 22 deletions src/lein_nsort/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
(:require [clojure.java.io :as io]
[com.rpl.specter :as s]
[clojure.tools.namespace.find :as ns-find]
[clojure.pprint :as pp]))
[clojure.tools.namespace.file :as file]
[clojure.pprint :as pp]
[rewrite-clj.zip :as z]
[rewrite-clj.zip.move :as m]
[rewrite-clj.parser :as p]))


(defn- get-index-of [ns]
Expand Down Expand Up @@ -30,35 +34,82 @@
(conj acc {:type (:type opts)
:ns (:ns opts)
:sorted sorted-nses
:duplicate-decl? (> nses-count 1)}))))
:duplicate-decl? (> nses-count 1)
:file (:file opts)}))))


(defn get-invalid-declarations [{:keys [src-dir]
:or {src-dir "src"} :as opts}]
(let [ns-decls (ns-find/find-ns-decls-in-dir (io/file src-dir) ns-find/clj)]
(defmacro ignore-reader-exception
[& body]
`(try ~@body
(catch Exception e#
(if (= :reader-exception (:type (ex-data e#)))
nil
(throw e#)))))


(defn- find-ns-decls-in-dir [dir platform]
(keep #(ignore-reader-exception
{:file %
:ns-decl (file/read-file-ns-decl % (:read-opts platform))})
(ns-find/find-sources-in-dir dir platform)))


(defn- get-invalid-declarations [{:keys [src-dir]
:or {src-dir "src"} :as opts}]
(let [ns-decls (find-ns-decls-in-dir (io/file src-dir) ns-find/clj)]
(reduce
(fn [acc decl]
(reduce-kv (fn [acc k v]
(add-decl-err acc {:type k
:ns (second decl)
:key-fn (or (when (keyword? (get opts k))
(get-in sort-fns [(get opts k) :fn]))
(when (list? (get-in opts [k :sort-fn]))
(eval (get-in opts [k :sort-fn])))
(get-in sort-fns [:asc :fn]))
:comp-fn (or (when (keyword? (get opts k))
(get-in sort-fns [(get opts k) :comp]))
(when (list? (get-in opts [k :comp]))
(eval (get-in opts [k :comp])))
compare)
:nses v}))
acc
(group-by first (s/select path decl))))
(let [{:keys [file ns-decl]} decl
decl ns-decl]
(reduce-kv (fn [acc k v]
(add-decl-err acc {:type k
:ns (second decl)
:key-fn (or (when (keyword? (get opts k))
(get-in sort-fns [(get opts k) :fn]))
(when (list? (get-in opts [k :sort-fn]))
(eval (get-in opts [k :sort-fn])))
(get-in sort-fns [:asc :fn]))
:comp-fn (or (when (keyword? (get opts k))
(get-in sort-fns [(get opts k) :comp]))
(when (list? (get-in opts [k :comp]))
(eval (get-in opts [k :comp])))
compare)
:nses v
:file file}))
acc
(group-by first (s/select path decl)))))
[]
ns-decls)))


(defn nsort [opts]
(defn- replace-ns-decls [opts]
(try
(let [start (. System (nanoTime))
files (atom #{})
nses (get-invalid-declarations (or opts {}))
_ (doseq [[ns* errors] (group-by :ns nses)
err errors]
(try
(println "Replacing ns:" ns* (:type err) "form")
(spit (:file err)
(let [form (with-out-str (pp/pprint (cons (:type err) (:sorted err))))
data (z/of-file (:file err))
prj-map (z/find-value data z/next 'ns)
req (z/find-value prj-map z/next (:type err))]
(-> req m/up (z/replace (p/parse-string form)) z/root-string)))
(swap! files conj (.getName (:file err)))
(catch Exception e
(println "Error occurred. Could not update ns: " ns*)
(clojure.pprint/pprint e))))
took (long (/ (double (- (. System (nanoTime)) start)) 1000000.0))]
(println "Took:" took "msecs -" (count @files) "files updated.")
(System/exit 0))
(catch Exception e
(pp/pprint e)
(System/exit 2))))


(defn- check-ns-decl [opts]
(try
(let [start (. System (nanoTime))
nses (get-invalid-declarations (or opts {}))
Expand All @@ -82,3 +133,9 @@
(catch Exception e
(pp/pprint e)
(System/exit 2))))


(defn nsort [opts subtask]
(case subtask
("-r" "--replace") (replace-ns-decls opts)
(check-ns-decl opts)))
15 changes: 9 additions & 6 deletions src/leiningen/nsort.clj
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@


(defn nsort
[project]
(let [project (project/merge-profiles project [(check-namespace-decls-profile project)])]
(lein/eval-in-project
project
`(lein-nsort.core/nsort '~(:nsort project))
'(require 'lein-nsort.core))))
"Checks namespace decelerations order"
([project]
(nsort project nil))
([project subtask]
(let [project (project/merge-profiles project [(check-namespace-decls-profile project)])]
(lein/eval-in-project
project
`(lein-nsort.core/nsort '~(:nsort project) ~subtask)
'(require 'lein-nsort.core)))))

0 comments on commit 0ef9812

Please sign in to comment.