Splint v1.9.0 and v1.10.0
Forgot to post after releasing v1.9.0 back in May, so this is gonna be fuckin huge.
In short: v1.9 added a new rule (style/prefer-clj-string) and a new cli flag (--[no-]summary). v1.10 added reading available deps.edn and project.clj files to determine the directories to check, changing the pattern DSL to use a variation of pangloss/pattern's DSL, and to add 5 new rules, 4 of which are performance rules (style/redundant-regex-constructor, performance/assoc-many, performance/avoid-satisfies, performance/get-in-literals, performance/get-keyword).
The change in v1.10 means that you can run bb splint or clojure -M:splint and it'll "just work": it'll check the primary directories and the directories under and :test alias without any extra fiddling. This makes it much easier to use quickly. I've always been annoyed at clj-kondo's insistence on forcing the --lint flag for choosing files, and loved Rubocop's "just run it" mentality.
The performance rules are disabled by default cuz they might make code more wordy or annoying to work with, and they're highly opinionated. I like them but I get it.
Full release docs/change logs under the fold.
v1.9.0
New Rules
style/prefer-clj-string: Preferclojure.stringfunctions over raw interop. Defaults totrue.
Added
--[no]summarycli flag to print or not print the summary line.
Changed
:filenameinDiagnosticis now ajava.io.Fileobject, not a string. This is propogated through everything. I suspect no one is using these so I think I could change theDiagnosticas well, but maybe I'll wait a min.make-edamame-optsnow accepts bothfeaturesandns-state, andparse-stringandparse-string-alltake infeaturesinstead ofns-state.- The runner tracks the filetype of each file and runs over
cljcfiles twice, bothcljandcljs, with their respective sides of the reader conditionals applied. - Diagnostics are deduped before printing.
lint/warn-on-reflectiononly runs incljfiles.- Remove
farolero. Didn't provide any benefits over judicioustry/catchuse. :( - Extend the
matcher-combinators.core/Matcherprotocol tojava.io.File, makingmatch?work nicely with both strings and file objects. - Performance improvements by converting
rules-by-typefrom a map of simple-type -> map of rule name -> rule to simple-type -> vec of rule.
Fixed
- Correctly print special characters/clojure.core vars (
@, notsplint/deref, etc).
v1.10.0
The big feature here is adding support to run splint without specifying paths. Now Splint will read the deps.edn or project.clj file in the current directory and check the paths in the base definition as well as :dev and :test aliases/profiles if no path argument is given. Splint still doesn't support specifying paths in .splint.edn, nor does it allow for using paths from a project file as well as additional paths when called, but those are planned.
The second big change is moving from the old DSL to the new pangloss/pattern inspired DSL. More flexible, more usable, overall better.
The third is adding performance rules. These are off by default and are designed for those who want to pinch their cycles. Some affect common code (get-in) and some are much more rare (satisfies), but they're all designed to help you be mindful of slower paths.
Breaking
- Moved
spat.parsertosplint.parser. - Moved
spat.patterntosplint.pattern. RIPspat, you treated me well for 9 months, but keepingspatandsplintseparate is no longer helpful. - Switched to the new pattern system, updated all rules.
New Rules
performance/assoc-many: Prefer(-> m (assoc :k1 1) (assoc :k2 2))over(assoc m :k1 1 :k2 2).performance/avoid-satisfies: Do not useclojure.core/satisfies?, full stop.performance/get-in-literals: Prefer(-> m :k1 :k2 :k3)over(get-in m [:k1 :k2 :k3]).performance/get-keyword: Prefer(:k m)over(get m :k).style/redundant-regex-constructor: Prefer#"abc"over(re-pattern #"abc").
Added
- Implemented faster/more efficient versions of Clojure standard library functions:
->list: concrete list building instead of apply . Useful anywhere a lazy-seq might be returned otherwise. seq/vec input: 40/43 us -> 28/15 usmapv*:mapvbut short-circuits empty input and usesobject-array. Still unsure of this one. 36 us -> 36 usrun!*:run!but short-circuits empty input and uses.iteratorto perform the side-effects. Does not supportreduced. 7 us -> 950 nspmap*: Avoids lazy-seq overhead and relies on Java's built-in Executors. 3.34 s -> 202 mswalk*andpostwalk*: Primarily useful inreplace, but may prove useful otherwise. Only supportssimple-typedefined types. 72 us -> 25 us
splint.config/read-project-filereturns a map of:clojure-versionand:paths, taken from the project file (deps.ednorproject.clj) in the current directory. If no file is found,:pathsisniland:clojure-versionis pulled from*clojure-version*.:min-clojure-versionindefrule, allowing for rules to specify the minimum version of clojure they require. Rules that are below the supported version are disabled at preparation time and can't be enabled during a run. Acceptable shape is a map of at least one of:major,:minor, and:incremental.- Include this in rule documentation.
test-helpers/with-temp-fileandtest-helpers/print-to-file!to test file contents.
Changed
- Move
spat.parser/parse-stringandspat.parser/parse-string-allinto the test-helper namespace, and replace withparse-filewhich accepts thefile-objmap. - Parse data reader/tagged literals as maps instead of lists, and put the extension (dialect) into the symbol's metadata.
- Defer building cli summary until needed.
- Use new
splint.config/slurp-ednto read config files, parsed with [edamame][edamame]. - Changed
:spat/litmetadata to:splint/lit.:spat/litstill works for the time being, but no promises. splint.printer/print-resultsnow accepts only theresultsobject, which should additionally have:checked-filesand:total-time.- Output formats
simple,full,andclj-kondonow print the number of files checked as well:"Linting took 1ms, checked 3 files, 3 style warnings" - Moved
splint.replace/revert-splint-reader-macrosintosplint.printerwhere it belongs. - Rely on undefined behavior in
symbolto correctly print unprintable special characters by converting sexprs to strings and then converting those to symbols. - Move
simple-typeanddrop-quotetosplint.utils.