I'm implementing a "missing protocol method arity" linter, but it occurs to me that it may be totally fine to omit arities. E.g. when implementing IFn, you often don't have to implement all 20 or so arities. Thoughts?
config to turn it on/off based on a/ protocol b/ implementing type c/ regex, namespace, etc?
I actually have two parts: mismatch, i.e. implementing an arity that does not match the protocol and missing arity: protocol declares arity which isn't implemented. I could split these into two different linters and default the latter to off.
Tangentially related, but it might have helped with a situation like this I ran into earlier this year:
(defprotocol Bounded
(beg [x])
(end [x])
(size [x]))
(defrecord Interval [lo hi]
Bounded
(beg [x] lo)
(end [x] hi))
; Syntax error (VerifyError) compiling new at (dev/repro.cljc:9:1).
; Bad type on operand stack
; Exception Details:
; Location:
; repro/Interval.size()Ljava/lang/Object; @6: areturn
; Reason:
; Type integer (current frame, stack[0]) is not assignable to reference type
; Current Frame:
; bci: @6
; flags: { }
; locals: { 'repro/Interval' }
; stack: { integer }
; Bytecode:
; 0000000: 2ab9 017d 0100 b0
After much confusion I eventually found out that it was due to a name conflict with java.util.Map/size injected by the defrecord constructoroops ignore the above, I realise clj-kondo already emits a Missing protocol method(s): size (clj-kondo-clj) warning which I must have missed at the time - in any case the method had to be renamed
I don't know how old the missing protocol method is, but it's fairly new
The 2 part approach makes sense to me but I'd still vote for detailed config of the latter if it does not complicate things too much. Might also suggest adding method name to it too. Some protocols and implementing types might have been designed with holes in mind similarly to ifn you wrote
I'll first push it out with off by default and then wait for more feedback. I want to get out a clj-kondo release this week :)
By all means. Just wanted to throw some ideas
people could also ignore it with #_{:clj-kondo/ignore [:missing-protocol-method-arity]}
I think the partial IFn implementation will be fairly common. I know at work we only ever implement just one or two arities for that, and we don't implement applyTo (or whatever it's called).
yeah
would it be possible to say "any protocol not in clojure.core raises a warning"?
would there be a reason not to write a protocol like IFn outside of core?
i'm sorry, i mean that the protocols in clojure.core wouldn't be checked for missing method arities, but usage of a protocol defined in idk noahtheduke.splint.foo would be checked for missing method arities
but i guess that could even be lowered to just IFn, as nearly everything else would want to be covered
my question is more like: why would core protocols be any different in nature than user written protocols
I was trying to think of a solution for folks not implementing all 20 IFn arities lol
I think IFn is probably a common but pathological case: lots of arities, almost no one implements all of them. For all other protocols, yes, the linter would be useful. So, I agree with @nbtheduke 🙂
to continue the bikeshed, i wonder if :missing-protocol-method-arity {:check-ifn false} would be a good default (similar to :exclude-destructured-as)
That's weirdly specific. If it's configurable beyond enable/disable globally/locally, I'd prefer that to be flexible to be applied to more protocols/types/namespaces/methods/arities etc.
https://github.com/clj-kondo/clj-kondo/blob/master/CHANGELOG.md#unreleased - try it out before it's too late ;)
@ericdallo perhaps you can try it, so I can release tomorrow without clojure-lsp regressions
thanks, but I'm pretty busy this week to test :/
ok no problem, then we'll just see.