https://github.com/camsaul/lein-check-namespace-decls.git
git clone 'https://github.com/camsaul/lein-check-namespace-decls.git'
(ql:quickload :camsaul.lein-check-namespace-decls)
A Leiningen plugin that lints source files in your Clojure project to
check whether the ns declarations are cleaned the way
refactor-nrepl
and
cljr-refactor
would clean them (such as with the M-x cljr-clean-ns command in
Emacs).
Checks the following:
ns declaration are sorted:require forms are used instead of :usens form follow the conventional
order:
:gen-class, :refer-clojure, :require, :import:require use shared prefixes (e.g. (:require [clojure [string :as str] [data :as data]]))For files with ns declarations that don't satisfy these rules, the
linter tells you how to fix namespace declarations that aren't cleaned
properly.

What happened? The linter detected an unused namespace,
clojure.string, and removed it; it sorted the namespaces as well.
For each ns declaration it finds that isn't “clean” (i.e. not
properly sorted or with unused namespaces), it will print a message
like the one above; if any unclean namespaces were found, the linter
will exit with a nonzero status.
:pluginsAdd [lein-check-namespace-decls "1.0.1"] into the :plugins vector of your
project.clj or ~/.lein/profiles.clj.
(defproject my-project
:plugins [[lein-check-namespace-decls "1.0.1"]])
Run the linter like this:
lein check-namespace-decls
This will check ns declaration forms for all Clojure source files in
the :source-paths of your project (usually ./src/).
Add a :check-namespace-decls key to your project.clj to configure
the way refactor-nrepl cleans namespaces. All options are passed
directly to refactor-nrepl.
(defproject my-project
:check-namespace-decls {:prefix-rewriting false})
The complete list of available options can be found here. The most interesting ones when using this as a linter are:
:prefix-rewritingBy setting {:prefix-rewriting false} the ns form will not be
expected to use prefix lists when including several libs whose names
have the same prefix. The default behavior uses prefixes:
;; Cleaned ns form with :prefix-rewriting true (default)
(ns my-project.core
(:require [clojure.tools.namespace
[find :as ns.find]
[parse :as ns.parse]]))
Contrast this to ns forms without prefixes:
;; Cleaned ns form with :prefix-rewriting false
(ns my-project.core
(:require [clojure.tools.namespace.find :as ns.find]
[clojure.tools.namespace.parse :as ns.parse]))
Opinions on whether or not to use prefixes in :require forms vary in
the Clojure community; I (@camsaul)
personally like them, so I stuck with the default behavior of
refactor-nrepl, which is to use them.
:ignore-pathsSpecify a collection of regexes of filenames to ignore.
;; ignore any files ending in core.clj
(defproject my-project
:check-namespace-decls {:ignore-paths [#".*core\.clj$"]})
:prune-ns-formWhether to remove unused namespaces from the ns form. Defaults to
true; if you don't want unused namespaces to be considered an error,
set this to false.
lein-check-namespace-decls simply checks any Clojure source files it finds in :source-paths, excluding any that match a pattern in :ignore-paths.
To include or exclude entire directories from the linter you can
modify or ^:replace :source-paths; the easiest way to do this without
affecting the rest of your project is to add a profile for
lein-check-namespace-decls and an alias that automatically applies
it:
;; Check the sources under `./test/` in addition to the normal :source-paths (e.g. `./src/`)
(defproject my-project
:aliases {"check-namespace-decls" ["with-profile" "+check-namespace-decls" "check-namespace-decls"]}
:plugins [[lein-check-namespace-decls "1.0.1"]]
:profiles {:check-namespace-decls {:source-paths ["test"]}})
If the above seems like black magic, the Leiningen documentation does a great job of explaining how Leiningen plugins work in more detail.
Like Leiningen itself, setting the environment variable DEBUG=true
will add additional log messages to linter output – specifically, it
will log messages about each file it checks and files that are skipped
due to patterns in :ignore-paths (and the patterns that matched
those files). This is useful for debugging which files are checked by the linter.
Copyright © 2019 Cam Saul.
Distributed under the Eclipse Public License, same as Clojure.