Giter Club home page Giter Club logo

clj-kondo's People

Contributors

abogoyavlensky avatar benedekfazekas avatar borkdude avatar cosineblast avatar dancek avatar delaguardo avatar ericdallo avatar heliosmaster avatar imrekoszo avatar jysandy avatar laurio avatar lispyclouds avatar lread avatar mainej avatar marcomorain avatar mk avatar mknoszlig avatar mrkam2 avatar noahtheduke avatar robert-stuttaford avatar severeoverfl0w avatar snoe avatar sogaiu avatar sumbach avatar svdo avatar timothypratley avatar tomdl89 avatar vemv avatar volrath avatar yuhan0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clj-kondo's Issues

Better local error handling

Instead of rejecting a whole file, we should report an error only on parts that could not be processed well, like namespace declarations.

Optimize linting single file with project cache

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.

clj-kondo fails with `No maching field found: getMessage for class java.lang.NullPointerException` when initializing cache

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)

Reader conditional support for defns and calls

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

clj-kondo chokes on string namespaces in require

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.

Improve help printing

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.

Support in-ns

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.

Config

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}}"
 }

Suggest using str/join

When detecting something like (str "foo" "/" "bar" "/" "baz") the linter might suggest using (str/join "/" ["foo" "bar" "baz"]).

Null pointer exception with nested namespaced maps

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."

  • Debian GNU/Linux 9.8 (stretch) x64
  • Clojure 1.10.0
  • openjdk 1.8.0_181
$ 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

`clj-kondo update` command

Inspired by the circleci command line tool:

clj-kondo update
clj-kondo update --unstable
clj-kondo update --check
clj-kondo update --check --unstable

minor improvements

  • make it clear in the README that clj-kondo is a static code analyzer
  • use no-doc on the macroexpand namespace
  • add screenshot of working IntelliJ setup

Suggest for modifiers

(for [i (range 10)]
    (let [j (* i 10)]
      j))

=>

(for [i (range 10)
        :let [j (* i 10)]]
    j)

Make calls order-aware of defns

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.

Experiment with clojure.spec for parsing defn forms

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)]]}]}]}

Support arity checking for common Java static methods

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

spec key typos

E.g.:

(s/fdef foo/foo :args (s/cat :x (s/keys :req-un [::bar]))))

(foo/foo {:baz 1})

info: did you mean bar?

Running without graalvm causes error

❯ 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

Write test for caching

When only linting clj(s) it should not read and write the cache for the other language.

clj-kondo creates cache directory in cwd if .clj-kondo doesn't exist

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.