Closed NoahTheDuke closed 2 years ago
Hi, thanks for the ♡!
Neither Lein startup time or JVM startup time are the bottleneck here - it's by and large tools.analyzer.
These days I'm fostering Eastwood, most of all, as a CI oriented solution, where startup time isn't perceived (people rarely stare at builds) and linting typically runs in parallel, relative to tests.
It tends to be a good idea to run clj-kondo before Eastwood, possibly fail-fasting it. As hopefully you know, both linters don't fully overlap, so running both is worth it.
One might further cut the run time by only running git-touched files, by comparing a PR against master
. Polylith (and similar architectures) are good at this, see e.g. https://github.com/polyfy/polylith/issues/179
Finally, it's also possible to run Eastwood from your REPL, integrated with a Reloaded workflow e.g. only refresh
ed files will be analyzed. https://github.com/nedap/formatting-stack is good at this, I use it daily however I don't consider it ready for prime time - just a few people actually use formatting-stack. We have some refactoring to do.
I hope this give you a good overview.
The only issue with being CI-oriented is that it's the last possible moment to catch certain classes of errors. For example, Eastwood reports that (java.math.BigInteger foo 1)
doesn't have a matching ctor, so I have to type hint foo
as a string, etc. Such reflection-based errors aren't being caught by clj-kondo, but I won't know that until I've created a set of commits and triggered a CI run that the code is "incorrect".
Being able to use the repl for instant feedback is nice, but it's not always possible sadly (some codebases aren't built for repl-driven development :sob:), so I like to do periodic lein eastwood "{:namespace [my-ns.core]}"
. If you have any hints that aren't "use the repl" to speed up execution (checking a single namespace takes 26 seconds on my fairly beefy machine), I'd love to hear them.
Hi again, sorry for the delay!
If you have any hints that aren't "use the repl" to speed up execution (checking a single namespace takes 26 seconds on my fairly beefy machine), I'd love to hear them.
repl means here more broadly "use your existing JVM to invoke Eastwood".
So if you already have a JVM for your server app, and invoke Eastwood programatically, checking a single ns will take < 0.5s - not 26s.
There are some caveats related to re-evaluation. Perhaps you are familiar with them: evaluating code in an unlucky order can mean opaque issues, particularly related to defprotocol<->defrecord relationships (not if you use metadata-based protocol extension).
By carefully checking out the README you can get a full idea of these tradeoffs.
If going the programmatic route, eastwood.lint/eastwood
is the defn to invoke. https://github.com/nedap/formatting-stack/blob/b77370f9ed972b21203b4f15197ad297688e4b29/src/formatting_stack/linters/eastwood.clj is a real-world example.
But honestly, as of 2022 I'm not very interested in fostering these ways. They can work, but they also can be a rabbit hole if hacking with Clojure tooling isn't already your bread and butter.
So as a pragmatic recommendation, I'd say:
*warn-on-reflection*
globally, strategically
Cheers - V
First off, love Eastwood, has saved my butt many times.
I'd love to use this from the command line.
lein eastwood
works butlein
incurs a heavy start-up cost. Is there any chance of a GraalVM-style standalone executable of Eastwood?