For a list of breaking changes, check here.
Clj-kondo: static analyzer and linter for Clojure code that sparks joy ✨
:equals-float
, warn on comparison of floating point numbers with =
. This level of this linter is :off
by default.nil
return from if
-like formsprintf
to vars linted by analyze-format
. (@tomdl89)if-let
etc condition as always truthyif-not
condition as always truthy:cljc
config option. (@NoahTheDuke):redundant-nested-call
for comp
, concat
, every-pred
and some-fn
since it may affect performance:redundant-ignore
:config-in-ns
and :discouraged-namespace
:discouraged-var
:redundant-nested-call
(@tomdl89), set to level :info
by default:redundant-ignore
, :redundant-str-call
linters to level :info
:redundant-do
in catch
--report-level
flagrequire
and :require
forms (@NoahTheDuke)gen-interface
(by suppressing unresolved symbols)cond->
and cond->>
(@tomdl89)str/replace
and ^String
annotation:redundant-ignore
linter:redundant-ignore
. See docsletfn
hooks-api/callstack
function--skip-lint
deftype
and defrecord
constructors can be used with Type/new
:sort
option to :unsorted-required-namespaces
linter to enable case-sensitive sort to match other toolsgen/fmap
var in cljs.spec.gen.alpha
byte/1
):destructured-or-binding-of-same-map
which warns about
:or
defaults referring to bindings of same map, which is undefined and may result in broken
behavior:analyze-call
hook:as-alias
with current namespace without warning about self-requiring namespace@x
should warn with type error about x
not being an IDeref, e.g. with @inc
do
and doto
type checking (@yuhan0):unused-value
or
without arguments--dependencies --copy-configs
:discouraged-namespace
can have :level
per namespace.clj-kondo/imports
but weren't pick up correctly. Thanks @frenchy64 for reporting the bug.:redundant-str-call
which detects unnecessary str
calls. Off by default.:equals-expected-position
to enforce expected value to be in first (or last) position. See docs--config {:output {:format :sarif}}
for
expressiondefn
body:flds
to be used in keys destructuring for ClojureDart:discouraged-var
on global JS values, like js/fetch
:java-static-field-call
.:shadowed-fn-param
which warns on using the same parameter name twice, as in (fn [x x])
String*
) may occur outside of metadatabigint
in CLJS is a known symbol in extend-type
:java-static-field-call
locally(Thread/interrupted)
:java-static-field-call
: calling static field as function should warn, e.g. (System/err)
assert
in hooksdatomic-type-extensions
to datalog syntax checking:exclude-files
in combination with linting from stdin + provided --filename
argument:macroexpand
hook:unused-value
using :config-in-call
:not-a-function
linter in reader tagns-map
unmaps var defined prior in namespaceif
/when
condition as always truthy, e.g. (when #'some-var 1)
:min-clj-kondo-version
in config.edn and warn when current version is too low (@snasphysicist):underscore-in-namespace
(@cosineblast):condition-always-true
linter, see docs:multiple-async-in-deftest
linter: warn on multiple async blocks in
cljs.test/deftest
, since only the first will run.deftype
a var that is referred with :refer :all
:line-length
warnings cannot be :clj-kondo/ignore
d#'foo/foo
and (var foo/foo)
the same treatment with respect to private calls:macroexpand
hook:self-requiring-namespace
:equals-false
, counterpart of :equals-true
(@svdo):syntax
check for var names starting or ending with dot (reserved by Clojure):level
in :discouraged-var
config:single-logical-operand
linter (@wtfleming)clojure.core/parse-uuid
from nilable/string
to string (@dbunin):end-row
and :end-col
in :pattern
output format (@joshgelbard):missing-else-branch
--copy-configs
is enabled but no config dir exists:unused-alias
and namespaced map:callstack
in analysis:unused-alias
. See docs.clojure.set/project
:lint-as clojure.core/defmacro
should suppress &env
as unresolved symbolclojure.core/zero?
to number -> boolean:unresolved-symbol
linter config contains unqualified symbol:keyword-binding
linter should ignore auto-resolved keywordsthrow
:exclude
option to :deprecated-namespace
linterdata_readers.clj(c)
:unused-refeferred-var
linterclj-kondo.hooks-api
interpreter namespace:case-symbol-test
:quoted-case-test-constant
to :case-quoted-test
:duplicate-case-test-constant
to :case-duplicate-test
:unsorted imports
:deprecated-namespace
linterdefprotocol
metadata (@lread).cljd
files when linting (@ericdallo)if-some
+ recur
java.util.List
type hint corresponds to :list
or nil:arglists
metadata to :arglist-strs
for analysis data (@lread):redundant-fn-wrapper
in CLJS when passing keyword to JSclj-kondo.hooks-api/*reload*
to true does not lint with the latest hook changes._
should not be reported as unused#?(:clj 1 2)
(2 is not a keyword):missing-test-assertion
introduced in 2023.05.18:refers
to :refer-all
findingswap!
:uninitialized-var
moved from default :level :off
to :warning
:equals-true
: suggest using (true? x)
over (= true x)
(defaults to :level :off
).:plus-one
and :minus-one
: suggest using (inc x)
over (+ x 1)
(and similarly for dec
and -
, defaults to :level :off
):unresolved-namespace :exclude
as already required namespaces--debug
is true#()
and #""
in .edn
files:sha
instead of :git/sha
in combination with git url in deps.edn
:defined-by->lint-as
key which contains the :lint-as
value for "defining" var, whereas :defined-as
now always contains the name of the original "defining var". This is a BREAKING change..java
files.:or
default in :local-usages analysis
data_readers.clj
:ns-groups
to be used with :analyze-call
and :macroexpand
hooks:keyword-binding
linter:lint-as clj-kondo.lint-as/def-catch-all
should ignore unresolved namespaces:missing-test-assertion
cases, e.g. (deftest foo (not (= 1 2)))
.cljc
files with :output {:langs true}
. See docs.Too many arguments to def
:discouraged-tag
linter for discouraged tag literals. See the docs.:gen
support on clojure.spec.alpha/keys
:exclude-patterns
in :unresolved-symbol
linter:def-fn
on def
+ reify
:unresolved-namespace
linter:symbols
+ :aliased-namespace-symbol
linter gives false positive in quoted symbol:exclude-pattern
in :unused-binding
schema.core/defn
with invalid s-exprs{:ignore [:unresolved-symbol]}
or {:ignore true}
, valid in ns-metadata, :config-in-ns
, :config-in-call
:var-same-name-except-case
linter: warn when vars have names that differ only in case (important for AOT compilation and case-insensitive filesystems) (@emlyn).:jvm-opts
in top level of deps.edn
update
, update-in
, swap!
, swap-vals!
, send
, send-off
, and send-via
(@jakemcc).java-member-definitions
bucket (@ericdallo).hooks-api/set-node
and hooks-api/set-node?
(@sritchie).clojure.core/aget
with more than two args:misplaced-docstring
in clojure.test/deftest
&
) symbol in fn syntaxdef
:uninitialized-var
linter. See docs.hooks-api/resolve
. See docs.:redundant-fn-wrapper
with syntax-quoted body:dynamic-var-not-earmuffed
should be opt-in:line-length
linter:macroexpand
:level :off
in :discouraged-var
config on var levelclj-kondo.lint-as/def-catch-all
doesn't emit locations, fixes navigation for lsp:macroexpand hook
(performance optimization)*err*
in hooks:discouraged-namespace
to be suppressed with #_:clj-kondo/ignore
:discouraged-namespace
linterdefn
properly:exclude-urls
and :exclude-pattern
:def-fn
: warn when using fn
inside def
, or fn
inside let
inside def
(@andreyorst).:aliased-namespace-var-usage
gives erroneous output for keywords:aliased-namespace-var-usage
: warn on var usage from namespaces that were used with :as-alias
. See demo.comment
forms (@mk). See demo.:symbols
analysis for navigation to symbols in quoted forms or EDN files. See demo.:as-alias
CLJ_KONDO_EXTRA_CONFIG_DIR
environment variable to enable extra linters after project configglibc
in dynamic linux binary to 2.31 by using fixed version of CircleCI image(def x :foo) (inc x)
will now give a warning:duplicate-field-name
linter for deftype and defrecord definitions.new
analysis from (String. x)
expansionnamespace-munge
for resolving hook files rather than munge
**
, ***
etc. to be a dynamic varsdefinterface
as unuseddefinterface
more similarly to defprotocol
for lsp-navigationhooks-api/generated-node?
function to check if a node was generatedre-find
for ns groups rather than re-matches:earmuffed-var-not-dynamic
and :dynamic-var-not-earmuffed
. See docs.:exclude
option to :used-underscored-binding
(@staifa).cljs
and .cljc
for :aliased-namespace-symbol
in interop calls. (@NoahTheDuke):derived-location
to analysis when location is derived from parent node:level :off
not being respected in :discouraged-var
configs that are merged in.clojure.spec.alpha/def
name positionschema.core/defrecord
clj-kondo-docker
pre-commit hook.:redundant-fn-wrapper
support for keyword and binding calls (@NoahTheDuke):include-macros
in .cljs
and .cljc
for :unknown-require-option
linter. (@NoahTheDuke):exclude
option to :unknown-require-option
:unused-value
by default.sha256
files along with released artifacts:unused-value
- see docs. Also see issue #1258.:line-length
- see docs (@ourkwest):unknown-require-option
- see docs. (@NoahTheDuke):aliased-namespace-symbol
- see docs. (@NoahTheDuke)nil
values (@sheluchin):unused-binding
config :exclude-destructured-as
flag. (@NoahTheDuke)deftype
in CLJS:config-in-call
- see docs:config-in-tag
- see docsfile-analyzed-fn
, bump babashka/fs to 0.1.11(require '[])
and (import '())
tag
function in clj-kondo.hooks-api
:filename-pattern
in :ns-group
clojure.pprint/pprint
to the hooks API:show-rule-name-in-message true
. See example in config guide.:imported-ns
in analysis of vars imported by potemkin:arglist-strs
support for functions defined with fn:discouraged-namespace
linter. See docs.sequence
with map
multi-arity transducerrecur
not in tail position with core.async alt!!
defrecord
, deftype
and definterface
.cljc
for just one language:macroexpand
:instance-invocations
analysis bucket.clj_kondo
files from configs:macroexpand
hooks (regression in 2022.05.27):warn-on-reflection
linter. See docs.:redundant-call
- warns when a function or macro call with 1 given argument returns the argument. See docs.clj-kondo.hooks-api
API ns for REPL usage. See
docs.:file-analyzed-fn
..pre-commit-hooks.yaml
:macroexpand
hook.clj_kondo
hook extensionclojure.test/deftest-
with-precision
:keyword-binding
- warns when a keyword
is used in a :keys
binding vector. This linter is :off
by default. See docs.:discouraged-var
. See docs.:config-in-ns
configuration option. See docs.:ns-groups
configuration option. See docsclojure.core.match
.
) should
be unresolved when not in fn position:non-arg-vec-return-type-hint
that warns when a return type hint is not placed on the arg vector (CLJ only). See docs.:namespace-name-mismatch
by default^:replace
override for nested config values--skip-lint
, to skip linting while still executing other tasks like copying configuration with --copy-configs
.re-find
Analysis:
:java-class-definitions
and :java-class-usages
. See docs.:end-row
and end-col
to analyze data for :namespace-definitions
:protocol-impls
deftype
reify
ns
+ require
:namespace-name-mismatch
until further notice due to problems on Windows:defmethod true
to defmethod var-usages
analysis.:namespace-name-mismatch
to detect when namespace name does not match file name. (@svdo):scope-end-row
is missing on multi-arity fn args (@mainej):deprecated-var
config in ns form metadatabb.edn
(@mknoszlig):depends
. (@mknoszlig):keys
can be used in :ret
position, also fixes types return map call as input for another typed map function. (@pfeodrippe)#(inc %)
. See
docs. This linter of :off
by default
but may be enabled by default in future versions after more testing.bb.edn
(@mknoszlig)recur
in cond->
gives warning about recur
not in tail position.:conflicting-fn-arity
: warn when an arity occurs more than once in a function that overloads on arity. #1136 (@mknoszlig):clj-kondo-config
which provides linting for .clj-kondo/config.edn
. #1527:reduce-without-init
for functions known to be safe #1519fdef
can be arbitrary namespace #1532:output {:progress true}
should print to stderr #1523--debug
is enabled. #1514:reduce-without-init
: warn against two argument version of
reduce. Disabled by
default. See docs. #1064 (@mknoszlig):quoted-case-test-constant
: warn on quoted test constants in case. #1496 (@mknoszlig).clj-kondo/*/*/config.edn
. This can be disabled with :auto-load-configs false
. #1492:duplicate-case-test-constant
: detect duplicate case test constants. See docs. #587 (@mknoszlig):unexpected-recur
: warn on recur
in unexpected (non-tail) position. #1126:used-underscored-binding
: warn on used bindings that start with underscore. Disabled by default. See docs. #1149 (@mknoszlig):docstring-blank
for checking empty docstring. See docs. #805 (@joodie):docstring-leading-trailing-whitespace
for checking leading and trailing whitespace in docstring. Disabled by default. See docs. #805 (@joodie):docstring-no-summary
for checking the absence of summary of args in docstring. Disabled by default. See docs. #805 (@joodie):exclude-defmulti-args
option for :unused-bindings
linter. See docs. #1188 (@mknoszlig):config-in-comment
#1473. See docs.clojure.data.json
:refer
suggestion so you can copy paste it #1293 (@vemv)extend-protocol
, extend-type
, reify
, specify!
#1333, #1447:context
in nodes in hooks for adding context to analysis #1211goog.object
, goog.string
etc must be required before use in newer releases
of CLJS #1422(exists? foo.bar/az)
complains about require #1472gen-class
if namespace has -main
fn
#1417. See docs.def
#1408def
+ fn
combination
#1410fn
type inference
#1412rseq
called on other type than vector or sorted-map now gives type error #1432.cljc
#1403:from-var
in higher order call #1404:duplicate-ns
to duplicate-require linter output #1421 (@ericdallo)if-let
/ if-some
with invalid arity no longer warn #1426import-vars
#1385case
to avoid false positives for constants #1388ns-unmap
pattern #1384:end-row
, :end-col
to :var-usages
analysis element #1387:row
and :col
for :var-usages
to use the start location of the call instead of the name location #1387:as-alias
(new feature in Clojure 1.11) #1378:loop-without-recuir
wrt/ fn
and other constructs that introduce a recur
target #1376:loop-without-recur
linter. #426deps.edn
and bb.edn
:paths
#1353 (@lread):refer
to var-usages when inside a require #1364 (@ericdallo)babashka.process/$
#1368defmulti
#1310ns-analysis
fn in hooks API #1349 (@hugoduncan)reg-finding!
#1344 (@ericdallo)declare
name positions in analysis #1343 (@ericdallo)deps.edn
to match Clojure CLI 1.10.1.933
(@dpassen):macroexpand
hook. This allows linting using the same or similar macros from
your code. See
docs.ex-info
#1314map
, filter
, reduce
, etc.) #1297map-node
and map-node?
to hooks API #1270:skip-comments false
doesn't override :skip-comments true
in namespace config #1295clojure.spec/keys
#1289clojure.spec.alpha/keys
#1272 (@daveduthie)clojure.template/do-template
#603clojure.test/are
#1284clojure.data.xml
imported via macro #1274([])
as invalid call to vector #1276:doc
from attr-map in defn
#1265.jar
files with --dependencies
when config(s) have changed #1285--fail-level
flag to specify the minimum severity for a non-zero exit code #1259 (@RickMoynihan)core.async
defblockingop
macro #1244:or
map #1242:defined-by
contains raw node for sgen fns #1231:report-duplicates
linter config for several linters. #1232 (@snoe)--copy-configs
flag to indicate copy configs from dependencies while linting. This replaces --no-warnings
.--dependencies
flag to indicate skipping already linted jars for performance. This replaces --no-warnings
.user.clj
#1190sgen/lazy-prims
#1192:lint-as
with cond->
#1205clojure.core.reducers/defcurried
#1217:defined-by
on missing var definitions #1219 (@ericdallo):unused-private-var
warning for deftype ^:private
#1222:exclude
config to :refer linter #1172:refer
#546clojure.data.xml/alias-uri
#1180Thanks to @snoe and @ericdallo for contributing to this release. Thanks to the sponsors on Github, OpenCollective and Clojurists Together for making this release possible.
:aliases
to ns ctx and :alias
to var-usages #1133 (@snoe):end-row
and :end-col
to var-definitions bucket on analysis #1147 (@ericdallo)clojure.spec.gen.alpha/fmap
#1157Thanks to @SevereOverfl0w, @jysandy, @tomdl89, @snoe, @audriu, and @ericdallo for contributing to this release.
:unresolved-var
. This detects unresolved vars in other namespaces, like set/onion
. See docs. #635lint-specific-calls!
#1116 (@tomdl89)and
and or
#1122 (@tomdl89):ns
to :unused-namespace
findings (@ericdallo):refer-clojure
+ :only
#957deftype
and defrecord
#140cljs.core/simple-benchmark
syntax #1079babashka.process/$
macro syntax #1089refer :all
when linting in parallel #1068amap
#1069deps.edn
causes false positive #1093deps.edn
#1094Thanks @bennyandresen, @jaihindhreddy, @mharju, @pepijn, @slipset and @nvuillam for contributing to this release. Thanks to Clojurists Together for sponsoring this release.
--filename
option to set filename when linting from stdin. This should be
used for editor plugins to enable deps.edn
linting.--no-warnings
flag to indicate linting is used to populate cache.:include
option for shadowed-var linter #1040:files
count in summary #1046:all
#1010format
#1044Thanks @zilti, @dharrigan and @sogaiu for contributing to this release. Thanks to Clojurists Together for sponsoring this release.
:as
binding
clj-kondo#1016 (@dharrigan)contains?
#1021let
and do
in hook-generated code #1038(or)
#1023Thanks to @cldwalker, @bfontaine, @snoe, @andreyorst, @jeroenvandijk, @jaihindhreddy, @sittim and @sogaiu for contributing to this release. Thanks to the people who helped designing the new features in Github issue conversations. Thanks to Clojurists Together for sponsoring this release.
Add --parallel
option to lint sources in parallel. This will speed up
linting an entire classpath. #632, #972
Detect error when calling a local that's not a function. #948
(let [inc "foo"]
(inc 1))
^--- String cannot be called as a function
Support ignore hints #872:
(inc 1 2 3)
^--- clojure.core/inc is called with 3 args but expects 1
#_:clj-kondo/ignore
(inc 1 2 3)
^--- arity warning ignored
#_{:clj-kondo/ignore[:invalid-arity]}
(do (inc 1 2 3))
^--- only redundant do is reported, but invalid arity is ignored
Also see config.md.
Merge config from $HOME/.config/clj-kondo
, respecting XDG_CONFIG_HOME
. See
config.md for details. #992
New :config-paths
option in <project>/.clj-kondo/config.edn
. This allows
extra configuration directories to be merged in. See
config.md for details. #992
Config tool that can spit out library
specific configurations that can be added via :config-paths
. Contributions
for libraries are welcome.
Experimental spec inspection tool that attempts to extract type information for linting. Also uses the new :config-paths
feature.
Allow pinned version in installation script #946 (@cldwalker)
defc
hook #960into
and transducer
#952native-image
build @jaihindhreddyDetails about releases prior to v2020.09.09 can be found here.
:defined-by->lint-as
key which contains the :lint-as
value for "defining" var, whereas :defined-as
now always contains the name of the original "defining var". This is a BREAKING change.:row
and :col
for :var-usages
to use the start location of the call instead of the name location #1387Can you improve this documentation? These fine people already did:
Michiel Borkent, Eric Dallo, Noah, mknoszlig, Tom Dalziel, Lee Read, Sam Umbach, Alex Sheluchin, Jacob Maine, André Ribeiro Camargo, Kirill Chernyshov, Renan Ribeiro, Artur Dumchev, Stefan van den Oord, Martin Kavalar, Jake McCrary, Joni Hämäläinen, Sebastian Andersen, Jacob Taylor-Hindle, Emlyn Corrin, yuhan0, Chance Russell, allie-jo, Joel Hess, Scott N A Smith, Vipin Nair, Ryan Schmukler, Wes Morgan, staifa, Dmytro Bunin, Iñaki Arenaza, ikappaki, Joshua Suskalo, Rick Moynihan, James Croft, Derek Passen, Pedro Girardi, Gian, Stig Brautaset, Rachel Westmacott, Klay, Sam Ritchie, Will Fleming, Yurii Hryhorenko, Josh Gelbard, Jakub Dundalek, Inge Solvoll, Magnar Sveen, Rahuλ Dé & Juho TeperiEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close