Fork me on GitHub
#clj-kondo
<
2021-03-09
>
Volodymyr Huzar13:03:26

I have a problem with linting usage of plumbing.core/?>

(let [live? true]
  (-> {}
    (plumbing.core/?> live? (assoc :live live))))
I am receiving two :invalid-arity errors
error: Insufficient input.
error: Expected: associative collection or nil, received: keyword.
Any thoughts on how to fix or ignore linting where it is used?

borkdude13:03:02

Is this macro syntactically similar to one in core?

borkdude13:03:59

it seems similar to cond-> am I right?

borkdude13:03:59

@vguzar I think this macro can be regarded as deprecated in favor of clojure.core/cond-> which I think does the same, but I could be missing something

borkdude13:03:58

But if you want to keep using it, you can use {:lint-as {plumbing.core/?> clojure.core/cond->}}

Volodymyr Huzar13:03:39

seems like you are right that cond-> should be used instead, but I don’t think :lint-as will work as it is used differently but let me check. By the way is it possible to deprecate by clj-kondo?

borkdude13:03:42

You mean say in your config: I regard these functions are deprecated, so give me a warning when you use them?

Volodymyr Huzar13:03:11

yes, something like that

Volodymyr Huzar13:03:06

as I suspected lint-as doesn’t help, ” No matching clause: “?>“” is shown as an error

borkdude13:03:20

We do have a deprecated var linter: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#deprecated-var But no way to add your own vars to that. That could be useful, but it's done automatically if the var is marked deprecated in the library already

borkdude13:03:11

That's a weird error message. Let me try this.

borkdude13:03:40

I can reproduce that, but it seems like a bug

Volodymyr Huzar14:03:38

It could be useful to have your own set of deprecated 3rd party stuff, like stop use that and start use this instead

borkdude14:03:48

yeah, I agree. similar stuff has been considered for clojure.core/read-string for example, but there are cases where you still might want to use that

borkdude14:03:57

but if a var is deprecated in favor of something else that is compatible then that config would make sense for :deprecated-var {:deprecated-var {foo.bar/baz foo.bar/quux}} => Var foo.bar/baz is deprecated. Use foo.bar/quux instead

👍 1
teodorlu15:03:30

{:deprecated-var {foo.bar/baz foo.bar/quux}}
Shot from the sideline, I'd prefer to be able to specify both what should be used instead (quux), and the reason for deprecation. So if you're designing a data structure for this, I'd put a map on the right side. Example:
{:deprecated-var {foo.bar/baz {:use-instead foo.bar/quux
                               :reason "baz has a bad API design, it doesn't handle X use case"}}}

borkdude15:03:24

yes, good idea. I also want to put a map in between: {:deprecated-var {:some-name {foo.bar/baz ...}}} but I don't know what this name should be

teodorlu15:03:38

Something like

{:deprecated {:vars {foo.bar/baz {:use-instead foo.bar/quux
                                  :reason "..."}}}}
? Not sure what you want to achieve.

borkdude15:03:20

Usually the structure is {:linter-name {:exclude {...}} so every setting has an explicit name within the linter map

👍 1
Volodymyr Huzar14:03:08

and here I have another question which could be related to what you have said in corner cases. Is it possible to mark some rules not be run on specific namespaces. For example I want

:private-call
rule fails on production code but ignore it for tests. Could I use something like
:private-call {:level :error
               :exclude {:namespaces [".*-tests$"]}} 
?

borkdude14:03:45

In tests you can use #'my.private/var

borkdude14:03:11

or you can turn it off in the namespace config:

(ns foo
  {:clj-kondo/config '{:linters {:private-call {:level :off}}}})

Volodymyr Huzar14:03:21

so it is not possible to set in configuration that some particular rule will be disabled for all namespaces matching pattern “.*-tests$“, is it?

borkdude14:03:49

This is what you use the namespace local config for

borkdude14:03:43

Are you using this in ClojureScript? AFAIK the Clojure compiler forbids using private vars unless via the var object

borkdude14:03:22

Can you create an issue about the deprecated var idea? I am fixing the bug with lint-as + cond-> as we speak.

yes 1
borkdude14:03:26

Fixed on master

👍 1
Volodymyr Huzar14:03:19

> Are you using this in ClojureScript? Yes, I’m, probably it should be okay to make them public in such case

borkdude14:03:30

In CLJS using #'foo/bar also works

thanks2 1
Volodymyr Huzar15:03:04

@borkdude issue for third-party deprecation is created https://github.com/clj-kondo/clj-kondo/issues/1207 Feel free to edit the description by itself

🙏 1
Volodymyr Huzar15:03:48

> In CLJS using `#'foo/bar` also works Maybe I got you wrong but this doesn’t work for cljs. (to add I am not so experience in Clojure syntax 😶) I have tried to change from

(ns test
  (:require [foo :refer [bar]))

(def test-bar bar)
to
(ns test)

(def test-bar #'foo/bar)
and it fixed the linter but broken the test in the same time

borkdude15:03:00

You should still require the namespace

borkdude15:03:39

You don't have to define test-bar, you can do it like this:

(ns test
  (:require foo))
(#'foo/bar 1 2 3)

borkdude15:03:13

foo=> (ns foo)
WARNING: foo is a single segment namespace at line 1
nil
foo=> (def ^:private x 1)
#'foo/x
foo=> @#'foo/x
1
foo=> (ns bar (:require foo))
WARNING: bar is a single segment namespace at line 1
Execution error (ExceptionInfo) at (<cljs repl>:1).
No such namespace: foo, could not locate foo.cljs, foo.cljc, or JavaScript source providing "foo"
foo=> @#'foo/x
1
This is from a REPL session

Volodymyr Huzar15:03:01

thanks, by bad knowledge on clojure syntax I have missed @