Skip to content

Commit cfa50df

Browse files
committed
Bump version for release
1 parent 72b3e9e commit cfa50df

File tree

10 files changed

+142
-61
lines changed

10 files changed

+142
-61
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ This changelog is loose. Versions are not semantic, they are incremental. Splint
44

55
## Unreleased
66

7+
## 1.22.0 - 2025-11-17
8+
79
BREAKING CHANGES:
810

911
* The pattern parser is less forgiving of mistakes, so custom patterns might break.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ More explicit instructions can be found in the [installation][installation], [us
2121
### Clojure CLI
2222

2323
```clojure lazytest/skip=true
24-
:aliases {:splint {:extra-deps {io.github.noahtheduke/splint {:mvn/version "1.21.0"}}
24+
:aliases {:splint {:extra-deps {io.github.noahtheduke/splint {:mvn/version "1.22.0"}}
2525
:main-opts ["-m" "noahtheduke.splint"]}}
2626
```
2727

@@ -32,7 +32,7 @@ Run with `clojure -M:splint [args...]`.
3232
Add this to `project.clj`:
3333

3434
```clojure lazytest/skip=true
35-
:profiles {:dev {:dependencies [[io.github.noahtheduke/splint "1.21.0"]]}}
35+
:profiles {:dev {:dependencies [[io.github.noahtheduke/splint "1.22.0"]]}}
3636
:aliases {"splint" ["run" "-m" "noahtheduke.splint"]})
3737
```
3838

@@ -43,7 +43,7 @@ Run with `lein splint [args...]`.
4343
Requires version 1.12.205 or later. If using `bb.edn`, add this to `bb.edn`:
4444

4545
```clojure lazytest/skip=true
46-
:tasks {splint {:extra-deps {io.github.noahtheduke/splint {:mvn/version "1.21.0"}}
46+
:tasks {splint {:extra-deps {io.github.noahtheduke/splint {:mvn/version "1.22.0"}}
4747
:task noahtheduke.splint/-main}}
4848
```
4949

docs/installation.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ When used in a project as a library, put it in an alias to make it easier to inv
55
## Clojure CLI
66

77
```clojure
8-
:aliases {:splint {:extra-deps {io.github.noahtheduke/splint {:mvn/version "1.21.0"}}
8+
:aliases {:splint {:extra-deps {io.github.noahtheduke/splint {:mvn/version "1.22.0"}}
99
:main-opts ["-m" "noahtheduke.splint"]}}
1010
```
1111

@@ -16,7 +16,7 @@ Run with `clojure -M:splint [args...]`.
1616
Add this to `project.clj`:
1717

1818
```clojure
19-
:profiles {:dev {:dependencies [[io.github.noahtheduke/splint "1.21.0"]]}}
19+
:profiles {:dev {:dependencies [[io.github.noahtheduke/splint "1.22.0"]]}}
2020
:aliases {"splint" ["run" "-m" "noahtheduke.splint"]}
2121
```
2222

@@ -27,7 +27,7 @@ Run with `lein splint [args...]`.
2727
Requires version 1.12.205 or later. If using `bb.edn`, add this to `bb.edn`:
2828

2929
```clojure
30-
:tasks {splint {:extra-deps {io.github.noahtheduke/splint {:mvn/version "1.21.0"}}
30+
:tasks {splint {:extra-deps {io.github.noahtheduke/splint {:mvn/version "1.22.0"}}
3131
:task noahtheduke.splint/-main}}
3232
```
3333

@@ -39,7 +39,7 @@ It can also be installed using `bbin`:
3939
$ bbin install io.github.noahtheduke/splint
4040
{:coords
4141
#:git{:url "https://github.com/noahtheduke/splint",
42-
:tag "v1.21.0",
42+
:tag "v1.22.0",
4343
:sha "..."},
4444
:lib io.github.noahtheduke/splint}
4545
```

docs/rules/lint.md

Lines changed: 84 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
- [lint/missing-body-in-when](#lintmissing-body-in-when)
3535
- [lint/no-catch](#lintno-catch)
3636
- [lint/no-op-assignment](#lintno-op-assignment)
37+
- [lint/no-target-for-method](#lintno-target-for-method)
3738
- [lint/not-empty?](#lintnot-empty)
3839
- [lint/prefer-method-values](#lintprefer-method-values)
3940
- [lint/prefer-require-over-use](#lintprefer-require-over-use)
@@ -45,6 +46,7 @@
4546
- [lint/thread-macro-one-arg](#lintthread-macro-one-arg)
4647
- [lint/try-splicing](#linttry-splicing)
4748
- [lint/underscore-in-namespace](#lintunderscore-in-namespace)
49+
- [lint/update-with-swap](#lintupdate-with-swap)
4850
- [lint/warn-on-reflection](#lintwarn-on-reflection)
4951

5052
<!-- tocstop -->
@@ -307,9 +309,7 @@ with the same name, but it's good to catch these things early too.
307309

308310
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
309311
| ------------------ | ---- | ----------- | ------------- | --------------- |
310-
| true | true | false | 1.21.0 | 1.21.0 |
311-
312-
**NOTE:** Requires Clojure version 1.11.0.
312+
| true | true | false | 1.21.0 | 1.22.0 |
313313

314314
Java has `PI` and `E` constants built-in, and `clojure.math` exposes them directly. Better to use them instead of poorly approximating them with vars.
315315

@@ -320,9 +320,13 @@ Java has `PI` and `E` constants built-in, and `clojure.math` exposes them direct
320320
(def pi 3.14)
321321
(def e 2.718)
322322

323-
; prefer
323+
; prefer (Clojure 1.11+)
324324
clojure.math/PI
325325
clojure.math/E
326+
327+
; prefer (Clojure 1.10)
328+
java.lang.Math/PI
329+
java.lang.Math/E
326330
```
327331

328332
---
@@ -558,16 +562,15 @@ Two `not`s cancel each other out.
558562

559563
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
560564
| ------------------ | ---- | ----------- | ------------- | --------------- |
561-
| true | true | false | 1.21.0 | 1.21.0 |
565+
| true | true | false | 1.21.0 | 1.22.0 |
562566

563-
It can be necessary to swap two variables. This usually requires an intermediate variable, but with destructuring, Clojure can perform this in a single line. However, without an intermediate variable or destructuring, manually swapping can result in both variables ending up with the same value.
567+
It can be necessary to swap two variables. This usually requires an intermediate variable, but with destructuring, Clojure can perform this in a single line. If the destructuring is done incorrectly, then the assignment is a no-op, indicating a bug.
564568

565569
### Examples
566570

567571
```clojure
568572
; avoid
569-
(let [a b
570-
b a] ...)
573+
(let [[a b] [a b]] ...)
571574

572575
; prefer
573576
(let [[a b] [b a]] ...)
@@ -800,7 +803,7 @@ In interop scenarios, it can be necessary to add a type hint to mark a function'
800803

801804
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
802805
| ------------------ | ---- | ----------- | ------------- | --------------- |
803-
| true | true | false | 1.21.0 | 1.21.0 |
806+
| true | true | false | 1.21.0 | 1.22.0 |
804807

805808
Try without a `catch` (or `finally`) clause is a no-op, and indicates something got changed or broken at some point.
806809

@@ -861,6 +864,32 @@ Skips if the expr is a reader conditional or has a type-hint.
861864

862865
---
863866

867+
## lint/no-target-for-method
868+
869+
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
870+
| ------------------ | ---- | ----------- | ------------- | --------------- |
871+
| true | true | false | 1.22.0 | 1.22.0 |
872+
873+
Instance methods require a target instance. If there's none or it's nil, highly likely there's a bug.
874+
875+
This rule ignores when a find is nested in a `doto` or similar form: `(doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))` will not raise a diagnostic.
876+
877+
### Examples
878+
879+
```clojure
880+
; avoid
881+
(.length)
882+
(.length nil)
883+
(String/.length)
884+
(String/.length nil)
885+
886+
; prefer
887+
(.length foo)
888+
(String/.length foo)
889+
```
890+
891+
---
892+
864893
## lint/not-empty?
865894

866895
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
@@ -898,23 +927,21 @@ Skips if the expr is a reader conditional or has a type-hint.
898927

899928
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
900929
| ------------------ | ---- | ----------- | ------------- | --------------- |
901-
| true | true | true | 1.13 | 1.13 |
930+
| true | true | false | 1.13 | 1.22.0 |
902931

903932
**NOTE:** Requires Clojure version 1.12.0.
904933

905-
Uniform qualified method values are a new syntax for calling into java code. They must resolve to a single static or instance method and to help with that, a new metadata syntax can be used: `^[]` aka `^{:param-tags []}`. Types are specified with classes, each corrosponding to an argument in the target method: `(^[long String] SomeClass/.someMethod 1 "Hello world!")`. It compiles to a direct call without any reflection, guaranteeing optimal performance.
906-
907-
Given that, it is preferable to exclusively use method values.
934+
Uniform qualified method values are a new syntax for calling into java code. Instead of type hints, methods are qualified with their class (and with the new `:param-tags` aka `^[]` metadata where ambiguous). This will be compiled into direct calls, making them both the most clear and the highest performing way to execute Java interop.
908935

909936
### Examples
910937

911938
```clojure
912939
; avoid
913-
(.toUpperCase "noah")
914-
(. "noah" toUpperCase)
940+
(.toUpperCase name-string)
941+
(. name-string toUpperCase)
915942

916943
; prefer
917-
(^[] String/toUpperCase "noah")
944+
(String/toUpperCase name-string)
918945
```
919946

920947
### Reference
@@ -963,11 +990,9 @@ In the `ns` form prefer `:require :as` over `:require :refer` over `:require :re
963990

964991
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
965992
| ------------------ | ---- | ----------- | ------------- | --------------- |
966-
| true | true | false | 1.21.0 | 1.21.0 |
967-
968-
`clojure.core/rand-int` returns an integer between `0` (inclusive) and `n` (exclusive), meaning that a call to `(rand-int 1)` will always return `0`.
993+
| true | true | false | 1.21.0 | 1.22.0 |
969994

970-
Checks the following numbers: `0`, `0.0`, `1`, `1.0`, `-1`, `-1.0`
995+
`clojure.core/rand-int` generates a float between `0` and `n` (exclusive) and then casts it to an integer. When given `1` (or a number less than `1`), `rand-int` will always return `0`.
971996

972997
### Examples
973998

@@ -978,7 +1003,6 @@ Checks the following numbers: `0`, `0.0`, `1`, `1.0`, `-1`, `-1.0`
9781003
(rand-int 1)
9791004
(rand-int 1.0)
9801005
(rand-int -1.0)
981-
(rand-int 1.5)
9821006
```
9831007

9841008
---
@@ -987,11 +1011,9 @@ Checks the following numbers: `0`, `0.0`, `1`, `1.0`, `-1`, `-1.0`
9871011

9881012
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
9891013
| ------------------ | ---- | ----------- | ------------- | --------------- |
990-
| true | true | true | 0.1 | 0.1 |
1014+
| true | true | true | 0.1 | 1.22.0 |
9911015

992-
A number of core functions take any number of arguments and return the arg
993-
if given only one. These calls are effectively no-ops, redundant, so they
994-
should be avoided.
1016+
A number of core functions take any number of arguments and return the arg if given only one. These calls are effectively no-ops, redundant, so they should be avoided.
9951017

9961018
Current list of clojure.core functions this linter checks:
9971019

@@ -1001,6 +1023,8 @@ Current list of clojure.core functions this linter checks:
10011023
* `comp`, `partial`, `merge`
10021024
* `min`, `max`, `distinct?`
10031025

1026+
This list can be expanded with the configuration `:fn-names`.
1027+
10041028
### Examples
10051029

10061030
```clojure
@@ -1018,10 +1042,19 @@ Current list of clojure.core functions this linter checks:
10181042
(max x)
10191043
(distinct? x)
10201044

1045+
; avoid (with `:fn-names [cool-fn]`)
1046+
(cool-fn x)
1047+
10211048
; prefer
10221049
x
10231050
```
10241051

1052+
### Configurable Attributes
1053+
1054+
| Name | Default | Options |
1055+
| ----------- | ------------------------------------------------------------------------------ | ------- |
1056+
| `:fn-names` | `#{cond->> comp min -> some->> cond-> merge some-> partial distinct? max ->>}` | Set |
1057+
10251058
---
10261059

10271060
## lint/redundant-str-call
@@ -1056,9 +1089,7 @@ x
10561089

10571090
Uniform qualified method values are a new syntax for calling into java code. They must resolve to a single static or instance method and to help with that, a new metadata syntax can be used: `^[]` aka `^{:param-tags []}`. Types are specified with classes, each corrosponding to an argument in the target method: `(^[long String] SomeClass/someMethod 1 "Hello world!")`
10581091

1059-
If `:param-tags` is left off of a method value, then the compiler treats it as taking no arguments (a 0-arity static method or a 1-arity instance method with the instance being the first argument). And an `_` can be used as a wild-card in the cases where there is only a single applicable method (no overloads).
1060-
1061-
These last two features are where there can be trouble. If, for whatever reason, the Java library adds an overload on type, then both the lack of `:param-tags` and a wild-card can lead to ambiguity. This is a rare occurence but risky/annoying enough that it's better to be explicit overall.
1092+
An `_` can be used as a wild-card in the cases where there is only a single applicable method (no overloads). If, for whatever reason, the Java library adds an overload on type, then both the lack of `:param-tags` and a wild-card can lead to ambiguity. This is a rare occurence but risky/annoying enough that it's better to be explicit overall.
10621093

10631094
The styles are named after what they're looking for:
10641095

@@ -1208,6 +1239,31 @@ Due to munging rules, underscores in namespaces can confuse tools and libraries
12081239

12091240
---
12101241

1242+
## lint/update-with-swap
1243+
1244+
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
1245+
| ------------------ | ----- | ----------- | ------------- | --------------- |
1246+
| true | false | false | 1.22.0 | 1.22.0 |
1247+
1248+
If an atom is stored inside if a map, the atom can be changed using `swap!` within an `update` or `update-in` call. However, `swap!` returns the new value, not the atom itself, so the container map will hold the deref'ed value of the atom, not the original atom. If the result of the `update` call is stored/used, this can lead to bugs.
1249+
1250+
Additionally, if the return value of the `update` call is ignored, then the `update` form will work as expected (because the return value won't overwrite the existing map and the atom will be updated in place). This should be avoided as it breaks expectations about the value of values and normal behavior.
1251+
1252+
### Safety
1253+
If the `update` call's return value isn't ignored (it's used in an assignment or passed to another call), switching to `swap!` will break the expected return value. Care must be exercised when switching.
1254+
1255+
### Examples
1256+
1257+
```clojure
1258+
; avoid
1259+
(update state :counter swap! + 5)
1260+
1261+
; prefer
1262+
(swap! (:counter state) + 5)
1263+
```
1264+
1265+
---
1266+
12111267
## lint/warn-on-reflection
12121268

12131269
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |

docs/rules/naming.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Uses simple string checking and can misunderstand English intention when `X-to-Y
9393

9494
| Enabled by default | Safe | Autocorrect | Version Added | Version Updated |
9595
| ------------------ | ----- | ----------- | ------------- | --------------- |
96-
| true | false | false | 1.3.0 | 1.3.0 |
96+
| true | false | false | 1.3.0 | 1.22.0 |
9797

9898
Use lisp-case for function and variable names. (Replacement is generated with [camel-snake-kebab](https://github.com/clj-commons/camel-snake-kebab).)
9999

@@ -116,6 +116,7 @@ Interop, json, and other styles can make it necessary to use such forms.
116116
; ignores
117117
(defn StackTraceElement->vec [o] ...)
118118
(defn NaN? [n] ...)
119+
(defn -objHandler ...)
119120
```
120121

121122
### Reference

0 commit comments

Comments
 (0)