clj-kondo / clj-kondo Goto Github PK
View Code? Open in Web Editor NEWStatic analyzer and linter for Clojure code that sparks joy
License: Eclipse Public License 1.0
Static analyzer and linter for Clojure code that sparks joy
License: Eclipse Public License 1.0
E.g. https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/repl.cljc#L1032
The function eval
isn't recognized as a binding right now.
(defn my-component []
[:div "Hello"])
[:div [my-component 1 2 3]] ;; <- arity error
Reader conditionals are only valid in .cljc
file, so we should get a warning when using them somewhere else.
Instead of rejecting a whole file, we should report an error only on parts that could not be processed well, like namespace declarations.
Currently the entire cache (an EDN file) is read and written each time clj-kondo is run.
We can optimize this by splitting the cache into files per namespace.
Reads:
When making calls to ns1, ns2 ..., we only need to read ns1.edn, ns2.edn.
Writes:
When detecting new function definitions for ns1 we only need to write ns1.edn.
I've just installed clj-kondo via homebrew on my Mac OS X (10.14.3) and tried to run it on a closed-source project (fairly non-trivial with lots of dependencies) but cache initialization fails after a while with the following error:
$ clj-kondo --version
clj-kondo v2019.04.07-alpha
$ clj-kondo --lint $(lein classpath) --cache
...
Exception in thread "main" java.lang.IllegalArgumentException: No matching field found: getMessage for class java.lang.NullPointerException
at clojure.lang.Reflector.getInstanceField(Reflector.java:397)
at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:440)
at clojure.stacktrace$print_throwable.invokeStatic(stacktrace.clj:43)
at clojure.stacktrace$print_stack_trace.invokeStatic(stacktrace.clj:55)
at clojure.stacktrace$print_stack_trace.invoke(stacktrace.clj:48)
at clojure.stacktrace$print_stack_trace.invokeStatic(stacktrace.clj:53)
at clojure.stacktrace$print_stack_trace.invoke(stacktrace.clj:48)
at clj_kondo.main$_main$fn__4224.invoke(main.clj:269)
at clj_kondo.main$_main.invokeStatic(main.clj:267)
at clj_kondo.main$_main.doInvoke(main.clj:265)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clj_kondo.main.main(Unknown Source)
I tried the same on my clojure-experiments public project and it fails again with the same error
I've tried both Java 8 and Java 11 => the same result.
I've got a bunch of extra dependencies in my ~/.lein/profiles.clj so I thought they may affect it too.
However, I ran this using only base lein profile and the result is again the same:
clj-kondo --lint $(lein with-profile base classpath) --cache
WARNING!!! version ranges found for:
[net.cgrand/sjacket "0.1.1"] -> [org.clojure/clojure "[1.3.0,)"]
Consider using [net.cgrand/sjacket "0.1.1" :exclusions [org.clojure/clojure]].
[net.cgrand/sjacket "0.1.1"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [net.cgrand/sjacket "0.1.1" :exclusions [org.clojure/clojure]].
[net.cgrand/sjacket "0.1.1"] -> [net.cgrand/parsley "0.9.2"] -> [net.cgrand/regex "1.1.0"] -> [org.clojure/clojure "[1.2.0,)"]
Consider using [net.cgrand/sjacket "0.1.1" :exclusions [org.clojure/clojure]].
Exception in thread "main" java.lang.IllegalArgumentException: No matching field found: getMessage for class java.lang.NullPointerException
at clojure.lang.Reflector.getInstanceField(Reflector.java:397)
at clojure.lang.Reflector.invokeNoArgInstanceMember(Reflector.java:440)
at clojure.stacktrace$print_throwable.invokeStatic(stacktrace.clj:43)
at clojure.stacktrace$print_stack_trace.invokeStatic(stacktrace.clj:55)
at clojure.stacktrace$print_stack_trace.invoke(stacktrace.clj:48)
at clojure.stacktrace$print_stack_trace.invokeStatic(stacktrace.clj:53)
at clojure.stacktrace$print_stack_trace.invoke(stacktrace.clj:48)
at clj_kondo.main$_main$fn__4224.invoke(main.clj:269)
at clj_kondo.main$_main.invokeStatic(main.clj:267)
at clj_kondo.main$_main.doInvoke(main.clj:265)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clj_kondo.main.main(Unknown Source)
E.g.:
#?(:cljs
(defn macroexpand [env form]
(loop [form form
form' (ana/macroexpand-1 env form)]
(if-not (identical? form form')
(recur form' (ana/macroexpand-1 env form'))
form'))))
(defn- pll-mod-body [env var-sym body]
(letfn [(inner [form]
(if (seq? form)
(let [form #?(:clj (macroexpand form)
:cljs (macroexpand env form))]
(condp = (first form)
'loop* form
'recur (concat `(recur (inc ~var-sym)) (rest form))
(walk/walk inner identity form)))
form))]
(walk/walk inner identity body)))
gives
cljs/pprint.cljc:93:40: error: Wrong number of args (1) passed to macroexpand
This may make it easier to process mixed forms. See #63
See https://cljdoc.org/d/lambdaisland/kaocha/0.0-409/doc/-clojure-test-assertion-extensions
and https://github.com/jonase/eastwood#suspicious-test
(require '[clojure.test :refer [deftest]])
(deftest foo
(= 1 2))
(deftest foo
(some? [1 2 3]))
(deftest foo
(is 1 2))
(deftest my-test
(is (= 4) 5))
Even though the fn
body has an implicit do
block, the fn
shorthand #()
requires us to write out an explicit do
if we want to do multiple operations in it.
See how Planck does it:
CLJS projects can have string namespaces. E.g.:
(ns myapp
(:require [reagent.core :as r :refer [atom]]
["react-native" :as rn :refer [AppRegistry]]
["react-native-navigation" :as rnn]
[env]))
Currently clj-kondo chokes on processing theses file. Moreover, it doesn't process the rest of the directory when one of the files is not readable. Both issues should be fixed.
Repro:
$ rlwrap clj-kondo --lint -
(defn get-bytes ^bytes [part] part)
(get-bytes :thing)
$ rlwrap clj-kondo --lint -
(defn get-bytes #^bytes [part] part)
(get-bytes :thing)
^D<stdin>:2:1: error: Wrong number of args (1) passed to user/get-bytes
Found when linting yada:
https://github.com/juxt/yada/blob/c69c003794d1f07336741dcd80aa7b8fa8ca5cdb/ext/multipart/src/yada/multipart.clj#L37
The --files
option should read --lint
.
Make it clear that the .clj-kondo
directory is not the caching directory, but a caching directory will be created inside of it.
Currently we don't support in-ns
: we just ignore it.
We should only handle top level in-ns
expression and ignore those in function bodies.
Right now when we handle a namespace clj-kondo thinks it sees the entire thing. So next time we see a namespace, it replaces the entire old one in the cache. This handles deleting functions well. This should still work when implementing in-ns
, so we should write a test for it.
E.g.:
#(parse-arities % lang 2 (set/union bindings fn-bindings))
^
instead of
#(parse-arities % lang 2 (set/union bindings fn-bindings))
^
See this config file
clj -A:clj-kondo --lint $(clj -Spath) --config '{:output {:remove ["^clojure" "^cljs" "^rewrite_clj"]}}'
clj -A:clj-kondo --lint $(clj -Spath) --config '{:linters {:cond-without-else {:level :off}}}'
Might change to:
{;; ;; *** lint contents inside comment sections, set to truthy to skip them
;; :skip-comments false
;; ;; *** linter level can be tweaked by setting :level to :error, :warn or :info (or any other keyword)
;; ;; *** all linters are enabled by default, but can be turned off by setting :level to :off.
;; :incorrect-arity {:level :error}
;; :private-call {:level :error}
;; :inline-def {:level :warning}
;; :redundant-do {:level :warning}
;; :redundant-let {:level :warning}
;; :cond-without-else {:level :warning}
;; :missing-test-assertion {:level :warning}
;; ;; *** set to truthy to print progress while linting
;; :progress false
;; ;; *** output can be filtered and removed by regex on filename. empty options leave the output untouched.
;; :include ["^src" "^test"]
;; :exclude ["^cljs/core"]
;; ;; *** the output pattern can be altered using a template:
;; :pattern "{{file}}:{{row}}:{{col}}: {{level}}: {{message}}"
}
When reading specs like
(s/fdef foo :args (s/cat :i int?))
we can detect wrong calls like (foo "string")
.
We could also offer a suggestion when the user types (foo _)
.
We might use speculative for checking core calls.
When detecting something like (str "foo" "/" "bar" "/" "baz")
the linter might suggest using (str/join "/" ["foo" "bar" "baz"])
.
When invoking clj-kondo on some code I got a null pointer exception. I have reduced it to a minimal test case
(ns ck.core
(:require [ck.it :as it])
(:gen-class))
(defn -main
[& args]
(println #::it {:a #::it {}}))
I get the error shown below. I've tried various combinations and it seems the nested use of auto-resolved namespaced keywords triggers it.
Probably related, if I use the current namespace, i.e. #:: {:a #:: {}}
, I get "[line 7, col 16] A single colon is not a valid keyword."
$ lein clj-kondo src/ck/core.clj
Exception in thread "main" Syntax error compiling at (/tmp/form-init2114187965721477842.clj:1:73).
at clojure.lang.Compiler.load(Compiler.java:7647)
at clojure.lang.Compiler.loadFile(Compiler.java:7573)
at clojure.main$load_script.invokeStatic(main.clj:452)
at clojure.main$init_opt.invokeStatic(main.clj:454)
at clojure.main$init_opt.invoke(main.clj:454)
at clojure.main$initialize.invokeStatic(main.clj:485)
at clojure.main$null_opt.invokeStatic(main.clj:519)
at clojure.main$null_opt.invoke(main.clj:516)
at clojure.main$main.invokeStatic(main.clj:598)
at clojure.main$main.doInvoke(main.clj:561)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:705)
at clojure.main.main(main.java:37)
Caused by: java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
at clojure.lang.Namespace.find(Namespace.java:188)
at clojure.core$find_ns.invokeStatic(core.clj:4130)
at clojure.core$the_ns.invokeStatic(core.clj:4160)
at clojure.core$ns_name.invokeStatic(core.clj:4164)
at clojure.core$ns_name.invoke(core.clj:4164)
at rewrite_clj.node.seq.NamespacedMapNode.sexpr(seq.clj:57)
at rewrite_clj.node.protocols$eval231$fn__275$G__237__277.invoke(protocols.clj:9)
at rewrite_clj.node.protocols$eval231$fn__275$G__236__280.invoke(protocols.clj:9)
at clojure.core$map$fn__5851.invoke(core.clj:2755)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.boundedLength(RT.java:1788)
at clojure.lang.RestFn.applyTo(RestFn.java:130)
at clojure.core$apply.invokeStatic(core.clj:665)
at clojure.core$apply.invoke(core.clj:660)
at rewrite_clj.node.seq$map_node$fn__2119.invoke(seq.clj:110)
at rewrite_clj.node.seq.SeqNode.sexpr(seq.clj:16)
at rewrite_clj.node.protocols$eval231$fn__275$G__237__277.invoke(protocols.clj:9)
at rewrite_clj.node.protocols$eval231$fn__275$G__236__280.invoke(protocols.clj:9)
at clojure.core$map$fn__5851.invoke(core.clj:2753)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.RT.seq(RT.java:531)
at clojure.lang.RT.countFrom(RT.java:646)
at clojure.lang.RT.count(RT.java:639)
at rewrite_clj.node.seq$assert_namespaced_map_children.invokeStatic(seq.clj:40)
at rewrite_clj.node.seq$assert_namespaced_map_children.invoke(seq.clj:37)
at rewrite_clj.node.seq$namespaced_map_node.invokeStatic(seq.clj:115)
at rewrite_clj.node.seq$namespaced_map_node.invoke(seq.clj:112)
at rewrite_clj.parser.core$eval2727$fn__2728.invoke(core.clj:123)
at clojure.lang.MultiFn.invoke(MultiFn.java:229)
at rewrite_clj.reader$read_with_meta.invokeStatic(reader.clj:132)
at rewrite_clj.reader$read_with_meta.invoke(reader.clj:128)
at rewrite_clj.parser.core$parse_next.invokeStatic(core.clj:35)
at rewrite_clj.parser.core$parse_next.invoke(core.clj:33)
at rewrite_clj.parser.core$parse_delim$fn__2683.invoke(core.clj:43)
at rewrite_clj.reader$read_repeatedly$fn__1399.invoke(reader.clj:141)
at clojure.core$repeatedly$fn__6448.invoke(core.clj:5149)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.RT.seq(RT.java:531)
at clojure.core$seq__5387.invokeStatic(core.clj:137)
at clojure.core$take_while$fn__5902.invoke(core.clj:2904)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:709)
at clojure.core$next__5371.invokeStatic(core.clj:64)
at clojure.core$dorun.invokeStatic(core.clj:3142)
at clojure.core$doall.invokeStatic(core.clj:3148)
at clojure.core$doall.invoke(core.clj:3148)
at rewrite_clj.reader$read_repeatedly.invokeStatic(reader.clj:143)
at rewrite_clj.reader$read_repeatedly.invoke(reader.clj:137)
at rewrite_clj.parser.core$parse_delim.invokeStatic(core.clj:44)
at rewrite_clj.parser.core$parse_delim.invoke(core.clj:39)
at rewrite_clj.parser.core$eval2751$fn__2752.invoke(core.clj:172)
at clojure.lang.MultiFn.invoke(MultiFn.java:229)
at rewrite_clj.reader$read_with_meta.invokeStatic(reader.clj:132)
at rewrite_clj.reader$read_with_meta.invoke(reader.clj:128)
at rewrite_clj.parser.core$parse_next.invokeStatic(core.clj:35)
at rewrite_clj.parser.core$parse_next.invoke(core.clj:33)
at rewrite_clj.parser.core$parse_delim$fn__2683.invoke(core.clj:43)
at rewrite_clj.reader$read_repeatedly$fn__1399.invoke(reader.clj:141)
at clojure.core$repeatedly$fn__6448.invoke(core.clj:5149)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.RT.seq(RT.java:531)
at clojure.core$seq__5387.invokeStatic(core.clj:137)
at clojure.core$take_while$fn__5902.invoke(core.clj:2904)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:709)
at clojure.core$next__5371.invokeStatic(core.clj:64)
at clojure.core$dorun.invokeStatic(core.clj:3142)
at clojure.core$doall.invokeStatic(core.clj:3148)
at clojure.core$doall.invoke(core.clj:3148)
at rewrite_clj.reader$read_repeatedly.invokeStatic(reader.clj:143)
at rewrite_clj.reader$read_repeatedly.invoke(reader.clj:137)
at rewrite_clj.parser.core$parse_delim.invokeStatic(core.clj:44)
at rewrite_clj.parser.core$parse_delim.invoke(core.clj:39)
at rewrite_clj.parser.core$eval2751$fn__2752.invoke(core.clj:172)
at clojure.lang.MultiFn.invoke(MultiFn.java:229)
at rewrite_clj.reader$read_with_meta.invokeStatic(reader.clj:132)
at rewrite_clj.reader$read_with_meta.invoke(reader.clj:128)
at rewrite_clj.parser.core$parse_next.invokeStatic(core.clj:35)
at rewrite_clj.parser.core$parse_next.invoke(core.clj:33)
at rewrite_clj.parser$parse.invokeStatic(parser.clj:13)
at rewrite_clj.parser$parse.invoke(parser.clj:10)
at rewrite_clj.parser$parse_all$fn__2768.invoke(parser.clj:18)
at clojure.core$repeatedly$fn__6448.invoke(core.clj:5149)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.RT.seq(RT.java:531)
at clojure.core$seq__5387.invokeStatic(core.clj:137)
at clojure.core$take_while$fn__5902.invoke(core.clj:2904)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.Cons.next(Cons.java:39)
at clojure.lang.RT.next(RT.java:709)
at clojure.core$next__5371.invokeStatic(core.clj:64)
at clojure.core$dorun.invokeStatic(core.clj:3142)
at clojure.core$doall.invokeStatic(core.clj:3148)
at clojure.core$doall.invoke(core.clj:3148)
at rewrite_clj.parser$parse_all.invokeStatic(parser.clj:20)
at rewrite_clj.parser$parse_all.invoke(parser.clj:15)
at rewrite_clj.parser$parse_string_all.invokeStatic(parser.clj:35)
at rewrite_clj.parser$parse_string_all.invoke(parser.clj:32)
at clj_kondo.core$process_input.invokeStatic(core.clj:95)
at clj_kondo.core$process_input.invoke(core.clj:87)
at clj_kondo.core$process_file.invokeStatic(core.clj:105)
at clj_kondo.core$process_file.invoke(core.clj:102)
at clojure.core$map$fn__5851.invoke(core.clj:2755)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:51)
at clojure.lang.RT.seq(RT.java:531)
at clojure.core$seq__5387.invokeStatic(core.clj:137)
at clojure.core$apply.invokeStatic(core.clj:660)
at clojure.core$mapcat.invokeStatic(core.clj:2783)
at clojure.core$mapcat.doInvoke(core.clj:2783)
at clojure.lang.RestFn.invoke(RestFn.java:423)
at clj_kondo.main$_main.invokeStatic(main.clj:24)
at clj_kondo.main$_main.doInvoke(main.clj:18)
at clojure.lang.RestFn.invoke(RestFn.java:423)
at clojure.lang.Var.invoke(Var.java:388)
at user$eval140.invokeStatic(form-init2114187965721477842.clj:1)
at user$eval140.invoke(form-init2114187965721477842.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7176)
at clojure.lang.Compiler.eval(Compiler.java:7166)
at clojure.lang.Compiler.load(Compiler.java:7635)
... 12 more
Inspired by the circleci
command line tool:
clj-kondo update
clj-kondo update --unstable
clj-kondo update --check
clj-kondo update --check --unstable
(dotimes [i 10] i)
vs
(doseq [i (range 10)]
i)
I often write (s/fdef foo (s/cat ...))
and forget the :args
key.
E.g.:
(ns ^:no-doc rewrite-clj.parser.core
(:require [rewrite-clj
[node :as node]
[reader :as reader]]
[rewrite-clj.parser
[keyword :refer [parse-keyword]]
[string :refer [parse-string parse-regex]]
[token :refer [parse-token]]
[whitespace :refer [parse-whitespace]]]
[clojure.tools.reader.reader-types :as r]))
https://github.com/xsc/rewrite-clj/blob/master/src/rewrite_clj/parser/core.clj#L1
It seems IntelliJ is sensitive to this.
(for [i (range 10)]
(let [j (* i 10)]
j))
=>
(for [i (range 10)
:let [j (* i 10)]]
j)
On line 342 of clojure.spec.alpha.clj a macro is defined with the name def
, but earlier calls already get resolved as using this macro.
E.g.:
(s/conform :clojure.core.specs.alpha/defn-args
'[foo
([x y z] (+ x y z))])
;;=>
{:fn-name foo,
:fn-tail
[:arity-n
{:bodies
[{:params {:params [[:local-symbol x] [:local-symbol y] [:local-symbol z]]},
:body [:body [(+ x y z)]]}]}]}
We can do this by stubbing out static class methods as Clojure functions:
$ clj-kondo --lint -
(ns java.lang.Thread)
(defn sleep ([ms]) ([ms nanos]))
(ns user (:require [java.lang.Thread :as Thread]))
(Thread/sleep 1 2 3)
<stdin>:4:1: error: Wrong number of args (3) passed to java.lang.Thread/sleep
linting took 99658ms, errors: 1, warnings: 0
These stub files we can put in a stubs
directory (don't put this dir on the classpath).
Then we analyze this and write to a cache. These cache files will then be used as built-ins.
We can add an implicit require like the example above to every analyzed namespace.
Maybe we can parse javadocs like https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
and scan for static methods, collect the arities and emit transit directly, bypassing the linter.
Quick POC with e.g.: https://github.com/RaidAndFade/javadoc-json-doclet
javadoc -doclet com.raidandfade.JsonDoclet.Main -docletpath builds/json-jdoc.jar ~/git/jdk/src/java.base/share/classes/java/lang/Thread.java
Example of using doclet with clojure:
https://github.com/oakes/play-clj/tree/3b7b7544e04ced125407d4ba4f0f0368e8f9caed/doclet
See the javadoc branch:
clj -Sdeps "{:deps {tools.jar {:local/root \"$JAVA_HOME/lib/tools.jar\"}}}"
(import 'com.sun.tools.javadoc.Main)
(compile 'clj-kondo.Doclet)
(Main/execute (into-array ["clojure.lang" "-classpath" "/Users/Borkdude/git/clojure/src/jvm" "-doclet" "clj_kondo.Doclet"]))
alexmiller [5:32 PM]
that stuff is dead
borkdude [5:32 PM]
is there something newer I should use?
alexmiller [5:33 PM]
yes - javax.tools.DocumentationTool
I don't know the coords for it, but you should just be using it as normal Maven artifact
borkdude [5:34 PM]
that seems to work out of the box:
```$ clj
Clojure 1.10.0
user=> (import 'javax.tools.DocumentationTool)
javax.tools.DocumentationTool```
Also see the migration part in: https://docs.oracle.com/en/java/javase/11/docs/api/jdk.javadoc/jdk/javadoc/doclet/package-summary.html
E.g.:
(s/fdef foo/foo :args (s/cat :x (s/keys :req-un [::bar]))))
(foo/foo {:baz 1})
info: did you mean bar?
❯ clj -Sdeps '{:deps {clj-kondo {:git/url "https://github.com/borkdude/clj-kondo" :sha "79c67cb9d3dbe0727e6c1e93066c16da36206f1a"}}}' -m clj-kondo.main --lint src
Exception in thread "main" Syntax error compiling at (main.clj:12:24).
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3707)
at clojure.lang.Compiler$DefExpr.eval(Compiler.java:457)
at clojure.lang.Compiler.eval(Compiler.java:7181)
at clojure.lang.Compiler.load(Compiler.java:7635)
at clojure.lang.RT.loadResourceScript(RT.java:381)
at clojure.lang.RT.loadResourceScript(RT.java:372)
at clojure.lang.RT.load(RT.java:463)
at clojure.lang.RT.load(RT.java:428)
at clojure.core$load$fn__6824.invoke(core.clj:6126)
at clojure.core$load.invokeStatic(core.clj:6125)
at clojure.core$load.doInvoke(core.clj:6109)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5908)
at clojure.core$load_one.invoke(core.clj:5903)
at clojure.core$load_lib$fn__6765.invoke(core.clj:5948)
at clojure.core$load_lib.invokeStatic(core.clj:5947)
at clojure.core$load_lib.doInvoke(core.clj:5928)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:667)
at clojure.core$load_libs.invokeStatic(core.clj:5985)
at clojure.core$load_libs.doInvoke(core.clj:5969)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:667)
at clojure.core$require.invokeStatic(core.clj:6007)
at clojure.main$main_opt.invokeStatic(main.clj:491)
at clojure.main$main_opt.invoke(main.clj:487)
at clojure.main$main.invokeStatic(main.clj:598)
at clojure.main$main.doInvoke(main.clj:561)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:705)
at clojure.main.main(main.java:37)
Caused by: java.io.FileNotFoundException: VERSION (No such file or directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at clojure.java.io$fn__11466.invokeStatic(io.clj:229)
at clojure.java.io$fn__11466.invoke(io.clj:229)
at clojure.java.io$fn__11379$G__11372__11386.invoke(io.clj:69)
at clojure.java.io$fn__11478.invokeStatic(io.clj:258)
at clojure.java.io$fn__11478.invoke(io.clj:254)
at clojure.java.io$fn__11379$G__11372__11386.invoke(io.clj:69)
at clojure.java.io$fn__11440.invokeStatic(io.clj:165)
at clojure.java.io$fn__11440.invoke(io.clj:165)
at clojure.java.io$fn__11392$G__11368__11399.invoke(io.clj:69)
at clojure.java.io$reader.invokeStatic(io.clj:102)
at clojure.java.io$reader.doInvoke(io.clj:86)
at clojure.lang.RestFn.invoke(RestFn.java:410)
at clojure.lang.AFn.applyToHelper(AFn.java:154)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.core$apply.invokeStatic(core.clj:667)
at clojure.core$slurp.invokeStatic(core.clj:6942)
at clojure.core$slurp.doInvoke(core.clj:6942)
at clojure.lang.RestFn.invoke(RestFn.java:410)
at clojure.lang.AFn.applyToHelper(AFn.java:154)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3702)
... 30 more
(let [x 1]
(if x 1 2))
When only linting clj(s) it should not read and write the cache for the other language.
Not all defns forms in https://github.com/tonsky/datascript/blob/master/src/datascript/db.cljc can be parsed by clj-kondo.
clj-kondo should print a warning if the --cache option exists, but isn't specified. the behavior is that it searches for the nearest .clj-kondo directory, but if this directory doesn't exist it now makes a .cache directory in the current working directory. Instead it should print a warning that the config directory could not be found.
(:refer-clojure :exclude [macroexpand-1 macroexpand var? record? boolean?])
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.